├── LICENCE ├── readme.md └── source └── 2.2.0 ├── dynamicColorPage-2.2.0.min.js └── dynamicColorPage-2.2.0.js /LICENCE: -------------------------------------------------------------------------------- 1 | First of all the code uses 2 | http://stackoverflow.com/a/13542669 3 | to generate the color shades. 4 | 5 | DynamicColorPage is published under "Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)". 6 | See https://creativecommons.org/licenses/by-nc-sa/4.0/ for detailed information. 7 | 8 | If you want to use this plugin for commercial projects, please contact me per Mail under "robinul [at] gmail . com". A tiny 9 | donation will be enough :) 10 | 11 | Please feel free to contact me, for other annotations, too :) 12 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # dynamicColorPage v2.2.0 2 | dynamicColorPage was previously a tiny jQuery plugin to easily adopt the page's color styling. 3 | Due to a rewrite, it is now a pure javascript "plugin" with some awesome new features! 4 | 5 | ## Demo: 6 | Please visit 7 | https://drohnen-videograf.de/dynamicColorPage/ 8 | to view an example page. The important button is the small blue one in the right bottom corner of the website. 9 | 10 | ## What is it for? 11 | dynamicColorPage was made to give the visitors of a website the possibility to choose their favourite style colors. 12 | All you have to do, is to add the class "dcl" (for dynamic text color), "dclHover" (for dynamic text color on hovering the element) or "dbg" (for dynamic background-color) to all elements, that should apply the given color scheme. 13 | 14 | The extended functionality applies some additional classes, in combination with an appended number 15 | (-100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100) at the end of the class (e.g. "dbg-70"). 16 | These colors are darked or lighted color versions of the basic color for the selected color. 17 | 18 | ## Changelog 19 | 20 | ### What's new in v2.2? 21 | Function and variable names prefixed with dynamicColorPage_ to avoid collisions with existing functions. The release now includes a minified version again. Added config variable to change when cookie will expire. 22 | ### What's new in v2.1? 23 | Now the script doesn't crash the browser when the already active color is clicked again. 24 | 25 | ### What's new in v2.0? 26 | Now the selected color is automatically stored in a cookie on the webpage, so a reload, or navigating to another page on the same server won't reset the selected color! 27 | 28 | ## Dependences: 29 | The script is written without the usage of any dependences! There is no jQuery or anything else needed for all releases since dynamicColorPage@2.0.0. 30 | 31 | ## Installation: 32 | The script only has to be included anywhere in the page. Then it automatically adds all the necessary DOM elements and stylesheets, 33 | that are automatically generated out of the given "colors" object. 34 | 35 | ## Options / Customization: 36 | The script was made to be easy to use. As a result, you can only customize four options. 37 | 38 | ### JS - "dynamicColorPage_colors" - Data type: object 39 | This object defines the choosable colors. These colors are automatically applied to the page and will get listed in the color- 40 | changer are by default. The "default" property (don't remove it!) sets the standard style, when the page is loaded. 41 | ### JS - "dynamicColorPage_useCookiesFeature" - Data type: Boolean 42 | With this variable you can define, whether the script should store the currently selected color in a cookie and automatically re-use this stored color, when the page is reloaded or the user navigates to another page with this script included. 43 | ### JS - "dynamicColorPage_cookieExpiresAfterDays" - Data type: int 44 | With this variable you can define, after how many days the cookie will expire and the user has to do the color selection again. 45 | ### JS - "dynamicColorPage_colorTilesPerRow" - Data type: int 46 | This variable defines, how many color tiles should be in one row of the color-changer element. 47 | ### JS - "dynamicColorPage_activeColor" - Data type: String 48 | With this variable you can define another standard color class, the script should look for, if the color is changed. 49 | For exaple if this variable is "grey", then you have to add "dclgrey" or "dbggrey" as classes to your elements to active the script 50 | and the color-change-functionality for these elements. For default the value is "", so you can just use "dcl" and "dbg" as classes. 51 | 52 | 53 | ### CSS - Styling 54 | The only possibility to directly change the css code of the color-changer, is, to adapt the css code that is written at the end of the javascript code and that is stored in the variable "css_string". 55 | 56 | ## How it works: 57 | When the user picks a new color, the script just replaces the previous "dcl", "dclHover" or "dbg" class of all elements and replaces this with the new color name. 58 | For example (colorChangerOldColor="", new_color="red"): 59 | "dcl" gets replaced with "dclred", 60 | "dclHover-50" gets replaced with "dclHoverred-50", 61 | ... 62 | 63 | ## Questions, suggestions, problems, etc.? 64 | Please create a new issue on Github :) 65 | -------------------------------------------------------------------------------- /source/2.2.0/dynamicColorPage-2.2.0.min.js: -------------------------------------------------------------------------------- 1 | /* Please visit https://github.com/ulrichrobin/dynamicColorPage/ for detailed documentation and license information */ 2 | /* Live demo available at https://drohnen-videograf.de/dynamicColorPage/ */ 3 | /* dynamicColorPage@2.2.0 */ 4 | 5 | var dynamicColorPage_colors = { 6 | standard: '#f34e36', 7 | red: '#f34e36', 8 | green: '#b5d947', 9 | purple: '#9d6fc8', 10 | blue: '#4abcdd', 11 | turquoise: '#1abc9c', 12 | pink: '#c61c72', 13 | orange: '#f4a622', 14 | emerald: '#2ecc71' 15 | }; 16 | var dynamicColorPage_useCookiesFeature = true; // Default value: true 17 | var dynamicColorPage_cookieExpiresAfterDays = 365; // Default value: 365 18 | var dynamicColorPage_colorTilesPerRow = 2; // Default value: 2 19 | var dynamicColorPage_activeColor = ''; // Default value: '' 20 | 21 | /* Don't change any code below! */ 22 | /* Don't change any code below! */ 23 | /* Don't change any code below! */ 24 | 25 | function dynamicColorPage_pageLoad(){var e=document.createElement("div");e.className="color_changer",document.body.appendChild(e);var o=document.createElement("button");o.className="color_changer-toggle",document.body.appendChild(o),document.body.addEventListener("click",function(e){dynamicColorPage_hasClass(document.getElementsByClassName("color_changer")[0],"expanded")&&!dynamicColorPage_hasClass(e.target,"color_changer-toggle")&&dynamicColorPage_removeClass(document.getElementsByClassName("color_changer")[0],"expanded")}),document.getElementsByClassName("color_changer-toggle")[0].addEventListener("click",function(e){(dynamicColorPage_hasClass(document.getElementsByClassName("color_changer")[0],"expanded")?dynamicColorPage_removeClass:dynamicColorPage_addClass)(document.getElementsByClassName("color_changer")[0],"expanded")});var a='
',r=0;for(var l in dynamicColorPage_colors)if(dynamicColorPage_colors.hasOwnProperty(l)){var n=dynamicColorPage_colors[l];"standard"==l?l="":r
'):(a=a+'
',a+='
',r=0);for(var c=!1,t=-100;t<101;t+=10)c||(css_string=(css_string=(css_string=css_string+".dcl"+l+"{color:"+n+"}")+".dclHover"+l+":hover{color:"+n+"}")+".dbg"+l+"{background-color:"+n+"}",c=!0),css_string=(css_string=(css_string=css_string+".dcl"+l+t+"{color:"+colorLuminance(n,t/100)+"}")+".dclHover"+l+t+":hover{color:"+colorLuminance(n,t/100)+"}")+".dbg"+l+t+"{background-color:"+colorLuminance(n,t/100)+"}"}a+="
",document.getElementsByClassName("color_changer")[0].innerHTML=a;for(var s=0;s'; 65 | } 66 | else { 67 | domElementContent = domElementContent + '
'; 68 | domElementContent = domElementContent + '
'; 69 | color_tiles_counter = 0; 70 | } 71 | } 72 | var plainKeyStyling_printed = false; 73 | for(var h = -100; h < 101; h += 10) { 74 | if(!plainKeyStyling_printed) { 75 | css_string = css_string + '.dcl' + key + '{color:' + property_value + '}'; 76 | css_string = css_string + '.dclHover' + key + ':hover{color:' + property_value + '}'; 77 | css_string = css_string + '.dbg' + key + '{background-color:' + property_value + '}'; 78 | plainKeyStyling_printed = true; 79 | } 80 | css_string = css_string + '.dcl' + key + h + '{color:' + colorLuminance(property_value, (h / 100)) + '}'; 81 | css_string = css_string + '.dclHover' + key + h + ':hover{color:' + colorLuminance(property_value, (h / 100)) + '}'; 82 | css_string = css_string + '.dbg' + key + h + '{background-color:' + colorLuminance(property_value, (h / 100)) + '}'; 83 | } 84 | } 85 | } 86 | domElementContent = domElementContent + '
'; 87 | document.getElementsByClassName('color_changer')[0].innerHTML = domElementContent; 88 | 89 | var this_element; 90 | 91 | // Events for clicking one of the color tiles 92 | for(var i = 0; i < document.getElementsByClassName('color_tile').length; i++) { 93 | document.getElementsByClassName('color_tile')[i].addEventListener('click', function(e) { 94 | dynamicColorChange_changeColor(e.target.getAttribute('data-color')); 95 | }); 96 | } 97 | 98 | // Include generated css string into document 99 | var cssStringStyle = document.createElement('style'); 100 | cssStringStyle.type = 'text/css'; 101 | cssStringStyleInner = document.createTextNode(css_string); 102 | cssStringStyle.appendChild(cssStringStyleInner); 103 | document.head.appendChild(cssStringStyle); 104 | 105 | // Auto get/set cookies to use the last selected color in the page automatically again 106 | if(dynamicColorPage_useCookiesFeature && dynamicColorPage_getCookie('dynamicColorPage_activeColor') != '') { 107 | if(dynamicColorPage_colors.hasOwnProperty(dynamicColorPage_getCookie('dynamicColorPage_activeColor'))) dynamicColorChange_changeColor(dynamicColorPage_getCookie('dynamicColorPage_activeColor')); 108 | } 109 | } 110 | function dynamicColorChange_changeColor(dynamicColorPage_newColor) { 111 | if(dynamicColorPage_activeColor == dynamicColorPage_newColor) return; 112 | // Change old dcl class to new one 113 | while(document.getElementsByClassName('dcl' + dynamicColorPage_activeColor).length != 0) { 114 | this_element = document.getElementsByClassName('dcl' + dynamicColorPage_activeColor)[0]; 115 | dynamicColorPage_removeClass(this_element, 'dcl' + dynamicColorPage_activeColor); 116 | dynamicColorPage_addClass(this_element, 'dcl' + dynamicColorPage_newColor); 117 | } 118 | // Change old dclHover class to new one 119 | while(document.getElementsByClassName('dclHover' + dynamicColorPage_activeColor).length != 0) { 120 | this_element = document.getElementsByClassName('dclHover' + dynamicColorPage_activeColor)[0]; 121 | dynamicColorPage_removeClass(this_element, 'dclHover' + dynamicColorPage_activeColor); 122 | dynamicColorPage_addClass(this_element, 'dclHover' + dynamicColorPage_newColor); 123 | } 124 | // Change old dbg class to new one 125 | while(document.getElementsByClassName('dbg' + dynamicColorPage_activeColor).length != 0) { 126 | this_element = document.getElementsByClassName('dbg' + dynamicColorPage_activeColor)[0]; 127 | dynamicColorPage_removeClass(this_element, 'dbg' + dynamicColorPage_activeColor); 128 | dynamicColorPage_addClass(this_element, 'dbg' + dynamicColorPage_newColor); 129 | } 130 | // Change old luminanceStep-classes to new ones 131 | for(var j = -100; j < 101; j += 10) { 132 | // Change old luminanceStep-dcl class to new one 133 | while(document.getElementsByClassName('dcl' + dynamicColorPage_activeColor + j).length != 0) { 134 | this_element = document.getElementsByClassName('dcl' + dynamicColorPage_activeColor + j)[0]; 135 | dynamicColorPage_removeClass(this_element, 'dcl' + dynamicColorPage_activeColor + j); 136 | dynamicColorPage_addClass(this_element, 'dcl' + dynamicColorPage_newColor + j); 137 | } 138 | // Change old luminanceStep-dclHover class to new one 139 | while(document.getElementsByClassName('dclHover' + dynamicColorPage_activeColor + j).length != 0) { 140 | this_element = document.getElementsByClassName('dclHover' + dynamicColorPage_activeColor + j)[0]; 141 | dynamicColorPage_removeClass(this_element, 'dclHover' + dynamicColorPage_activeColor + j); 142 | dynamicColorPage_addClass(this_element, 'dclHover' + dynamicColorPage_newColor + j); 143 | } 144 | // Change old luminanceStep-dbg class to new one 145 | while(document.getElementsByClassName('dbg' + dynamicColorPage_activeColor + j).length != 0) { 146 | this_element = document.getElementsByClassName('dbg' + dynamicColorPage_activeColor + j)[0]; 147 | dynamicColorPage_removeClass(this_element, 'dbg' + dynamicColorPage_activeColor + j); 148 | dynamicColorPage_addClass(this_element, 'dbg' + dynamicColorPage_newColor + j); 149 | } 150 | } 151 | dynamicColorPage_activeColor = dynamicColorPage_newColor; 152 | if(dynamicColorPage_useCookiesFeature) dynamicColorPage_setCookie('dynamicColorPage_activeColor', dynamicColorPage_newColor); 153 | } 154 | 155 | 156 | /* Helper functions */ 157 | function dynamicColorPage_removeClass(element, classToRemove) { 158 | var reg = new RegExp('(\\s|^)' + classToRemove + '(\\s|$)'); 159 | element.className = (element.className.replace(reg, ' ')).trim(); 160 | } 161 | function dynamicColorPage_addClass(element, classToAdd) { 162 | element.className = (element.className + " " + classToAdd).trim(); 163 | } 164 | function dynamicColorPage_hasClass(element, classToCheckFor) { 165 | return (element.className.indexOf(classToCheckFor) >= 0); 166 | } 167 | function colorLuminance(color_hex, factor) { 168 | color_hex = String(color_hex).replace(/[^0-9a-f]/gi, ''); 169 | if(color_hex.length < 6) color_hex = color_hex[0] + color_hex[0] + color_hex[1] + color_hex[1] + color_hex[2] + color_hex[2]; 170 | factor = factor || 0; 171 | var rgb='#', c, i; 172 | for(var i = 0; i < 3; i++) { 173 | c = parseInt(color_hex.substr(i * 2, 2), 16); 174 | c = Math.round(Math.min(Math.max(0, c + (c * factor)), 255)).toString(16); 175 | rgb += ('00' + c).substr(c.length); 176 | } 177 | return rgb; 178 | } 179 | function dynamicColorPage_setCookie(cookieName, cookieValue) { 180 | var date = new Date(); 181 | date.setTime(date.getTime() + (dynamicColorPage_cookieExpiresAfterDays*1000*60*60*24)); 182 | document.cookie = cookieName + '=' + cookieValue + '; expires=' + date.toUTCString(); 183 | } 184 | function dynamicColorPage_getCookie(cookieName) { 185 | cookieName = cookieName + '='; 186 | var cookiesArray = document.cookie.split(';'); 187 | for(var i = 0; i < cookiesArray.length; i++) { 188 | var currentIndex = cookiesArray[i]; 189 | while(currentIndex.charAt(0) == ' ') currentIndex = currentIndex.substring(1); 190 | if(currentIndex.indexOf(cookieName) == 0) return currentIndex.substring(cookieName.length, currentIndex.length); 191 | } 192 | return ''; 193 | } 194 | 195 | /* Write css strings here, to have a better order in the code */ 196 | var css_string = '.color_changer-toggle{border:0px solid transparent;background-color:transparent;position:fixed;right:10px;bottom:10px;z-index:10000;width:38px;height:38px;background-repeat:no-repeat;background-size:contain;}.color_changer{position:fixed;right:10px;bottom:55px;z-index:10000;max-height:0vh;overflow:hidden;transition:all 1s ease-out, background-color linear 1ms 1s;border:1px solid transparent;padding:5px;margin-bottom:0px;border-radius:4px;}.color_changer.expanded{transition:all 1s ease-in, background-color linear 1ms;max-height:100vh;border:1px solid gray;background-color:white;}.color_changer_row .color_tile{width:25px;height:25px;border-radius:4px;float:left;margin:5px;cursor:pointer}'; 197 | css_string = css_string + '.color_changer-toggle{background-image:url("data:image/png;base64,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");}'; 198 | --------------------------------------------------------------------------------