- Linting: ESLint (or ignore) JavaScript files; unfinished: editor/jgraduate and editor/extensions folders, editor/ (root), test/ (root) HTML

- Fix: An apparent bug in jquery.svgicons.js whereby a variable `holder` was declared in too nested of a scope
- Fix: `addBezierCurve` in canvg.js had undeclared `i`
- Fix: Undeclared variable in opera widget
- Fix: Screencast `showNotes`
This commit is contained in:
Brett Zamir
2018-05-13 18:47:00 +08:00
parent 820964334c
commit 5894398c36
16 changed files with 6846 additions and 6996 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,294 +1,291 @@
/*jslint vars: true*/
/* eslint-disable no-var */
/**
* A class to parse color values
* @author Stoyan Stefanov <sstoo@gmail.com>
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
* @license Use it if you like it
*/
function RGBColor(color_string) { 'use strict';
this.ok = false;
function RGBColor (colorString) { // eslint-disable-line no-unused-vars
'use strict';
this.ok = false;
// strip any leading #
if (color_string.charAt(0) === '#') { // remove # if any
color_string = color_string.substr(1,6);
}
// strip any leading #
if (colorString.charAt(0) === '#') { // remove # if any
colorString = colorString.substr(1, 6);
}
color_string = color_string.replace(/ /g,'');
color_string = color_string.toLowerCase();
colorString = colorString.replace(/ /g, '');
colorString = colorString.toLowerCase();
// before getting into regexps, try simple matches
// and overwrite the input
var simple_colors = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred : 'cd5c5c',
indigo : '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
var key;
for (key in simple_colors) {
if (simple_colors.hasOwnProperty(key)) {
if (color_string == key) {
color_string = simple_colors[key];
}
}
}
// emd of simple type-in colors
// before getting into regexps, try simple matches
// and overwrite the input
var simpleColors = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred: 'cd5c5c',
indigo: '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
var key;
for (key in simpleColors) {
if (simpleColors.hasOwnProperty(key)) {
if (colorString === key) {
colorString = simpleColors[key];
}
}
}
// emd of simple type-in colors
// array of color definition objects
var color_defs = [
{
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function (bits){
return [
parseInt(bits[1], 10),
parseInt(bits[2], 10),
parseInt(bits[3], 10)
];
}
},
{
re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'],
process: function (bits){
return [
parseInt(bits[1], 16),
parseInt(bits[2], 16),
parseInt(bits[3], 16)
];
}
},
{
re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'],
process: function (bits){
return [
parseInt(bits[1] + bits[1], 16),
parseInt(bits[2] + bits[2], 16),
parseInt(bits[3] + bits[3], 16)
];
}
}
];
// array of color definition objects
var colorDefs = [
{
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function (bits) {
return [
parseInt(bits[1], 10),
parseInt(bits[2], 10),
parseInt(bits[3], 10)
];
}
},
{
re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'],
process: function (bits) {
return [
parseInt(bits[1], 16),
parseInt(bits[2], 16),
parseInt(bits[3], 16)
];
}
},
{
re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'],
process: function (bits) {
return [
parseInt(bits[1] + bits[1], 16),
parseInt(bits[2] + bits[2], 16),
parseInt(bits[3] + bits[3], 16)
];
}
}
];
var i;
// search through the definitions to find a match
for (i = 0; i < color_defs.length; i++) {
var re = color_defs[i].re;
var processor = color_defs[i].process;
var bits = re.exec(color_string);
if (bits) {
var channels = processor(bits);
this.r = channels[0];
this.g = channels[1];
this.b = channels[2];
this.ok = true;
}
var i;
// search through the definitions to find a match
for (i = 0; i < colorDefs.length; i++) {
var re = colorDefs[i].re;
var processor = colorDefs[i].process;
var bits = re.exec(colorString);
if (bits) {
var channels = processor(bits);
this.r = channels[0];
this.g = channels[1];
this.b = channels[2];
this.ok = true;
}
}
}
// validate/cleanup values
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
// validate/cleanup values
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
// some getters
this.toRGB = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
};
this.toHex = function () {
var r = this.r.toString(16);
var g = this.g.toString(16);
var b = this.b.toString(16);
if (r.length === 1) { r = '0' + r; }
if (g.length === 1) { g = '0' + g; }
if (b.length === 1) { b = '0' + b; }
return '#' + r + g + b;
};
// some getters
this.toRGB = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
};
this.toHex = function () {
var r = this.r.toString(16);
var g = this.g.toString(16);
var b = this.b.toString(16);
if (r.length === 1) {r = '0' + r;}
if (g.length === 1) {g = '0' + g;}
if (b.length === 1) {b = '0' + b;}
return '#' + r + g + b;
};
// help
this.getHelpXML = function () {
var i, j;
var examples = [];
// add regexps
for (i = 0; i < color_defs.length; i++) {
var example = color_defs[i].example;
for (j = 0; j < example.length; j++) {
examples[examples.length] = example[j];
}
}
// add type-in colors
var sc;
for (sc in simple_colors) {
if (simple_colors.hasOwnProperty(sc)) {
examples[examples.length] = sc;
}
}
var xml = document.createElement('ul');
xml.setAttribute('id', 'rgbcolor-examples');
for (i = 0; i < examples.length; i++) {
try {
var list_item = document.createElement('li');
var list_color = new RGBColor(examples[i]);
var example_div = document.createElement('div');
example_div.style.cssText =
'margin: 3px; '
+ 'border: 1px solid black; '
+ 'background:' + list_color.toHex() + '; '
+ 'color:' + list_color.toHex()
;
example_div.appendChild(document.createTextNode('test'));
var list_item_value = document.createTextNode(
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
);
list_item.appendChild(example_div);
list_item.appendChild(list_item_value);
xml.appendChild(list_item);
} catch(e){}
}
return xml;
};
// help
this.getHelpXML = function () {
var i, j;
var examples = [];
// add regexps
for (i = 0; i < colorDefs.length; i++) {
var example = colorDefs[i].example;
for (j = 0; j < example.length; j++) {
examples[examples.length] = example[j];
}
}
// add type-in colors
var sc;
for (sc in simpleColors) {
if (simpleColors.hasOwnProperty(sc)) {
examples[examples.length] = sc;
}
}
var xml = document.createElement('ul');
xml.setAttribute('id', 'rgbcolor-examples');
for (i = 0; i < examples.length; i++) {
try {
var listItem = document.createElement('li');
var listColor = new RGBColor(examples[i]);
var exampleDiv = document.createElement('div');
exampleDiv.style.cssText =
'margin: 3px; ' +
'border: 1px solid black; ' +
'background:' + listColor.toHex() + '; ' +
'color:' + listColor.toHex()
;
exampleDiv.appendChild(document.createTextNode('test'));
var listItemValue = document.createTextNode(
' ' + examples[i] + ' -> ' + listColor.toRGB() + ' -> ' + listColor.toHex()
);
listItem.appendChild(exampleDiv);
listItem.appendChild(listItemValue);
xml.appendChild(listItem);
} catch (e) {}
}
return xml;
};
}

