wp/wp-admin/js/svg-painter.js
changeset 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
       
     1 /**
       
     2  * Attempt to re-color SVG icons used in the admin menu or the toolbar
       
     3  *
       
     4  */
       
     5 
       
     6 window.wp = window.wp || {};
       
     7 
       
     8 wp.svgPainter = ( function( $, window, document, undefined ) {
       
     9 	'use strict';
       
    10 	var selector, base64, painter,
       
    11 		colorscheme = {},
       
    12 		elements = [];
       
    13 
       
    14 	$(document).ready( function() {
       
    15 		// detection for browser SVG capability
       
    16 		if ( document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#Image', '1.1' ) ) {
       
    17 			$( document.body ).removeClass( 'no-svg' ).addClass( 'svg' );
       
    18 			wp.svgPainter.init();
       
    19 		}
       
    20 	});
       
    21 
       
    22 	/**
       
    23 	 * Needed only for IE9
       
    24 	 *
       
    25 	 * Based on jquery.base64.js 0.0.3 - https://github.com/yckart/jquery.base64.js
       
    26 	 *
       
    27 	 * Based on: https://gist.github.com/Yaffle/1284012
       
    28 	 *
       
    29 	 * Copyright (c) 2012 Yannick Albert (http://yckart.com)
       
    30 	 * Licensed under the MIT license
       
    31 	 * http://www.opensource.org/licenses/mit-license.php
       
    32 	 */
       
    33 	base64 = ( function() {
       
    34 		var c,
       
    35 			b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
       
    36 			a256 = '',
       
    37 			r64 = [256],
       
    38 			r256 = [256],
       
    39 			i = 0;
       
    40 
       
    41 		function init() {
       
    42 			while( i < 256 ) {
       
    43 				c = String.fromCharCode(i);
       
    44 				a256 += c;
       
    45 				r256[i] = i;
       
    46 				r64[i] = b64.indexOf(c);
       
    47 				++i;
       
    48 			}
       
    49 		}
       
    50 
       
    51 		function code( s, discard, alpha, beta, w1, w2 ) {
       
    52 			var tmp, length,
       
    53 				buffer = 0,
       
    54 				i = 0,
       
    55 				result = '',
       
    56 				bitsInBuffer = 0;
       
    57 
       
    58 			s = String(s);
       
    59 			length = s.length;
       
    60 
       
    61 			while( i < length ) {
       
    62 				c = s.charCodeAt(i);
       
    63 				c = c < 256 ? alpha[c] : -1;
       
    64 
       
    65 				buffer = ( buffer << w1 ) + c;
       
    66 				bitsInBuffer += w1;
       
    67 
       
    68 				while( bitsInBuffer >= w2 ) {
       
    69 					bitsInBuffer -= w2;
       
    70 					tmp = buffer >> bitsInBuffer;
       
    71 					result += beta.charAt(tmp);
       
    72 					buffer ^= tmp << bitsInBuffer;
       
    73 				}
       
    74 				++i;
       
    75 			}
       
    76 
       
    77 			if ( ! discard && bitsInBuffer > 0 ) {
       
    78 				result += beta.charAt( buffer << ( w2 - bitsInBuffer ) );
       
    79 			}
       
    80 
       
    81 			return result;
       
    82 		}
       
    83 
       
    84 		function btoa( plain ) {
       
    85 			if ( ! c ) {
       
    86 				init();
       
    87 			}
       
    88 
       
    89 			plain = code( plain, false, r256, b64, 8, 6 );
       
    90 			return plain + '===='.slice( ( plain.length % 4 ) || 4 );
       
    91 		}
       
    92 
       
    93 		function atob( coded ) {
       
    94 			var i;
       
    95 
       
    96 			if ( ! c ) {
       
    97 				init();
       
    98 			}
       
    99 
       
   100 			coded = coded.replace( /[^A-Za-z0-9\+\/\=]/g, '' );
       
   101 			coded = String(coded).split('=');
       
   102 			i = coded.length;
       
   103 
       
   104 			do {
       
   105 				--i;
       
   106 				coded[i] = code( coded[i], true, r64, a256, 6, 8 );
       
   107 			} while ( i > 0 );
       
   108 
       
   109 			coded = coded.join('');
       
   110 			return coded;
       
   111 		}
       
   112 
       
   113 		return {
       
   114 			atob: atob,
       
   115 			btoa: btoa
       
   116 		};
       
   117 	})();
       
   118 
       
   119 	return {
       
   120 		init: function() {
       
   121 			painter = this;
       
   122 			selector = $( '#adminmenu .wp-menu-image, #wpadminbar .ab-item' );
       
   123 
       
   124 			this.setColors();
       
   125 			this.findElements();
       
   126 			this.paint();
       
   127 		},
       
   128 
       
   129 		setColors: function( colors ) {
       
   130 			if ( typeof colors === 'undefined' && typeof window._wpColorScheme !== 'undefined' ) {
       
   131 				colors = window._wpColorScheme;
       
   132 			}
       
   133 
       
   134 			if ( colors && colors.icons && colors.icons.base && colors.icons.current && colors.icons.focus ) {
       
   135 				colorscheme = colors.icons;
       
   136 			}
       
   137 		},
       
   138 
       
   139 		findElements: function() {
       
   140 			selector.each( function() {
       
   141 				var $this = $(this), bgImage = $this.css( 'background-image' );
       
   142 
       
   143 				if ( bgImage && bgImage.indexOf( 'data:image/svg+xml;base64' ) != -1 ) {
       
   144 					elements.push( $this );
       
   145 				}
       
   146 			});
       
   147 		},
       
   148 
       
   149 		paint: function() {
       
   150 			// loop through all elements
       
   151 			$.each( elements, function( index, $element ) {
       
   152 				var $menuitem = $element.parent().parent();
       
   153 
       
   154 				if ( $menuitem.hasClass( 'current' ) || $menuitem.hasClass( 'wp-has-current-submenu' ) ) {
       
   155 					// paint icon in 'current' color
       
   156 					painter.paintElement( $element, 'current' );
       
   157 				} else {
       
   158 					// paint icon in base color
       
   159 					painter.paintElement( $element, 'base' );
       
   160 
       
   161 					// set hover callbacks
       
   162 					$menuitem.hover(
       
   163 						function() {
       
   164 							painter.paintElement( $element, 'focus' );
       
   165 						},
       
   166 						function() {
       
   167 							// Match the delay from hoverIntent
       
   168 							window.setTimeout( function() {
       
   169 								painter.paintElement( $element, 'base' );
       
   170 							}, 100 );
       
   171 						}
       
   172 					);
       
   173 				}
       
   174 			});
       
   175 		},
       
   176 
       
   177 		paintElement: function( $element, colorType ) {
       
   178 			var xml, encoded, color;
       
   179 
       
   180 			if ( ! colorType || ! colorscheme.hasOwnProperty( colorType ) ) {
       
   181 				return;
       
   182 			}
       
   183 
       
   184 			color = colorscheme[ colorType ];
       
   185 
       
   186 			// only accept hex colors: #101 or #101010
       
   187 			if ( ! color.match( /^(#[0-9a-f]{3}|#[0-9a-f]{6})$/i ) ) {
       
   188 				return;
       
   189 			}
       
   190 
       
   191 			xml = $element.data( 'wp-ui-svg-' + color );
       
   192 
       
   193 			if ( xml === 'none' ) {
       
   194 				return;
       
   195 			}
       
   196 
       
   197 			if ( ! xml ) {
       
   198 				encoded = $element.css( 'background-image' ).match( /.+data:image\/svg\+xml;base64,([A-Za-z0-9\+\/\=]+)/ );
       
   199 
       
   200 				if ( ! encoded || ! encoded[1] ) {
       
   201 					$element.data( 'wp-ui-svg-' + color, 'none' );
       
   202 					return;
       
   203 				}
       
   204 
       
   205 				try {
       
   206 					if ( 'atob' in window ) {
       
   207 						xml = window.atob( encoded[1] );
       
   208 					} else {
       
   209 						xml = base64.atob( encoded[1] );
       
   210 					}
       
   211 				} catch ( error ) {}
       
   212 
       
   213 				if ( xml ) {
       
   214 					// replace `fill` attributes
       
   215 					xml = xml.replace( /fill="(.+?)"/g, 'fill="' + color + '"');
       
   216 
       
   217 					// replace `style` attributes
       
   218 					xml = xml.replace( /style="(.+?)"/g, 'style="fill:' + color + '"');
       
   219 
       
   220 					// replace `fill` properties in `<style>` tags
       
   221 					xml = xml.replace( /fill:.*?;/g, 'fill: ' + color + ';');
       
   222 
       
   223 					if ( 'btoa' in window ) {
       
   224 						xml = window.btoa( xml );
       
   225 					} else {
       
   226 						xml = base64.btoa( xml );
       
   227 					}
       
   228 
       
   229 					$element.data( 'wp-ui-svg-' + color, xml );
       
   230 				} else {
       
   231 					$element.data( 'wp-ui-svg-' + color, 'none' );
       
   232 					return;
       
   233 				}
       
   234 			}
       
   235 
       
   236 			$element.attr( 'style', 'background-image: url("data:image/svg+xml;base64,' + xml + '") !important;' );
       
   237 		}
       
   238 	};
       
   239 
       
   240 })( jQuery, window, document );