- 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

View File

@@ -1,3 +1,13 @@
node_modules node_modules
editor/jspdf/jspdf.min.js editor/jspdf/jspdf.min.js
editor/jspdf/underscore-min.js editor/jspdf/underscore-min.js
jgraduate/jpicker.min.js
jgraduate/jquery.jgraduate.js
jquery-ui
jquerybbq
js-hotkeys
spinbtn/JQuerySpinBtn.min.js
test/qunit
test/sinon
wave/json2.js

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 * A class to parse color values
* @author Stoyan Stefanov <sstoo@gmail.com> * @author Stoyan Stefanov <sstoo@gmail.com>
* @link http://www.phpied.com/rgb-color-parser-in-javascript/ * @link http://www.phpied.com/rgb-color-parser-in-javascript/
* @license Use it if you like it * @license Use it if you like it
*/ */
function RGBColor(color_string) { 'use strict'; function RGBColor (colorString) { // eslint-disable-line no-unused-vars
this.ok = false; 'use strict';
this.ok = false;
// strip any leading # // strip any leading #
if (color_string.charAt(0) === '#') { // remove # if any if (colorString.charAt(0) === '#') { // remove # if any
color_string = color_string.substr(1,6); colorString = colorString.substr(1, 6);
} }
color_string = color_string.replace(/ /g,''); colorString = colorString.replace(/ /g, '');
color_string = color_string.toLowerCase(); colorString = colorString.toLowerCase();
// before getting into regexps, try simple matches // before getting into regexps, try simple matches
// and overwrite the input // and overwrite the input
var simple_colors = { var simpleColors = {
aliceblue: 'f0f8ff', aliceblue: 'f0f8ff',
antiquewhite: 'faebd7', antiquewhite: 'faebd7',
aqua: '00ffff', aqua: '00ffff',
aquamarine: '7fffd4', aquamarine: '7fffd4',
azure: 'f0ffff', azure: 'f0ffff',
beige: 'f5f5dc', beige: 'f5f5dc',
bisque: 'ffe4c4', bisque: 'ffe4c4',
black: '000000', black: '000000',
blanchedalmond: 'ffebcd', blanchedalmond: 'ffebcd',
blue: '0000ff', blue: '0000ff',
blueviolet: '8a2be2', blueviolet: '8a2be2',
brown: 'a52a2a', brown: 'a52a2a',
burlywood: 'deb887', burlywood: 'deb887',
cadetblue: '5f9ea0', cadetblue: '5f9ea0',
chartreuse: '7fff00', chartreuse: '7fff00',
chocolate: 'd2691e', chocolate: 'd2691e',
coral: 'ff7f50', coral: 'ff7f50',
cornflowerblue: '6495ed', cornflowerblue: '6495ed',
cornsilk: 'fff8dc', cornsilk: 'fff8dc',
crimson: 'dc143c', crimson: 'dc143c',
cyan: '00ffff', cyan: '00ffff',
darkblue: '00008b', darkblue: '00008b',
darkcyan: '008b8b', darkcyan: '008b8b',
darkgoldenrod: 'b8860b', darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9', darkgray: 'a9a9a9',
darkgreen: '006400', darkgreen: '006400',
darkkhaki: 'bdb76b', darkkhaki: 'bdb76b',
darkmagenta: '8b008b', darkmagenta: '8b008b',
darkolivegreen: '556b2f', darkolivegreen: '556b2f',
darkorange: 'ff8c00', darkorange: 'ff8c00',
darkorchid: '9932cc', darkorchid: '9932cc',
darkred: '8b0000', darkred: '8b0000',
darksalmon: 'e9967a', darksalmon: 'e9967a',
darkseagreen: '8fbc8f', darkseagreen: '8fbc8f',
darkslateblue: '483d8b', darkslateblue: '483d8b',
darkslategray: '2f4f4f', darkslategray: '2f4f4f',
darkturquoise: '00ced1', darkturquoise: '00ced1',
darkviolet: '9400d3', darkviolet: '9400d3',
deeppink: 'ff1493', deeppink: 'ff1493',
deepskyblue: '00bfff', deepskyblue: '00bfff',
dimgray: '696969', dimgray: '696969',
dodgerblue: '1e90ff', dodgerblue: '1e90ff',
feldspar: 'd19275', feldspar: 'd19275',
firebrick: 'b22222', firebrick: 'b22222',
floralwhite: 'fffaf0', floralwhite: 'fffaf0',
forestgreen: '228b22', forestgreen: '228b22',
fuchsia: 'ff00ff', fuchsia: 'ff00ff',
gainsboro: 'dcdcdc', gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff', ghostwhite: 'f8f8ff',
gold: 'ffd700', gold: 'ffd700',
goldenrod: 'daa520', goldenrod: 'daa520',
gray: '808080', gray: '808080',
green: '008000', green: '008000',
greenyellow: 'adff2f', greenyellow: 'adff2f',
honeydew: 'f0fff0', honeydew: 'f0fff0',
hotpink: 'ff69b4', hotpink: 'ff69b4',
indianred : 'cd5c5c', indianred: 'cd5c5c',
indigo : '4b0082', indigo: '4b0082',
ivory: 'fffff0', ivory: 'fffff0',
khaki: 'f0e68c', khaki: 'f0e68c',
lavender: 'e6e6fa', lavender: 'e6e6fa',
lavenderblush: 'fff0f5', lavenderblush: 'fff0f5',
lawngreen: '7cfc00', lawngreen: '7cfc00',
lemonchiffon: 'fffacd', lemonchiffon: 'fffacd',
lightblue: 'add8e6', lightblue: 'add8e6',
lightcoral: 'f08080', lightcoral: 'f08080',
lightcyan: 'e0ffff', lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2', lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3', lightgrey: 'd3d3d3',
lightgreen: '90ee90', lightgreen: '90ee90',
lightpink: 'ffb6c1', lightpink: 'ffb6c1',
lightsalmon: 'ffa07a', lightsalmon: 'ffa07a',
lightseagreen: '20b2aa', lightseagreen: '20b2aa',
lightskyblue: '87cefa', lightskyblue: '87cefa',
lightslateblue: '8470ff', lightslateblue: '8470ff',
lightslategray: '778899', lightslategray: '778899',
lightsteelblue: 'b0c4de', lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0', lightyellow: 'ffffe0',
lime: '00ff00', lime: '00ff00',
limegreen: '32cd32', limegreen: '32cd32',
linen: 'faf0e6', linen: 'faf0e6',
magenta: 'ff00ff', magenta: 'ff00ff',
maroon: '800000', maroon: '800000',
mediumaquamarine: '66cdaa', mediumaquamarine: '66cdaa',
mediumblue: '0000cd', mediumblue: '0000cd',
mediumorchid: 'ba55d3', mediumorchid: 'ba55d3',
mediumpurple: '9370d8', mediumpurple: '9370d8',
mediumseagreen: '3cb371', mediumseagreen: '3cb371',
mediumslateblue: '7b68ee', mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a', mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc', mediumturquoise: '48d1cc',
mediumvioletred: 'c71585', mediumvioletred: 'c71585',
midnightblue: '191970', midnightblue: '191970',
mintcream: 'f5fffa', mintcream: 'f5fffa',
mistyrose: 'ffe4e1', mistyrose: 'ffe4e1',
moccasin: 'ffe4b5', moccasin: 'ffe4b5',
navajowhite: 'ffdead', navajowhite: 'ffdead',
navy: '000080', navy: '000080',
oldlace: 'fdf5e6', oldlace: 'fdf5e6',
olive: '808000', olive: '808000',
olivedrab: '6b8e23', olivedrab: '6b8e23',
orange: 'ffa500', orange: 'ffa500',
orangered: 'ff4500', orangered: 'ff4500',
orchid: 'da70d6', orchid: 'da70d6',
palegoldenrod: 'eee8aa', palegoldenrod: 'eee8aa',
palegreen: '98fb98', palegreen: '98fb98',
paleturquoise: 'afeeee', paleturquoise: 'afeeee',
palevioletred: 'd87093', palevioletred: 'd87093',
papayawhip: 'ffefd5', papayawhip: 'ffefd5',
peachpuff: 'ffdab9', peachpuff: 'ffdab9',
peru: 'cd853f', peru: 'cd853f',
pink: 'ffc0cb', pink: 'ffc0cb',
plum: 'dda0dd', plum: 'dda0dd',
powderblue: 'b0e0e6', powderblue: 'b0e0e6',
purple: '800080', purple: '800080',
red: 'ff0000', red: 'ff0000',
rosybrown: 'bc8f8f', rosybrown: 'bc8f8f',
royalblue: '4169e1', royalblue: '4169e1',
saddlebrown: '8b4513', saddlebrown: '8b4513',
salmon: 'fa8072', salmon: 'fa8072',
sandybrown: 'f4a460', sandybrown: 'f4a460',
seagreen: '2e8b57', seagreen: '2e8b57',
seashell: 'fff5ee', seashell: 'fff5ee',
sienna: 'a0522d', sienna: 'a0522d',
silver: 'c0c0c0', silver: 'c0c0c0',
skyblue: '87ceeb', skyblue: '87ceeb',
slateblue: '6a5acd', slateblue: '6a5acd',
slategray: '708090', slategray: '708090',
snow: 'fffafa', snow: 'fffafa',
springgreen: '00ff7f', springgreen: '00ff7f',
steelblue: '4682b4', steelblue: '4682b4',
tan: 'd2b48c', tan: 'd2b48c',
teal: '008080', teal: '008080',
thistle: 'd8bfd8', thistle: 'd8bfd8',
tomato: 'ff6347', tomato: 'ff6347',
turquoise: '40e0d0', turquoise: '40e0d0',
violet: 'ee82ee', violet: 'ee82ee',
violetred: 'd02090', violetred: 'd02090',
wheat: 'f5deb3', wheat: 'f5deb3',
white: 'ffffff', white: 'ffffff',
whitesmoke: 'f5f5f5', whitesmoke: 'f5f5f5',
yellow: 'ffff00', yellow: 'ffff00',
yellowgreen: '9acd32' yellowgreen: '9acd32'
}; };
var key; var key;
for (key in simple_colors) { for (key in simpleColors) {
if (simple_colors.hasOwnProperty(key)) { if (simpleColors.hasOwnProperty(key)) {
if (color_string == key) { if (colorString === key) {
color_string = simple_colors[key]; colorString = simpleColors[key];
} }
} }
} }
// emd of simple type-in colors // emd of simple type-in colors
// array of color definition objects // array of color definition objects
var color_defs = [ var colorDefs = [
{ {
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function (bits){ process: function (bits) {
return [ return [
parseInt(bits[1], 10), parseInt(bits[1], 10),
parseInt(bits[2], 10), parseInt(bits[2], 10),
parseInt(bits[3], 10) parseInt(bits[3], 10)
]; ];
} }
}, },
{ {
re: /^(\w{2})(\w{2})(\w{2})$/, re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'], example: ['#00ff00', '336699'],
process: function (bits){ process: function (bits) {
return [ return [
parseInt(bits[1], 16), parseInt(bits[1], 16),
parseInt(bits[2], 16), parseInt(bits[2], 16),
parseInt(bits[3], 16) parseInt(bits[3], 16)
]; ];
} }
}, },
{ {
re: /^(\w{1})(\w{1})(\w{1})$/, re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'], example: ['#fb0', 'f0f'],
process: function (bits){ process: function (bits) {
return [ return [
parseInt(bits[1] + bits[1], 16), parseInt(bits[1] + bits[1], 16),
parseInt(bits[2] + bits[2], 16), parseInt(bits[2] + bits[2], 16),
parseInt(bits[3] + bits[3], 16) parseInt(bits[3] + bits[3], 16)
]; ];
} }
} }
]; ];
var i; var i;
// search through the definitions to find a match // search through the definitions to find a match
for (i = 0; i < color_defs.length; i++) { for (i = 0; i < colorDefs.length; i++) {
var re = color_defs[i].re; var re = colorDefs[i].re;
var processor = color_defs[i].process; var processor = colorDefs[i].process;
var bits = re.exec(color_string); var bits = re.exec(colorString);
if (bits) { if (bits) {
var channels = processor(bits); var channels = processor(bits);
this.r = channels[0]; this.r = channels[0];
this.g = channels[1]; this.g = channels[1];
this.b = channels[2]; this.b = channels[2];
this.ok = true; 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 // some getters
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); this.toRGB = function () {
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : 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 // help
this.toRGB = function () { this.getHelpXML = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; var i, j;
}; var examples = [];
this.toHex = function () { // add regexps
var r = this.r.toString(16); for (i = 0; i < colorDefs.length; i++) {
var g = this.g.toString(16); var example = colorDefs[i].example;
var b = this.b.toString(16); for (j = 0; j < example.length; j++) {
if (r.length === 1) {r = '0' + r;} examples[examples.length] = example[j];
if (g.length === 1) {g = '0' + g;} }
if (b.length === 1) {b = '0' + b;} }
return '#' + r + g + b; // add type-in colors
}; var sc;
for (sc in simpleColors) {
// help if (simpleColors.hasOwnProperty(sc)) {
this.getHelpXML = function () { examples[examples.length] = sc;
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;
};
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 // jQuery Context Menu Plugin
// //
// Version 1.01 // Version 1.01
@@ -13,191 +15,191 @@
// This plugin is dual-licensed under the GNU General Public License // This plugin is dual-licensed under the GNU General Public License
// and the MIT License and is copyright A Beautiful Site, LLC. // and the MIT License and is copyright A Beautiful Site, LLC.
// //
if(jQuery)( function() { if (jQuery) {
var win = $(window); (function () {
var doc = $(document); var win = $(window);
var doc = $(document);
$.extend($.fn, { $.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);
// Add contextMenu class contextMenu: function (o, callback) {
menu.addClass('contextMenu'); // Defaults
// Simulate a true right click if (o.menu === undefined) return false;
$(this).bind( "mousedown", function(e) { if (o.inSpeed === undefined) o.inSpeed = 150;
var evt = e; if (o.outSpeed === undefined) o.outSpeed = 75;
$(this).mouseup( function(e) { // 0 needs to be -1 for expected results (no fade)
var srcElement = $(this); if (o.inSpeed === 0) o.inSpeed = -1;
srcElement.unbind('mouseup'); if (o.outSpeed === 0) o.outSpeed = -1;
if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) { // Loop each context menu
e.stopPropagation(); $(this).each(function () {
// Hide context menus that may be showing var el = $(this);
$(".contextMenu").hide(); var offset = $(el).offset();
// 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();
if(x > x_off - 15) x = x_off-15; var menu = $('#' + o.menu);
if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF
// Add contextMenu class
// Show the menu menu.addClass('contextMenu');
doc.unbind('click'); // Simulate a true right click
menu.css({ top: y, left: x }).fadeIn(o.inSpeed); $(this).bind('mousedown', function (e) {
// Hover events var evt = e;
menu.find('A').mouseover( function() { $(this).mouseup(function (e) {
menu.find('LI.hover').removeClass('hover'); var srcElement = $(this);
$(this).parent().addClass('hover'); srcElement.unbind('mouseup');
}).mouseout( function() { if (evt.button === 2 || o.allowLeft ||
menu.find('LI.hover').removeClass('hover'); (evt.ctrlKey && svgedit.browser.isMac())) {
}); e.stopPropagation();
// Hide context menus that may be showing
// Keyboard $('.contextMenu').hide();
doc.keypress( function(e) { // Get this context menu
switch( e.keyCode ) {
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 case 38: // up
if( !menu.find('LI.hover').length ) { if (!menu.find('LI.hover').length) {
menu.find('LI:last').addClass('hover'); menu.find('LI:last').addClass('hover');
} else { } else {
menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); 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 case 40: // down
if( menu.find('LI.hover').length == 0 ) { if (menu.find('LI.hover').length === 0) {
menu.find('LI:first').addClass('hover'); menu.find('LI:first').addClass('hover');
} else { } else {
menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); 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 case 13: // enter
menu.find('LI.hover A').trigger('click'); menu.find('LI.hover A').trigger('click');
break; break;
case 27: // esc case 27: // esc
doc.trigger('click'); doc.trigger('click');
break break;
} }
}); });
// When items are selected // When items are selected
menu.find('A').unbind('mouseup'); menu.find('A').unbind('mouseup');
menu.find('LI:not(.disabled) A').mouseup( function() { 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() {
doc.unbind('click').unbind('keypress'); 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; 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; });
}); });
return $(this);
// Disable text selection },
if( $.browser.mozilla ) {
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); }); // Disable context menu items on the fly
} else if( $.browser.msie ) { disableContextMenuItems: function (o) {
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); }); if (o === undefined) {
} else { // Disable all
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); }); $(this).find('LI').addClass('disabled');
return $(this);
} }
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome) $(this).each(function () {
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; }); if (o !== undefined) {
var d = o.split(',');
}); for (var i = 0; i < d.length; i++) {
return $(this); $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
}, }
// 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');
} }
});
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 () {
return( $(this) ); if (o !== undefined) {
}, var d = o.split(',');
for (var i = 0; i < d.length; i++) {
// Enable context menu items on the fly $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
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');
} }
} });
}); return $(this);
return( $(this) ); },
},
// Disable context menu(s)
// Disable context menu(s) disableContextMenu: function () {
disableContextMenu: function() { $(this).each(function () {
$(this).each( function() { $(this).addClass('disabled');
$(this).addClass('disabled'); });
}); return $(this);
return( $(this) ); },
},
// Enable context menu(s)
// Enable context menu(s) enableContextMenu: function () {
enableContextMenu: function() { $(this).each(function () {
$(this).each( function() { $(this).removeClass('disabled');
$(this).removeClass('disabled'); });
}); return $(this);
return( $(this) ); },
},
// Destroy context menu(s)
// Destroy context menu(s) destroyContextMenu: function () {
destroyContextMenu: function() { // Destroy specified context menus
// Destroy specified context menus $(this).each(function () {
$(this).each( function() { // Disable action
// Disable action $(this).unbind('mousedown').unbind('mouseup');
$(this).unbind('mousedown').unbind('mouseup'); });
}); return $(this);
return( $(this) ); }
}
});
}); })(jQuery);
})(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*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals $, svgEditor */
/* SpinButton control /* SpinButton control
* *
* Adds bells and whistles to any ordinary textbox to * Adds bells and whistles to any ordinary textbox to
@@ -37,15 +37,15 @@
* v1.2 27 Sep 2006 - Mark Gibson - Major enhancements * v1.2 27 Sep 2006 - Mark Gibson - Major enhancements
* v1.3a 28 Sep 2006 - George Adamson - Minor enhancements * v1.3a 28 Sep 2006 - George Adamson - Minor enhancements
* v1.4 18 Jun 2009 - Jeff Schiller - Added callback function * v1.4 18 Jun 2009 - Jeff Schiller - Added callback function
* v1.5 06 Jul 2009 - Jeff Schiller - Fixes for Opera. * v1.5 06 Jul 2009 - Jeff Schiller - Fixes for Opera.
* v1.6 13 Oct 2009 - Alexis Deveria - Added stepfunc function * v1.6 13 Oct 2009 - Alexis Deveria - Added stepfunc function
* v1.7 21 Oct 2009 - Alexis Deveria - Minor fixes * v1.7 21 Oct 2009 - Alexis Deveria - Minor fixes
* Fast-repeat for keys and live updating as you type. * Fast-repeat for keys and live updating as you type.
* v1.8 12 Jan 2010 - Benjamin Thomas - Fixes for mouseout behavior. * v1.8 12 Jan 2010 - Benjamin Thomas - Fixes for mouseout behavior.
* Added smallStep * Added smallStep
Sample usage: Sample usage:
// Create group of settings to initialise spinbutton(s). (Optional) // Create group of settings to initialise spinbutton(s). (Optional)
var myOptions = { var myOptions = {
min: 0, // Set lower limit. min: 0, // Set lower limit.
@@ -56,37 +56,37 @@
upClass: mySpinUpClass, // CSS class for style when mouse over up button. upClass: mySpinUpClass, // CSS class for style when mouse over up button.
downClass: mySpinDnClass // CSS class for style when mouse over down button. downClass: mySpinDnClass // CSS class for style when mouse over down button.
} }
$(document).ready(function(){ $(document).ready(function(){
// Initialise INPUT element(s) as SpinButtons: (passing options if desired) // Initialise INPUT element(s) as SpinButtons: (passing options if desired)
$("#myInputElement").SpinButton(myOptions); $("#myInputElement").SpinButton(myOptions);
}); });
*/ */
$.fn.SpinButton = function(cfg) { 'use strict'; $.fn.SpinButton = function (cfg) {
function coord(el,prop) { 'use strict';
function coord (el, prop) {
var c = el[prop], b = document.body; 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')) { if (!$.browser.msie || (el.currentStyle.position !== 'relative')) {
c += el[prop]; c += el[prop];
} }
} }
return c; return c;
} }
return this.each(function(){ return this.each(function () {
this.repeating = false; this.repeating = false;
// Apply specified options or defaults: // Apply specified options or defaults:
// (Ought to refactor this some day to use $.extend() instead) // (Ought to refactor this some day to use $.extend() instead)
this.spinCfg = { this.spinCfg = {
//min: cfg && cfg.min ? Number(cfg.min) : null, // min: cfg && cfg.min ? Number(cfg.min) : null,
//max: cfg && cfg.max ? Number(cfg.max) : null, // max: cfg && cfg.max ? Number(cfg.max) : null,
min: cfg && !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, // Fixes bug with min:0 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, max: cfg && !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null,
step: cfg && cfg.step ? Number(cfg.step) : 1, 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 // if a smallStep isn't supplied, use half the regular step
this.spinCfg.smallStep = cfg && cfg.smallStep ? cfg.smallStep : this.spinCfg.step/2; this.spinCfg.smallStep = cfg && cfg.smallStep ? cfg.smallStep : this.spinCfg.step / 2;
this.adjustValue = function(i){ this.adjustValue = function (i) {
var v; var v;
if(isNaN(this.value)) { if (isNaN(this.value)) {
v = this.spinCfg.reset; v = this.spinCfg.reset;
} else if($.isFunction(this.spinCfg.stepfunc)) { } else if ($.isFunction(this.spinCfg.stepfunc)) {
v = this.spinCfg.stepfunc(this, i); v = this.spinCfg.stepfunc(this, i);
} else { } else {
// weirdest javascript bug ever: 5.1 + 0.1 = 5.199999999 // weirdest javascript bug ever: 5.1 + 0.1 = 5.199999999
v = Number((Number(this.value) + Number(i)).toFixed(5)); v = Number((Number(this.value) + Number(i)).toFixed(5));
} }
if (this.spinCfg.min !== null) {v = Math.max(v, this.spinCfg.min);} 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.max !== null) { v = Math.min(v, this.spinCfg.max); }
this.value = v; this.value = v;
if ($.isFunction(this.spinCfg.callback)) {this.spinCfg.callback(this);} if ($.isFunction(this.spinCfg.callback)) { this.spinCfg.callback(this); }
}; };
$(this) $(this)
.addClass(cfg && cfg.spinClass ? cfg.spinClass : 'spin-button') .addClass(cfg && cfg.spinClass ? cfg.spinClass : 'spin-button')
.mousemove(function(e){ .mousemove(function (e) {
// Determine which button mouse is over, or not (spin direction): // Determine which button mouse is over, or not (spin direction):
var x = e.pageX || e.x; var x = e.pageX || e.x;
var y = e.pageY || e.y; var y = e.pageY || e.y;
var el = e.target || e.srcElement; var el = e.target || e.srcElement;
var scale = svgEditor.tool_scale || 1; var scale = svgEditor.tool_scale || 1;
var height = $(el).height()/2; var height = $(el).height() / 2;
var direction = var direction =
(x > coord(el,'offsetLeft') + el.offsetWidth*scale - this.spinCfg._btn_width) (x > coord(el, 'offsetLeft') +
? ((y < coord(el,'offsetTop') + height*scale) ? 1 : -1) : 0; 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: if (direction !== this.spinCfg._direction) {
switch(direction){ // Style up/down buttons:
switch (direction) {
case 1: // Up arrow: case 1: // Up arrow:
$(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass); $(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass);
break; break;
@@ -149,124 +150,121 @@ $.fn.SpinButton = function(cfg) { 'use strict';
break; break;
default: // Mouse is elsewhere in the textbox default: // Mouse is elsewhere in the textbox
$(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass); $(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() { // Set spin direction:
self.adjustValue(self.spinCfg._direction * stepSize); this.spinCfg._direction = direction;
};
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 { .mouseout(function () {
this.repeating = true; // 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);
// clear the 'repeating' flag window.clearTimeout(this.spinCfg._delay);
.keyup(function(e) { })
this.repeating = false;
switch(e.keyCode){ .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 38: // Up
case 40: // Down case 40: // Down
case 33: // PageUp case 33: // PageUp
case 34: // PageDown case 34: // PageDown
case 13: this.adjustValue(0); break; // Enter/Return case 13: this.adjustValue(0); break; // Enter/Return
} }
}) })
.bind("mousewheel", function(e){ .bind('mousewheel', function (e) {
// Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120) // Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120)
if (e.wheelDelta >= 120) { if (e.wheelDelta >= 120) {
this.adjustValue(this.spinCfg.step); this.adjustValue(this.spinCfg.step);
} } else if (e.wheelDelta <= -120) {
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) {
this.adjustValue(-this.spinCfg.step); 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); this.adjustValue(this.spinCfg.step);
} }
e.preventDefault(); e.preventDefault();
}, false); }, false);
} }

View File

@@ -1,4 +1,6 @@
/* /* eslint-disable no-var */
/* globals jQuery */
/*
* SVG Icon Loader 2.0 * SVG Icon Loader 2.0
* *
* jQuery Plugin for loading SVG icons from a single file * 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: 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 <g> elements. Each <g> element should contain the markup of an SVG
icon. The <g> element has an ID that should icon. The <g> element has an ID that should
correspond with the ID of the HTML element used on the page that should contain 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 or optionally be replaced by the icon. Additionally, one empty element should be
added at the end with id "svg_eof". 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 - 'fallback (object literal)': List of raster images with each
key being the SVG icon ID to replace, and the value the image file name. 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 - 'fallback_path (string)': The path to use for all images
listed under "fallback" listed under "fallback"
- 'replace (boolean)': If set to true, HTML elements will be replaced by, - 'replace (boolean)': If set to true, HTML elements will be replaced by,
rather than include the SVG icon. 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 - 'resize (object literal)': List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons. as values. This allows an easy way to resize specific icons.
- 'callback (function)': A function to call when all icons have been loaded. - '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 Includes an object literal as its argument with as keys all icon IDs and the
icon as a jQuery object as its value. icon as a jQuery object as its value.
- 'id_match (boolean)': Automatically attempt to match SVG icon ids with - 'id_match (boolean)': Automatically attempt to match SVG icon ids with
corresponding HTML id (default: true) corresponding HTML id (default: true)
- 'no_img (boolean)': Prevent attempting to convert the icon into an <img> - 'no_img (boolean)': Prevent attempting to convert the icon into an <img>
element (may be faster, help for browser consistency) element (may be faster, help for browser consistency)
@@ -68,17 +70,16 @@ All options are optional and can include:
$.getSvgIcon(id (string)); $.getSvgIcon(id (string));
This will return the icon (as jQuery object) with a given ID. 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: 6. To resize icons at a later point without using the callback, use this:
$.resizeSvgIcons(resizeOptions) (use the same way as the "resize" parameter) $.resizeSvgIcons(resizeOptions) (use the same way as the "resize" parameter)
Example usage #1: Example usage #1:
$(function() { $(function() {
$.svgIcons('my_icon_set.svg'); // The SVG file that contains all icons $.svgIcons('my_icon_set.svg'); // The SVG file that contains all icons
// No options have been set, so all icons will automatically be inserted // No options have been set, so all icons will automatically be inserted
// into HTML elements that match the same IDs. // into HTML elements that match the same IDs.
}); });
Example usage #2: Example usage #2:
@@ -114,372 +115,372 @@ $(function() {
resize: function() { resize: function() {
'#save_icon .svg_icon': 64 // The "save" icon will be resized to 64 x 64px '#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'); icons['close'].css('background','red');
}, },
svgz: true // Indicates that an SVGZ file is being used svgz: true // Indicates that an SVGZ file is being used
}) })
}); });
*/ */
(function ($) {
var svgIcons = {}, fixIDs;
(function($) { $.svgIcons = function (file, opts) {
var svg_icons = {}, fixIDs; 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) { if (opts.svgz) {
var svgns = "http://www.w3.org/2000/svg", var dataEl = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide();
xlinkns = "http://www.w3.org/1999/xlink", try {
icon_w = opts.w?opts.w : 24, svgdoc = dataEl[0].contentDocument;
icon_h = opts.h?opts.h : 24, dataEl.load(getIcons);
elems, svgdoc, testImg, getIcons(0, true); // Opera will not run "load" event if file is already cached
icons_made = false, data_loaded = false, load_attempts = 0, } catch (err1) {
ua = navigator.userAgent, isOpera = !!window.opera, isSafari = (ua.indexOf('Safari/') > -1 && ua.indexOf('Chrome/')==-1), useFallback();
data_pre = 'data:image/svg+xml;charset=utf-8;base64,'; }
} else {
if(opts.svgz) { var parser = new DOMParser();
var data_el = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide(); $.ajax({
try { url: file,
svgdoc = data_el[0].contentDocument; dataType: 'string',
data_el.load(getIcons); success: function (data) {
getIcons(0, true); // Opera will not run "load" event if file is already cached if (!data) {
} catch(err1) { $(useFallback);
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;
}
return; 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) { function getIcons (evt, noWait) {
var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D'; if (evt !== 'ajax') {
if (dataLoaded) return;
testImg = $(new Image()).attr({ // Webkit sometimes says svgdoc is undefined, other times
src: testSrc, // it fails to load all nodes. Thus we must make sure the "eof"
width: 0, // element is loaded.
height: 0 svgdoc = dataEl[0].contentDocument; // Needed again for Webkit
}).appendTo('body') 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 () { .load(function () {
// Safari 4 crashes, Opera and Chrome don't // Safari 4 crashes, Opera and Chrome don't
makeIcons(true); makeIcons(true);
}).error(function () { }).error(function () {
makeIcons(); makeIcons();
}); });
} else { } else {
setTimeout(function() { setTimeout(function () {
if(!icons_made) makeIcons(); if (!iconsMade) makeIcons();
},500); }, 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. var setIcon = function (target, icon, id, setID) {
// With cloning, causes issue in Opera/Win/Non-EN if (isOpera) icon.css('visibility', 'hidden');
if(!isOpera) svg = svg.cloneNode(true); if (opts.replace) {
if (setID) icon.attr('id', id);
svgroot.appendChild(svg); var cl = target.attr('class');
var icon; if (cl) icon.attr('class', 'svg_icon ' + cl);
if(toImage) { target.replaceWith(icon);
temp_holder.empty().append(svgroot); } else {
var str = data_pre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot)))); target.append(icon);
icon = $(new Image()) }
.attr({'class':'svg_icon', src:str}); if (isOpera) {
} else { setTimeout(function () {
icon = fixIDs($(svgroot), i); icon.removeAttr('style');
} }, 1);
addIcon(icon, id); }
} };
} var holder;
var addIcon = function (icon, id) {
if(opts.placement) { if (opts.id_match === undefined || opts.id_match !== false) {
$.each(opts.placement, function(sel, id) { setIcon(holder, icon, id, true);
if(!svg_icons[id]) return; }
$(sel).each(function(i) { svgIcons[id] = icon;
var copy = svg_icons[id].clone(); };
if(i > 0 && !toImage) copy = fixIDs(copy, i, true);
setIcon($(this), copy, id); 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); addIcon(icon, id);
} });
} else {
fixIDs = function(svg_el, svg_num, force) { var len = elems.length;
var defs = svg_el.find('defs'); for (var i = 0; i < len; i++) {
if(!defs.length) return svg_el; var elem = elems[i];
var id_elems; var id = elem.id;
if(isOpera) { if (id === 'svg_eof') break;
id_elems = defs.find('*').filter(function() { holder = $('#' + id);
return !!this.id; var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];
}); var svgroot = document.createElementNS(svgns, 'svg');
} else { // Per http://www.w3.org/TR/xml-names11/#defaulting, the namespace for
id_elems = defs.find('[id]'); // attributes should have no value.
} svgroot.setAttributeNS(null, 'viewBox', [0, 0, iconW, iconH].join(' '));
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 + ')');
// });
for(i = 0; i < len; i++) { // Make flexible by converting width/height to viewBox
var elem = all_elems[i]; var w = svg.getAttribute('width');
if(elem.getAttribute('fill') === old_val) { var h = svg.getAttribute('height');
elem.setAttribute('fill', new_val); svg.removeAttribute('width');
} svg.removeAttribute('height');
if(elem.getAttribute('stroke') === old_val) {
elem.setAttribute('stroke', new_val); var vb = svg.getAttribute('viewBox');
} if (!vb) {
if(elem.getAttribute('filter') === old_val) { svg.setAttribute('viewBox', [0, 0, w, h].join(' '));
elem.setAttribute('filter', new_val);
}
} }
});
return svg_el; // Not using jQuery to be a bit faster
}; svgroot.setAttribute('xmlns', svgns);
svgroot.setAttribute('width', iconW);
function useFallback() { svgroot.setAttribute('height', iconH);
if(file.indexOf('.svgz') != -1) { svgroot.setAttribute('xmlns:xlink', xlinkns);
var reg_file = file.replace('.svgz','.svg'); svgroot.setAttribute('class', 'svg_icon');
if(window.console) {
console.log('.svgz failed, trying with .svg'); // 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); addIcon(icon, id);
} else if(opts.fallback) {
makeIcons(false, opts.fallback);
} }
} }
function encode64(input) { if (opts.placement) {
// base64 strings are 4/3 larger than the original string $.each(opts.placement, function (sel, id) {
if(window.btoa) return window.btoa(input); if (!svgIcons[id]) return;
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; $(sel).each(function (i) {
var output = new Array( Math.floor( (input.length + 2) / 3 ) * 4 ); var copy = svgIcons[id].clone();
var chr1, chr2, chr3; if (i > 0 && !toImage) copy = fixIDs(copy, i, true);
var enc1, enc2, enc3, enc4; setIcon($(this), copy, id);
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 (!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);

View File

@@ -1,4 +1,5 @@
function start_svg_edit() { /* eslint-disable no-var */
var url = "chrome://svg-edit/content/editor/svg-editor.html"; function startSvgEdit () { // eslint-disable-line no-unused-vars
window.openDialog(url, "SVG Editor", "width=1024,height=700,menubar=no,toolbar=no"); var url = 'chrome://svg-edit/content/editor/svg-editor.html';
window.openDialog(url, 'SVG Editor', 'width=1024,height=700,menubar=no,toolbar=no');
} }

View File

@@ -11,14 +11,14 @@
<menupopup id="menu_ToolsPopup"> <menupopup id="menu_ToolsPopup">
<menuitem insertafter="devToolsSeparator" label="SVG Editor" <menuitem insertafter="devToolsSeparator" label="SVG Editor"
oncommand="start_svg_edit();" /> oncommand="startSvgEdit();" />
</menupopup> </menupopup>
<!-- Firefox --> <!-- Firefox -->
<statusbar id="status-bar"> <statusbar id="status-bar">
<statusbarpanel id="svg-edit-statusbar-button" <statusbarpanel id="svg-edit-statusbar-button"
class="statusbarpanel-menu-iconic" class="statusbarpanel-menu-iconic"
onclick="return start_svg_edit()" onclick="return startSvgEdit()"
tooltip="SvgEdit"> tooltip="SvgEdit">
</statusbarpanel> </statusbarpanel>
</statusbar> </statusbar>

View File

@@ -1,55 +1,56 @@
/* eslint-disable no-var */
/* global $, Components, svgCanvas, netscape */
// Note: This JavaScript file must be included as the last script on the main HTML editor page to override the open/save handlers // Note: This JavaScript file must be included as the last script on the main HTML editor page to override the open/save handlers
$(function() { $(function () {
if(!window.Components) return; if (!window.Components) return;
function moz_file_picker(readflag) { function mozFilePicker (readflag) {
var fp = window.Components.classes["@mozilla.org/filepicker;1"]. var fp = window.Components.classes['@mozilla.org/filepicker;1']
createInstance(Components.interfaces.nsIFilePicker); .createInstance(Components.interfaces.nsIFilePicker);
if(readflag) if (readflag) fp.init(window, 'Pick a SVG file', fp.modeOpen);
fp.init(window, "Pick a SVG file", fp.modeOpen); else fp.init(window, 'Pick a SVG file', fp.modeSave);
else fp.defaultExtension = '*.svg';
fp.init(window, "Pick a SVG file", fp.modeSave); fp.show();
fp.defaultExtension = "*.svg"; return fp.file;
fp.show();
return fp.file;
} }
svgCanvas.setCustomHandlers({ svgCanvas.setCustomHandlers({
'open':function() { open: function () {
try {
netscape.security.PrivilegeManager.
enablePrivilege("UniversalXPConnect");
var file = moz_file_picker(true);
if(!file)
return(null);
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
inputStream.init(file, 0x01, 00004, null);
var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
sInputStream.init(inputStream);
svgCanvas.setSvgString(sInputStream.
read(sInputStream.available()));
} catch(e) {
console.log("Exception while attempting to load" + e);
}
},
'save':function(svg, str) {
try { try {
var file = moz_file_picker(false); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
if(!file) var file = mozFilePicker(true);
if (!file) {
return null;
}
var inputStream = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);
inputStream.init(file, 0x01, parseInt('00004', 8), null);
var sInputStream = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream);
sInputStream.init(inputStream);
svgCanvas.setSvgString(sInputStream.read(sInputStream.available()));
} catch (e) {
console.log('Exception while attempting to load' + e);
}
},
save: function (svg, str) {
try {
var file = mozFilePicker(false);
if (!file) {
return; return;
}
if (!file.exists()) if (!file.exists()) {
file.create(0, 0664); file.create(0, parseInt('0664', 8));
}
var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); var out = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
out.init(file, 0x20 | 0x02, 00004,null); out.init(file, 0x20 | 0x02, parseInt('00004', 8), null);
out.write(str, str.length); out.write(str, str.length);
out.flush(); out.flush();
out.close(); out.close();
} catch(e) { } catch (e) {
alert(e); alert(e);
} }
} }
}); });
}); });

View File

@@ -1,62 +1,59 @@
/* eslint-disable no-var */
/* globals $, svgCanvas */
// Note: This JavaScript file must be included as the last script on the main HTML editor page to override the open/save handlers // Note: This JavaScript file must be included as the last script on the main HTML editor page to override the open/save handlers
$(function() { $(function () {
if(window.opera && window.opera.io && window.opera.io.filesystem) { if (window.opera && window.opera.io && window.opera.io.filesystem) {
svgCanvas.setCustomHandlers({ svgCanvas.setCustomHandlers({
'open':function() { open: function () {
try { try {
window.opera.io.filesystem.browseForFile( window.opera.io.filesystem.browseForFile(
new Date().getTime(), /* mountpoint name */ new Date().getTime(), /* mountpoint name */
"", /* default location */ '', /* default location */
function(file) { function (file) {
try { try {
if (file) { if (file) {
fstream = file.open(file, "r"); var fstream = file.open(file, 'r');
var output = ""; var output = '';
while (!fstream.eof) { while (!fstream.eof) {
output += fstream.readLine(); output += fstream.readLine();
} }
svgCanvas.setSvgString(output); /* 'this' is bound to the filestream object here */ svgCanvas.setSvgString(output); /* 'this' is bound to the filestream object here */
} }
} } catch (e) {
catch(e) { console.log('Reading file failed.');
console.log("Reading file failed.");
} }
}, },
false, /* not persistent */ false, /* not persistent */
false, /* no multiple selections */ false, /* no multiple selections */
"*.svg" /* file extension filter */ '*.svg' /* file extension filter */
); );
} catch (e) {
console.log('Open file failed.');
} }
catch(e) {
console.log("Open file failed.");
}
}, },
'save':function(window, svg) { save: function (window, svg) {
try { try {
window.opera.io.filesystem.browseForSave( window.opera.io.filesystem.browseForSave(
new Date().getTime(), /* mountpoint name */ new Date().getTime(), /* mountpoint name */
"", /* default location */ '', /* default location */
function(file) { function (file) {
try { try {
if (file) { if (file) {
var fstream = file.open(file, "w"); var fstream = file.open(file, 'w');
fstream.write(svg, "UTF-8"); fstream.write(svg, 'UTF-8');
fstream.close(); fstream.close();
} }
} catch (e) {
console.log('Write to file failed.');
} }
catch(e) { },
console.log("Write to file failed.");
}
},
false /* not persistent */ false /* not persistent */
); );
} } catch (e) {
catch(e) { console.log('Save file failed.');
console.log("Save file failed.");
} }
} }
}); });
} }
}); });

View File

@@ -6,14 +6,12 @@
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<script> <script>
/** this method adds the script that overrides the default open/save handlers */ /** this method adds the script that overrides the default open/save handlers */
function addHandlers() function addHandlers () {
{ var cdoc = document.getElementById('container').contentDocument;
var cdoc = document.getElementById("container").contentDocument; if (cdoc) {
if(cdoc) var scriptelm = cdoc.createElement('script');
{ scriptelm.src = '../handlers.js';
var scriptelm = cdoc.createElement("script"); cdoc.getElementsByTagName('head')[0].appendChild(scriptelm);
scriptelm.src = "../handlers.js";
cdoc.getElementsByTagName("head")[0].appendChild(scriptelm);
} }
} }
</script> </script>

View File

@@ -206,10 +206,10 @@
<h2>Plugin Architecture</h2> <h2>Plugin Architecture</h2>
</header> </header>
<pre> <pre>
svgEditor.addExtension("Hello World", function() { svgEditor.addExtension("Hello World", function () {
return { return {
svgicons: "extensions/helloworld-icon.xml", svgicons: 'extensions/helloworld-icon.xml',
buttons: [{...}], buttons: [{...}],
mouseDown: function() { mouseDown: function() {
... ...

View File

@@ -1,390 +1,375 @@
(function() { /* eslint-disable no-var */
var doc = document; (function () {
var disableBuilds = true; var doc = document;
var disableBuilds = true;
var ctr = 0; var ctr = 0;
var spaces = /\s+/, a1 = ['']; var spaces = /\s+/, a1 = [''];
var toArray = function(list) { var toArray = function (list) {
return Array.prototype.slice.call(list || [], 0); return Array.prototype.slice.call(list || [], 0);
}; };
var byId = function(id) { var byId = function (id) {
if (typeof id == 'string') { return doc.getElementById(id); } if (typeof id === 'string') { return doc.getElementById(id); }
return id; return id;
}; };
var query = function(query, root) { var query = function (query, root) {
if (!query) { return []; } if (!query) { return []; }
if (typeof query != 'string') { return toArray(query); } if (typeof query !== 'string') { return toArray(query); }
if (typeof root == 'string') { if (typeof root === 'string') {
root = byId(root); root = byId(root);
if(!root){ return []; } if (!root) { return []; }
} }
root = root || document; root = root || document;
var rootIsDoc = (root.nodeType == 9); var rootIsDoc = (root.nodeType === 9);
var doc = rootIsDoc ? root : (root.ownerDocument || document); var doc = rootIsDoc ? root : (root.ownerDocument || document);
// rewrite the query to be ID rooted // rewrite the query to be ID rooted
if (!rootIsDoc || ('>~+'.indexOf(query.charAt(0)) >= 0)) { if (!rootIsDoc || ('>~+'.indexOf(query.charAt(0)) >= 0)) {
root.id = root.id || ('qUnique' + (ctr++)); root.id = root.id || ('qUnique' + (ctr++));
query = '#' + root.id + ' ' + query; query = '#' + root.id + ' ' + query;
} }
// don't choke on something like ".yada.yada >" // don't choke on something like ".yada.yada >"
if ('>~+'.indexOf(query.slice(-1)) >= 0) { query += ' *'; } if ('>~+'.indexOf(query.slice(-1)) >= 0) { query += ' *'; }
return toArray(doc.querySelectorAll(query)); return toArray(doc.querySelectorAll(query));
}; };
var strToArray = function(s) { var strToArray = function (s) {
if (typeof s == 'string' || s instanceof String) { if (typeof s === 'string' || s instanceof String) {
if (s.indexOf(' ') < 0) { if (s.indexOf(' ') < 0) {
a1[0] = s; a1[0] = s;
return a1; return a1;
} else { }
return s.split(spaces); return s.split(spaces);
} }
} return s;
return s; };
};
var addClass = function(node, classStr) { var addClass = function (node, classStr) {
classStr = strToArray(classStr); classStr = strToArray(classStr);
var cls = ' ' + node.className + ' '; var cls = ' ' + node.className + ' ';
for (var i = 0, len = classStr.length, c; i < len; ++i) { for (var i = 0, len = classStr.length, c; i < len; ++i) {
c = classStr[i]; c = classStr[i];
if (c && cls.indexOf(' ' + c + ' ') < 0) { if (c && cls.indexOf(' ' + c + ' ') < 0) {
cls += c + ' '; cls += c + ' ';
} }
} }
node.className = cls.trim(); node.className = cls.trim();
}; };
var removeClass = function(node, classStr) { var removeClass = function (node, classStr) {
var cls; var cls;
if (classStr !== undefined) { if (classStr !== undefined) {
classStr = strToArray(classStr); classStr = strToArray(classStr);
cls = ' ' + node.className + ' '; cls = ' ' + node.className + ' ';
for (var i = 0, len = classStr.length; i < len; ++i) { for (var i = 0, len = classStr.length; i < len; ++i) {
cls = cls.replace(' ' + classStr[i] + ' ', ' '); cls = cls.replace(' ' + classStr[i] + ' ', ' ');
} }
cls = cls.trim(); cls = cls.trim();
} else { } else {
cls = ''; cls = '';
} }
if (node.className != cls) { if (node.className !== cls) {
node.className = cls; node.className = cls;
} }
}; };
var toggleClass = function(node, classStr) { var toggleClass = function (node, classStr) {
var cls = ' ' + node.className + ' '; var cls = ' ' + node.className + ' ';
if (cls.indexOf(' ' + classStr.trim() + ' ') >= 0) { if (cls.indexOf(' ' + classStr.trim() + ' ') >= 0) {
removeClass(node, classStr); removeClass(node, classStr);
} else { } else {
addClass(node, classStr); addClass(node, classStr);
} }
}; };
var ua = navigator.userAgent; var ua = navigator.userAgent;
var isFF = parseFloat(ua.split('Firefox/')[1]) || undefined; var isFF = parseFloat(ua.split('Firefox/')[1]) || undefined;
var isWK = parseFloat(ua.split('WebKit/')[1]) || undefined; var isWK = parseFloat(ua.split('WebKit/')[1]) || undefined;
var isOpera = parseFloat(ua.split('Opera/')[1]) || undefined; var isOpera = parseFloat(ua.split('Opera/')[1]) || undefined;
var canTransition = (function() { var canTransition = (function () {
var ver = parseFloat(ua.split('Version/')[1]) || undefined; var ver = parseFloat(ua.split('Version/')[1]) || undefined;
// test to determine if this browser can handle CSS transitions. // test to determine if this browser can handle CSS transitions.
var cachedCanTransition = var cachedCanTransition =
(isWK || (isFF && isFF > 3.6 ) || (isOpera && ver >= 10.5)); (isWK || (isFF && isFF > 3.6) || (isOpera && ver >= 10.5));
return function() { return cachedCanTransition; } return function () { return cachedCanTransition; };
})(); })();
// //
// Slide class // Slide class
// //
var Slide = function(node, idx) { var Slide = function (node, idx) {
this._node = node; this._node = node;
if (idx >= 0) { if (idx >= 0) {
this._count = idx + 1; this._count = idx + 1;
} }
if (this._node) { if (this._node) {
addClass(this._node, 'slide distant-slide'); addClass(this._node, 'slide distant-slide');
} }
this._makeCounter(); this._makeCounter();
this._makeBuildList(); this._makeBuildList();
}; };
Slide.prototype = { Slide.prototype = {
_node: null, _node: null,
_count: 0, _count: 0,
_buildList: [], _buildList: [],
_visited: false, _visited: false,
_currentState: '', _currentState: '',
_states: [ 'distant-slide', 'far-past', _states: [ 'distant-slide', 'far-past',
'past', 'current', 'future', 'past', 'current', 'future',
'far-future', 'distant-slide' ], 'far-future', 'distant-slide' ],
setState: function(state) { setState: function (state) {
if (typeof state != 'string') { if (typeof state !== 'string') {
state = this._states[state]; state = this._states[state];
} }
if (state == 'current' && !this._visited) { if (state === 'current' && !this._visited) {
this._visited = true; this._visited = true;
this._makeBuildList(); this._makeBuildList();
} }
removeClass(this._node, this._states); removeClass(this._node, this._states);
addClass(this._node, state); addClass(this._node, state);
this._currentState = state; this._currentState = state;
// delay first auto run. Really wish this were in CSS. // delay first auto run. Really wish this were in CSS.
/* /*
this._runAutos(); this._runAutos();
*/ */
var _t = this; var _t = this;
setTimeout(function(){ _t._runAutos(); } , 400); setTimeout(function () { _t._runAutos(); }, 400);
}, },
_makeCounter: function() { _makeCounter: function () {
if(!this._count || !this._node) { return; } if (!this._count || !this._node) { return; }
var c = doc.createElement('span'); var c = doc.createElement('span');
c.innerHTML = this._count; c.innerHTML = this._count;
c.className = 'counter'; c.className = 'counter';
this._node.appendChild(c); this._node.appendChild(c);
}, },
_makeBuildList: function() { _makeBuildList: function () {
this._buildList = []; this._buildList = [];
if (disableBuilds) { return; } if (disableBuilds) { return; }
if (this._node) { if (this._node) {
this._buildList = query('[data-build] > *', this._node); this._buildList = query('[data-build] > *', this._node);
} }
this._buildList.forEach(function(el) { this._buildList.forEach(function (el) {
addClass(el, 'to-build'); addClass(el, 'to-build');
}); });
}, },
_runAutos: function() { _runAutos: function () {
if (this._currentState != 'current') { if (this._currentState !== 'current') {
return; return;
} }
// find the next auto, slice it out of the list, and run it // find the next auto, slice it out of the list, and run it
var idx = -1; var idx = -1;
this._buildList.some(function(n, i) { this._buildList.some(function (n, i) {
if (n.hasAttribute('data-auto')) { if (n.hasAttribute('data-auto')) {
idx = i; idx = i;
return true; return true;
} }
return false; return false;
}); });
if (idx >= 0) { if (idx >= 0) {
var elem = this._buildList.splice(idx, 1)[0]; var elem = this._buildList.splice(idx, 1)[0];
var transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd'); var transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd');
var _t = this; var _t = this;
if (canTransition()) { if (canTransition()) {
var l = function(evt) { var l = function (evt) {
elem.parentNode.removeEventListener(transitionEnd, l, false); elem.parentNode.removeEventListener(transitionEnd, l, false);
_t._runAutos(); _t._runAutos();
}; };
elem.parentNode.addEventListener(transitionEnd, l, false); elem.parentNode.addEventListener(transitionEnd, l, false);
removeClass(elem, 'to-build'); removeClass(elem, 'to-build');
} else { } else {
setTimeout(function() { setTimeout(function () {
removeClass(elem, 'to-build'); removeClass(elem, 'to-build');
_t._runAutos(); _t._runAutos();
}, 400); }, 400);
} }
} }
}, },
buildNext: function() { buildNext: function () {
if (!this._buildList.length) { if (!this._buildList.length) {
return false; return false;
} }
removeClass(this._buildList.shift(), 'to-build'); removeClass(this._buildList.shift(), 'to-build');
return true; return true;
}, }
}; };
// //
// SlideShow class // SlideShow class
// //
var SlideShow = function(slides) { var SlideShow = function (slides) {
this._slides = (slides || []).map(function(el, idx) { this._slides = (slides || []).map(function (el, idx) {
return new Slide(el, idx); return new Slide(el, idx);
}); });
var h = window.location.hash; var h = window.location.hash;
try { try {
this.current = parseInt(h.split('#slide')[1], 10); this.current = parseInt(h.split('#slide')[1], 10);
}catch (e) { /* squeltch */ } } catch (e) { /* squeltch */ }
this.current = isNaN(this.current) ? 1 : this.current; this.current = isNaN(this.current) ? 1 : this.current;
var _t = this; var _t = this;
doc.addEventListener('keydown', doc.addEventListener('keydown',
function(e) { _t.handleKeys(e); }, false); function (e) { _t.handleKeys(e); }, false);
doc.addEventListener('mousewheel', doc.addEventListener('mousewheel',
function(e) { _t.handleWheel(e); }, false); function (e) { _t.handleWheel(e); }, false);
doc.addEventListener('DOMMouseScroll', doc.addEventListener('DOMMouseScroll',
function(e) { _t.handleWheel(e); }, false); function (e) { _t.handleWheel(e); }, false);
doc.addEventListener('touchstart', doc.addEventListener('touchstart',
function(e) { _t.handleTouchStart(e); }, false); function (e) { _t.handleTouchStart(e); }, false);
doc.addEventListener('touchend', doc.addEventListener('touchend',
function(e) { _t.handleTouchEnd(e); }, false); function (e) { _t.handleTouchEnd(e); }, false);
window.addEventListener('popstate', window.addEventListener('popstate',
function(e) { _t.go(e.state); }, false); function (e) { _t.go(e.state); }, false);
this._update(); this._update();
}; };
SlideShow.prototype = { SlideShow.prototype = {
_slides: [], _slides: [],
_update: function(dontPush) { _update: function (dontPush) {
document.querySelector('#presentation-counter').innerText = this.current; document.querySelector('#presentation-counter').innerText = this.current;
if (history.pushState) { if (history.pushState) {
if (!dontPush) { if (!dontPush) {
history.pushState(this.current, 'Slide ' + this.current, '#slide' + this.current); history.pushState(this.current, 'Slide ' + this.current, '#slide' + this.current);
} }
} else { } else {
window.location.hash = 'slide' + this.current; window.location.hash = 'slide' + this.current;
} }
for (var x = this.current-1; x < this.current + 7; x++) { for (var x = this.current - 1; x < this.current + 7; x++) {
if (this._slides[x-4]) { if (this._slides[x - 4]) {
this._slides[x-4].setState(Math.max(0, x-this.current)); this._slides[x - 4].setState(Math.max(0, x - this.current));
} }
} }
}, },
current: 0, current: 0,
next: function() { next: function () {
if (!this._slides[this.current-1].buildNext()) { if (!this._slides[this.current - 1].buildNext()) {
this.current = Math.min(this.current + 1, this._slides.length); this.current = Math.min(this.current + 1, this._slides.length);
this._update(); this._update();
} }
}, },
prev: function() { prev: function () {
this.current = Math.max(this.current-1, 1); this.current = Math.max(this.current - 1, 1);
this._update(); this._update();
}, },
go: function(num) { go: function (num) {
if (history.pushState && this.current != num) { if (history.pushState && this.current !== num) {
history.replaceState(this.current, 'Slide ' + this.current, '#slide' + this.current); history.replaceState(this.current, 'Slide ' + this.current, '#slide' + this.current);
} }
this.current = num; this.current = num;
this._update(true); this._update(true);
}, },
_notesOn: false, _notesOn: false,
showNotes: function() { showNotes: function () {
var isOn = this._notesOn = !this._notesOn; var notesOn = this._notesOn = !this._notesOn;
query('.notes').forEach(function(el) { query('.notes').forEach(function (el) {
el.style.display = (notesOn) ? 'block' : 'none'; el.style.display = (notesOn) ? 'block' : 'none';
}); });
}, },
switch3D: function() { switch3D: function () {
toggleClass(document.body, 'three-d'); toggleClass(document.body, 'three-d');
}, },
handleWheel: function(e) { handleWheel: function (e) {
var delta = 0; var delta = 0;
if (e.wheelDelta) { if (e.wheelDelta) {
delta = e.wheelDelta/120; delta = e.wheelDelta / 120;
if (isOpera) { if (isOpera) {
delta = -delta; delta = -delta;
} }
} else if (e.detail) { } else if (e.detail) {
delta = -e.detail/3; delta = -e.detail / 3;
} }
if (delta > 0 ) { if (delta > 0) {
this.prev(); this.prev();
return; return;
} }
if (delta < 0 ) { if (delta < 0) {
this.next(); this.next();
return; }
} },
}, handleKeys: function (e) {
handleKeys: function(e) { if (/^(input|textarea)$/i.test(e.target.nodeName)) return;
if (/^(input|textarea)$/i.test(e.target.nodeName)) return; switch (e.keyCode) {
case 37: // left arrow
this.prev(); break;
case 39: // right arrow
case 32: // space
this.next(); break;
case 50: // 2
this.showNotes(); break;
case 51: // 3
this.switch3D(); break;
}
},
_touchStartX: 0,
handleTouchStart: function (e) {
this._touchStartX = e.touches[0].pageX;
},
handleTouchEnd: function (e) {
var delta = this._touchStartX - e.changedTouches[0].pageX;
var SWIPE_SIZE = 150;
if (delta > SWIPE_SIZE) {
this.next();
} else if (delta < -SWIPE_SIZE) {
this.prev();
}
}
};
switch (e.keyCode) { // Initialize
case 37: // left arrow var slideshow = new SlideShow(query('.slide')); // eslint-disable-line no-unused-vars
this.prev(); break;
case 39: // right arrow
case 32: // space
this.next(); break;
case 50: // 2
this.showNotes(); break;
case 51: // 3
this.switch3D(); break;
}
},
_touchStartX: 0,
handleTouchStart: function(e) {
this._touchStartX = e.touches[0].pageX;
},
handleTouchEnd: function(e) {
var delta = this._touchStartX - e.changedTouches[0].pageX;
var SWIPE_SIZE = 150;
if (delta > SWIPE_SIZE) {
this.next();
} else if (delta< -SWIPE_SIZE) {
this.prev();
}
},
};
// Initialize document.querySelector('#toggle-counter').addEventListener('click', toggleCounter, false);
var slideshow = new SlideShow(query('.slide')); document.querySelector('#toggle-size').addEventListener('click', toggleSize, false);
document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions, false);
document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients, false);
var counters = document.querySelectorAll('.counter');
var slides = document.querySelectorAll('.slide');
function toggleCounter () {
toArray(counters).forEach(function (el) {
el.style.display = (el.offsetHeight) ? 'none' : 'block';
});
}
function toggleSize () {
toArray(slides).forEach(function (el) {
if (!/reduced/.test(el.className)) {
addClass(el, 'reduced');
} else {
removeClass(el, 'reduced');
}
});
}
function toggleTransitions () {
toArray(slides).forEach(function (el) {
if (!/no-transitions/.test(el.className)) {
addClass(el, 'no-transitions');
} else {
removeClass(el, 'no-transitions');
}
});
}
document.querySelector('#toggle-counter').addEventListener('click', toggleCounter, false); function toggleGradients () {
document.querySelector('#toggle-size').addEventListener('click', toggleSize, false); toArray(slides).forEach(function (el) {
document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions, false); if (!/no-gradients/.test(el.className)) {
document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients, false); addClass(el, 'no-gradients');
} else {
removeClass(el, 'no-gradients');
var counters = document.querySelectorAll('.counter'); }
var slides = document.querySelectorAll('.slide'); });
}
function toggleCounter() { })();
toArray(counters).forEach(function(el) {
el.style.display = (el.offsetHeight) ? 'none' : 'block';
});
}
function toggleSize() {
toArray(slides).forEach(function(el) {
if (!/reduced/.test(el.className)) {
addClass(el, 'reduced');
}
else {
removeClass(el, 'reduced');
}
});
}
function toggleTransitions() {
toArray(slides).forEach(function(el) {
if (!/no-transitions/.test(el.className)) {
addClass(el, 'no-transitions');
}
else {
removeClass(el, 'no-transitions');
}
});
}
function toggleGradients() {
toArray(slides).forEach(function(el) {
if (!/no-gradients/.test(el.className)) {
addClass(el, 'no-gradients');
}
else {
removeClass(el, 'no-gradients');
}
});
}
})();

View File

@@ -1,147 +1,138 @@
/* eslint-disable no-var */
/* globals wave, $, svgCanvas */
var shapetime = {}; var shapetime = {};
var nodelete = false; var nodelete = false;
function stateUpdated() { function stateUpdated () {
// 'state' is an object of key-value pairs that map ids to JSON serialization of SVG elements
// 'keys' is an array of all the keys in the state
var state = wave.getState();
var keys = state.getKeys();
svgCanvas.each(function (e) {
// 'this' is the SVG DOM element node (ellipse, rect, etc)
// 'e' is an integer describing the position within the document
var k = this.id;
var v = state.get(k);
if (k === 'selectorParentGroup' || k === 'svgcontent') {
// meh
} else if (v) {
var ob = JSON.parse(v);
if (ob) {
// do nothing
} else {
// var node = document.getElementById(k);
// if (node) node.parentNode.removeChild(node);
}
// keys.remove(k);
} else if (!nodelete) {
this.parentNode.removeChild(this);
}
});
// 'state' is an object of key-value pairs that map ids to JSON serialization of SVG elements // New nodes
// 'keys' is an array of all the keys in the state for (var k in keys) {
var state = wave.getState(); var v = state.get(keys[k]);
var keys = state.getKeys(); var ob = JSON.parse(v);
svgCanvas.each(function(e) { if (ob) {
// 'this' is the SVG DOM element node (ellipse, rect, etc) if (!shapetime[k] || ob.time > shapetime[k]) {
// 'e' is an integer describing the position within the document var a = document.getElementById(k);
var k = this.id; if (a) {
var v = state.get(k); var attrs = getAttrs(a);
if(k == "selectorParentGroup" || k == "svgcontent"){ if (JSON.stringify(attrs) !== JSON.stringify(ob.attr)) {
//meh shapetime[k] = ob.time;
}else if (v) { svgCanvas.updateElementFromJson(ob);
var ob = JSON.parse(v); }
if (ob) { } else {
// do nothing shapetime[k] = ob.time;
} else { svgCanvas.updateElementFromJson(ob);
//var node = document.getElementById(k); }
//if (node) node.parentNode.removeChild(node); }
} }
//keys.remove(k); }
} else if(!nodelete){
this.parentNode.removeChild(this);
}
});
// New nodes
for (var k in keys) {
var v = state.get(keys[k]);
var ob = JSON.parse(v);
if (ob){
if(!shapetime[k] || ob.time > shapetime[k]){
var a;
if(a = document.getElementById(k)){
var attrs = get_attrs(a);
if(JSON.stringify(attrs) != JSON.stringify(ob.attr)){
shapetime[k] = ob.time
svgCanvas.updateElementFromJson(ob)
}
}else{
shapetime[k] = ob.time
svgCanvas.updateElementFromJson(ob)
}
}
}
}
} }
function getId (canvas, objnum) {
function getId(canvas, objnum) { var id = wave.getViewer().getId().split('@')[0];
var id = wave.getViewer().getId().split("@")[0]; var extra = SHA256(wave.getViewer().getId()); // in case the next step kills all the characters
var extra = SHA256(wave.getViewer().getId()); //in case the next step kills all the characters for (var i = 0, l = id.length, n = ''; i < l; i++) {
for(var i = 0, l = id.length, n = ""; i < l; i++){ if ('abcdefghijklmnopqrstuvwxyz0123456789'.indexOf(id[i]) > -1) {
if("abcdefghijklmnopqrstuvwxyz0123456789".indexOf(id[i]) != -1){ n += id[i];
n+=id[i]; }
} }
} return 'svg_' + n + '_' + extra.substr(0, 5) + '_' + objnum;
return "svg_"+n+"_"+extra.substr(0,5)+"_"+objnum;
} }
function get_attrs(a){ function getAttrs (a) {
var attrs = {}; var attrs = {};
for(var i = a.length; i--;){ for (var i = a.length; i--;) {
var attr = a.item(i).nodeName; var attr = a.item(i).nodeName;
if(",style,".indexOf(","+attr+",") == -1){ if (',style,'.indexOf(',' + attr + ',') === -1) {
attrs[attr] = a.item(i).nodeValue; attrs[attr] = a.item(i).nodeValue;
} }
} }
return attrs return attrs;
} }
function main() { function main () {
$(document).ready(function(){ $(document).ready(function () {
if (wave && wave.isInWaveContainer()) { if (wave && wave.isInWaveContainer()) {
wave.setStateCallback(function(){setTimeout(stateUpdated,10)}); wave.setStateCallback(function () {
} setTimeout(stateUpdated, 10);
});
var oldchanged = svgCanvas.bind("changed", function(canvas, elem){ }
if(oldchanged)oldchanged.apply(this, [canvas,elem]);
var oldchanged = svgCanvas.bind('changed', function (canvas, elem) {
var delta = {} if (oldchanged) oldchanged.apply(this, [canvas, elem]);
$.each(elem, function(){
var delta = {};
var attrs = {}; $.each(elem, function () {
var a = this.attributes; var a = this.attributes;
if(a){ if (a) {
var attrs = get_attrs(a) var attrs = getAttrs(a);
var ob = {element: this.nodeName, attr: attrs}; var ob = {element: this.nodeName, attr: attrs};
ob.time = shapetime[this.id] = (new Date).getTime() ob.time = shapetime[this.id] = new Date().getTime();
delta[this.id] = JSON.stringify(ob); delta[this.id] = JSON.stringify(ob);
} }
}) });
wave.getState().submitDelta(delta) wave.getState().submitDelta(delta);
//sendDelta(canvas, elem) // sendDelta(canvas, elem)
});
}); // *
//* var oldselected = svgCanvas.bind('selected', function (canvas, elem) {
if (oldselected) oldselected.apply(this, [canvas, elem]);
var oldselected = svgCanvas.bind("selected", function(canvas, elem){
var delta = {};
if(oldselected)oldselected.apply(this, [canvas,elem]); var deletions = 0;
$.each(elem, function () {
if (!this.parentNode && this !== window) {
var delta = {} delta[this.id] = null;
var deletions = 0; deletions++;
$.each(elem, function(){ }
if(!this.parentNode && this != window){ });
delta[this.id] = null; if (deletions > 0) {
deletions ++ wave.getState().submitDelta(delta);
} }
}); });
if(deletions > 0){ //
wave.getState().submitDelta(delta) svgCanvas.bind('cleared', function () {
} // alert("cleared")
}); var state = {}, keys = wave.getState().getKeys();
/// for (var i = 0; i < keys.length; i++) {
svgCanvas.bind("cleared", function(){ state[keys[i]] = null;
//alert("cleared") }
var state = {}, keys = wave.getState().getKeys() wave.getState().submitDelta(state);
for(var i = 0; i < keys.length; i++){ });
state[keys[i]] = null; // */
} svgCanvas.bind('getid', getId);
wave.getState().submitDelta(state) });
});
//*/
svgCanvas.bind("getid", getId);
})
} }
if (window.gadgets) window.gadgets.util.registerOnLoadHandler(main);
// $(main)
if(window.gadgets) gadgets.util.registerOnLoadHandler(main); /* eslint-disable */
// and why not use my stuff?
//$(main)
//and why not use my stuff?
function SHA256(b){function h(j,k){return(j>>e)+(k>>e)+((p=(j&o)+(k&o))>>e)<<e|p&o}function f(j,k){return j>>>k|j<<32-k}var g=[],d,c=3,l=[2],p,i,q,a,m=[],n=[];i=b.length*8;for(var e=16,o=65535,r="";c<312;c++){for(d=l.length;d--&&c%l[d]!=0;);d<0&&l.push(c)}b+="\u0080";for(c=0;c<=i;c+=8)n[c>>5]|=(b.charCodeAt(c/8)&255)<<24-c%32;n[(i+64>>9<<4)+15]=i;for(c=8;c--;)m[c]=parseInt(Math.pow(l[c],0.5).toString(e).substr(2,8),e);for(c=0;c<n.length;c+=e){a=m.slice(0);for(b=0;b<64;b++){g[b]=b<e?n[b+c]:h(h(h(f(g[b-2],17)^f(g[b-2],19)^g[b-2]>>>10,g[b-7]),f(g[b-15],7)^f(g[b-15],18)^g[b-15]>>>3),g[b-e]);i=h(h(h(h(a[7],f(a[4],6)^f(a[4],11)^f(a[4],25)),a[4]&a[5]^~a[4]&a[6]),parseInt(Math.pow(l[b],1/3).toString(e).substr(2,8),e)),g[b]);q=(f(a[0],2)^f(a[0],13)^f(a[0],22))+(a[0]&a[1]^a[0]&a[2]^a[1]&a[2]);for(d=8;--d;)a[d]=d==4?h(a[3],i):a[d-1];a[0]=h(i,q)}for(d=8;d--;)m[d]+=a[d]}for(c=0;c<8;c++)for(b=8;b--;)r+=(m[c]>>>b*4&15).toString(e);return r} function SHA256(b){function h(j,k){return(j>>e)+(k>>e)+((p=(j&o)+(k&o))>>e)<<e|p&o}function f(j,k){return j>>>k|j<<32-k}var g=[],d,c=3,l=[2],p,i,q,a,m=[],n=[];i=b.length*8;for(var e=16,o=65535,r="";c<312;c++){for(d=l.length;d--&&c%l[d]!=0;);d<0&&l.push(c)}b+="\u0080";for(c=0;c<=i;c+=8)n[c>>5]|=(b.charCodeAt(c/8)&255)<<24-c%32;n[(i+64>>9<<4)+15]=i;for(c=8;c--;)m[c]=parseInt(Math.pow(l[c],0.5).toString(e).substr(2,8),e);for(c=0;c<n.length;c+=e){a=m.slice(0);for(b=0;b<64;b++){g[b]=b<e?n[b+c]:h(h(h(f(g[b-2],17)^f(g[b-2],19)^g[b-2]>>>10,g[b-7]),f(g[b-15],7)^f(g[b-15],18)^g[b-15]>>>3),g[b-e]);i=h(h(h(h(a[7],f(a[4],6)^f(a[4],11)^f(a[4],25)),a[4]&a[5]^~a[4]&a[6]),parseInt(Math.pow(l[b],1/3).toString(e).substr(2,8),e)),g[b]);q=(f(a[0],2)^f(a[0],13)^f(a[0],22))+(a[0]&a[1]^a[0]&a[2]^a[1]&a[2]);for(d=8;--d;)a[d]=d==4?h(a[3],i):a[d-1];a[0]=h(i,q)}for(d=8;d--;)m[d]+=a[d]}for(c=0;c<8;c++)for(b=8;b--;)r+=(m[c]>>>b*4&15).toString(e);return r}