//this file hacked to be svg-edit only and work with JSONP /* * SVG Icon Loader 2.0 * * jQuery Plugin for loading SVG icons from a single file * * Copyright (c) 2009 Alexis Deveria * http://a.deveria.com * * Apache 2 License */ (function($) { var svg_icons = {}; $.svgIcons = function(file, opts) { var svgns = "http://www.w3.org/2000/svg", xlinkns = "http://www.w3.org/1999/xlink", icon_w = opts.w?opts.w : 24, icon_h = opts.h?opts.h : 24, elems, svgdoc, testImg, icons_made = false, data_loaded = false, load_attempts = 0, ua = navigator.userAgent, isOpera = !!window.opera, isSafari = (ua.indexOf('Safari/') > -1 && ua.indexOf('Chrome/')==-1), data_pre = 'data:image/svg+xml;charset=utf-8;base64,'; if(opts.svgz) { var data_el = $('').appendTo('body').hide(); try { svgdoc = data_el[0].contentDocument; // TODO: IE still loads this, shouldn't even bother. data_el.load(getIcons); getIcons(0, true); // Opera will not run "load" event if file is already cached } catch(err1) { useFallback(); } } else { $.ajax({ url: "http://anti15.welfarehost.com/svgeditproxy.php?whoot=?", dataType: 'jsonp', success: function(data) { if (window.DOMParser) { parser=new DOMParser(); xmlDoc=parser.parseFromString(data,"text/xml"); } else // Internet Explorer { xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async="false"; xmlDoc.loadXML(data); } svgdoc = xmlDoc; $(function() { getIcons('ajax'); }); }, error: function() { $(function() { useFallback(); }); } }); } function getIcons(evt, no_wait) { if(evt !== 'ajax') { if(data_loaded) return; // Webkit sometimes says svgdoc is undefined, other times // it fails to load all nodes. Thus we must make sure the "eof" // element is loaded. svgdoc = data_el[0].contentDocument; // Needed again for Webkit var isReady = (svgdoc && svgdoc.getElementById('svg_eof')); if(!isReady && !(no_wait && isReady)) { load_attempts++; if(load_attempts < 50) { setTimeout(getIcons, 20); } else { useFallback(); data_loaded = true; } return; } data_loaded = true; } // Clean source SVGs (mostly for Inkscape files) // TODO: Find a way to do this without crashing Safari (when converting to IMG) $(svgdoc).find('metadata').remove().end() .find('*').each(function(i, el) { if(el.nodeName.indexOf(':') != -1) { $(el).remove(); } var attrs = $.extend(false, el.attributes, {}); for(i in attrs) { var attr = attrs[i]; var fullattr = attr.prefix?attr.prefix + ':' + attr.localName:''; if(attr.prefix) { el.removeAttribute(attr.localName); // for Opera el.removeAttribute(fullattr); // for Webkit } if(fullattr == 'xlink:href') { el.setAttribute('xlink:href', attr.nodeValue); } } }); elems = $(svgdoc.firstChild).children(); //.getElementsByTagName('foreignContent'); var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D'; testImg = $(new Image()).attr({ src: testSrc, width: 0, height: 0 }).appendTo('body') .load(function () { // Safari 4 crashes, Opera and Chrome don't makeIcons(!isSafari); }).error(function () { makeIcons(); }); } function makeIcons(toImage, fallback) { if(icons_made) return; if(opts.no_img) toImage = false; var holder; var setIcon = function(target, icon, id, setID) { if(isOpera) icon.css('visibility','hidden'); if(opts.replace) { if(setID) icon.attr('id',id); var cl = target.attr('class'); if(cl) icon.attr('class','svg_icon '+cl); target.replaceWith(icon); } else { target.append(icon); } if(isOpera) { setTimeout(function() { icon.attr('style','visibility:visible;'); },1); } } var addIcon = function(icon, id) { if(opts.id_match === undefined || opts.id_match !== false) { setIcon(holder, icon, id, true); } svg_icons[id] = icon; } if(toImage) { var temp_holder = $(document.createElement('div')); temp_holder.hide().appendTo('body'); } if(fallback) { var path = opts.fallback_path?opts.fallback_path:''; $.each(fallback, function(id, imgsrc) { holder = $('#' + id); var icon = $(new Image()) .attr({ 'class':'svg_icon', src: path + imgsrc, 'width': icon_w, 'height': icon_h, 'alt': 'icon' }); addIcon(icon, id); }); } else { $.each(elems, function(i, elem) { var id = elem.getAttribute('id'); if(id == 'svg_eof') return; holder = $('#' + id); var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0]; var svgroot = svgdoc.createElementNS(svgns, "svg"); svgroot.setAttributeNS(svgns, 'viewBox', [0,0,icon_w,icon_h].join(' ')); $(svgroot).attr({ "xmlns": svgns, "width": icon_w, "height": icon_h, "xmlns:xlink": xlinkns, "class": 'svg_icon' }); // Without cloning, Firefox will make another GET request. // With cloning, causes issue in Opera/Win/Non-EN if(!isOpera) svg = svg.cloneNode(true); svgroot.appendChild(svg); if(toImage) { // Without cloning, Safari will crash // With cloning, causes issue in Opera/Win/Non-EN var svgcontent = isOpera?svgroot:svgroot.cloneNode(true); temp_holder.empty().append(svgroot); var str = data_pre + encode64(temp_holder.html()); var icon = $(new Image()) .attr({'class':'svg_icon', src:str}); } else { var icon = fixIDs($(svgroot), i); } addIcon(icon, id); }); } if(opts.placement) { $.each(opts.placement, function(sel, id) { if(!svg_icons[id]) return; $(sel).each(function(i) { var copy = svg_icons[id].clone(); if(i > 0 && !toImage) copy = fixIDs(copy, i, true); setIcon($(this), copy, id); }) }); } if(!fallback) { if(toImage) temp_holder.remove(); if(data_el) data_el.remove(); testImg.remove(); } if(opts.resize) $.resizeSvgIcons(opts.resize); icons_made = true; if(opts.callback) opts.callback(svg_icons); } function fixIDs(svg_el, svg_num, force) { var defs = svg_el.find('defs'); if(!defs.length) return svg_el; defs.find('[id]').each(function(i) { var id = this.id; var no_dupes = ($(svgdoc).find('#' + id).length <= 1); if(isOpera) no_dupes = false; // Opera didn't clone svg_el, so not reliable if(!force && no_dupes) return; var new_id = id + svg_num + i; $(this).attr('id', new_id); svg_el.find('[fill="url(#' + id + ')"]').each(function() { $(this).attr('fill', 'url(#' + new_id + ')'); }).end().find('[stroke="url(#' + id + ')"]').each(function() { $(this).attr('stroke', 'url(#' + new_id + ')'); }).end().find('use').each(function() { if(this.getAttribute('xlink:href') == '#' + id) { this.setAttributeNS(xlinkns,'href','#' + new_id); } }); }); return svg_el; } function useFallback() { if(file.indexOf('.svgz') != -1) { var reg_file = file.replace('.svgz','.svg'); if(window.console) { console.log('.svgz failed, trying with .svg'); } $.svgIcons(reg_file, opts); } else if(opts.fallback) { makeIcons(false, opts.fallback); } } function encode64(input) { // base64 strings are 4/3 larger than the original string if(window.btoa) return window.btoa(input); var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var output = new Array( Math.floor( (input.length + 2) / 3 ) * 4 ); var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0, p = 0; do { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output[p++] = _keyStr.charAt(enc1); output[p++] = _keyStr.charAt(enc2); output[p++] = _keyStr.charAt(enc3); output[p++] = _keyStr.charAt(enc4); } while (i < input.length); return output.join(''); } } $.getSvgIcon = function(id) { return svg_icons[id]; } $.resizeSvgIcons = function(obj) { // FF2 and older don't detect .svg_icon, so we change it detect svg elems instead var change_sel = !$('.svg_icon:first').length; $.each(obj, function(sel, size) { var arr = $.isArray(size); var w = arr?size[0]:size, h = arr?size[1]:size; if(change_sel) { sel = sel.replace(/\.svg_icon/g,'svg'); } $(sel).each(function() { this.setAttribute('width', w); this.setAttribute('height', h); }); }); } })(jQuery);