diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d8a392a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Change Log + +## [Unreleased] + +## [1.1.1] - 2015-12-15 +### Added +- Plugin version in vanilla JavaScript. +- Option to remove 'philter' from data attributes to make markup shorter. +### Fixed +- False element width or height being set on custom SVG filters. +## [1.1.0] - 2015-11-07 +### Changed +- Changed classes to data attributes to describe filters. +### Removed +- Describing filters with classes. The old version still can be found in dist directory. diff --git a/README.md b/README.md index 24c9d31..377b1a3 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,40 @@ -# Philter v1.1.0 -Philter is a jQuery plugin giving you the power to control CSS filters with HTML data attributes. +# Philter v1.1.1 +Philter is a JS plugin giving you the power to control CSS filters with HTML data attributes. Visit the [Demo page](http://specro.github.io/Philter/) for examples. ## Dependencies -You probably already guessed it. You need jQuery for this one: +Philter comes in two flavors - jQuery and vanilla JS. Choose the one you want just don't forget in jQuery case to include it: ```HTML ``` -You could also use Bower which is my prefered method. +You could also use Bower which is my preferred method. ## Installation Download the plugin and move the 'philter' directory to your 'js' directory, then include it in your page: ```HTML ``` +or in jQuery +```HTML + +``` And that's it! You're ready to go! ## How To First initiate the plugin: +```HTML + +``` +or again in jQuery + ```HTML ``` -You can pass 2 parameters to Philter: -* transitionTime - the hover transition time of default CSS filters +You can pass 3 parameters to Philter: +* transitionTime - The hover transition time of default CSS filters * url - Philter loads custom SVG filters from external files. Its default path is '../js' where it reaches the filters in default 'philter' folder. If your directory differs somehow e. g. you use 'scripts' instead of 'js' directory, you should pass the path to 'philter' directory in the url parameter. You don't need the trailing slash! +* tag - This enables the 'philter' part in data-philter-. If you don't use any plugins which use data attributes or they won't collide with Philter, you can set this to false to omit this part and shorten your markup. Now you can start using the filters. The plugin uses this kind of syntax format: ``` @@ -77,11 +89,16 @@ Drop shadow filter supports only black color because with it's already long clas ## Class version (1.0.0) First version of Philter was based on CSS classes but it was deprecated in favor of data attributes. You still can use and edit the 1.0.0 version that is located in the dist directory. For more info on that version read the README supplied with it. ## Compatibility -Philter was developed on Chrome 46, Firefox 41 and Edge 20. The default CSS filters should be compatible with most versions of browsers that support filters. The custom filters support only Firefox and Chrome. -You may notice glitching on Edge when more than one hover element is on the page. +Philter was developed on Chrome 46, Firefox 41, Opera 34 and Edge 20. The default CSS filters should be compatible with most versions of browsers that support filters. The custom filters support only Firefox, Chrome and Opera. +You may notice glitching on Edge when more than one hover element is on the page and loss of some filters when they are stacked on one element. +## Issues +This is mainly due to SVG filter limitations or complexities. It may be solved in the future... or it may not. +* SVG filters don't stack with any other filters. That means one SVG filter for one HTML element. +* SVG filters don't support transitions. +* SVG filters have no idea what to do when you hover over them. + ## WIP -* Transitions on custom SVG filters -* False element width or height being sent to custom SVG filters * More custom SVG filters + ## License Philter is licensed under MIT License. diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..696ea61 --- /dev/null +++ b/bower.json @@ -0,0 +1,32 @@ +{ + "name": "Philter", + "description": "Philter is a jQuery plugin giving you the power to control CSS filters with HTML attributes", + "main": "dist/philter.js", + "moduleType": [ + "globals" + ], + "keywords": [ + "filters", + "CSS", + "HTML", + "JS", + "JavaScript", + "philter" + ], + "authors": [ + { "name": "Liudas Dzisevicius", "email": "liudas.dzisevicius@gmail.com" }, + ], + "license": "MIT", + "ignore": [ + "source", + "spec", + ".bowerrc", + ".gitignore", + ".jshintignore", + ".jshintrc", + "bower.json", + "gruntfile.js", + "package.json", + "README.md" + ] +} diff --git a/dist/philter-1.0.0/README.md b/dist/1.0.0/README.md similarity index 100% rename from dist/philter-1.0.0/README.md rename to dist/1.0.0/README.md diff --git a/dist/philter-1.0.0/philter.js b/dist/1.0.0/philter.js similarity index 100% rename from dist/philter-1.0.0/philter.js rename to dist/1.0.0/philter.js diff --git a/dist/philter-1.0.0/philter.min.js b/dist/1.0.0/philter.min.js similarity index 100% rename from dist/philter-1.0.0/philter.min.js rename to dist/1.0.0/philter.min.js diff --git a/dist/philter/philter.js b/dist/jquery.philter.js similarity index 92% rename from dist/philter/philter.js rename to dist/jquery.philter.js index e280c23..6225e1d 100644 --- a/dist/philter/philter.js +++ b/dist/jquery.philter.js @@ -1,4 +1,4 @@ -/* Philter v1.1.0 | (c) 2015 Liudas Dzisevicius | MIT License */ +/* Philter v1.1.1 | (c) 2015 Liudas Dzisevicius | MIT License */ (function ($) { 'use strict'; @@ -73,7 +73,7 @@ $.philter = function (params) { - params = $.extend({transitionTime: 0.5, url: '../js'}, params); + params = $.extend({transitionTime: 0.5, url: '../js', tag: true}, params); var filters = [ 'blur', @@ -94,8 +94,14 @@ var styleString = '",r("head").append(l)}}(jQuery); diff --git a/dist/philter.js b/dist/philter.js new file mode 100644 index 0000000..a9cc062 --- /dev/null +++ b/dist/philter.js @@ -0,0 +1,223 @@ +/* Philter v1.1.1 | (c) 2015 Liudas Dzisevicius | MIT License */ +(function() { + + 'use strict'; + + window.Philter = function() { + + var defaults = { + transitionTime: 0.5, + url: '../js', + tag: true + }; + var sheet = document.createElement('style'); + this.errors = { + falsePath: 'Philter Error: you probably didn\'t declare the right path to philter folder!' + }; + this.filterCount = { + 'color': 0 + }; + this.filters = [ + 'blur', + 'grayscale', + 'hue-rotate', + 'saturate', + 'sepia', + 'contrast', + 'invert', + 'opacity', + 'brightness', + 'drop-shadow', + 'svg', + 'color' + ]; + this.elements = []; + this.styleString = ''; + + if (arguments[0] && typeof arguments[0] === "object") { + this.options = extendDefaults(defaults, arguments[0]); + } else { + this.options = defaults; + } + + getElements.call(this); + parseElements.call(this); + + this.styleString += '*{transition:filter ' + this.options.transitionTime + 's,-webkit-filter ' + this.options.transitionTime + 's;}'; + sheet.innerHTML = this.styleString; + document.head.appendChild(sheet); + } + + function getElements() { + for (var i = 0; i < this.filters.length; i++) { + if (this.options.tag) { + var query = document.querySelectorAll('[data-philter-' + this.filters[i] + ']'); + } else { + var query = document.querySelectorAll('[data-' + this.filters[i] + ']'); + } + if (query) { + for (var j = 0; j < query.length; j++) { + if (this.elements.indexOf(query[j]) < 0) { + this.elements.push(query[j]); + } + } + } + } + } + + function parseElements() { + var filterStrings = ['', '']; + + for (var i = 0; i < this.elements.length; i++) { + for (var j = 0; j < this.filters.length; j++) { + if (this.options.tag) { + var filter = this.elements[i].getAttribute('data-philter-' + this.filters[j] + ''); + } else { + var filter = this.elements[i].getAttribute('data-' + this.filters[j] + ''); + } + if (filter) { + if (this.options.tag) { + var selector = '[data-philter-' + this.filters[j] + '="' + filter + '"]'; + } else { + var selector = '[data-' + this.filters[j] + '="' + filter + '"]'; + } + var width = this.elements[i].offsetWidth; + var height = this.elements[i].offsetHeight; + + filter = filter.split(' '); + filter.unshift(this.filters[j]); + filterStrings = getFilterString.call(this, filterStrings, filter, getUnits(filter[0]), width, height); + } + } + + this.styleString += selector + '{filter:' + filterStrings[0] + ';-webkit-filter:' + filterStrings[0] + ';}'; + if (filterStrings[0] != filterStrings[1]) { + this.styleString += selector + ':hover{filter:' + filterStrings[1] + ';-webkit-filter:' + filterStrings[1] + ';}'; + } + + filterStrings = ['', '']; + selector = ''; + } + } + + function getFilterString (filterStrings, filter, units, width, height) { + switch (filter[0]) { + case 'drop-shadow': + filterStrings[0] = filterStrings[0] + filter[0] + '(' + filter[1] + units + ' ' + filter[2] + units + ' ' + filter[3] + units + ' rgba(0,0,0,' + filter[4]*0.01 + ')) '; + if (filter[5] && filter[6] && filter[7] && filter[8]) { + filterStrings[1] = filterStrings[1] + filter[0] + '(' + filter[5] + units + ' ' + filter[6] + units + ' ' + filter[7] + units + ' rgba(0,0,0,' + filter[8]*0.01 + ')) '; + } else { + filterStrings[1] = filterStrings[1] + filter[0] + '(' + filter[1] + units + ' ' + filter[2] + units + ' ' + filter[3] + units + ' rgba(0,0,0,' + filter[4]*0.01 + ')) '; + } + break; + case 'svg': + filterStrings[0] = filterStrings[0] + 'url(' + units + filter[1] + ') '; + if (filter[2]) { + filterStrings[1] = filterStrings[1] + 'url(' + units + filter[2] + ') '; + } else { + filterStrings[1] = filterStrings[1] + 'url(' + units + filter[1] + ') '; + } + break; + case 'color': + ++this.filterCount['color']; + createColorFilter.call(this, filter[1], filter[2], width, height); + filterStrings[0] = filterStrings[0] + 'url(' + units + 'color-' + this.filterCount['color'] + ') '; + if (filter[3] && filter[4]) { + ++this.filterCount['color']; + createColorFilter.call(this, filter[3], filter[4], width, height); + filterStrings[1] = filterStrings[1] + 'url(' + units + 'color-' + this.filterCount['color'] + ') '; + } else { + filterStrings[1] = filterStrings[1] + 'url(' + units + 'color-' + this.filterCount['color'] + ') '; + } + break; + default: + filterStrings[0] = filterStrings[0] + filter[0] + '(' + filter[1] + units + ') '; + if (filter[2]) { + filterStrings[1] = filterStrings[1] + filter[0] + '(' + filter[2] + units + ') '; + } else { + filterStrings[1] = filterStrings[1] + filter[0] + '(' + filter[1] + units + ') '; + } + } + + return filterStrings; + } + + function createColorFilter(color, opacity, width, height, url) { + var svg = document.getElementById('svg'); + if (!svg) { + svg = document.createElement('div'); + svg.setAttribute('id', 'svg'); + svg.innerHTML = ''; + } + opacity = opacity * 0.01; + var xhr = new XMLHttpRequest(); + xhr.open('GET', this.options.url + '/philter/svg/color.svg'); + xhr.send(null); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + var data = xhr.response; + if (data) { + svg.querySelector('defs').innerHTML = data; + svg.querySelector('filter').setAttribute('id', 'color-' + this.filterCount['color']); + var flood = svg.querySelector('feFlood'); + setAttributes(flood, { 'flood-opacity': opacity, 'flood-color': color, 'width': width, 'height': height }); + document.body.appendChild(svg); + } else { + console.error(this.errors.falsePath); + } + } else if (xhr.status === 404) { + console.error(this.errors.falsePath); + } + } + }.bind(this); + } + + function getUnits(filter) { + var units = { + 'blur': 'px', + 'hue-rotate': 'deg', + 'drop-shadow': 'px', + 'svg': '#', + 'color': '#', + 'default': '%' + }; + + switch (filter) { + case 'blur': + return units[filter]; + break; + case 'hue-rotate': + return units[filter]; + break; + case 'drop-shadow': + return units[filter]; + break; + case 'svg': + return units[filter]; + break; + case 'color': + return units[filter]; + break; + default: + return units['default']; + } + } + + function setAttributes(el, attrs) { + for(var key in attrs) { + el.setAttribute(key, attrs[key]); + } + } + + function extendDefaults(source, properties) { + var property; + for (property in properties) { + if (properties.hasOwnProperty(property)) { + source[property] = properties[property]; + } + } + return source; + } + +}()); diff --git a/dist/philter.min.js b/dist/philter.min.js new file mode 100644 index 0000000..18fd82c --- /dev/null +++ b/dist/philter.min.js @@ -0,0 +1,2 @@ +/* Philter v1.1.1 | (c) 2015 Liudas Dzisevicius | MIT License */ +!function(){"use strict";function t(){for(var t=0;t'),e=.01*e;var n=new XMLHttpRequest;n.open("GET",this.options.url+"/philter/svg/color.svg"),n.send(null),n.onreadystatechange=function(){if(4===n.readyState)if(200===n.status){var s=n.response;if(s){l.querySelector("defs").innerHTML=s,l.querySelector("filter").setAttribute("id","color-"+this.filterCount.color);var a=l.querySelector("feFlood");o(a,{"flood-opacity":e,"flood-color":t,width:r,height:i}),document.body.appendChild(l)}else console.error(this.errors.falsePath)}else 404===n.status&&console.error(this.errors.falsePath)}.bind(this)}function s(t){var e={blur:"px","hue-rotate":"deg","drop-shadow":"px",svg:"#",color:"#","default":"%"};switch(t){case"blur":return e[t];case"hue-rotate":return e[t];case"drop-shadow":return e[t];case"svg":return e[t];case"color":return e[t];default:return e["default"]}}function o(t,e){for(var r in e)t.setAttribute(r,e[r])}function l(t,e){var r;for(r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);return t}window.Philter=function(){var r={transitionTime:.5,url:"../js",tag:!0},i=document.createElement("style");this.errors={falsePath:"Philter Error: you probably didn't declare the right path to philter folder!"},this.filterCount={color:0},this.filters=["blur","grayscale","hue-rotate","saturate","sepia","contrast","invert","opacity","brightness","drop-shadow","svg","color"],this.elements=[],this.styleString="",arguments[0]&&"object"==typeof arguments[0]?this.options=l(r,arguments[0]):this.options=r,t.call(this),e.call(this),this.styleString+="*{transition:filter "+this.options.transitionTime+"s,-webkit-filter "+this.options.transitionTime+"s;}",i.innerHTML=this.styleString,document.head.appendChild(i)}}(); diff --git a/dist/philter/philter.min.js b/dist/philter/philter.min.js deleted file mode 100644 index f6f1015..0000000 --- a/dist/philter/philter.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* Philter v1.1.0 | (c) 2015 Liudas Dzisevicius | MIT License */ -!function(r){"use strict";function t(r,t,i,l,a,s){return"drop-shadow"==t[0]?(r[0]=r[0]+t[0]+"("+t[1]+i+" "+t[2]+i+" "+t[3]+i+" rgba(0,0,0,"+.01*t[4]+")) ",t[5]&&t[6]&&t[7]&&t[8]?r[1]=r[1]+t[0]+"("+t[5]+i+" "+t[6]+i+" "+t[7]+i+" rgba(0,0,0,"+.01*t[8]+")) ":r[1]=r[1]+t[0]+"("+t[1]+i+" "+t[2]+i+" "+t[3]+i+" rgba(0,0,0,"+.01*t[4]+")) "):"svg"==t[0]?(r[0]=r[0]+"url("+i+t[1]+") ",t[2]?r[1]=r[1]+"url("+i+t[2]+") ":r[1]=r[1]+"url("+i+t[1]+") "):"color"==t[0]?(o.color=o.color+1,e(t[1],t[2],l,a,s),r[0]=r[0]+"url("+i+"color-"+o.color+") ",t[3]&&t[4]?(o.color=o.color+1,e(t[3],t[4],l,a,s),r[1]=r[1]+"url("+i+"color-"+o.color+") "):r[1]=r[1]+"url("+i+"color-"+o.color+") "):(r[0]=r[0]+t[0]+"("+t[1]+i+") ",t[2]?r[1]=r[1]+t[0]+"("+t[2]+i+") ":r[1]=r[1]+t[0]+"("+t[1]+i+") "),r}function e(t,e,i,l,a){r("#svg").length||(r("body").append('
'),r("#svg").append('')),e=.01*e,r.ajax({url:a+"/philter/svg/color.svg",success:function(a){r(a).find("filter").attr("id","color-"+o.color),r(a).find("feFlood").attr({"flood-opacity":e,"flood-color":t,width:i,height:l});var s=(new XMLSerializer).serializeToString(a.documentElement);r("defs").append(s),r("#svg").html(r("#svg").html())},error:function(r,t,e){console.error(e)},async:!1})}var o=[];o.color=0,r.philter=function(e){e=r.extend({transitionTime:.5,url:"../js"},e);for(var o=["blur","grayscale","hue-rotate","saturate","sepia","contrast","invert","opacity","brightness","drop-shadow","svg","color"],i=[],l=["",""],a="",r("head").append(a)}}(jQuery); diff --git a/dist/philter/svg/color.svg b/dist/svg/color.svg similarity index 100% rename from dist/philter/svg/color.svg rename to dist/svg/color.svg