var parser = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
function parseUri(str) {
var m = parser.exec(str);
var uri = {};
var i = 14;
while (i--) {
var key = keys[i];
var value = m[i] || "";
var encoded = ['user', 'password'].indexOf(key) !== -1;
- // if setTimeout wasn't available but was latter defined
- if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
- cachedSetTimeout = setTimeout;
- return setTimeout(fun, 0);
+
+ for (var i = 0; i < strArray.length; i++) {
+ var component = strArray[i];
+
+ if (typeof component !== 'string') {
+ throw new TypeError('Url must be a string. Received ' + component);
+ }
+
+ if (component === '') { continue; }
+
+ if (i > 0) {
+ // Removing the starting slashes for each component but the first.
+ component = component.replace(/^[\/]+/, '');
+ }
+ if (i < strArray.length - 1) {
+ // Removing the ending slashes for each component but the last.
+ component = component.replace(/[\/]+$/, '');
+ } else {
+ // For the last component we will combine multiple slashes to a single one.
+ component = component.replace(/[\/]+$/, '/');
+ }
+
+ resultArray.push(component);
+
}
- try {
- // when when somebody has screwed with setTimeout but no I.E. maddness
- return cachedSetTimeout(fun, 0);
- } catch(e){
- try {
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
- return cachedSetTimeout.call(null, fun, 0);
- } catch(e){
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
- return cachedSetTimeout.call(this, fun, 0);
- }
+
+ var str = resultArray.join('/');
+ // Each input component is now separated by a single slash except the possible first plain protocol part.
+
+ // remove trailing slash before parameters or hash
- // if clearTimeout wasn't available but was latter defined
- if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
- cachedClearTimeout = clearTimeout;
- return clearTimeout(marker);
- }
- try {
- // when when somebody has screwed with setTimeout but no I.E. maddness
- return cachedClearTimeout(marker);
- } catch (e){
- try {
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
- return cachedClearTimeout.call(null, marker);
- } catch (e){
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
- // Some versions of I.E. have different rules for clearTimeout vs setTimeout
- return cachedClearTimeout.call(this, marker);
- }
- }
+ for (var i = 0; i < rules.length; i++) {
+ var ins = rules[i];
+ if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase();
// , noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in config.js or in the URL
});
// OTHER CONFIG
svgEditor.setConfig({
// canvasName: 'default',
canvas_expansion: 1,
initFill: {
color: 'FFFFFF', // solid white
opacity: 0
},
initStroke: {
width: 3,
color: '000000', // solid black
// opacity: 1
},
// initOpacity: 1,
// colorPickerCSS: null,
// initTool: 'select',
// exportWindowType: 'new', // 'same'
wireframe: false,
showlayers: false,
// no_save_warning: false,
// PATH CONFIGURATION
// imgPath: 'images/',
// langPath: 'locale/',
// extPath: 'extensions/',
// jGraduatePath: 'jgraduate/images/',
/*
Uncomment the following to allow at least same domain (embedded) access,
including file:// access.
Setting as `['*']` would allow any domain to access but would be unsafe to
data privacy and integrity.
*/
// allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL
// DOCUMENT PROPERTIES
dimensions: [777, 666],
// EDITOR OPTIONS
// gridSnapping: false,
// gridColor: '#000',
// baseUnit: 'px',
// snappingStep: 10,
showRulers: false,
// EXTENSION-RELATED (GRID)
// showGrid: false, // Set by ext-grid.js
// EXTENSION-RELATED (STORAGE)
// noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage
// forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not
// emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store
});
// PREF CHANGES
/**
setConfig() can also be used to set preferences in addition to
configuration (see defaultPrefs in svg-editor.js for a list of
possible settings), but at least if you are using ext-storage.js
to store preferences, it will probably be better to let your
users control these.
As with configuration, one may use allowInitialUserOverride, but
in the case of preferences, any previously stored preferences
will also thereby be enabled to override this setting (and at a
higher priority than any URL preference setting overrides).
Failing to use allowInitialUserOverride will ensure preferences
are hard-coded here regardless of URL or prior user storage setting.
*/
svgEditor.setConfig(
{
// lang: '', // Set dynamically within locale.js if not previously set
// iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise
/**
* When showing the preferences dialog, svg-editor.js currently relies
* on curPrefs instead of $.pref, so allowing an override for bkgd_color
* means that this value won't have priority over block auto-detection as
* far as determining which color shows initially in the preferences
* dialog (though it can be changed and saved).
*/
bkgd_color: 'transparent',
bkgd_url: '',
// img_save: 'embed',
// Only shows in UI as far as alert notices
// save_notice_done: false,
// export_notice_done: false
}
);
svgEditor.setConfig(
{
// Indicate pref settings here if you wish to allow user storage or URL settings
// to be able to override your default preferences (unless other config options
// have already explicitly prevented one or the other)
editor.tool_scale = 1; // Dependent on icon size, so any use to making configurable instead? Used by JQuerySpinBtn.js
editor.exportWindowCt = 0;
editor.langChanged = false;
editor.showSaveWarning = false;
editor.storagePromptClosed = false; // For use with ext-storage.js
var svgCanvas, urldata,
Utils = svgedit.utilities,
isReady = false,
customExportImage = false,
customExportPDF = false,
callbacks = [],
/**
* PREFS AND CONFIG
*/
// The iteration algorithm for defaultPrefs does not currently support array/objects
defaultPrefs = {
// EDITOR OPTIONS (DIALOG)
lang: '', // Default to "en" if locale.js detection does not detect another language
iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise
bkgd_color: '#FFF',
bkgd_url: '',
// DOCUMENT PROPERTIES (DIALOG)
img_save: 'embed',
// ALERT NOTICES
// Only shows in UI as far as alert notices, but useful to remember, so keeping as pref
save_notice_done: false,
export_notice_done: false
},
curPrefs = {},
// Note: The difference between Prefs and Config is that Prefs
// can be changed in the UI and are stored in the browser,
// while config cannot
curConfig = {
// We do not put on defaultConfig to simplify object copying
// procedures (we obtain instead from defaultExtensions)
extensions: [],
/**
* Can use window.location.origin to indicate the current
* origin. Can contain a '*' to allow all domains or 'null' (as
* a string) to support all file:// URLs. Cannot be set by
* URL for security reasons (not safe, at least for
* privacy or data integrity of SVG content).
* Might have been fairly safe to allow
* `new URL(window.location.href).origin` by default but
* avoiding it ensures some more security that even third
* party apps on the same domain also cannot communicate
* with this app by default.
* For use with ext-xdomain-messaging.js
* @todo We might instead make as a user-facing preference.
*/
allowedOrigins: []
},
defaultExtensions = [
//'ext-overview_window.js',
//'ext-markers.js',
//'ext-connector.js',
//'ext-eyedropper.js',
//'ext-shapes.js',
//'ext-imagelib.js',
//'ext-grid.js',
//'ext-polygon.js',
//'ext-star.js',
//'ext-panning.js',
//'ext-storage.js'
],
defaultConfig = {
// Todo: svgcanvas.js also sets and checks: show_outside_canvas, selectNew; add here?
// Change the following to preferences and add pref controls to the UI (e.g., initTool, wireframe, showlayers)?
canvasName: 'default',
canvas_expansion: 3,
initFill: {
color: 'FF0000', // solid red
opacity: 1
},
initStroke: {
width: 5,
color: '000000', // solid black
opacity: 1
},
initOpacity: 1,
colorPickerCSS: null, // Defaults to 'left' with a position equal to that of the fill_color or stroke_color element minus 140, and a 'bottom' equal to 40
initTool: 'select',
exportWindowType: 'new', // 'same' (todo: also support 'download')
wireframe: false,
showlayers: false,
no_save_warning: true,
// PATH CONFIGURATION
// The following path configuration items are disallowed in the URL (as should any future path configurations)
imgPath: 'img/',
langPath: 'js/svg-edit/locale/',
extPath: 'js/svg-edit/extensions/',
jGraduatePath: 'jgraduate/images/',
// DOCUMENT PROPERTIES
// Change the following to a preference (already in the Document Properties dialog)?
dimensions: [640, 480],
// EDITOR OPTIONS
// Change the following to preferences (already in the Editor Options dialog)?
gridSnapping: false,
gridColor: '#000',
baseUnit: 'px',
snappingStep: 10,
showRulers: true,
// URL BEHAVIOR CONFIGURATION
preventAllURLConfig: false,
preventURLContentLoading: false,
// EXTENSION CONFIGURATION (see also preventAllURLConfig)
lockExtensions: false, // Disallowed in URL setting
noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in config.js or in the URL
// EXTENSION-RELATED (GRID)
showGrid: false, // Set by ext-grid.js
// EXTENSION-RELATED (STORAGE)
noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage
forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not
emptyStorageOnDecline: false // Used by ext-storage.js; empty any prior storage if the user declines to store
},
/**
* LOCALE
* @todo Can we remove now that we are always loading even English? (unless locale is set to null)
*/
uiStrings = editor.uiStrings = {
common: {
ok: 'OK',
cancel: 'Cancel',
key_up: 'Up',
key_down: 'Down',
key_backspace: 'Backspace',
key_del: 'Del'
},
// This is needed if the locale is English, since the locale strings are not read in that instance.
layers: {
layer: 'Layer'
},
notification: {
invalidAttrValGiven: 'Invalid value given',
noContentToFitTo: 'No content to fit to',
dupeLayerName: 'There is already a layer named that!',
enterUniqueLayerName: 'Please enter a unique layer name',
enterNewLayerName: 'Please enter the new layer name',
layerHasThatName: 'Layer already has that name',
QmoveElemsToLayer: 'Move selected elements to layer \'%s\'?',
QwantToClear: 'Do you want to clear the drawing?\nThis will also erase your undo history!',
QwantToOpen: 'Do you want to open a new file?\nThis will also erase your undo history!',
QerrorsRevertToSource: 'There were parsing errors in your SVG source.\nRevert back to original SVG source?',
QignoreSourceChanges: 'Ignore changes made to SVG source?',
featNotSupported: 'Feature not supported',
enterNewImgURL: 'Enter the new image URL',
defsFailOnSave: 'NOTE: Due to a bug in your browser, this image may appear wrong (missing gradients or elements). It will however appear correct once actually saved.',
loadingImage: 'Loading image, please wait...',
saveFromBrowser: 'Select \'Save As...\' in your browser to save this image as a %s file.',
noteTheseIssues: 'Also note the following issues: ',
unsavedChanges: 'There are unsaved changes.',
enterNewLinkURL: 'Enter the new hyperlink URL',
errorLoadingSVG: 'Error: Unable to load SVG data',
URLloadFail: 'Unable to load from URL',
retrieving: 'Retrieving \'%s\' ...'
}
};
function loadSvgString (str, callback) {
var success = svgCanvas.setSvgString(str) !== false;
// In the future, more options can be provided here
var saveOpts = {
'images': $.pref('img_save'),
'round_digits': 6
};
svgCanvas.save(saveOpts);
};
var clickExport = function() {
$.select('Select an image type for export: ', [
// See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support
// 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG'
'PNG',
'JPEG', 'BMP', 'WEBP', 'PDF'
], function (imgType) { // todo: replace hard-coded msg with uiStrings.notification.
// showSaveWarning is set to 'false' when the page is saved.
if (!curConfig.no_save_warning && editor.showSaveWarning) {
// Browser already asks question about closing the page
e.returnValue = uiStrings.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)