View File

@@ -1,3 +1,5 @@
/* eslint-disable no-var */
/* globals jQuery, $, svgedit */
// jQuery Context Menu Plugin
//
// Version 1.01
@@ -13,191 +15,191 @@
// This plugin is dual-licensed under the GNU General Public License
// and the MIT License and is copyright A Beautiful Site, LLC.
//
if(jQuery)( function() {
var win = $(window);
var doc = $(document);
if (jQuery) {
(function () {
var win = $(window);
var doc = $(document);
$.extend($.fn, {
contextMenu: function(o, callback) {
// Defaults
if( o.menu == undefined ) return false;
if( o.inSpeed == undefined ) o.inSpeed = 150;
if( o.outSpeed == undefined ) o.outSpeed = 75;
// 0 needs to be -1 for expected results (no fade)
if( o.inSpeed == 0 ) o.inSpeed = -1;
if( o.outSpeed == 0 ) o.outSpeed = -1;
// Loop each context menu
$(this).each( function() {
var el = $(this);
var offset = $(el).offset();
var menu = $('#' + o.menu);
$.extend($.fn, {
// Add contextMenu class
menu.addClass('contextMenu');
// Simulate a true right click
$(this).bind( "mousedown", function(e) {
var evt = e;
$(this).mouseup( function(e) {
var srcElement = $(this);
srcElement.unbind('mouseup');
if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) {
e.stopPropagation();
// Hide context menus that may be showing
$(".contextMenu").hide();
// Get this context menu
if( el.hasClass('disabled') ) return false;
// Detect mouse position
var d = {}, x = e.pageX, y = e.pageY;
var x_off = win.width() - menu.width(),
y_off = win.height() - menu.height();
contextMenu: function (o, callback) {
// Defaults
if (o.menu === undefined) return false;
if (o.inSpeed === undefined) o.inSpeed = 150;
if (o.outSpeed === undefined) o.outSpeed = 75;
// 0 needs to be -1 for expected results (no fade)
if (o.inSpeed === 0) o.inSpeed = -1;
if (o.outSpeed === 0) o.outSpeed = -1;
// Loop each context menu
$(this).each(function () {
var el = $(this);
var offset = $(el).offset();
if(x > x_off - 15) x = x_off-15;
if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF
// Show the menu
doc.unbind('click');
menu.css({ top: y, left: x }).fadeIn(o.inSpeed);
// Hover events
menu.find('A').mouseover( function() {
menu.find('LI.hover').removeClass('hover');
$(this).parent().addClass('hover');
}).mouseout( function() {
menu.find('LI.hover').removeClass('hover');
});
// Keyboard
doc.keypress( function(e) {
switch( e.keyCode ) {
var menu = $('#' + o.menu);
// Add contextMenu class
menu.addClass('contextMenu');
// Simulate a true right click
$(this).bind('mousedown', function (e) {
var evt = e;
$(this).mouseup(function (e) {
var srcElement = $(this);
srcElement.unbind('mouseup');
if (evt.button === 2 || o.allowLeft ||
(evt.ctrlKey && svgedit.browser.isMac())) {
e.stopPropagation();
// Hide context menus that may be showing
$('.contextMenu').hide();
// Get this context menu
if (el.hasClass('disabled')) return false;
// Detect mouse position
var x = e.pageX, y = e.pageY;
var xOff = win.width() - menu.width(),
yOff = win.height() - menu.height();
if (x > xOff - 15) x = xOff - 15;
if (y > yOff - 30) y = yOff - 30; // 30 is needed to prevent scrollbars in FF
// Show the menu
doc.unbind('click');
menu.css({ top: y, left: x }).fadeIn(o.inSpeed);
// Hover events
menu.find('A').mouseover(function () {
menu.find('LI.hover').removeClass('hover');
$(this).parent().addClass('hover');
}).mouseout(function () {
menu.find('LI.hover').removeClass('hover');
});
// Keyboard
doc.keypress(function (e) {
switch (e.keyCode) {
case 38: // up
if( !menu.find('LI.hover').length ) {
if (!menu.find('LI.hover').length) {
menu.find('LI:last').addClass('hover');
} else {
menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover');
if (!menu.find('LI.hover').length) menu.find('LI:last').addClass('hover');
}
break;
break;
case 40: // down
if( menu.find('LI.hover').length == 0 ) {
if (menu.find('LI.hover').length === 0) {
menu.find('LI:first').addClass('hover');
} else {
menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover');
if (!menu.find('LI.hover').length) menu.find('LI:first').addClass('hover');
}
break;
break;
case 13: // enter
menu.find('LI.hover A').trigger('click');
break;
break;
case 27: // esc
doc.trigger('click');
break
}
});
// When items are selected
menu.find('A').unbind('mouseup');
menu.find('LI:not(.disabled) A').mouseup( function() {
doc.unbind('click').unbind('keypress');
$(".contextMenu").hide();
// Callback
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
return false;
});
// Hide bindings
setTimeout( function() { // Delay for Mozilla
doc.click( function() {
break;
}
});
// When items are selected
menu.find('A').unbind('mouseup');
menu.find('LI:not(.disabled) A').mouseup(function () {
doc.unbind('click').unbind('keypress');
menu.fadeOut(o.outSpeed);
$('.contextMenu').hide();
// Callback
if (callback) callback($(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y});
return false;
});
}, 0);
}
// Hide bindings
setTimeout(function () { // Delay for Mozilla
doc.click(function () {
doc.unbind('click').unbind('keypress');
menu.fadeOut(o.outSpeed);
return false;
});
}, 0);
}
});
});
// Disable text selection
if ($.browser.mozilla) {
$('#' + o.menu).each(function () { $(this).css({'MozUserSelect': 'none'}); });
} else if ($.browser.msie) {
$('#' + o.menu).each(function () { $(this).bind('selectstart.disableTextSelect', function () { return false; }); });
} else {
$('#' + o.menu).each(function () { $(this).bind('mousedown.disableTextSelect', function () { return false; }); });
}
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
$(el).add($('UL.contextMenu')).bind('contextmenu', function () { return false; });
});
// Disable text selection
if( $.browser.mozilla ) {
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
} else if( $.browser.msie ) {
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
} else {
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
return $(this);
},
// Disable context menu items on the fly
disableContextMenuItems: function (o) {
if (o === undefined) {
// Disable all
$(this).find('LI').addClass('disabled');
return $(this);
}
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
});
return $(this);
},
// Disable context menu items on the fly
disableContextMenuItems: function(o) {
if( o == undefined ) {
// Disable all
$(this).find('LI').addClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
$(this).each(function () {
if (o !== undefined) {
var d = o.split(',');
for (var i = 0; i < d.length; i++) {
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
}
}
});
return $(this);
},
// Enable context menu items on the fly
enableContextMenuItems: function (o) {
if (o === undefined) {
// Enable all
$(this).find('LI.disabled').removeClass('disabled');
return $(this);
}
});
return( $(this) );
},
// Enable context menu items on the fly
enableContextMenuItems: function(o) {
if( o == undefined ) {
// Enable all
$(this).find('LI.disabled').removeClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
$(this).each(function () {
if (o !== undefined) {
var d = o.split(',');
for (var i = 0; i < d.length; i++) {
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
}
}
}
});
return( $(this) );
},
// Disable context menu(s)
disableContextMenu: function() {
$(this).each( function() {
$(this).addClass('disabled');
});
return( $(this) );
},
// Enable context menu(s)
enableContextMenu: function() {
$(this).each( function() {
$(this).removeClass('disabled');
});
return( $(this) );
},
// Destroy context menu(s)
destroyContextMenu: function() {
// Destroy specified context menus
$(this).each( function() {
// Disable action
$(this).unbind('mousedown').unbind('mouseup');
});
return( $(this) );
}
});
})(jQuery);
});
return $(this);
},
// Disable context menu(s)
disableContextMenu: function () {
$(this).each(function () {
$(this).addClass('disabled');
});
return $(this);
},
// Enable context menu(s)
enableContextMenu: function () {
$(this).each(function () {
$(this).removeClass('disabled');
});
return $(this);
},
// Destroy context menu(s)
destroyContextMenu: function () {
// Destroy specified context menus
$(this).each(function () {
// Disable action
$(this).unbind('mousedown').unbind('mouseup');
});
return $(this);
}
});
})(jQuery);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*globals $, svgEditor*/
/*jslint vars: true, eqeq: true*/
/* eslint-disable no-var */
/* globals $, svgEditor */
/* SpinButton control
*
* Adds bells and whistles to any ordinary textbox to
@@ -37,15 +37,15 @@
* v1.2 27 Sep 2006 - Mark Gibson - Major enhancements
* v1.3a 28 Sep 2006 - George Adamson - Minor enhancements
* v1.4 18 Jun 2009 - Jeff Schiller - Added callback function
* v1.5 06 Jul 2009 - Jeff Schiller - Fixes for Opera.
* v1.6 13 Oct 2009 - Alexis Deveria - Added stepfunc function
* v1.5 06 Jul 2009 - Jeff Schiller - Fixes for Opera.
* v1.6 13 Oct 2009 - Alexis Deveria - Added stepfunc function
* v1.7 21 Oct 2009 - Alexis Deveria - Minor fixes
* Fast-repeat for keys and live updating as you type.
* v1.8 12 Jan 2010 - Benjamin Thomas - Fixes for mouseout behavior.
* Added smallStep
Sample usage:
// Create group of settings to initialise spinbutton(s). (Optional)
var myOptions = {
min: 0, // Set lower limit.
@@ -56,37 +56,37 @@
upClass: mySpinUpClass, // CSS class for style when mouse over up button.
downClass: mySpinDnClass // CSS class for style when mouse over down button.
}
$(document).ready(function(){
// Initialise INPUT element(s) as SpinButtons: (passing options if desired)
$("#myInputElement").SpinButton(myOptions);
});
*/
$.fn.SpinButton = function(cfg) { 'use strict';
function coord(el,prop) {
$.fn.SpinButton = function (cfg) {
'use strict';
function coord (el, prop) {
var c = el[prop], b = document.body;
while ((el = el.offsetParent) && (el != b)) {
while ((el = el.offsetParent) && (el !== b)) {
if (!$.browser.msie || (el.currentStyle.position !== 'relative')) {
c += el[prop];
}
}
return c;
}
return this.each(function(){
return this.each(function () {
this.repeating = false;
// Apply specified options or defaults:
// (Ought to refactor this some day to use $.extend() instead)
this.spinCfg = {
//min: cfg && cfg.min ? Number(cfg.min) : null,
//max: cfg && cfg.max ? Number(cfg.max) : null,
// min: cfg && cfg.min ? Number(cfg.min) : null,
// max: cfg && cfg.max ? Number(cfg.max) : null,
min: cfg && !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, // Fixes bug with min:0
max: cfg && !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null,
step: cfg && cfg.step ? Number(cfg.step) : 1,
@@ -105,42 +105,43 @@ $.fn.SpinButton = function(cfg) { 'use strict';
};
// if a smallStep isn't supplied, use half the regular step
this.spinCfg.smallStep = cfg && cfg.smallStep ? cfg.smallStep : this.spinCfg.step/2;
this.adjustValue = function(i){
this.spinCfg.smallStep = cfg && cfg.smallStep ? cfg.smallStep : this.spinCfg.step / 2;
this.adjustValue = function (i) {
var v;
if(isNaN(this.value)) {
if (isNaN(this.value)) {
v = this.spinCfg.reset;
} else if($.isFunction(this.spinCfg.stepfunc)) {
} else if ($.isFunction(this.spinCfg.stepfunc)) {
v = this.spinCfg.stepfunc(this, i);
} else {
// weirdest javascript bug ever: 5.1 + 0.1 = 5.199999999
v = Number((Number(this.value) + Number(i)).toFixed(5));
}
if (this.spinCfg.min !== null) {v = Math.max(v, this.spinCfg.min);}
if (this.spinCfg.max !== null) {v = Math.min(v, this.spinCfg.max);}
if (this.spinCfg.min !== null) { v = Math.max(v, this.spinCfg.min); }
if (this.spinCfg.max !== null) { v = Math.min(v, this.spinCfg.max); }
this.value = v;
if ($.isFunction(this.spinCfg.callback)) {this.spinCfg.callback(this);}
if ($.isFunction(this.spinCfg.callback)) { this.spinCfg.callback(this); }
};
$(this)
.addClass(cfg && cfg.spinClass ? cfg.spinClass : 'spin-button')
.mousemove(function(e){
// Determine which button mouse is over, or not (spin direction):
var x = e.pageX || e.x;
var y = e.pageY || e.y;
var el = e.target || e.srcElement;
var scale = svgEditor.tool_scale || 1;
var height = $(el).height()/2;
var direction =
(x > coord(el,'offsetLeft') + el.offsetWidth*scale - this.spinCfg._btn_width)
? ((y < coord(el,'offsetTop') + height*scale) ? 1 : -1) : 0;
if (direction !== this.spinCfg._direction) {
// Style up/down buttons:
switch(direction){
.addClass(cfg && cfg.spinClass ? cfg.spinClass : 'spin-button')
.mousemove(function (e) {
// Determine which button mouse is over, or not (spin direction):
var x = e.pageX || e.x;
var y = e.pageY || e.y;
var el = e.target || e.srcElement;
var scale = svgEditor.tool_scale || 1;
var height = $(el).height() / 2;
var direction =
(x > coord(el, 'offsetLeft') +
el.offsetWidth * scale - this.spinCfg._btn_width)
? ((y < coord(el, 'offsetTop') + height * scale) ? 1 : -1) : 0;
if (direction !== this.spinCfg._direction) {
// Style up/down buttons:
switch (direction) {
case 1: // Up arrow:
$(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass);
break;
@@ -149,124 +150,121 @@ $.fn.SpinButton = function(cfg) { 'use strict';
break;
default: // Mouse is elsewhere in the textbox
$(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
}
// Set spin direction:
this.spinCfg._direction = direction;
}
})
.mouseout(function(){
// Reset up/down buttons to their normal appearance when mouse moves away:
$(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
this.spinCfg._direction = null;
window.clearInterval(this.spinCfg._repeat);
window.clearTimeout(this.spinCfg._delay);
})
.mousedown(function(e){
if (e.button === 0 && this.spinCfg._direction != 0) {
// Respond to click on one of the buttons:
var self = this;
var stepSize = e.shiftKey ? self.spinCfg.smallStep : self.spinCfg.step;
}
var adjust = function() {
self.adjustValue(self.spinCfg._direction * stepSize);
};
adjust();
// Initial delay before repeating adjustment
self.spinCfg._delay = window.setTimeout(function() {
adjust();
// Repeat adjust at regular intervals
self.spinCfg._repeat = window.setInterval(adjust, self.spinCfg.interval);
}, self.spinCfg.delay);
}
})
.mouseup(function(e){
// Cancel repeating adjustment
window.clearInterval(this.spinCfg._repeat);
window.clearTimeout(this.spinCfg._delay);
})
.dblclick(function(e) {
if ($.browser.msie) {
this.adjustValue(this.spinCfg._direction * this.spinCfg.step);
}
})
.keydown(function(e){
// Respond to up/down arrow keys.
switch(e.keyCode){
case 38: this.adjustValue(this.spinCfg.step); break; // Up
case 40: this.adjustValue(-this.spinCfg.step); break; // Down
case 33: this.adjustValue(this.spinCfg.page); break; // PageUp
case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown
}
})
/*
http://unixpapa.com/js/key.html describes the current state-of-affairs for
key repeat events:
- Safari 3.1 changed their model so that keydown is reliably repeated going forward
- Firefox and Opera still only repeat the keypress event, not the keydown
*/
.keypress(function(e){
if (this.repeating) {
// Respond to up/down arrow keys.
switch(e.keyCode){
case 38: this.adjustValue(this.spinCfg.step); break; // Up
case 40: this.adjustValue(-this.spinCfg.step); break; // Down
case 33: this.adjustValue(this.spinCfg.page); break; // PageUp
case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown
// Set spin direction:
this.spinCfg._direction = direction;
}
}
// we always ignore the first keypress event (use the keydown instead)
else {
this.repeating = true;
}
})
// clear the 'repeating' flag
.keyup(function(e) {
this.repeating = false;
switch(e.keyCode){
})
.mouseout(function () {
// Reset up/down buttons to their normal appearance when mouse moves away:
$(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
this.spinCfg._direction = null;
window.clearInterval(this.spinCfg._repeat);
window.clearTimeout(this.spinCfg._delay);
})
.mousedown(function (e) {
if (e.button === 0 && this.spinCfg._direction !== 0) {
// Respond to click on one of the buttons:
var self = this;
var stepSize = e.shiftKey ? self.spinCfg.smallStep : self.spinCfg.step;
var adjust = function () {
self.adjustValue(self.spinCfg._direction * stepSize);
};
adjust();
// Initial delay before repeating adjustment
self.spinCfg._delay = window.setTimeout(function () {
adjust();
// Repeat adjust at regular intervals
self.spinCfg._repeat = window.setInterval(adjust, self.spinCfg.interval);
}, self.spinCfg.delay);
}
})
.mouseup(function (e) {
// Cancel repeating adjustment
window.clearInterval(this.spinCfg._repeat);
window.clearTimeout(this.spinCfg._delay);
})
.dblclick(function (e) {
if ($.browser.msie) {
this.adjustValue(this.spinCfg._direction * this.spinCfg.step);
}
})
.keydown(function (e) {
// Respond to up/down arrow keys.
switch (e.keyCode) {
case 38: this.adjustValue(this.spinCfg.step); break; // Up
case 40: this.adjustValue(-this.spinCfg.step); break; // Down
case 33: this.adjustValue(this.spinCfg.page); break; // PageUp
case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown
}
})
/*
http://unixpapa.com/js/key.html describes the current state-of-affairs for
key repeat events:
- Safari 3.1 changed their model so that keydown is reliably repeated going forward
- Firefox and Opera still only repeat the keypress event, not the keydown
*/
.keypress(function (e) {
if (this.repeating) {
// Respond to up/down arrow keys.
switch (e.keyCode) {
case 38: this.adjustValue(this.spinCfg.step); break; // Up
case 40: this.adjustValue(-this.spinCfg.step); break; // Down
case 33: this.adjustValue(this.spinCfg.page); break; // PageUp
case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown
}
// we always ignore the first keypress event (use the keydown instead)
} else {
this.repeating = true;
}
})
// clear the 'repeating' flag
.keyup(function (e) {
this.repeating = false;
switch (e.keyCode) {
case 38: // Up
case 40: // Down
case 33: // PageUp
case 34: // PageDown
case 13: this.adjustValue(0); break; // Enter/Return
}
})
.bind("mousewheel", function(e){
// Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120)
if (e.wheelDelta >= 120) {
this.adjustValue(this.spinCfg.step);
}
else if (e.wheelDelta <= -120) {
this.adjustValue(-this.spinCfg.step);
}
e.preventDefault();
})
.change(function(e){
this.adjustValue(0);
});
if (this.addEventListener) {
// Respond to mouse wheel in Firefox
this.addEventListener('DOMMouseScroll', function(e) {
if (e.detail > 0) {
}
})
.bind('mousewheel', function (e) {
// Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120)
if (e.wheelDelta >= 120) {
this.adjustValue(this.spinCfg.step);
} else if (e.wheelDelta <= -120) {
this.adjustValue(-this.spinCfg.step);
}
else if (e.detail < 0) {
e.preventDefault();
})
.change(function (e) {
this.adjustValue(0);
});
if (this.addEventListener) {
// Respond to mouse wheel in Firefox
this.addEventListener('DOMMouseScroll', function (e) {
if (e.detail > 0) {
this.adjustValue(-this.spinCfg.step);
} else if (e.detail < 0) {
this.adjustValue(this.spinCfg.step);
}
e.preventDefault();
}, false);
}

View File

@@ -1,4 +1,6 @@
/*
/* eslint-disable no-var */
/* globals jQuery */
/*
* SVG Icon Loader 2.0
*
* jQuery Plugin for loading SVG icons from a single file
@@ -12,10 +14,10 @@ How to use:
1. Create the SVG master file that includes all icons:
The master SVG icon-containing file is an SVG file that contains
The master SVG icon-containing file is an SVG file that contains
<g> elements. Each <g> element should contain the markup of an SVG
icon. The <g> element has an ID that should
correspond with the ID of the HTML element used on the page that should contain
icon. The <g> element has an ID that should
correspond with the ID of the HTML element used on the page that should contain
or optionally be replaced by the icon. Additionally, one empty element should be
added at the end with id "svg_eof".
@@ -37,10 +39,10 @@ All options are optional and can include:
- 'fallback (object literal)': List of raster images with each
key being the SVG icon ID to replace, and the value the image file name.
- 'fallback_path (string)': The path to use for all images
listed under "fallback"
- 'replace (boolean)': If set to true, HTML elements will be replaced by,
rather than include the SVG icon.
@@ -49,14 +51,14 @@ All options are optional and can include:
- 'resize (object literal)': List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons.
- 'callback (function)': A function to call when all icons have been loaded.
Includes an object literal as its argument with as keys all icon IDs and the
- 'callback (function)': A function to call when all icons have been loaded.
Includes an object literal as its argument with as keys all icon IDs and the
icon as a jQuery object as its value.
- 'id_match (boolean)': Automatically attempt to match SVG icon ids with
corresponding HTML id (default: true)
- 'no_img (boolean)': Prevent attempting to convert the icon into an <img>
element (may be faster, help for browser consistency)
@@ -68,17 +70,16 @@ All options are optional and can include:
$.getSvgIcon(id (string));
This will return the icon (as jQuery object) with a given ID.
6. To resize icons at a later point without using the callback, use this:
$.resizeSvgIcons(resizeOptions) (use the same way as the "resize" parameter)
Example usage #1:
$(function() {
$.svgIcons('my_icon_set.svg'); // The SVG file that contains all icons
// No options have been set, so all icons will automatically be inserted
// into HTML elements that match the same IDs.
// No options have been set, so all icons will automatically be inserted
// into HTML elements that match the same IDs.
});
Example usage #2:
@@ -114,372 +115,372 @@ $(function() {
resize: function() {
'#save_icon .svg_icon': 64 // The "save" icon will be resized to 64 x 64px
},
callback: function(icons) { // Sets background color for "close" icon
callback: function(icons) { // Sets background color for "close" icon
icons['close'].css('background','red');
},
svgz: true // Indicates that an SVGZ file is being used
})
});
*/
(function ($) {
var svgIcons = {}, fixIDs;
(function($) {
var svg_icons = {}, fixIDs;
$.svgIcons = function (file, opts) {
var svgns = 'http://www.w3.org/2000/svg',
xlinkns = 'http://www.w3.org/1999/xlink',
iconW = opts.w || 24,
iconH = opts.h || 24,
elems, svgdoc, testImg,
iconsMade = false, dataLoaded = false, loadAttempts = 0,
// ua = navigator.userAgent,
isOpera = !!window.opera,
// isSafari = (ua.indexOf('Safari/') > -1 && ua.indexOf('Chrome/') === -1),
dataPre = 'data:image/svg+xml;charset=utf-8;base64,';
$.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 = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide();
try {
svgdoc = data_el[0].contentDocument;
data_el.load(getIcons);
getIcons(0, true); // Opera will not run "load" event if file is already cached
} catch(err1) {
useFallback();
}
} else {
var parser = new DOMParser();
$.ajax({
url: file,
dataType: 'string',
success: function(data) {
if(!data) {
$(useFallback);
return;
}
svgdoc = parser.parseFromString(data, "text/xml");
$(function() {
getIcons('ajax');
});
},
error: function(err) {
// TODO: Fix Opera widget icon bug
if(window.opera) {
$(function() {
useFallback();
});
} else {
if(err.responseText) {
svgdoc = parser.parseFromString(err.responseText, "text/xml");
if(!svgdoc.childNodes.length) {
$(useFallback);
}
$(function() {
getIcons('ajax');
});
} else {
$(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;
}
if (opts.svgz) {
var dataEl = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide();
try {
svgdoc = dataEl[0].contentDocument;
dataEl.load(getIcons);
getIcons(0, true); // Opera will not run "load" event if file is already cached
} catch (err1) {
useFallback();
}
} else {
var parser = new DOMParser();
$.ajax({
url: file,
dataType: 'string',
success: function (data) {
if (!data) {
$(useFallback);
return;
}
data_loaded = true;
svgdoc = parser.parseFromString(data, 'text/xml');
$(function () {
getIcons('ajax');
});
},
error: function (err) {
// TODO: Fix Opera widget icon bug
if (window.opera) {
$(function () {
useFallback();
});
} else {
if (err.responseText) {
svgdoc = parser.parseFromString(err.responseText, 'text/xml');
if (!svgdoc.childNodes.length) {
$(useFallback);
}
$(function () {
getIcons('ajax');
});
} else {
$(useFallback);
}
}
}
elems = $(svgdoc.firstChild).children(); //.getElementsByTagName('foreignContent');
if(!opts.no_img) {
var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';
testImg = $(new Image()).attr({
src: testSrc,
width: 0,
height: 0
}).appendTo('body')
});
}
function getIcons (evt, noWait) {
if (evt !== 'ajax') {
if (dataLoaded) 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 = dataEl[0].contentDocument; // Needed again for Webkit
var isReady = (svgdoc && svgdoc.getElementById('svg_eof'));
if (!isReady && !(noWait && isReady)) {
loadAttempts++;
if (loadAttempts < 50) {
setTimeout(getIcons, 20);
} else {
useFallback();
dataLoaded = true;
}
return;
}
dataLoaded = true;
}
elems = $(svgdoc.firstChild).children(); // .getElementsByTagName('foreignContent');
if (!opts.no_img) {
var testSrc = dataPre + '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(true);
}).error(function () {
makeIcons();
});
} else {
setTimeout(function() {
if(!icons_made) makeIcons();
},500);
}
} else {
setTimeout(function () {
if (!iconsMade) makeIcons();
}, 500);
}
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.removeAttr('style');
},1);
}
};
var addIcon = function(icon, id) {
if(opts.id_match === undefined || opts.id_match !== false) {
setIcon(holder, icon, id, true);
}
svg_icons[id] = icon;
};
function makeIcons(toImage, fallback) {
if(icons_made) return;
if(opts.no_img) toImage = false;
var holder, temp_holder;
if(toImage) {
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 {
var len = elems.length;
for(var i = 0; i < len; i++) {
var elem = elems[i];
var id = elem.id;
if(id === 'svg_eof') break;
holder = $('#' + id);
var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];
var svgroot = document.createElementNS(svgns, "svg");
// Per http://www.w3.org/TR/xml-names11/#defaulting, the namespace for
// attributes should have no value.
svgroot.setAttributeNS(null, 'viewBox', [0,0,icon_w,icon_h].join(' '));
// Make flexible by converting width/height to viewBox
var w = svg.getAttribute('width');
var h = svg.getAttribute('height');
svg.removeAttribute('width');
svg.removeAttribute('height');
var vb = svg.getAttribute('viewBox');
if(!vb) {
svg.setAttribute('viewBox', [0,0,w,h].join(' '));
}
// Not using jQuery to be a bit faster
svgroot.setAttribute('xmlns', svgns);
svgroot.setAttribute('width', icon_w);
svgroot.setAttribute('height', icon_h);
svgroot.setAttribute("xmlns:xlink", xlinkns);
svgroot.setAttribute("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);
var icon;
if(toImage) {
temp_holder.empty().append(svgroot);
var str = data_pre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
icon = $(new Image())
.attr({'class':'svg_icon', src:str});
} else {
icon = fixIDs($(svgroot), i);
}
addIcon(icon, id);
}
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.removeAttr('style');
}, 1);
}
};
}
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);
var holder;
var addIcon = function (icon, id) {
if (opts.id_match === undefined || opts.id_match !== false) {
setIcon(holder, icon, id, true);
}
svgIcons[id] = icon;
};
function makeIcons (toImage, fallback) {
if (iconsMade) return;
if (opts.no_img) toImage = false;
var tempHolder;
if (toImage) {
tempHolder = $(document.createElement('div'));
tempHolder.hide().appendTo('body');
}
if (fallback) {
var path = opts.fallback_path || '';
$.each(fallback, function (id, imgsrc) {
holder = $('#' + id);
var icon = $(new Image())
.attr({
'class': 'svg_icon',
src: path + imgsrc,
'width': iconW,
'height': iconH,
'alt': 'icon'
});
});
}
if(!fallback) {
if(toImage) temp_holder.remove();
if(data_el) data_el.remove();
if(testImg) testImg.remove();
}
if(opts.resize) $.resizeSvgIcons(opts.resize);
icons_made = true;
if(opts.callback) opts.callback(svg_icons);
}
fixIDs = function(svg_el, svg_num, force) {
var defs = svg_el.find('defs');
if(!defs.length) return svg_el;
var id_elems;
if(isOpera) {
id_elems = defs.find('*').filter(function() {
return !!this.id;
});
} else {
id_elems = defs.find('[id]');
}
var all_elems = svg_el[0].getElementsByTagName('*'), len = all_elems.length;
id_elems.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 = 'x' + id + svg_num + i;
this.id = new_id;
var old_val = 'url(#' + id + ')';
var new_val = 'url(#' + new_id + ')';
// Selector method, possibly faster but fails in Opera / jQuery 1.4.3
// svg_el.find('[fill="url(#' + id + ')"]').each(function() {
// this.setAttribute('fill', 'url(#' + new_id + ')');
// }).end().find('[stroke="url(#' + id + ')"]').each(function() {
// this.setAttribute('stroke', 'url(#' + new_id + ')');
// }).end().find('use').each(function() {
// if(this.getAttribute('xlink:href') == '#' + id) {
// this.setAttributeNS(xlinkns,'href','#' + new_id);
// }
// }).end().find('[filter="url(#' + id + ')"]').each(function() {
// this.setAttribute('filter', 'url(#' + new_id + ')');
// });
addIcon(icon, id);
});
} else {
var len = elems.length;
for (var i = 0; i < len; i++) {
var elem = elems[i];
var id = elem.id;
if (id === 'svg_eof') break;
holder = $('#' + id);
var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];
var svgroot = document.createElementNS(svgns, 'svg');
// Per http://www.w3.org/TR/xml-names11/#defaulting, the namespace for
// attributes should have no value.
svgroot.setAttributeNS(null, 'viewBox', [0, 0, iconW, iconH].join(' '));
for(i = 0; i < len; i++) {
var elem = all_elems[i];
if(elem.getAttribute('fill') === old_val) {
elem.setAttribute('fill', new_val);
}
if(elem.getAttribute('stroke') === old_val) {
elem.setAttribute('stroke', new_val);
}
if(elem.getAttribute('filter') === old_val) {
elem.setAttribute('filter', new_val);
}
// Make flexible by converting width/height to viewBox
var w = svg.getAttribute('width');
var h = svg.getAttribute('height');
svg.removeAttribute('width');
svg.removeAttribute('height');
var vb = svg.getAttribute('viewBox');
if (!vb) {
svg.setAttribute('viewBox', [0, 0, w, h].join(' '));
}
});
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');
// Not using jQuery to be a bit faster
svgroot.setAttribute('xmlns', svgns);
svgroot.setAttribute('width', iconW);
svgroot.setAttribute('height', iconH);
svgroot.setAttribute('xmlns:xlink', xlinkns);
svgroot.setAttribute('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);
var icon;
if (toImage) {
tempHolder.empty().append(svgroot);
var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
icon = $(new Image())
.attr({'class': 'svg_icon', src: str});
} else {
icon = fixIDs($(svgroot), i);
}
$.svgIcons(reg_file, opts);
} else if(opts.fallback) {
makeIcons(false, opts.fallback);
addIcon(icon, id);
}
}
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, uniqueClone) {
var icon = svg_icons[id];
if(uniqueClone && icon) {
icon = fixIDs(icon, 0, true).clone(true);
}
return icon;
};
$.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);
if(window.opera && window.widget) {
this.parentNode.style.width = w + 'px';
this.parentNode.style.height = h + 'px';
}
if (opts.placement) {
$.each(opts.placement, function (sel, id) {
if (!svgIcons[id]) return;
$(sel).each(function (i) {
var copy = svgIcons[id].clone();
if (i > 0 && !toImage) copy = fixIDs(copy, i, true);
setIcon($(this), copy, id);
});
});
}
if (!fallback) {
if (toImage) tempHolder.remove();
if (dataEl) dataEl.remove();
if (testImg) testImg.remove();
}
if (opts.resize) $.resizeSvgIcons(opts.resize);
iconsMade = true;
if (opts.callback) opts.callback(svgIcons);
}
fixIDs = function (svgEl, svgNum, force) {
var defs = svgEl.find('defs');
if (!defs.length) return svgEl;
var idElems;
if (isOpera) {
idElems = defs.find('*').filter(function () {
return !!this.id;
});
} else {
idElems = defs.find('[id]');
}
var allElems = svgEl[0].getElementsByTagName('*'), len = allElems.length;
idElems.each(function (i) {
var id = this.id;
/*
var noDupes = ($(svgdoc).find('#' + id).length <= 1);
if (isOpera) noDupes = false; // Opera didn't clone svgEl, so not reliable
if(!force && noDupes) return;
*/
var newId = 'x' + id + svgNum + i;
this.id = newId;
var oldVal = 'url(#' + id + ')';
var newVal = 'url(#' + newId + ')';
// Selector method, possibly faster but fails in Opera / jQuery 1.4.3
// svgEl.find('[fill="url(#' + id + ')"]').each(function() {
// this.setAttribute('fill', 'url(#' + newId + ')');
// }).end().find('[stroke="url(#' + id + ')"]').each(function() {
// this.setAttribute('stroke', 'url(#' + newId + ')');
// }).end().find('use').each(function() {
// if(this.getAttribute('xlink:href') == '#' + id) {
// this.setAttributeNS(xlinkns,'href','#' + newId);
// }
// }).end().find('[filter="url(#' + id + ')"]').each(function() {
// this.setAttribute('filter', 'url(#' + newId + ')');
// });
for (i = 0; i < len; i++) {
var elem = allElems[i];
if (elem.getAttribute('fill') === oldVal) {
elem.setAttribute('fill', newVal);
}
if (elem.getAttribute('stroke') === oldVal) {
elem.setAttribute('stroke', newVal);
}
if (elem.getAttribute('filter') === oldVal) {
elem.setAttribute('filter', newVal);
}
}
});
return svgEl;
};
})(jQuery);
function useFallback () {
if (file.indexOf('.svgz') > -1) {
var regFile = file.replace('.svgz', '.svg');
if (window.console) {
console.log('.svgz failed, trying with .svg');
}
$.svgIcons(regFile, 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, uniqueClone) {
var icon = svgIcons[id];
if (uniqueClone && icon) {
icon = fixIDs(icon, 0, true).clone(true);
}
return icon;
};
$.resizeSvgIcons = function (obj) {
// FF2 and older don't detect .svg_icon, so we change it detect svg elems instead
var changeSel = !$('.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 (changeSel) {
sel = sel.replace(/\.svg_icon/g, 'svg');
}
$(sel).each(function () {
this.setAttribute('width', w);
this.setAttribute('height', h);
if (window.opera && window.widget) {
this.parentNode.style.width = w + 'px';
this.parentNode.style.height = h + 'px';
}
});
});
};
})(jQuery);