2014-06-01 21:29:54 +00:00
/*globals svgEditor:true, globalStorage, widget, svgedit, canvg, jQuery, $, DOMParser, FileReader */
2014-02-10 13:14:38 +00:00
/*jslint vars: true, eqeq: true, todo: true, forin: true, continue: true, regexp: true */
2010-01-31 07:11:57 +00:00
/ *
2009-11-25 13:51:42 +00:00
* svg - editor . js
*
2012-09-16 18:53:27 +00:00
* Licensed under the MIT License
2009-11-25 13:51:42 +00:00
*
2010-01-13 21:03:00 +00:00
* Copyright ( c ) 2010 Alexis Deveria
* Copyright ( c ) 2010 Pavol Rusnak
* Copyright ( c ) 2010 Jeff Schiller
2010-04-02 12:47:00 +00:00
* Copyright ( c ) 2010 Narendra Sisodiya
2014-02-18 23:57:49 +00:00
* Copyright ( c ) 2014 Brett Zamir
2009-11-25 13:51:42 +00:00
*
* /
2009-06-01 15:55:21 +00:00
2010-11-06 00:45:21 +00:00
// Dependencies:
2010-11-07 05:20:03 +00:00
// 1) units.js
2011-01-13 07:47:21 +00:00
// 2) browser.js
// 3) svgcanvas.js
2010-11-06 00:45:21 +00:00
2014-02-18 15:06:27 +00:00
/ *
2014-04-07 04:13:01 +00:00
TODOS
2014-02-18 15:06:27 +00:00
1. JSDoc
* /
( function ( ) {
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
if ( window . svgEditor ) {
return ;
}
2014-02-10 13:14:38 +00:00
window . svgEditor = ( function ( $ ) {
2014-02-18 15:06:27 +00:00
var editor = { } ;
// EDITOR PROPERTIES: (defined below)
// curPrefs, curConfig, canvas, storage, uiStrings
//
// STATE MAINTENANCE PROPERTIES
2014-02-18 23:57:49 +00:00
editor . tool _scale = 1 ; // Dependent on icon size, so any use to making configurable instead? Used by JQuerySpinBtn.js
2014-05-22 07:22:57 +00:00
editor . exportWindowCt = 0 ;
2014-02-18 15:06:27 +00:00
editor . langChanged = false ;
editor . showSaveWarning = false ;
editor . storagePromptClosed = false ; // For use with ext-storage.js
var svgCanvas , urldata ,
2014-02-19 01:37:21 +00:00
Utils = svgedit . utilities ,
2013-02-15 21:57:35 +00:00
isReady = false ,
2014-05-15 05:16:39 +00:00
customExportImage = false ,
2014-05-22 10:21:29 +00:00
customExportPDF = false ,
2014-02-18 15:06:27 +00:00
callbacks = [ ] ,
/ * *
* PREFS AND CONFIG
* /
// The iteration algorithm for defaultPrefs does not currently support array/objects
2013-02-15 13:38:55 +00:00
defaultPrefs = {
2014-02-18 15:06:27 +00:00
// 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
2013-02-15 13:38:55 +00:00
bkgd _color : '#FFF' ,
bkgd _url : '' ,
2014-02-18 15:06:27 +00:00
// 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
2010-03-11 21:07:13 +00:00
} ,
curPrefs = { } ,
2014-02-18 15:06:27 +00:00
// 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
2010-03-11 21:07:13 +00:00
curConfig = {
2014-02-18 15:06:27 +00:00
// We do not put on defaultConfig to simplify object copying
// procedures (we obtain instead from defaultExtensions)
2014-02-22 04:08:24 +00:00
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 : [ ]
2014-02-18 15:06:27 +00:00
} ,
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)?
2013-01-09 23:14:35 +00:00
canvasName : 'default' ,
2010-03-12 20:43:33 +00:00
canvas _expansion : 3 ,
initFill : {
2013-10-13 23:23:08 +00:00
color : 'FF0000' , // solid red
2010-03-12 20:43:33 +00:00
opacity : 1
} ,
initStroke : {
2010-03-18 14:37:09 +00:00
width : 5 ,
2013-10-13 23:23:08 +00:00
color : '000000' , // solid black
2010-03-12 20:43:33 +00:00
opacity : 1
} ,
2016-03-15 07:43:24 +00:00
text : {
stroke _width : 0 ,
font _size : 24 ,
font _family : 'serif'
} ,
2010-03-16 19:28:57 +00:00
initOpacity : 1 ,
2014-04-09 01:33:11 +00:00
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
2014-02-18 15:06:27 +00:00
initTool : 'select' ,
2014-05-22 07:22:57 +00:00
exportWindowType : 'new' , // 'same' (todo: also support 'download')
2014-02-18 15:06:27 +00:00
wireframe : false ,
showlayers : false ,
no _save _warning : false ,
// PATH CONFIGURATION
// The following path configuration items are disallowed in the URL (as should any future path configurations)
2010-03-16 19:28:57 +00:00
imgPath : 'images/' ,
langPath : 'locale/' ,
2010-03-24 20:13:13 +00:00
extPath : 'extensions/' ,
2010-07-27 20:25:50 +00:00
jGraduatePath : 'jgraduate/images/' ,
2014-02-18 15:06:27 +00:00
// 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)?
2010-09-10 13:23:31 +00:00
gridSnapping : false ,
2013-02-15 21:57:35 +00:00
gridColor : '#000' ,
2010-10-05 17:13:00 +00:00
baseUnit : 'px' ,
2010-10-01 18:59:12 +00:00
snappingStep : 10 ,
2014-02-18 15:06:27 +00:00
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
2010-03-12 20:43:33 +00:00
} ,
2014-02-18 15:06:27 +00:00
/ * *
* LOCALE
* @ todo Can we remove now that we are always loading even English ? ( unless locale is set to null )
* /
uiStrings = editor . uiStrings = {
2011-01-03 18:45:36 +00:00
common : {
2013-02-15 21:57:35 +00:00
ok : 'OK' ,
cancel : 'Cancel' ,
key _up : 'Up' ,
key _down : 'Down' ,
key _backspace : 'Backspace' ,
key _del : 'Del'
2011-01-03 18:45:36 +00:00
} ,
2011-01-16 20:25:57 +00:00
// This is needed if the locale is English, since the locale strings are not read in that instance.
layers : {
2013-02-15 21:57:35 +00:00
layer : 'Layer'
2011-01-16 20:25:57 +00:00
} ,
2011-01-03 18:45:36 +00:00
notification : {
2013-02-15 21:57:35 +00:00
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\' ...'
2011-01-03 18:45:36 +00:00
}
2014-02-18 15:06:27 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
function loadSvgString ( str , callback ) {
2014-02-10 13:14:38 +00:00
var success = svgCanvas . setSvgString ( str ) !== false ;
callback = callback || $ . noop ;
if ( success ) {
callback ( true ) ;
} else {
$ . alert ( uiStrings . notification . errorLoadingSVG , function ( ) {
callback ( false ) ;
} ) ;
}
}
2014-04-09 06:53:08 +00:00
2014-02-18 15:06:27 +00:00
/ * *
* EXPORTS
* /
2014-02-11 00:05:17 +00:00
/ * *
* Store and retrieve preferences
2014-02-11 00:05:59 +00:00
* @ param { string } key The preference name to be retrieved or set
2014-02-18 15:06:27 +00:00
* @ param { string } [ val ] The value . If the value supplied is missing or falsey , no change to the preference will be made .
* @ returns { string } If val is missing or falsey , the value of the previously stored preference will be returned .
* @ todo Can we change setting on the jQuery namespace ( onto editor ) to avoid conflicts ?
* @ todo Review whether any remaining existing direct references to
* getting curPrefs can be changed to use $ . pref ( ) getting to ensure
* defaultPrefs fallback ( also for sake of allowInitialUserOverride ) ; specifically , bkgd _color could be changed so that
* the pref dialog has a button to auto - calculate background , but otherwise uses $ . pref ( ) to be able to get default prefs
* or overridable settings
2014-02-11 00:05:17 +00:00
* /
2014-02-18 15:06:27 +00:00
$ . pref = function ( key , val ) {
2014-01-31 00:27:46 +00:00
if ( val ) {
curPrefs [ key ] = val ;
2014-02-18 15:06:27 +00:00
editor . curPrefs = curPrefs ; // Update exported value
return ;
2014-01-31 00:27:46 +00:00
}
2014-02-18 15:06:27 +00:00
return ( key in curPrefs ) ? curPrefs [ key ] : defaultPrefs [ key ] ;
} ;
/ * *
* EDITOR PUBLIC METHODS
2014-02-19 00:46:52 +00:00
* locale . js also adds "putLang" and "readLang" as editor methods
2014-02-18 15:06:27 +00:00
* @ todo Sort these methods per invocation order , ideally with init at the end
* @ todo Prevent execution until init executes if dependent on it ?
* /
/ * *
* Where permitted , sets canvas and / or defaultPrefs based on previous
* storage . This will override URL settings ( for security reasons ) but
* not config . js configuration ( unless initial user overriding is explicitly
* permitted there via allowInitialUserOverride ) .
* @ todo Split allowInitialUserOverride into allowOverrideByURL and
* allowOverrideByUserStorage so config . js can disallow some
* individual items for URL setting but allow for user storage AND / OR
* change URL setting so that it always uses a different namespace ,
* so it won ' t affect pre - existing user storage ( but then if users saves
* that , it will then be subject to tampering
* /
editor . loadContentAndPrefs = function ( ) {
if ( ! curConfig . forceStorage && ( curConfig . noStorageOnLoad || ! document . cookie . match ( /(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/ ) ) ) {
return ;
}
// LOAD CONTENT
2014-02-19 04:36:49 +00:00
if ( editor . storage && // Cookies do not have enough available memory to hold large documents
2014-02-18 15:06:27 +00:00
( curConfig . forceStorage || ( ! curConfig . noStorageOnLoad && document . cookie . match ( /(?:^|;\s*)store=prefsAndContent/ ) ) )
) {
var name = 'svgedit-' + curConfig . canvasName ;
2014-02-19 04:36:49 +00:00
var cached = editor . storage . getItem ( name ) ;
2014-02-18 15:06:27 +00:00
if ( cached ) {
editor . loadFromString ( cached ) ;
}
}
// LOAD PREFS
2014-02-19 04:36:49 +00:00
var key ;
2014-02-18 15:06:27 +00:00
for ( key in defaultPrefs ) {
if ( defaultPrefs . hasOwnProperty ( key ) ) { // It's our own config, so we don't need to iterate up the prototype chain
var storeKey = 'svg-edit-' + key ;
2014-02-19 04:36:49 +00:00
if ( editor . storage ) {
var val = editor . storage . getItem ( storeKey ) ;
2014-02-18 15:06:27 +00:00
if ( val ) {
defaultPrefs [ key ] = String ( val ) ; // Convert to string for FF (.value fails in Webkit)
}
}
else if ( window . widget ) {
defaultPrefs [ key ] = widget . preferenceForKey ( storeKey ) ;
}
else {
2014-02-19 01:37:21 +00:00
var result = document . cookie . match ( new RegExp ( '(?:^|;\\s*)' + Utils . preg _quote ( encodeURIComponent ( storeKey ) ) + '=([^;]+)' ) ) ;
2014-02-18 15:06:27 +00:00
defaultPrefs [ key ] = result ? decodeURIComponent ( result [ 1 ] ) : '' ;
}
2010-03-11 21:07:13 +00:00
}
2010-01-21 17:38:37 +00:00
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
/ * *
* Allows setting of preferences or configuration ( including extensions ) .
* @ param { object } opts The preferences or configuration ( including extensions )
* @ param { object } [ cfgCfg ] Describes configuration which applies to the particular batch of supplied options
* @ param { boolean } [ cfgCfg . allowInitialUserOverride = false ] Set to true if you wish
* to allow initial overriding of settings by the user via the URL
* ( if permitted ) or previously stored preferences ( if permitted ) ;
* note that it will be too late if you make such calls in extension
* code because the URL or preference storage settings will
* have already taken place .
* @ param { boolean } [ cfgCfg . overwrite = true ] Set to false if you wish to
* prevent the overwriting of prior - set preferences or configuration
* ( URL settings will always follow this requirement for security
* reasons , so config . js settings cannot be overridden unless it
* explicitly permits via "allowInitialUserOverride" but extension config
* can be overridden as they will run after URL settings ) . Should
* not be needed in config . js .
* /
editor . setConfig = function ( opts , cfgCfg ) {
cfgCfg = cfgCfg || { } ;
function extendOrAdd ( cfgObj , key , val ) {
if ( cfgObj [ key ] && typeof cfgObj [ key ] === 'object' ) {
$ . extend ( true , cfgObj [ key ] , val ) ;
}
else {
cfgObj [ key ] = val ;
}
return ;
}
2010-03-11 21:07:13 +00:00
$ . each ( opts , function ( key , val ) {
2014-02-18 15:06:27 +00:00
if ( opts . hasOwnProperty ( key ) ) {
// Only allow prefs defined in defaultPrefs
if ( defaultPrefs . hasOwnProperty ( key ) ) {
if ( cfgCfg . overwrite === false && (
curConfig . preventAllURLConfig ||
curPrefs . hasOwnProperty ( key )
) ) {
return ;
}
if ( cfgCfg . allowInitialUserOverride === true ) {
defaultPrefs [ key ] = val ;
}
else {
$ . pref ( key , val ) ;
}
}
2014-02-22 04:08:24 +00:00
else if ( [ 'extensions' , 'allowedOrigins' ] . indexOf ( key ) > - 1 ) {
2014-02-18 15:06:27 +00:00
if ( cfgCfg . overwrite === false &&
2014-02-22 04:08:24 +00:00
(
curConfig . preventAllURLConfig ||
key === 'allowedOrigins' ||
( key === 'extensions' && curConfig . lockExtensions )
)
2014-02-18 15:06:27 +00:00
) {
return ;
}
2014-02-22 04:08:24 +00:00
curConfig [ key ] = curConfig [ key ] . concat ( val ) ; // We will handle any dupes later
2014-02-18 15:06:27 +00:00
}
// Only allow other curConfig if defined in defaultConfig
else if ( defaultConfig . hasOwnProperty ( key ) ) {
if ( cfgCfg . overwrite === false && (
curConfig . preventAllURLConfig ||
curConfig . hasOwnProperty ( key )
) ) {
return ;
}
// Potentially overwriting of previously set config
if ( curConfig . hasOwnProperty ( key ) ) {
if ( cfgCfg . overwrite === false ) {
return ;
}
extendOrAdd ( curConfig , key , val ) ;
}
else {
if ( cfgCfg . allowInitialUserOverride === true ) {
extendOrAdd ( defaultConfig , key , val ) ;
}
else {
if ( defaultConfig [ key ] && typeof defaultConfig [ key ] === 'object' ) {
curConfig [ key ] = { } ;
$ . extend ( true , curConfig [ key ] , val ) ; // Merge properties recursively, e.g., on initFill, initStroke objects
}
else {
curConfig [ key ] = val ;
}
}
}
}
2010-02-12 20:29:59 +00:00
}
2010-03-11 21:07:13 +00:00
} ) ;
2014-02-18 15:06:27 +00:00
editor . curConfig = curConfig ; // Update exported value
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
/ * *
* @ param { object } opts Extension mechanisms may call setCustomHandlers with three functions : opts . open , opts . save , and opts . exportImage
* opts . open ' s responsibilities are :
* - invoke a file chooser dialog in 'open' mode
* - let user pick a SVG file
2014-05-08 03:47:14 +00:00
* - calls svgCanvas . setSvgString ( ) with the string contents of that file
2014-02-18 15:06:27 +00:00
* opts . save ' s responsibilities are :
* - accept the string contents of the current document
* - invoke a file chooser dialog in 'save' mode
* - save the file to location chosen by the user
* opts . exportImage ' s responsibilities ( with regard to the object it is supplied in its 2 nd argument ) are :
* - inform user of any issues supplied via the "issues" property
* - convert the "svg" property SVG string into an image for export ;
* utilize the properties "type" ( currently 'PNG' , 'JPEG' , 'BMP' ,
2014-04-08 05:13:54 +00:00
* 'WEBP' , 'PDF' ) , "mimeType" , and "quality" ( for 'JPEG' and 'WEBP'
2014-02-18 15:06:27 +00:00
* types ) to determine the proper output .
* /
editor . setCustomHandlers = function ( opts ) {
editor . ready ( function ( ) {
2013-02-15 21:57:35 +00:00
if ( opts . open ) {
2010-08-13 15:30:00 +00:00
$ ( '#tool_open > input[type="file"]' ) . remove ( ) ;
2010-07-16 15:46:54 +00:00
$ ( '#tool_open' ) . show ( ) ;
svgCanvas . open = opts . open ;
}
2013-02-15 21:57:35 +00:00
if ( opts . save ) {
2014-02-18 15:06:27 +00:00
editor . showSaveWarning = false ;
2013-02-15 21:57:35 +00:00
svgCanvas . bind ( 'saved' , opts . save ) ;
2010-07-16 15:46:54 +00:00
}
2014-04-07 23:31:00 +00:00
if ( opts . exportImage ) {
2014-05-22 01:30:42 +00:00
customExportImage = opts . exportImage ;
2014-06-01 21:29:54 +00:00
svgCanvas . bind ( 'exported' , customExportImage ) ; // canvg and our RGBColor will be available to the method
2014-05-22 10:21:29 +00:00
}
if ( opts . exportPDF ) {
customExportPDF = opts . exportPDF ;
2014-06-01 21:29:54 +00:00
svgCanvas . bind ( 'exportedPDF' , customExportPDF ) ; // jsPDF and our RGBColor will be available to the method
2010-07-16 15:46:54 +00:00
}
} ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . randomizeIds = function ( ) {
2013-02-15 13:38:55 +00:00
svgCanvas . randomizeIds ( arguments ) ;
} ;
2010-03-12 09:41:50 +00:00
2014-02-18 15:06:27 +00:00
editor . init = function ( ) {
2014-02-19 04:36:49 +00:00
// var host = location.hostname,
// onWeb = host && host.indexOf('.') >= 0;
// Some FF versions throw security errors here when directly accessing
try {
if ( 'localStorage' in window ) { // && onWeb removed so Webkit works locally
editor . storage = localStorage ;
}
} catch ( err ) { }
2014-02-18 15:06:27 +00:00
// Todo: Avoid var-defined functions and group functions together, etc. where possible
var good _langs = [ ] ;
$ ( '#lang_select option' ) . each ( function ( ) {
good _langs . push ( this . value ) ;
} ) ;
2010-09-22 19:09:21 +00:00
2014-02-18 15:06:27 +00:00
function setupCurPrefs ( ) {
curPrefs = $ . extend ( true , { } , defaultPrefs , curPrefs ) ; // Now safe to merge with priority for curPrefs in the event any are already set
// Export updated prefs
editor . curPrefs = curPrefs ;
}
function setupCurConfig ( ) {
curConfig = $ . extend ( true , { } , defaultConfig , curConfig ) ; // Now safe to merge with priority for curConfig in the event any are already set
2014-02-22 04:08:24 +00:00
// Now deal with extensions and other array config
2014-02-18 15:06:27 +00:00
if ( ! curConfig . noDefaultExtensions ) {
curConfig . extensions = curConfig . extensions . concat ( defaultExtensions ) ;
}
// ...and remove any dupes
2014-02-22 04:08:24 +00:00
$ . each ( [ 'extensions' , 'allowedOrigins' ] , function ( i , cfg ) {
curConfig [ cfg ] = $ . grep ( curConfig [ cfg ] , function ( n , i ) {
return i === curConfig [ cfg ] . indexOf ( n ) ;
} ) ;
2014-02-18 15:06:27 +00:00
} ) ;
// Export updated config
editor . curConfig = curConfig ;
}
2010-03-12 20:43:33 +00:00
( function ( ) {
// Load config/data from URL if given
2014-02-18 15:06:27 +00:00
var src , qstr ;
urldata = $ . deparam . querystring ( true ) ;
2013-02-15 21:57:35 +00:00
if ( ! $ . isEmptyObject ( urldata ) ) {
if ( urldata . dimensions ) {
2010-03-12 20:43:33 +00:00
urldata . dimensions = urldata . dimensions . split ( ',' ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( urldata . bkgd _color ) {
2010-03-16 19:28:57 +00:00
urldata . bkgd _color = '#' + urldata . bkgd _color ;
}
2014-01-31 08:23:27 +00:00
Potentially breaking change: Prevent setting of extPath via URL and prevent setting of cross-domain or cross-folder extensions via URL, i.e., if the extensions string possesses the character ":", "/", or, to be extra safe, "\", (issue #4 of mailing list post "Agenda for resolving security issues"). extPath and extensions can still be meaningfully set freely via setConfig calls, e.g., "svgCanvas.setConfig({extPath: ..., extensions: ...});" if made before Editor.init() is called in svg-editor.js (which is called on a jQuery ready (i.e., DOMContentLoaded) event). To avoid modifying svg-editor.html, one could build an extension which loaded its own scripts as done by the simple extFunc() function in svg-editor.js, but this would occur a little later (Should we export extFunc() for this usage?).
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2671 eee81c28-f429-11dd-99c0-75d572ba1ddd
2014-02-10 05:33:05 +00:00
if ( urldata . extensions ) {
// For security reasons, disallow cross-domain or cross-folder extensions via URL
urldata . extensions = urldata . extensions . match ( /[:\/\\]/ ) ? '' : urldata . extensions . split ( ',' ) ;
}
// Disallowing extension paths via URL for
2014-02-10 10:21:55 +00:00
// security reasons, even for same-domain
// ones given potential to interact in undesirable
// ways with other script resources
2014-02-18 15:06:27 +00:00
$ . each (
[
'extPath' , 'imgPath' ,
'langPath' , 'jGraduatePath'
] ,
function ( pathConfig ) {
if ( urldata [ pathConfig ] ) {
delete urldata [ pathConfig ] ;
}
}
) ;
2012-10-22 10:47:50 +00:00
2014-04-09 04:26:34 +00:00
editor . setConfig ( urldata , { overwrite : false } ) ; // Note: source and url (as with storagePrompt later) are not set on config but are used below
2014-02-18 15:06:27 +00:00
setupCurConfig ( ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
if ( ! curConfig . preventURLContentLoading ) {
src = urldata . source ;
qstr = $ . param . querystring ( ) ;
if ( ! src ) { // urldata.source may have been null if it ended with '='
if ( qstr . indexOf ( 'source=data:' ) >= 0 ) {
src = qstr . match ( /source=(data:[^&]*)/ ) [ 1 ] ;
}
2010-10-08 17:54:45 +00:00
}
2014-02-18 15:06:27 +00:00
if ( src ) {
if ( src . indexOf ( 'data:' ) === 0 ) {
editor . loadFromDataURI ( src ) ;
} else {
editor . loadFromString ( src ) ;
}
return ;
}
if ( urldata . url ) {
2014-02-18 23:57:49 +00:00
editor . loadFromURL ( urldata . url ) ;
2014-02-18 15:06:27 +00:00
return ;
2010-03-12 20:43:33 +00:00
}
}
2014-02-18 15:06:27 +00:00
if ( ! urldata . noStorageOnLoad || curConfig . forceStorage ) {
2014-02-18 23:57:49 +00:00
editor . loadContentAndPrefs ( ) ;
2013-01-09 23:14:35 +00:00
}
2014-02-18 15:06:27 +00:00
setupCurPrefs ( ) ;
}
else {
setupCurConfig ( ) ;
2014-02-18 23:57:49 +00:00
editor . loadContentAndPrefs ( ) ;
2014-02-18 15:06:27 +00:00
setupCurPrefs ( ) ;
2010-03-12 20:43:33 +00:00
}
2014-01-31 00:27:46 +00:00
} ( ) ) ;
2014-02-18 15:06:27 +00:00
var setIcon = editor . setIcon = function ( elem , icon _id , forcedSize ) {
2014-02-10 10:21:55 +00:00
var icon = ( typeof icon _id === 'string' ) ? $ . getSvgIcon ( icon _id , true ) : icon _id . clone ( ) ;
if ( ! icon ) {
console . log ( 'NOTE: Icon image missing: ' + icon _id ) ;
return ;
}
$ ( elem ) . empty ( ) . append ( icon ) ;
} ;
2010-03-29 18:06:51 +00:00
var extFunc = function ( ) {
$ . each ( curConfig . extensions , function ( ) {
2010-07-22 19:10:51 +00:00
var extname = this ;
2014-02-19 05:26:46 +00:00
if ( ! extname . match ( /^ext-.*\.js/ ) ) { // Ensure URL cannot specify some other unintended file in the extPath
return ;
}
2010-07-22 19:10:51 +00:00
$ . getScript ( curConfig . extPath + extname , function ( d ) {
// Fails locally in Chrome 5
2013-02-15 21:57:35 +00:00
if ( ! d ) {
2010-07-22 19:10:51 +00:00
var s = document . createElement ( 'script' ) ;
s . src = curConfig . extPath + extname ;
document . querySelector ( 'head' ) . appendChild ( s ) ;
}
} ) ;
2010-03-29 18:06:51 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
// var lang = ('lang' in curPrefs) ? curPrefs.lang : null;
2014-02-18 15:06:27 +00:00
editor . putLocale ( null , good _langs ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-03-24 20:13:13 +00:00
// Load extensions
2010-09-20 12:49:36 +00:00
// Bit of a hack to run extensions in local Opera/IE9
2013-02-15 21:57:35 +00:00
if ( document . location . protocol === 'file:' ) {
2010-09-20 12:49:36 +00:00
setTimeout ( extFunc , 100 ) ;
2010-03-29 18:06:51 +00:00
} else {
extFunc ( ) ;
}
2010-03-16 19:28:57 +00:00
$ . svgIcons ( curConfig . imgPath + 'svg_edit_icons.svg' , {
w : 24 , h : 24 ,
id _match : false ,
2013-02-15 13:38:55 +00:00
no _img : ! svgedit . browser . isWebkit ( ) , // Opera & Firefox 4 gives odd behavior w/images
2010-03-16 19:28:57 +00:00
fallback _path : curConfig . imgPath ,
2013-02-15 21:57:35 +00:00
fallback : {
'new_image' : 'clear.png' ,
'save' : 'save.png' ,
'open' : 'open.png' ,
'source' : 'source.png' ,
'docprops' : 'document-properties.png' ,
'wireframe' : 'wireframe.png' ,
'undo' : 'undo.png' ,
'redo' : 'redo.png' ,
'select' : 'select.png' ,
'select_node' : 'select_node.png' ,
'pencil' : 'fhpath.png' ,
'pen' : 'line.png' ,
'square' : 'square.png' ,
'rect' : 'rect.png' ,
'fh_rect' : 'freehand-square.png' ,
'circle' : 'circle.png' ,
'ellipse' : 'ellipse.png' ,
'fh_ellipse' : 'freehand-circle.png' ,
'path' : 'path.png' ,
'text' : 'text.png' ,
'image' : 'image.png' ,
'zoom' : 'zoom.png' ,
'clone' : 'clone.png' ,
'node_clone' : 'node_clone.png' ,
'delete' : 'delete.png' ,
'node_delete' : 'node_delete.png' ,
2014-02-11 02:03:54 +00:00
'group' : 'shape_group_elements.png' ,
2013-02-15 21:57:35 +00:00
'ungroup' : 'shape_ungroup.png' ,
'move_top' : 'move_top.png' ,
'move_bottom' : 'move_bottom.png' ,
'to_path' : 'to_path.png' ,
'link_controls' : 'link_controls.png' ,
'reorient' : 'reorient.png' ,
'align_left' : 'align-left.png' ,
'align_center' : 'align-center.png' ,
'align_right' : 'align-right.png' ,
'align_top' : 'align-top.png' ,
'align_middle' : 'align-middle.png' ,
'align_bottom' : 'align-bottom.png' ,
'go_up' : 'go-up.png' ,
'go_down' : 'go-down.png' ,
'ok' : 'save.png' ,
'cancel' : 'cancel.png' ,
'arrow_right' : 'flyouth.png' ,
'arrow_down' : 'dropdown.gif'
2010-03-16 19:28:57 +00:00
} ,
placement : {
2013-02-15 21:57:35 +00:00
'#logo' : 'logo' ,
'#tool_clear div,#layer_new' : 'new_image' ,
'#tool_save div' : 'save' ,
'#tool_export div' : 'export' ,
'#tool_open div div' : 'open' ,
'#tool_import div div' : 'import' ,
'#tool_source' : 'source' ,
'#tool_docprops > div' : 'docprops' ,
'#tool_wireframe' : 'wireframe' ,
'#tool_undo' : 'undo' ,
'#tool_redo' : 'redo' ,
'#tool_select' : 'select' ,
'#tool_fhpath' : 'pencil' ,
'#tool_line' : 'pen' ,
'#tool_rect,#tools_rect_show' : 'rect' ,
'#tool_square' : 'square' ,
'#tool_fhrect' : 'fh_rect' ,
'#tool_ellipse,#tools_ellipse_show' : 'ellipse' ,
'#tool_circle' : 'circle' ,
'#tool_fhellipse' : 'fh_ellipse' ,
'#tool_path' : 'path' ,
'#tool_text,#layer_rename' : 'text' ,
'#tool_image' : 'image' ,
'#tool_zoom' : 'zoom' ,
'#tool_clone,#tool_clone_multi' : 'clone' ,
'#tool_node_clone' : 'node_clone' ,
'#layer_delete,#tool_delete,#tool_delete_multi' : 'delete' ,
'#tool_node_delete' : 'node_delete' ,
'#tool_add_subpath' : 'add_subpath' ,
'#tool_openclose_path' : 'open_path' ,
'#tool_move_top' : 'move_top' ,
'#tool_move_bottom' : 'move_bottom' ,
'#tool_topath' : 'to_path' ,
'#tool_node_link' : 'link_controls' ,
'#tool_reorient' : 'reorient' ,
2014-02-11 01:58:57 +00:00
'#tool_group_elements' : 'group_elements' ,
2013-02-15 21:57:35 +00:00
'#tool_ungroup' : 'ungroup' ,
'#tool_unlink_use' : 'unlink_use' ,
'#tool_alignleft, #tool_posleft' : 'align_left' ,
'#tool_aligncenter, #tool_poscenter' : 'align_center' ,
'#tool_alignright, #tool_posright' : 'align_right' ,
'#tool_aligntop, #tool_postop' : 'align_top' ,
'#tool_alignmiddle, #tool_posmiddle' : 'align_middle' ,
'#tool_alignbottom, #tool_posbottom' : 'align_bottom' ,
'#cur_position' : 'align' ,
'#linecap_butt,#cur_linecap' : 'linecap_butt' ,
'#linecap_round' : 'linecap_round' ,
'#linecap_square' : 'linecap_square' ,
'#linejoin_miter,#cur_linejoin' : 'linejoin_miter' ,
'#linejoin_round' : 'linejoin_round' ,
'#linejoin_bevel' : 'linejoin_bevel' ,
'#url_notice' : 'warning' ,
'#layer_up' : 'go_up' ,
'#layer_down' : 'go_down' ,
'#layer_moreopts' : 'context_menu' ,
'#layerlist td.layervis' : 'eye' ,
'#tool_source_save,#tool_docprops_save,#tool_prefs_save' : 'ok' ,
'#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel' : 'cancel' ,
'#rwidthLabel, #iwidthLabel' : 'width' ,
'#rheightLabel, #iheightLabel' : 'height' ,
'#cornerRadiusLabel span' : 'c_radius' ,
'#angleLabel' : 'angle' ,
'#linkLabel,#tool_make_link,#tool_make_link_multi' : 'globe_link' ,
'#zoomLabel' : 'zoom' ,
2010-04-20 13:21:51 +00:00
'#tool_fill label' : 'fill' ,
'#tool_stroke .icon_label' : 'stroke' ,
'#group_opacityLabel' : 'opacity' ,
2010-04-20 15:53:19 +00:00
'#blurLabel' : 'blur' ,
'#font_sizeLabel' : 'fontsize' ,
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
'.flyout_arrow_horiz' : 'arrow_right' ,
'.dropdown button, #main_button .dropdown' : 'arrow_down' ,
'#palette .palette_item:first, #fill_bg, #stroke_bg' : 'no_color'
2010-03-16 19:28:57 +00:00
} ,
resize : {
2012-11-28 01:42:57 +00:00
'#logo .svg_icon' : 28 ,
2010-03-16 19:28:57 +00:00
'.flyout_arrow_horiz .svg_icon' : 5 ,
'.layer_button .svg_icon, #layerlist td.layervis .svg_icon' : 14 ,
'.dropdown button .svg_icon' : 7 ,
'#main_button .dropdown .svg_icon' : 9 ,
2012-11-28 01:42:57 +00:00
'.palette_item:first .svg_icon' : 15 ,
'#fill_bg .svg_icon, #stroke_bg .svg_icon' : 16 ,
2013-02-15 21:57:35 +00:00
'.toolbar_button button .svg_icon' : 16 ,
2010-04-20 13:21:51 +00:00
'.stroke_tool div div .svg_icon' : 20 ,
'#tools_bottom label .svg_icon' : 18
2010-03-16 19:28:57 +00:00
} ,
callback : function ( icons ) {
$ ( '.toolbar_button button > svg, .toolbar_button button > img' ) . each ( function ( ) {
$ ( this ) . parent ( ) . prepend ( this ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
var min _height ,
tleft = $ ( '#tools_left' ) ;
2013-02-15 21:57:35 +00:00
if ( tleft . length !== 0 ) {
2014-01-31 00:27:46 +00:00
min _height = tleft . offset ( ) . top + tleft . outerHeight ( ) ;
2010-07-14 19:15:44 +00:00
}
2014-02-18 15:06:27 +00:00
var size = $ . pref ( 'iconsize' ) ;
2014-02-18 23:57:49 +00:00
editor . setIconSize ( size || ( $ ( window ) . height ( ) < min _height ? 's' : 'm' ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-16 19:28:57 +00:00
// Look for any missing flyout icons from plugins
$ ( '.tools_flyout' ) . each ( function ( ) {
var shower = $ ( '#' + this . id + '_show' ) ;
var sel = shower . attr ( 'data-curopt' ) ;
// Check if there's an icon here
2013-02-15 21:57:35 +00:00
if ( ! shower . children ( 'svg, img' ) . length ) {
2010-03-16 19:28:57 +00:00
var clone = $ ( sel ) . children ( ) . clone ( ) ;
2013-02-15 21:57:35 +00:00
if ( clone . length ) {
2010-07-09 19:09:37 +00:00
clone [ 0 ] . removeAttribute ( 'style' ) ; //Needed for Opera
shower . append ( clone ) ;
}
2010-03-16 19:28:57 +00:00
}
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 23:57:49 +00:00
editor . runCallbacks ( ) ;
2012-10-22 10:47:50 +00:00
2010-10-04 16:01:58 +00:00
setTimeout ( function ( ) {
$ ( '.flyout_arrow_horiz:empty' ) . each ( function ( ) {
$ ( this ) . append ( $ . getSvgIcon ( 'arrow_right' ) . width ( 5 ) . height ( 5 ) ) ;
} ) ;
} , 1 ) ;
2010-03-16 19:28:57 +00:00
}
} ) ;
2010-03-12 20:43:33 +00:00
2014-02-18 15:06:27 +00:00
editor . canvas = svgCanvas = new $ . SvgCanvas ( document . getElementById ( 'svgcanvas' ) , curConfig ) ;
var supportsNonSS , resize _timer , changeZoom , Actions , curScrollPos ,
palette = [ // Todo: Make into configuration item?
'#000000' , '#3f3f3f' , '#7f7f7f' , '#bfbfbf' , '#ffffff' ,
'#ff0000' , '#ff7f00' , '#ffff00' , '#7fff00' ,
'#00ff00' , '#00ff7f' , '#00ffff' , '#007fff' ,
'#0000ff' , '#7f00ff' , '#ff00ff' , '#ff007f' ,
'#7f0000' , '#7f3f00' , '#7f7f00' , '#3f7f00' ,
'#007f00' , '#007f3f' , '#007f7f' , '#003f7f' ,
'#00007f' , '#3f007f' , '#7f007f' , '#7f003f' ,
'#ffaaaa' , '#ffd4aa' , '#ffffaa' , '#d4ffaa' ,
'#aaffaa' , '#aaffd4' , '#aaffff' , '#aad4ff' ,
'#aaaaff' , '#d4aaff' , '#ffaaff' , '#ffaad4'
2013-02-15 21:57:35 +00:00
] ,
2013-02-18 18:22:00 +00:00
modKey = ( svgedit . browser . isMac ( ) ? 'meta+' : 'ctrl+' ) , // ⌘
2010-03-11 21:07:13 +00:00
path = svgCanvas . pathActions ,
2010-06-21 18:06:21 +00:00
undoMgr = svgCanvas . undoMgr ,
2013-02-20 21:40:21 +00:00
defaultImageURL = curConfig . imgPath + 'logo.png' ,
2013-02-15 21:57:35 +00:00
workarea = $ ( '#workarea' ) ,
canv _menu = $ ( '#cmenu_canvas' ) ,
2014-02-18 15:06:27 +00:00
// layer_menu = $('#cmenu_layers'), // Unused
2012-10-22 10:47:50 +00:00
exportWindow = null ,
2010-09-27 18:58:04 +00:00
zoomInIcon = 'crosshair' ,
zoomOutIcon = 'crosshair' ,
2010-10-12 15:20:17 +00:00
ui _context = 'toolbars' ,
2013-02-15 22:07:05 +00:00
origSource = '' ,
2010-10-12 18:35:45 +00:00
paintBox = { fill : null , stroke : null } ;
2016-03-23 10:40:42 +00:00
// For external openers
( function ( ) {
// let the opener know SVG Edit is ready (now that config is set up)
var svgEditorReadyEvent ,
w = window . opener ;
if ( w ) {
try {
svgEditorReadyEvent = w . document . createEvent ( 'Event' ) ;
svgEditorReadyEvent . initEvent ( 'svgEditorReady' , true , true ) ;
w . document . documentElement . dispatchEvent ( svgEditorReadyEvent ) ;
}
catch ( e ) { }
}
} ( ) ) ;
2014-02-18 15:06:27 +00:00
2010-03-11 21:07:13 +00:00
// This sets up alternative dialog boxes. They mostly work the same way as
// their UI counterparts, expect instead of returning the result, a callback
// needs to be included that returns the result as its first parameter.
2012-10-22 10:47:50 +00:00
// In the future we may want to add additional types of dialog boxes, since
2010-03-11 21:07:13 +00:00
// they should be easy to handle this way.
( function ( ) {
2013-02-15 21:57:35 +00:00
$ ( '#dialog_container' ) . draggable ( { cancel : '#dialog_content, #dialog_buttons *' , containment : 'window' } ) ;
var box = $ ( '#dialog_box' ) ,
btn _holder = $ ( '#dialog_buttons' ) ,
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
dialog _content = $ ( '#dialog_content' ) ,
2014-02-18 15:06:27 +00:00
dbox = function ( type , msg , callback , defaultVal , opts , changeCb , checkbox ) {
var ok , ctrl , chkbx ;
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
dialog _content . html ( '<p>' + msg . replace ( /\n/g , '</p><p>' ) + '</p>' )
2013-02-19 15:00:56 +00:00
. toggleClass ( 'prompt' , ( type == 'prompt' ) ) ;
btn _holder . empty ( ) ;
2012-10-22 10:47:50 +00:00
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
ok = $ ( '<input type="button" value="' + uiStrings . common . ok + '">' ) . appendTo ( btn _holder ) ;
2012-10-22 10:47:50 +00:00
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
if ( type !== 'alert' ) {
2013-02-19 15:00:56 +00:00
$ ( '<input type="button" value="' + uiStrings . common . cancel + '">' )
. appendTo ( btn _holder )
2014-05-22 23:20:43 +00:00
. click ( function ( ) { box . hide ( ) ; if ( callback ) { callback ( false ) ; } } ) ;
2013-02-19 15:00:56 +00:00
}
2012-10-22 10:47:50 +00:00
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
if ( type === 'prompt' ) {
ctrl = $ ( '<input type="text">' ) . prependTo ( btn _holder ) ;
ctrl . val ( defaultVal || '' ) ;
ctrl . bind ( 'keydown' , 'return' , function ( ) { ok . click ( ) ; } ) ;
}
else if ( type === 'select' ) {
var div = $ ( '<div style="text-align:center;">' ) ;
ctrl = $ ( '<select>' ) . appendTo ( div ) ;
2014-02-18 15:06:27 +00:00
if ( checkbox ) {
var label = $ ( '<label>' ) . text ( checkbox . label ) ;
chkbx = $ ( '<input type="checkbox">' ) . appendTo ( label ) ;
chkbx . val ( checkbox . value ) ;
if ( checkbox . tooltip ) {
label . attr ( 'title' , checkbox . tooltip ) ;
}
chkbx . prop ( 'checked' , ! ! checkbox . checked ) ;
div . append ( $ ( '<div>' ) . append ( label ) ) ;
}
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
$ . each ( opts || [ ] , function ( opt , val ) {
2014-02-18 15:06:27 +00:00
if ( typeof val === 'object' ) {
ctrl . append ( $ ( '<option>' ) . val ( val . value ) . html ( val . text ) ) ;
}
else {
ctrl . append ( $ ( '<option>' ) . html ( val ) ) ;
}
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
} ) ;
dialog _content . append ( div ) ;
if ( defaultVal ) {
ctrl . val ( defaultVal ) ;
}
2013-10-29 07:07:09 +00:00
if ( changeCb ) {
ctrl . bind ( 'change' , 'return' , changeCb ) ;
}
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
ctrl . bind ( 'keydown' , 'return' , function ( ) { ok . click ( ) ; } ) ;
2013-02-19 15:00:56 +00:00
}
2014-05-22 23:20:43 +00:00
else if ( type === 'process' ) {
2013-02-19 15:00:56 +00:00
ok . hide ( ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-19 15:00:56 +00:00
box . show ( ) ;
2012-10-22 10:47:50 +00:00
2013-02-19 15:00:56 +00:00
ok . click ( function ( ) {
box . hide ( ) ;
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
var resp = ( type === 'prompt' || type === 'select' ) ? ctrl . val ( ) : true ;
2014-01-31 00:27:46 +00:00
if ( callback ) {
2014-02-18 15:06:27 +00:00
if ( chkbx ) {
callback ( resp , chkbx . prop ( 'checked' ) ) ;
}
else {
callback ( resp ) ;
}
2014-01-31 00:27:46 +00:00
}
2013-02-19 15:00:56 +00:00
} ) . focus ( ) ;
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
if ( type === 'prompt' || type === 'select' ) {
ctrl . focus ( ) ;
}
2013-02-19 15:00:56 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ . alert = function ( msg , cb ) { dbox ( 'alert' , msg , cb ) ; } ;
$ . confirm = function ( msg , cb ) { dbox ( 'confirm' , msg , cb ) ; } ;
2013-02-19 15:00:56 +00:00
$ . process _cancel = function ( msg , cb ) { dbox ( 'process' , msg , cb ) ; } ;
2010-03-11 21:07:13 +00:00
$ . prompt = function ( msg , txt , cb ) { dbox ( 'prompt' , msg , cb , txt ) ; } ;
2014-02-18 15:06:27 +00:00
$ . select = function ( msg , opts , cb , changeCb , txt , checkbox ) { dbox ( 'select' , msg , cb , txt , opts , changeCb , checkbox ) ; } ;
2010-03-11 21:07:13 +00:00
} ( ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
var setSelectMode = function ( ) {
2010-09-09 17:38:33 +00:00
var curr = $ ( '.tool_button_current' ) ;
2013-02-15 21:57:35 +00:00
if ( curr . length && curr [ 0 ] . id !== 'tool_select' ) {
2010-09-09 17:38:33 +00:00
curr . removeClass ( 'tool_button_current' ) . addClass ( 'tool_button' ) ;
$ ( '#tool_select' ) . addClass ( 'tool_button_current' ) . removeClass ( 'tool_button' ) ;
$ ( '#styleoverrides' ) . text ( '#svgcanvas svg *{cursor:move;pointer-events:all} #svgcanvas svg{cursor:default}' ) ;
}
2010-03-11 21:07:13 +00:00
svgCanvas . setMode ( 'select' ) ;
2013-02-15 21:57:35 +00:00
workarea . css ( 'cursor' , 'auto' ) ;
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 10:21:55 +00:00
// used to make the flyouts stay on the screen longer the very first time
2014-02-18 15:06:27 +00:00
// var flyoutspeed = 1250; // Currently unused
2014-02-10 10:21:55 +00:00
var textBeingEntered = false ;
var selectedElement = null ;
var multiselected = false ;
var editingsource = false ;
var docprops = false ;
var preferences = false ;
var cur _context = '' ;
var origTitle = $ ( 'title:first' ) . text ( ) ;
2014-02-10 13:14:38 +00:00
// Make [1,2,5] array
var r _intervals = [ ] ;
var i ;
for ( i = 0.1 ; i < 1E5 ; i *= 10 ) {
r _intervals . push ( i ) ;
r _intervals . push ( 2 * i ) ;
r _intervals . push ( 5 * i ) ;
}
2014-02-10 10:21:55 +00:00
2014-02-10 13:14:38 +00:00
// This function highlights the layer passed in (by fading out the other layers)
2014-02-10 10:21:55 +00:00
// if no layer is passed in, this function restores the other layers
var toggleHighlightLayer = function ( layerNameToHighlight ) {
2014-02-18 15:06:27 +00:00
var i , curNames = [ ] , numLayers = svgCanvas . getCurrentDrawing ( ) . getNumLayers ( ) ;
for ( i = 0 ; i < numLayers ; i ++ ) {
2014-02-10 10:21:55 +00:00
curNames [ i ] = svgCanvas . getCurrentDrawing ( ) . getLayerName ( i ) ;
}
if ( layerNameToHighlight ) {
2014-02-18 15:06:27 +00:00
for ( i = 0 ; i < numLayers ; ++ i ) {
2014-02-10 10:21:55 +00:00
if ( curNames [ i ] != layerNameToHighlight ) {
svgCanvas . getCurrentDrawing ( ) . setLayerOpacity ( curNames [ i ] , 0.5 ) ;
}
}
} else {
2014-02-18 15:06:27 +00:00
for ( i = 0 ; i < numLayers ; ++ i ) {
2014-02-10 10:21:55 +00:00
svgCanvas . getCurrentDrawing ( ) . setLayerOpacity ( curNames [ i ] , 1.0 ) ;
}
}
} ;
var populateLayers = function ( ) {
svgCanvas . clearSelection ( ) ;
var layerlist = $ ( '#layerlist tbody' ) . empty ( ) ;
var selLayerNames = $ ( '#selLayerNames' ) . empty ( ) ;
var drawing = svgCanvas . getCurrentDrawing ( ) ;
var currentLayerName = drawing . getCurrentLayerName ( ) ;
var layer = svgCanvas . getCurrentDrawing ( ) . getNumLayers ( ) ;
var icon = $ . getSvgIcon ( 'eye' ) ;
// we get the layers in the reverse z-order (the layer rendered on top is listed first)
while ( layer -- ) {
var name = drawing . getLayerName ( layer ) ;
var layerTr = $ ( '<tr class="layer">' ) . toggleClass ( 'layersel' , name === currentLayerName ) ;
var layerVis = $ ( '<td class="layervis">' ) . toggleClass ( 'layerinvis' , ! drawing . getLayerVisibility ( name ) ) ;
var layerName = $ ( '<td class="layername">' + name + '</td>' ) ;
layerlist . append ( layerTr . append ( layerVis , layerName ) ) ;
selLayerNames . append ( '<option value="' + name + '">' + name + '</option>' ) ;
}
if ( icon !== undefined ) {
var copy = icon . clone ( ) ;
2014-02-18 15:06:27 +00:00
$ ( 'td.layervis' , layerlist ) . append ( copy ) ;
2014-02-10 10:21:55 +00:00
$ . resizeSvgIcons ( { 'td.layervis .svg_icon' : 14 } ) ;
}
// handle selection of layer
$ ( '#layerlist td.layername' )
. mouseup ( function ( evt ) {
$ ( '#layerlist tr.layer' ) . removeClass ( 'layersel' ) ;
$ ( this . parentNode ) . addClass ( 'layersel' ) ;
svgCanvas . setCurrentLayer ( this . textContent ) ;
evt . preventDefault ( ) ;
} )
. mouseover ( function ( ) {
toggleHighlightLayer ( this . textContent ) ;
} )
. mouseout ( function ( ) {
toggleHighlightLayer ( ) ;
} ) ;
$ ( '#layerlist td.layervis' ) . click ( function ( ) {
var row = $ ( this . parentNode ) . prevAll ( ) . length ;
var name = $ ( '#layerlist tr.layer:eq(' + row + ') td.layername' ) . text ( ) ;
var vis = $ ( this ) . hasClass ( 'layerinvis' ) ;
svgCanvas . setLayerVisibility ( name , vis ) ;
$ ( this ) . toggleClass ( 'layerinvis' ) ;
} ) ;
// if there were too few rows, let's add a few to make it not so lonely
var num = 5 - $ ( '#layerlist tr.layer' ) . size ( ) ;
while ( num -- > 0 ) {
// FIXME: there must a better way to do this
layerlist . append ( '<tr><td style="color:white">_</td><td/></tr>' ) ;
}
} ;
var showSourceEditor = function ( e , forSaving ) {
if ( editingsource ) { return ; }
editingsource = true ;
origSource = svgCanvas . getSvgString ( ) ;
$ ( '#save_output_btns' ) . toggle ( ! ! forSaving ) ;
$ ( '#tool_source_back' ) . toggle ( ! forSaving ) ;
$ ( '#svg_source_textarea' ) . val ( origSource ) ;
$ ( '#svg_source_editor' ) . fadeIn ( ) ;
$ ( '#svg_source_textarea' ) . focus ( ) ;
} ;
2010-03-11 21:07:13 +00:00
var togglePathEditMode = function ( editmode , elems ) {
$ ( '#path_node_panel' ) . toggle ( editmode ) ;
$ ( '#tools_bottom_2,#tools_bottom_3' ) . toggle ( ! editmode ) ;
2013-02-15 21:57:35 +00:00
if ( editmode ) {
2010-03-11 21:07:13 +00:00
// Change select icon
$ ( '.tool_button_current' ) . removeClass ( 'tool_button_current' ) . addClass ( 'tool_button' ) ;
2010-05-12 15:45:43 +00:00
$ ( '#tool_select' ) . addClass ( 'tool_button_current' ) . removeClass ( 'tool_button' ) ;
setIcon ( '#tool_select' , 'select_node' ) ;
2010-03-11 21:07:13 +00:00
multiselected = false ;
2013-02-15 21:57:35 +00:00
if ( elems . length ) {
2010-03-11 21:07:13 +00:00
selectedElement = elems [ 0 ] ;
}
} else {
2013-10-14 01:24:52 +00:00
setTimeout ( function ( ) {
setIcon ( '#tool_select' , 'select' ) ;
} , 1000 ) ;
2010-01-29 18:27:26 +00:00
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
var saveHandler = function ( wind , svg ) {
editor . showSaveWarning = false ;
2012-10-22 10:47:50 +00:00
// by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs)
2010-03-11 21:07:13 +00:00
// can just provide their own custom save handler and might not want the XML prolog
2010-07-27 15:38:23 +00:00
svg = '<?xml version="1.0"?>\n' + svg ;
2012-10-22 10:47:50 +00:00
2013-02-16 15:36:19 +00:00
// IE9 doesn't allow standalone Data URLs
// https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves
if ( svgedit . browser . isIE ( ) ) {
2013-02-15 21:57:35 +00:00
showSourceEditor ( 0 , true ) ;
2012-10-22 10:47:50 +00:00
return ;
2010-08-23 20:16:27 +00:00
}
2013-02-16 15:36:19 +00:00
// Opens the SVG in new window
2014-02-18 15:06:27 +00:00
var win = wind . open ( 'data:image/svg+xml;base64,' + Utils . encode64 ( svg ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Alert will only appear the first time saved OR the first time the bug is encountered
var done = $ . pref ( 'save_notice_done' ) ;
2013-02-15 21:57:35 +00:00
if ( done !== 'all' ) {
2011-01-03 18:45:36 +00:00
var note = uiStrings . notification . saveFromBrowser . replace ( '%s' , 'SVG' ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Check if FF and has <defs/>
2013-02-16 15:36:19 +00:00
if ( svgedit . browser . isGecko ( ) ) {
2013-02-15 21:57:35 +00:00
if ( svg . indexOf ( '<defs' ) !== - 1 ) {
2013-02-16 15:36:19 +00:00
// warning about Mozilla bug #308590 when applicable (seems to be fixed now in Feb 2013)
2013-02-15 21:57:35 +00:00
note += '\n\n' + uiStrings . notification . defsFailOnSave ;
2010-03-11 21:07:13 +00:00
$ . pref ( 'save_notice_done' , 'all' ) ;
2013-02-15 21:57:35 +00:00
done = 'all' ;
2010-03-11 21:07:13 +00:00
} else {
$ . pref ( 'save_notice_done' , 'part' ) ;
}
} else {
2012-10-22 10:47:50 +00:00
$ . pref ( 'save_notice_done' , 'all' ) ;
2010-02-16 21:07:13 +00:00
}
2013-02-15 21:57:35 +00:00
if ( done !== 'part' ) {
2010-03-11 21:07:13 +00:00
win . alert ( note ) ;
2010-02-16 21:07:13 +00:00
}
}
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-04-08 13:49:58 +00:00
var exportHandler = function ( win , data ) {
Support PNG, JPEG, BMP, WEBP export formats by change of "Export to PNG" menu item into "Export" with its own pull-down dialog (and a HTML5 range type input element for "quality" selection for JPEG or WEBP files), including changes for the server_opensave extension; change locale key from "export_png" to "export_img" and change the corresponding localized strings (currently CS, DE, ES, FR, IT, NL, PT-BR, RO, SK, all reset to English to avoid translation errors); within the setCustomHandlers() API, deprecate "pngsave" in favor of "exportImage" (chosen to avoid just using the simpler but reserved JS keyword "export") including use within the server_opensave extension; a few JSLint-friendly changes
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2602 eee81c28-f429-11dd-99c0-75d572ba1ddd
2013-10-28 03:53:30 +00:00
var issues = data . issues ,
2014-05-22 10:21:29 +00:00
exportWindowName = data . exportWindowName ;
2012-10-22 10:47:50 +00:00
2014-05-08 03:47:14 +00:00
if ( exportWindowName ) {
exportWindow = window . open ( '' , exportWindowName ) ; // A hack to get the window via JSON-able name without opening a new one
}
2014-04-09 06:53:08 +00:00
2014-06-01 21:29:54 +00:00
exportWindow . location . href = data . datauri ;
var done = $ . pref ( 'export_notice_done' ) ;
if ( done !== 'all' ) {
var note = uiStrings . notification . saveFromBrowser . replace ( '%s' , data . type ) ;
2012-10-22 10:47:50 +00:00
2014-06-01 21:29:54 +00:00
// Check if there's issues
if ( issues . length ) {
var pre = '\n \u2022 ' ;
note += ( '\n\n' + uiStrings . notification . noteTheseIssues + pre + issues . join ( pre ) ) ;
2010-08-17 20:28:04 +00:00
}
2014-06-01 21:29:54 +00:00
// Note that this will also prevent the notice even though new issues may appear later.
// May want to find a way to deal with that without annoying the user
$ . pref ( 'export_notice_done' , 'all' ) ;
exportWindow . alert ( note ) ;
}
2010-04-14 17:30:25 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var operaRepaint = function ( ) {
// Repaints canvas in Opera. Needed for stroke-dasharray change as well as fill change
if ( ! window . opera ) {
return ;
2014-01-31 00:27:46 +00:00
}
2014-02-10 13:14:38 +00:00
$ ( '<p/>' ) . hide ( ) . appendTo ( 'body' ) . remove ( ) ;
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
function setStrokeOpt ( opt , changeElem ) {
var id = opt . id ;
var bits = id . split ( '_' ) ;
var pre = bits [ 0 ] ;
var val = bits [ 1 ] ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( changeElem ) {
svgCanvas . setStrokeAttr ( 'stroke-' + pre , val ) ;
2014-01-31 00:27:46 +00:00
}
2014-02-10 13:14:38 +00:00
operaRepaint ( ) ;
2014-02-18 15:06:27 +00:00
setIcon ( '#cur_' + pre , id , 20 ) ;
2014-02-10 13:14:38 +00:00
$ ( opt ) . addClass ( 'current' ) . siblings ( ) . removeClass ( 'current' ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// This is a common function used when a tool has been clicked (chosen)
// It does several common things:
// - removes the tool_button_current class from whatever tool currently has it
// - hides any flyouts
// - adds the tool_button_current class to the button passed in
2014-02-18 15:06:27 +00:00
var toolButtonClick = editor . toolButtonClick = function ( button , noHiding ) {
2014-02-10 13:14:38 +00:00
if ( $ ( button ) . hasClass ( 'disabled' ) ) { return false ; }
if ( $ ( button ) . parent ( ) . hasClass ( 'tools_flyout' ) ) { return true ; }
var fadeFlyouts = 'normal' ;
if ( ! noHiding ) {
$ ( '.tools_flyout' ) . fadeOut ( fadeFlyouts ) ;
2011-01-27 14:23:33 +00:00
}
2014-02-10 13:14:38 +00:00
$ ( '#styleoverrides' ) . text ( '' ) ;
workarea . css ( 'cursor' , 'auto' ) ;
$ ( '.tool_button_current' ) . removeClass ( 'tool_button_current' ) . addClass ( 'tool_button' ) ;
$ ( button ) . addClass ( 'tool_button_current' ) . removeClass ( 'tool_button' ) ;
return true ;
2011-01-27 14:23:33 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
var clickSelect = editor . clickSelect = function ( ) {
2014-02-10 13:14:38 +00:00
if ( toolButtonClick ( '#tool_select' ) ) {
svgCanvas . setMode ( 'select' ) ;
$ ( '#styleoverrides' ) . text ( '#svgcanvas svg *{cursor:move;pointer-events:all}, #svgcanvas svg{cursor:default}' ) ;
2010-09-09 17:38:33 +00:00
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
var setImageURL = editor . setImageURL = function ( url ) {
2014-02-10 13:14:38 +00:00
if ( ! url ) {
url = defaultImageURL ;
2010-01-29 18:27:26 +00:00
}
2014-02-10 13:14:38 +00:00
svgCanvas . setImageURL ( url ) ;
$ ( '#image_url' ) . val ( url ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( url . indexOf ( 'data:' ) === 0 ) {
// data URI found
$ ( '#image_url' ) . hide ( ) ;
$ ( '#change_image_url' ) . show ( ) ;
} else {
// regular URL
svgCanvas . embedImage ( url , function ( dataURI ) {
// Couldn't embed, so show warning
$ ( '#url_notice' ) . toggle ( ! dataURI ) ;
defaultImageURL = url ;
} ) ;
$ ( '#image_url' ) . show ( ) ;
$ ( '#change_image_url' ) . hide ( ) ;
2010-10-12 20:09:37 +00:00
}
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
function setBackground ( color , url ) {
// if (color == $.pref('bkgd_color') && url == $.pref('bkgd_url')) {return;}
2014-02-10 13:14:38 +00:00
$ . pref ( 'bkgd_color' , color ) ;
$ . pref ( 'bkgd_url' , url ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// This should be done in svgcanvas.js for the borderRect fill
svgCanvas . setBackground ( color , url ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
function promptImgURL ( ) {
var curhref = svgCanvas . getHref ( selectedElement ) ;
curhref = curhref . indexOf ( 'data:' ) === 0 ? '' : curhref ;
$ . prompt ( uiStrings . notification . enterNewImgURL , curhref , function ( url ) {
if ( url ) { setImageURL ( url ) ; }
} ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var setInputWidth = function ( elem ) {
var w = Math . min ( Math . max ( 12 + elem . value . length * 6 , 50 ) , 300 ) ;
$ ( elem ) . width ( w ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
function updateRulers ( scanvas , zoom ) {
if ( ! zoom ) { zoom = svgCanvas . getZoom ( ) ; }
if ( ! scanvas ) { scanvas = $ ( '#svgcanvas' ) ; }
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var d , i ;
var limit = 30000 ;
var contentElem = svgCanvas . getContentElem ( ) ;
var units = svgedit . units . getTypeMap ( ) ;
var unit = units [ curConfig . baseUnit ] ; // 1 = 1px
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// draw x ruler then y ruler
for ( d = 0 ; d < 2 ; d ++ ) {
var isX = ( d === 0 ) ;
var dim = isX ? 'x' : 'y' ;
var lentype = isX ? 'width' : 'height' ;
var contentDim = Number ( contentElem . getAttribute ( dim ) ) ;
2010-09-23 19:53:43 +00:00
2014-02-10 13:14:38 +00:00
var $hcanv _orig = $ ( '#ruler_' + dim + ' canvas:first' ) ;
2010-09-23 19:53:43 +00:00
2014-02-10 13:14:38 +00:00
// Bit of a hack to fully clear the canvas in Safari & IE9
var $hcanv = $hcanv _orig . clone ( ) ;
$hcanv _orig . replaceWith ( $hcanv ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var hcanv = $hcanv [ 0 ] ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Set the canvas size to the width of the container
var ruler _len = scanvas [ lentype ] ( ) ;
var total _len = ruler _len ;
hcanv . parentNode . style [ lentype ] = total _len + 'px' ;
var ctx _num = 0 ;
var ctx = hcanv . getContext ( '2d' ) ;
2014-02-18 15:06:27 +00:00
var ctx _arr , num , ctx _arr _num ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
ctx . fillStyle = 'rgb(200,0,0)' ;
ctx . fillRect ( 0 , 0 , hcanv . width , hcanv . height ) ;
2012-03-22 10:31:25 +00:00
2014-02-10 13:14:38 +00:00
// Remove any existing canvasses
$hcanv . siblings ( ) . remove ( ) ;
2014-02-18 15:06:27 +00:00
2014-02-10 13:14:38 +00:00
// Create multiple canvases when necessary (due to browser limits)
if ( ruler _len >= limit ) {
2014-02-18 15:06:27 +00:00
ctx _arr _num = parseInt ( ruler _len / limit , 10 ) + 1 ;
ctx _arr = [ ] ;
2014-02-10 13:14:38 +00:00
ctx _arr [ 0 ] = ctx ;
var copy ;
2014-02-18 15:06:27 +00:00
for ( i = 1 ; i < ctx _arr _num ; i ++ ) {
2014-02-10 13:14:38 +00:00
hcanv [ lentype ] = limit ;
copy = hcanv . cloneNode ( true ) ;
hcanv . parentNode . appendChild ( copy ) ;
ctx _arr [ i ] = copy . getContext ( '2d' ) ;
}
2012-03-22 10:31:25 +00:00
2014-02-10 13:14:38 +00:00
copy [ lentype ] = ruler _len % limit ;
2012-03-22 10:31:25 +00:00
2014-02-10 13:14:38 +00:00
// set copy width to last
ruler _len = limit ;
}
2012-03-22 10:31:25 +00:00
2014-02-10 13:14:38 +00:00
hcanv [ lentype ] = ruler _len ;
2012-03-22 10:31:25 +00:00
2014-02-10 13:14:38 +00:00
var u _multi = unit * zoom ;
2012-03-22 10:31:25 +00:00
2014-02-10 13:14:38 +00:00
// Calculate the main number interval
var raw _m = 50 / u _multi ;
var multi = 1 ;
for ( i = 0 ; i < r _intervals . length ; i ++ ) {
num = r _intervals [ i ] ;
multi = num ;
if ( raw _m <= num ) {
break ;
}
2010-01-27 21:03:43 +00:00
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var big _int = multi * u _multi ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
ctx . font = '9px sans-serif' ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var ruler _d = ( ( contentDim / u _multi ) % multi ) * u _multi ;
var label _pos = ruler _d - big _int ;
// draw big intervals
while ( ruler _d < total _len ) {
label _pos += big _int ;
2014-02-18 15:06:27 +00:00
// var real_d = ruler_d - contentDim; // Currently unused
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var cur _d = Math . round ( ruler _d ) + 0.5 ;
if ( isX ) {
ctx . moveTo ( cur _d , 15 ) ;
ctx . lineTo ( cur _d , 0 ) ;
}
else {
ctx . moveTo ( 15 , cur _d ) ;
ctx . lineTo ( 0 , cur _d ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
num = ( label _pos - contentDim ) / u _multi ;
var label ;
if ( multi >= 1 ) {
label = Math . round ( num ) ;
}
else {
var decs = String ( multi ) . split ( '.' ) [ 1 ] . length ;
label = num . toFixed ( decs ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Change 1000s to Ks
if ( label !== 0 && label !== 1000 && label % 1000 === 0 ) {
label = ( label / 1000 ) + 'K' ;
}
2010-07-27 13:37:52 +00:00
2014-02-10 13:14:38 +00:00
if ( isX ) {
ctx . fillText ( label , ruler _d + 2 , 8 ) ;
} else {
// draw label vertically
var str = String ( label ) . split ( '' ) ;
for ( i = 0 ; i < str . length ; i ++ ) {
ctx . fillText ( str [ i ] , 1 , ( ruler _d + 9 ) + i * 9 ) ;
}
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var part = big _int / 10 ;
// draw the small intervals
for ( i = 1 ; i < 10 ; i ++ ) {
var sub _d = Math . round ( ruler _d + part * i ) + 0.5 ;
if ( ctx _arr && sub _d > ruler _len ) {
ctx _num ++ ;
ctx . stroke ( ) ;
2014-02-18 15:06:27 +00:00
if ( ctx _num >= ctx _arr _num ) {
2014-02-10 13:14:38 +00:00
i = 10 ;
ruler _d = total _len ;
continue ;
}
ctx = ctx _arr [ ctx _num ] ;
ruler _d -= limit ;
sub _d = Math . round ( ruler _d + part * i ) + 0.5 ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// odd lines are slighly longer
var line _num = ( i % 2 ) ? 12 : 10 ;
if ( isX ) {
ctx . moveTo ( sub _d , 15 ) ;
ctx . lineTo ( sub _d , line _num ) ;
} else {
ctx . moveTo ( 15 , sub _d ) ;
ctx . lineTo ( line _num , sub _d ) ;
}
}
ruler _d += big _int ;
2010-07-27 13:37:52 +00:00
}
2014-02-10 13:14:38 +00:00
ctx . strokeStyle = '#000' ;
ctx . stroke ( ) ;
2010-07-27 13:37:52 +00:00
}
2014-02-10 13:14:38 +00:00
}
2010-07-27 13:37:52 +00:00
2014-02-18 15:06:27 +00:00
var updateCanvas = editor . updateCanvas = function ( center , new _ctr ) {
2014-02-10 13:14:38 +00:00
var w = workarea . width ( ) , h = workarea . height ( ) ;
var w _orig = w , h _orig = h ;
var zoom = svgCanvas . getZoom ( ) ;
var w _area = workarea ;
var cnvs = $ ( '#svgcanvas' ) ;
var old _ctr = {
x : w _area [ 0 ] . scrollLeft + w _orig / 2 ,
y : w _area [ 0 ] . scrollTop + h _orig / 2
2013-02-15 13:38:55 +00:00
} ;
2014-02-10 13:14:38 +00:00
var multi = curConfig . canvas _expansion ;
w = Math . max ( w _orig , svgCanvas . contentW * zoom * multi ) ;
h = Math . max ( h _orig , svgCanvas . contentH * zoom * multi ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( w == w _orig && h == h _orig ) {
workarea . css ( 'overflow' , 'hidden' ) ;
} else {
workarea . css ( 'overflow' , 'scroll' ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var old _can _y = cnvs . height ( ) / 2 ;
var old _can _x = cnvs . width ( ) / 2 ;
cnvs . width ( w ) . height ( h ) ;
var new _can _y = h / 2 ;
var new _can _x = w / 2 ;
var offset = svgCanvas . updateCanvas ( w , h ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var ratio = new _can _x / old _can _x ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var scroll _x = w / 2 - w _orig / 2 ;
var scroll _y = h / 2 - h _orig / 2 ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( ! new _ctr ) {
var old _dist _x = old _ctr . x - old _can _x ;
var new _x = new _can _x + old _dist _x * ratio ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var old _dist _y = old _ctr . y - old _can _y ;
var new _y = new _can _y + old _dist _y * ratio ;
2010-05-27 13:27:04 +00:00
2014-02-10 13:14:38 +00:00
new _ctr = {
x : new _x ,
y : new _y
} ;
} else {
new _ctr . x += offset . x ;
new _ctr . y += offset . y ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( center ) {
// Go to top-left for larger documents
if ( svgCanvas . contentW > w _area . width ( ) ) {
// Top-left
workarea [ 0 ] . scrollLeft = offset . x - 10 ;
workarea [ 0 ] . scrollTop = offset . y - 10 ;
} else {
// Center
w _area [ 0 ] . scrollLeft = scroll _x ;
w _area [ 0 ] . scrollTop = scroll _y ;
}
} else {
w _area [ 0 ] . scrollLeft = new _ctr . x - w _orig / 2 ;
w _area [ 0 ] . scrollTop = new _ctr . y - h _orig / 2 ;
}
if ( curConfig . showRulers ) {
updateRulers ( cnvs , zoom ) ;
workarea . scroll ( ) ;
}
2014-02-18 15:06:27 +00:00
if ( urldata . storagePrompt !== true && ! editor . storagePromptClosed ) {
$ ( '#dialog_box' ) . hide ( ) ;
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var updateToolButtonState = function ( ) {
var index , button ;
var bNoFill = ( svgCanvas . getColor ( 'fill' ) == 'none' ) ;
var bNoStroke = ( svgCanvas . getColor ( 'stroke' ) == 'none' ) ;
var buttonsNeedingStroke = [ '#tool_fhpath' , '#tool_line' ] ;
var buttonsNeedingFillAndStroke = [ '#tools_rect .tool_button' , '#tools_ellipse .tool_button' , '#tool_text' , '#tool_path' ] ;
if ( bNoStroke ) {
for ( index in buttonsNeedingStroke ) {
button = buttonsNeedingStroke [ index ] ;
if ( $ ( button ) . hasClass ( 'tool_button_current' ) ) {
clickSelect ( ) ;
}
$ ( button ) . addClass ( 'disabled' ) ;
}
} else {
for ( index in buttonsNeedingStroke ) {
button = buttonsNeedingStroke [ index ] ;
$ ( button ) . removeClass ( 'disabled' ) ;
}
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( bNoStroke && bNoFill ) {
for ( index in buttonsNeedingFillAndStroke ) {
button = buttonsNeedingFillAndStroke [ index ] ;
if ( $ ( button ) . hasClass ( 'tool_button_current' ) ) {
clickSelect ( ) ;
}
$ ( button ) . addClass ( 'disabled' ) ;
}
} else {
for ( index in buttonsNeedingFillAndStroke ) {
button = buttonsNeedingFillAndStroke [ index ] ;
$ ( button ) . removeClass ( 'disabled' ) ;
}
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
svgCanvas . runExtensions ( 'toolButtonStateUpdate' , {
nofill : bNoFill ,
nostroke : bNoStroke
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Disable flyouts if all inside are disabled
$ ( '.tools_flyout' ) . each ( function ( ) {
var shower = $ ( '#' + this . id + '_show' ) ;
var has _enabled = false ;
$ ( this ) . children ( ) . each ( function ( ) {
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
has _enabled = true ;
2010-03-11 21:07:13 +00:00
}
} ) ;
2014-02-10 13:14:38 +00:00
shower . toggleClass ( 'disabled' , ! has _enabled ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
operaRepaint ( ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Updates the toolbar (colors, opacity, etc) based on the selected element
// This function also updates the opacity and id elements that are in the context panel
var updateToolbar = function ( ) {
var i , len ;
if ( selectedElement != null ) {
switch ( selectedElement . tagName ) {
case 'use' :
case 'image' :
case 'foreignObject' :
break ;
case 'g' :
case 'a' :
// Look for common styles
var gWidth = null ;
var childs = selectedElement . getElementsByTagName ( '*' ) ;
for ( i = 0 , len = childs . length ; i < len ; i ++ ) {
var swidth = childs [ i ] . getAttribute ( 'stroke-width' ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( i === 0 ) {
gWidth = swidth ;
} else if ( gWidth !== swidth ) {
gWidth = null ;
2010-07-14 18:05:03 +00:00
}
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
$ ( '#stroke_width' ) . val ( gWidth === null ? '' : gWidth ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
paintBox . fill . update ( true ) ;
paintBox . stroke . update ( true ) ;
2014-02-10 10:53:51 +00:00
2014-02-10 13:14:38 +00:00
break ;
default :
paintBox . fill . update ( true ) ;
paintBox . stroke . update ( true ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
$ ( '#stroke_width' ) . val ( selectedElement . getAttribute ( 'stroke-width' ) || 1 ) ;
$ ( '#stroke_style' ) . val ( selectedElement . getAttribute ( 'stroke-dasharray' ) || 'none' ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var attr = selectedElement . getAttribute ( 'stroke-linejoin' ) || 'miter' ;
2012-10-22 10:47:50 +00:00
2014-01-31 02:13:37 +00:00
if ( $ ( '#linejoin_' + attr ) . length != 0 ) {
2010-12-20 21:37:04 +00:00
setStrokeOpt ( $ ( '#linejoin_' + attr ) [ 0 ] ) ;
2014-01-31 02:13:37 +00:00
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
attr = selectedElement . getAttribute ( 'stroke-linecap' ) || 'butt' ;
2012-10-22 10:47:50 +00:00
2014-01-31 02:13:37 +00:00
if ( $ ( '#linecap_' + attr ) . length != 0 ) {
2010-12-20 21:37:04 +00:00
setStrokeOpt ( $ ( '#linecap_' + attr ) [ 0 ] ) ;
2014-01-31 02:13:37 +00:00
}
2010-12-20 21:37:04 +00:00
}
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// All elements including image and group have opacity
2013-02-15 21:57:35 +00:00
if ( selectedElement != null ) {
var opac _perc = ( ( selectedElement . getAttribute ( 'opacity' ) || 1.0 ) * 100 ) ;
2010-03-11 21:07:13 +00:00
$ ( '#group_opacity' ) . val ( opac _perc ) ;
$ ( '#opac_slider' ) . slider ( 'option' , 'value' , opac _perc ) ;
$ ( '#elem_id' ) . val ( selectedElement . id ) ;
2015-09-24 14:15:34 +00:00
$ ( '#elem_class' ) . val ( selectedElement . getAttribute ( "class" ) ) ;
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
updateToolButtonState ( ) ;
} ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// updates the context panel tools based on the selected element
var updateContextPanel = function ( ) {
var elem = selectedElement ;
// If element has just been deleted, consider it null
2014-01-31 02:13:37 +00:00
if ( elem != null && ! elem . parentNode ) { elem = null ; }
2011-01-30 17:11:56 +00:00
var currentLayerName = svgCanvas . getCurrentDrawing ( ) . getCurrentLayerName ( ) ;
2010-03-11 21:07:13 +00:00
var currentMode = svgCanvas . getMode ( ) ;
2010-10-19 17:20:28 +00:00
var unit = curConfig . baseUnit !== 'px' ? curConfig . baseUnit : null ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
var is _node = currentMode == 'pathedit' ; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
2010-09-24 17:44:34 +00:00
var menu _items = $ ( '#cmenu_canvas li' ) ;
2014-01-31 02:13:37 +00:00
$ ( '#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,' +
'#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,' +
' #use_panel, #a_panel' ) . hide ( ) ;
2010-03-11 21:07:13 +00:00
if ( elem != null ) {
var elname = elem . nodeName ;
2010-04-08 13:34:18 +00:00
// If this is a link with no transform and one child, pretend
// its child is selected
2014-01-31 00:27:46 +00:00
// if (elname === 'a') { // && !$(elem).attr('transform')) {
// elem = elem.firstChild;
// }
2010-04-08 13:34:18 +00:00
2010-03-11 21:07:13 +00:00
var angle = svgCanvas . getRotationAngle ( elem ) ;
$ ( '#angle' ) . val ( angle ) ;
2012-10-22 10:47:50 +00:00
2010-04-06 18:40:10 +00:00
var blurval = svgCanvas . getBlur ( elem ) ;
$ ( '#blur' ) . val ( blurval ) ;
$ ( '#blur_slider' ) . slider ( 'option' , 'value' , blurval ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( svgCanvas . addedNew ) {
2016-03-10 16:08:08 +00:00
if ( elname === 'image' && svgCanvas . getMode ( ) === 'image' ) {
2010-07-05 15:38:06 +00:00
// Prompt for URL if not a data URL
2013-02-15 21:57:35 +00:00
if ( svgCanvas . getHref ( elem ) . indexOf ( 'data:' ) !== 0 ) {
2010-07-05 15:38:06 +00:00
promptImgURL ( ) ;
}
2013-02-15 21:57:35 +00:00
} / * else if ( elname == 'text' ) {
2010-03-11 21:07:13 +00:00
// TODO: Do something here for new text
2011-02-09 06:14:47 +00:00
} * /
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( ! is _node && currentMode != 'pathedit' ) {
2010-03-11 21:07:13 +00:00
$ ( '#selected_panel' ) . show ( ) ;
// Elements in this array already have coord fields
2013-02-15 21:57:35 +00:00
if ( [ 'line' , 'circle' , 'ellipse' ] . indexOf ( elname ) >= 0 ) {
2010-03-11 21:07:13 +00:00
$ ( '#xy_panel' ) . hide ( ) ;
} else {
2014-02-10 10:53:51 +00:00
var x , y ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Get BBox vals for g, polyline and path
2013-02-15 21:57:35 +00:00
if ( [ 'g' , 'polyline' , 'path' ] . indexOf ( elname ) >= 0 ) {
2010-03-11 21:07:13 +00:00
var bb = svgCanvas . getStrokedBBox ( [ elem ] ) ;
2013-02-15 21:57:35 +00:00
if ( bb ) {
2010-03-11 21:07:13 +00:00
x = bb . x ;
y = bb . y ;
}
} else {
x = elem . getAttribute ( 'x' ) ;
y = elem . getAttribute ( 'y' ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( unit ) {
2011-02-02 17:28:43 +00:00
x = svgedit . units . convertUnit ( x ) ;
y = svgedit . units . convertUnit ( y ) ;
2012-10-22 10:47:50 +00:00
}
2010-03-11 21:07:13 +00:00
$ ( '#selected_x' ) . val ( x || 0 ) ;
$ ( '#selected_y' ) . val ( y || 0 ) ;
$ ( '#xy_panel' ) . show ( ) ;
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Elements in this array cannot be converted to a path
2010-09-29 18:37:51 +00:00
var no _path = [ 'image' , 'text' , 'path' , 'g' , 'use' ] . indexOf ( elname ) == - 1 ;
2010-03-11 21:07:13 +00:00
$ ( '#tool_topath' ) . toggle ( no _path ) ;
2013-02-23 18:34:23 +00:00
$ ( '#tool_reorient' ) . toggle ( elname === 'path' ) ;
$ ( '#tool_reorient' ) . toggleClass ( 'disabled' , angle === 0 ) ;
2010-03-11 21:07:13 +00:00
} else {
var point = path . getNodePoint ( ) ;
$ ( '#tool_add_subpath' ) . removeClass ( 'push_button_pressed' ) . addClass ( 'tool_button' ) ;
$ ( '#tool_node_delete' ) . toggleClass ( 'disabled' , ! path . canDeleteNodes ) ;
2012-10-22 10:47:50 +00:00
2010-03-24 20:13:13 +00:00
// Show open/close button based on selected point
2010-05-12 15:45:43 +00:00
setIcon ( '#tool_openclose_path' , path . closed _subpath ? 'open_path' : 'close_path' ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( point ) {
2010-03-11 21:07:13 +00:00
var seg _type = $ ( '#seg_type' ) ;
2013-02-15 21:57:35 +00:00
if ( unit ) {
2011-02-02 17:28:43 +00:00
point . x = svgedit . units . convertUnit ( point . x ) ;
point . y = svgedit . units . convertUnit ( point . y ) ;
2010-10-19 17:20:28 +00:00
}
2010-03-11 21:07:13 +00:00
$ ( '#path_node_x' ) . val ( point . x ) ;
$ ( '#path_node_y' ) . val ( point . y ) ;
2013-02-15 21:57:35 +00:00
if ( point . type ) {
2010-03-11 21:07:13 +00:00
seg _type . val ( point . type ) . removeAttr ( 'disabled' ) ;
} else {
2013-02-15 22:32:35 +00:00
seg _type . val ( 4 ) . attr ( 'disabled' , 'disabled' ) ;
2010-03-11 21:07:13 +00:00
}
}
return ;
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// update contextual tools here
var panels = {
g : [ ] ,
2010-12-01 17:54:11 +00:00
a : [ ] ,
2013-02-15 22:32:35 +00:00
rect : [ 'rx' , 'width' , 'height' ] ,
image : [ 'width' , 'height' ] ,
circle : [ 'cx' , 'cy' , 'r' ] ,
ellipse : [ 'cx' , 'cy' , 'rx' , 'ry' ] ,
line : [ 'x1' , 'y1' , 'x2' , 'y2' ] ,
2010-07-22 19:10:51 +00:00
text : [ ] ,
2013-02-15 22:32:35 +00:00
use : [ ]
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
var el _name = elem . tagName ;
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
// if ($(elem).data('gsvg')) {
// $('#g_panel').show();
// }
2012-10-22 10:47:50 +00:00
2010-12-01 17:54:11 +00:00
var link _href = null ;
if ( el _name === 'a' ) {
link _href = svgCanvas . getHref ( elem ) ;
$ ( '#g_panel' ) . show ( ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( elem . parentNode . tagName === 'a' ) {
if ( ! $ ( elem ) . siblings ( ) . length ) {
2010-12-01 17:54:11 +00:00
$ ( '#a_panel' ) . show ( ) ;
link _href = svgCanvas . getHref ( elem . parentNode ) ;
}
}
2012-10-22 10:47:50 +00:00
2010-12-01 17:54:11 +00:00
// Hide/show the make_link buttons
$ ( '#tool_make_link, #tool_make_link' ) . toggle ( ! link _href ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( link _href ) {
2010-12-01 17:54:11 +00:00
$ ( '#link_url' ) . val ( link _href ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( panels [ el _name ] ) {
2010-03-11 21:07:13 +00:00
var cur _panel = panels [ el _name ] ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( '#' + el _name + '_panel' ) . show ( ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ . each ( cur _panel , function ( i , item ) {
2010-10-19 17:20:28 +00:00
var attrVal = elem . getAttribute ( item ) ;
2013-02-15 21:57:35 +00:00
if ( curConfig . baseUnit !== 'px' && elem [ item ] ) {
2010-10-19 17:20:28 +00:00
var bv = elem [ item ] . baseVal . value ;
2011-02-02 17:28:43 +00:00
attrVal = svgedit . units . convertUnit ( bv ) ;
2010-10-19 17:20:28 +00:00
}
$ ( '#' + el _name + '_' + item ) . val ( attrVal || 0 ) ;
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( el _name == 'text' ) {
$ ( '#text_panel' ) . css ( 'display' , 'inline' ) ;
2016-03-11 10:04:11 +00:00
$ ( '#tool_font_size' ) . css ( 'display' , 'inline' ) ;
2010-03-11 21:07:13 +00:00
if ( svgCanvas . getItalic ( ) ) {
$ ( '#tool_italic' ) . addClass ( 'push_button_pressed' ) . removeClass ( 'tool_button' ) ;
2013-02-15 21:57:35 +00:00
} else {
2010-03-11 21:07:13 +00:00
$ ( '#tool_italic' ) . removeClass ( 'push_button_pressed' ) . addClass ( 'tool_button' ) ;
}
if ( svgCanvas . getBold ( ) ) {
$ ( '#tool_bold' ) . addClass ( 'push_button_pressed' ) . removeClass ( 'tool_button' ) ;
2013-02-15 21:57:35 +00:00
} else {
2010-03-11 21:07:13 +00:00
$ ( '#tool_bold' ) . removeClass ( 'push_button_pressed' ) . addClass ( 'tool_button' ) ;
}
2013-02-15 21:57:35 +00:00
$ ( '#font_family' ) . val ( elem . getAttribute ( 'font-family' ) ) ;
$ ( '#font_size' ) . val ( elem . getAttribute ( 'font-size' ) ) ;
2010-03-11 21:07:13 +00:00
$ ( '#text' ) . val ( elem . textContent ) ;
if ( svgCanvas . addedNew ) {
2010-09-16 16:20:48 +00:00
// Timeout needed for IE9
setTimeout ( function ( ) {
$ ( '#text' ) . focus ( ) . select ( ) ;
2013-02-15 22:32:35 +00:00
} , 100 ) ;
2010-03-11 21:07:13 +00:00
}
} // text
2016-03-10 16:08:08 +00:00
else if ( el _name == 'image' && svgCanvas . getMode ( ) == 'image' ) {
2010-08-16 17:53:15 +00:00
setImageURL ( svgCanvas . getHref ( elem ) ) ;
2010-03-11 21:07:13 +00:00
} // image
2013-02-15 21:57:35 +00:00
else if ( el _name === 'g' || el _name === 'use' ) {
2010-07-29 15:22:09 +00:00
$ ( '#container_panel' ) . show ( ) ;
2010-07-22 19:10:51 +00:00
var title = svgCanvas . getTitle ( ) ;
2010-07-29 19:43:52 +00:00
var label = $ ( '#g_title' ) [ 0 ] ;
label . value = title ;
setInputWidth ( label ) ;
2013-10-29 06:54:31 +00:00
$ ( '#g_title' ) . prop ( 'disabled' , el _name == 'use' ) ;
2010-07-22 19:10:51 +00:00
}
2010-03-11 21:07:13 +00:00
}
2013-02-15 21:57:35 +00:00
menu _items [ ( el _name === 'g' ? 'en' : 'dis' ) + 'ableContextMenuItems' ] ( '#ungroup' ) ;
menu _items [ ( ( el _name === 'g' || ! multiselected ) ? 'dis' : 'en' ) + 'ableContextMenuItems' ] ( '#group' ) ;
2010-03-11 21:07:13 +00:00
} // if (elem != null)
else if ( multiselected ) {
$ ( '#multiselected_panel' ) . show ( ) ;
2010-09-24 17:44:34 +00:00
menu _items
. enableContextMenuItems ( '#group' )
. disableContextMenuItems ( '#ungroup' ) ;
2010-08-16 20:26:06 +00:00
} else {
2010-09-27 14:20:20 +00:00
menu _items . disableContextMenuItems ( '#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back' ) ;
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// update history buttons
2013-02-16 16:07:19 +00:00
$ ( '#tool_undo' ) . toggleClass ( 'disabled' , undoMgr . getUndoStackSize ( ) === 0 ) ;
$ ( '#tool_redo' ) . toggleClass ( 'disabled' , undoMgr . getRedoStackSize ( ) === 0 ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
svgCanvas . addedNew = false ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
if ( ( elem && ! is _node ) || multiselected ) {
// update the selected elements' layer
2011-01-26 03:18:59 +00:00
$ ( '#selLayerNames' ) . removeAttr ( 'disabled' ) . val ( currentLayerName ) ;
2012-10-22 10:47:50 +00:00
2010-08-16 20:26:06 +00:00
// Enable regular menu options
2010-09-27 14:20:20 +00:00
canv _menu . enableContextMenuItems ( '#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back' ) ;
2013-02-15 21:57:35 +00:00
} else {
2010-03-11 21:07:13 +00:00
$ ( '#selLayerNames' ) . attr ( 'disabled' , 'disabled' ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var updateWireFrame = function ( ) {
// Test support
if ( supportsNonSS ) { return ; }
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var rule = '#workarea.wireframe #svgcontent * { stroke-width: ' + 1 / svgCanvas . getZoom ( ) + 'px; }' ;
$ ( '#wireframe_rules' ) . text ( workarea . hasClass ( 'wireframe' ) ? rule : '' ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var updateTitle = function ( title ) {
title = title || svgCanvas . getDocumentTitle ( ) ;
var newTitle = origTitle + ( title ? ': ' + title : '' ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Remove title update with current context info, isn't really necessary
// if (cur_context) {
// new_title = new_title + cur_context;
// }
$ ( 'title:first' ) . text ( newTitle ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// called when we've selected a different element
2014-02-18 15:06:27 +00:00
var selectedChanged = function ( win , elems ) {
2014-02-10 13:14:38 +00:00
var mode = svgCanvas . getMode ( ) ;
if ( mode === 'select' ) {
setSelectMode ( ) ;
}
var is _node = ( mode == "pathedit" ) ;
// if elems[1] is present, then we have more than one element
selectedElement = ( elems . length === 1 || elems [ 1 ] == null ? elems [ 0 ] : null ) ;
multiselected = ( elems . length >= 2 && elems [ 1 ] != null ) ;
if ( selectedElement != null ) {
// unless we're already in always set the mode of the editor to select because
// upon creation of a text element the editor is switched into
// select mode and this event fires - we need our UI to be in sync
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( ! is _node ) {
updateToolbar ( ) ;
}
} // if (elem != null)
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Deal with pathedit mode
togglePathEditMode ( is _node , elems ) ;
updateContextPanel ( ) ;
svgCanvas . runExtensions ( 'selectedChanged' , {
elems : elems ,
selectedElement : selectedElement ,
multiselected : multiselected
} ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Call when part of element is in process of changing, generally
// on mousemove actions like rotate, move, etc.
2014-02-18 15:06:27 +00:00
var elementTransition = function ( win , elems ) {
2014-02-10 13:14:38 +00:00
var mode = svgCanvas . getMode ( ) ;
var elem = elems [ 0 ] ;
if ( ! elem ) {
return ;
}
multiselected = ( elems . length >= 2 && elems [ 1 ] != null ) ;
// Only updating fields for single elements for now
if ( ! multiselected ) {
switch ( mode ) {
case 'rotate' :
var ang = svgCanvas . getRotationAngle ( elem ) ;
$ ( '#angle' ) . val ( ang ) ;
$ ( '#tool_reorient' ) . toggleClass ( 'disabled' , ang === 0 ) ;
break ;
// TODO: Update values that change on move/resize, etc
// case "select":
// case "resize":
// break;
}
}
svgCanvas . runExtensions ( 'elementTransition' , {
elems : elems
} ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2016-04-29 20:13:35 +00:00
/ * *
* Test whether an element is a layer or not .
* @ param { SVGGElement } elem - The SVGGElement to test .
* @ returns { boolean } True if the element is a layer
* /
function isLayer ( elem ) {
2016-05-02 02:58:41 +00:00
return elem && elem . tagName === 'g' && svgedit . draw . Layer . CLASS _REGEX . test ( elem . getAttribute ( 'class' ) )
2016-04-29 20:13:35 +00:00
}
2014-02-10 13:14:38 +00:00
// called when any element has changed
2014-02-18 15:06:27 +00:00
var elementChanged = function ( win , elems ) {
2014-02-10 13:14:38 +00:00
var i ,
mode = svgCanvas . getMode ( ) ;
if ( mode === 'select' ) {
setSelectMode ( ) ;
2010-03-11 21:07:13 +00:00
}
2014-02-10 13:14:38 +00:00
for ( i = 0 ; i < elems . length ; ++ i ) {
var elem = elems [ i ] ;
2016-04-29 20:13:35 +00:00
var isSvgElem = ( elem && elem . tagName === 'svg' ) ;
if ( isSvgElem || isLayer ( elem ) ) {
2014-02-10 13:14:38 +00:00
populateLayers ( ) ;
2016-04-29 20:13:35 +00:00
// if the element changed was the svg, then it could be a resolution change
if ( isSvgElem ) {
updateCanvas ( ) ;
}
2014-02-10 13:14:38 +00:00
}
// Update selectedElement if element is no longer part of the image.
// This occurs for the text elements in Firefox
else if ( elem && selectedElement && selectedElement . parentNode == null ) {
// || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why
selectedElement = elem ;
}
}
2014-02-18 15:06:27 +00:00
editor . showSaveWarning = true ;
2014-02-10 13:14:38 +00:00
// we update the contextual panel with potentially new
// positional/sizing information (we DON'T want to update the
// toolbar here as that creates an infinite loop)
// also this updates the history buttons
// we tell it to skip focusing the text control if the
// text element was previously in focus
updateContextPanel ( ) ;
// In the event a gradient was flipped:
if ( selectedElement && mode === 'select' ) {
paintBox . fill . update ( ) ;
paintBox . stroke . update ( ) ;
}
svgCanvas . runExtensions ( 'elementChanged' , {
elems : elems
} ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var zoomDone = function ( ) {
updateWireFrame ( ) ;
// updateCanvas(); // necessary?
} ;
2014-02-18 15:06:27 +00:00
var zoomChanged = svgCanvas . zoomChanged = function ( win , bbox , autoCenter ) {
2014-02-10 13:14:38 +00:00
var scrbar = 15 ,
2014-02-18 15:06:27 +00:00
// res = svgCanvas.getResolution(), // Currently unused
w _area = workarea ;
// var canvas_pos = $('#svgcanvas').position(); // Currently unused
2014-02-10 13:14:38 +00:00
var z _info = svgCanvas . setBBoxZoom ( bbox , w _area . width ( ) - scrbar , w _area . height ( ) - scrbar ) ;
if ( ! z _info ) { return ; }
var zoomlevel = z _info . zoom ,
bb = z _info . bbox ;
if ( zoomlevel < 0.001 ) {
changeZoom ( { value : 0.1 } ) ;
return ;
}
$ ( '#zoom' ) . val ( ( zoomlevel * 100 ) . toFixed ( 1 ) ) ;
if ( autoCenter ) {
updateCanvas ( ) ;
} else {
updateCanvas ( false , { x : bb . x * zoomlevel + ( bb . width * zoomlevel ) / 2 , y : bb . y * zoomlevel + ( bb . height * zoomlevel ) / 2 } ) ;
}
if ( svgCanvas . getMode ( ) == 'zoom' && bb . width ) {
// Go to select if a zoom box was drawn
setSelectMode ( ) ;
}
zoomDone ( ) ;
2013-02-15 13:38:55 +00:00
} ;
2014-02-10 13:14:38 +00:00
changeZoom = function ( ctl ) {
2010-03-11 21:07:13 +00:00
var zoomlevel = ctl . value / 100 ;
2014-01-31 02:13:37 +00:00
if ( zoomlevel < 0.001 ) {
ctl . value = 0.1 ;
2010-10-21 20:30:42 +00:00
return ;
}
2010-03-11 21:07:13 +00:00
var zoom = svgCanvas . getZoom ( ) ;
var w _area = workarea ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
zoomChanged ( window , {
width : 0 ,
height : 0 ,
// center pt of scroll position
2012-10-22 10:47:50 +00:00
x : ( w _area [ 0 ] . scrollLeft + w _area . width ( ) / 2 ) / zoom ,
2010-03-11 21:07:13 +00:00
y : ( w _area [ 0 ] . scrollTop + w _area . height ( ) / 2 ) / zoom ,
zoom : zoomlevel
} , true ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
$ ( '#cur_context_panel' ) . delegate ( 'a' , 'click' , function ( ) {
var link = $ ( this ) ;
if ( link . attr ( 'data-root' ) ) {
svgCanvas . leaveContext ( ) ;
} else {
svgCanvas . setContext ( link . text ( ) ) ;
2010-01-13 18:28:19 +00:00
}
2014-02-10 13:14:38 +00:00
svgCanvas . clearSelection ( ) ;
return false ;
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var contextChanged = function ( win , context ) {
var link _str = '' ;
if ( context ) {
var str = '' ;
link _str = '<a href="#" data-root="y">' + svgCanvas . getCurrentDrawing ( ) . getCurrentLayerName ( ) + '</a>' ;
$ ( context ) . parentsUntil ( '#svgcontent > g' ) . andSelf ( ) . each ( function ( ) {
if ( this . id ) {
str += ' > ' + this . id ;
if ( this !== context ) {
link _str += ' > <a href="#">' + this . id + '</a>' ;
} else {
link _str += ' > ' + this . id ;
}
}
} ) ;
cur _context = str ;
2010-04-28 16:34:02 +00:00
} else {
2014-02-10 13:14:38 +00:00
cur _context = null ;
2010-04-06 18:40:10 +00:00
}
2014-02-10 13:14:38 +00:00
$ ( '#cur_context_panel' ) . toggle ( ! ! context ) . html ( link _str ) ;
updateTitle ( ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Makes sure the current selected paint is available to work with
var prepPaints = function ( ) {
paintBox . fill . prep ( ) ;
paintBox . stroke . prep ( ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var flyout _funcs = { } ;
2010-04-01 19:02:36 +00:00
2014-02-10 13:14:38 +00:00
var setFlyoutTitles = function ( ) {
$ ( '.tools_flyout' ) . each ( function ( ) {
var shower = $ ( '#' + this . id + '_show' ) ;
if ( shower . data ( 'isLibrary' ) ) {
return ;
}
2010-04-01 19:02:36 +00:00
2014-02-10 13:14:38 +00:00
var tooltips = [ ] ;
$ ( this ) . children ( ) . each ( function ( ) {
tooltips . push ( this . title ) ;
} ) ;
shower [ 0 ] . title = tooltips . join ( ' / ' ) ;
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var setFlyoutPositions = function ( ) {
$ ( '.tools_flyout' ) . each ( function ( ) {
var shower = $ ( '#' + this . id + '_show' ) ;
var pos = shower . offset ( ) ;
var w = shower . outerWidth ( ) ;
2014-02-18 15:06:27 +00:00
$ ( this ) . css ( { left : ( pos . left + w ) * editor . tool _scale , top : pos . top } ) ;
2014-02-10 13:14:38 +00:00
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var setupFlyouts = function ( holders ) {
$ . each ( holders , function ( hold _sel , btn _opts ) {
var buttons = $ ( hold _sel ) . children ( ) ;
var show _sel = hold _sel + '_show' ;
var shower = $ ( show _sel ) ;
var def = false ;
buttons . addClass ( 'tool_button' )
. unbind ( 'click mousedown mouseup' ) // may not be necessary
. each ( function ( i ) {
// Get this buttons options
var opts = btn _opts [ i ] ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Remember the function that goes with this ID
flyout _funcs [ opts . sel ] = opts . fn ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( opts . isDefault ) { def = i ; }
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Clicking the icon in flyout should set this set's icon
var func = function ( event ) {
var options = opts ;
//find the currently selected tool if comes from keystroke
if ( event . type === 'keydown' ) {
var flyoutIsSelected = $ ( options . parent + '_show' ) . hasClass ( 'tool_button_current' ) ;
var currentOperation = $ ( options . parent + '_show' ) . attr ( 'data-curopt' ) ;
$ . each ( holders [ opts . parent ] , function ( i , tool ) {
if ( tool . sel == currentOperation ) {
if ( ! event . shiftKey || ! flyoutIsSelected ) {
options = tool ;
} else {
options = holders [ opts . parent ] [ i + 1 ] || holders [ opts . parent ] [ 0 ] ;
}
}
} ) ;
}
if ( $ ( this ) . hasClass ( 'disabled' ) ) { return false ; }
if ( toolButtonClick ( show _sel ) ) {
options . fn ( ) ;
}
var icon ;
if ( options . icon ) {
icon = $ . getSvgIcon ( options . icon , true ) ;
} else {
icon = $ ( options . sel ) . children ( ) . eq ( 0 ) . clone ( ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
icon [ 0 ] . setAttribute ( 'width' , shower . width ( ) ) ;
icon [ 0 ] . setAttribute ( 'height' , shower . height ( ) ) ;
shower . children ( ':not(.flyout_arrow_horiz)' ) . remove ( ) ;
shower . append ( icon ) . attr ( 'data-curopt' , options . sel ) ; // This sets the current mode
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
$ ( this ) . mouseup ( func ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( opts . key ) {
$ ( document ) . bind ( 'keydown' , opts . key [ 0 ] + ' shift+' + opts . key [ 0 ] , func ) ;
}
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( def ) {
shower . attr ( 'data-curopt' , btn _opts [ def ] . sel ) ;
} else if ( ! shower . attr ( 'data-curopt' ) ) {
// Set first as default
shower . attr ( 'data-curopt' , btn _opts [ 0 ] . sel ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var timer ;
var pos = $ ( show _sel ) . position ( ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Clicking the "show" icon should set the current mode
shower . mousedown ( function ( evt ) {
if ( shower . hasClass ( 'disabled' ) ) {
return false ;
}
var holder = $ ( hold _sel ) ;
var l = pos . left + 34 ;
var w = holder . width ( ) * - 1 ;
var time = holder . data ( 'shown_popop' ) ? 200 : 0 ;
timer = setTimeout ( function ( ) {
// Show corresponding menu
if ( ! shower . data ( 'isLibrary' ) ) {
holder . css ( 'left' , w ) . show ( ) . animate ( {
left : l
} , 150 ) ;
} else {
holder . css ( 'left' , l ) . show ( ) ;
}
holder . data ( 'shown_popop' , true ) ;
} , time ) ;
evt . preventDefault ( ) ;
} ) . mouseup ( function ( evt ) {
clearTimeout ( timer ) ;
var opt = $ ( this ) . attr ( 'data-curopt' ) ;
// Is library and popped up, so do nothing
if ( shower . data ( 'isLibrary' ) && $ ( show _sel . replace ( '_show' , '' ) ) . is ( ':visible' ) ) {
toolButtonClick ( show _sel , true ) ;
return ;
}
if ( toolButtonClick ( show _sel ) && flyout _funcs [ opt ] ) {
flyout _funcs [ opt ] ( ) ;
}
} ) ;
// $('#tools_rect').mouseleave(function(){$('#tools_rect').fadeOut();});
} ) ;
setFlyoutTitles ( ) ;
setFlyoutPositions ( ) ;
} ;
2010-10-19 17:20:28 +00:00
2014-02-10 13:14:38 +00:00
var makeFlyoutHolder = function ( id , child ) {
var div = $ ( '<div>' , {
'class' : 'tools_flyout' ,
id : id
} ) . appendTo ( '#svg_editor' ) . append ( child ) ;
return div ;
} ;
2014-02-18 15:06:27 +00:00
var uaPrefix = ( function ( ) {
var prop ;
var regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/ ;
var someScript = document . getElementsByTagName ( 'script' ) [ 0 ] ;
for ( prop in someScript . style ) {
if ( regex . test ( prop ) ) {
// test is faster than match, so it's better to perform
// that on the lot and match only when necessary
return prop . match ( regex ) [ 0 ] ;
}
}
// Nothing found so far?
if ( 'WebkitOpacity' in someScript . style ) { return 'Webkit' ; }
if ( 'KhtmlOpacity' in someScript . style ) { return 'Khtml' ; }
return '' ;
} ( ) ) ;
2014-02-10 13:14:38 +00:00
var scaleElements = function ( elems , scale ) {
2014-02-18 15:06:27 +00:00
// var prefix = '-' + uaPrefix.toLowerCase() + '-'; // Currently unused
2014-02-10 13:14:38 +00:00
var sides = [ 'top' , 'left' , 'bottom' , 'right' ] ;
elems . each ( function ( ) {
// Handled in CSS
// this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')';
var i ;
var el = $ ( this ) ;
var w = el . outerWidth ( ) * ( scale - 1 ) ;
var h = el . outerHeight ( ) * ( scale - 1 ) ;
2014-02-18 15:06:27 +00:00
// var margins = {}; // Currently unused
2014-02-10 13:14:38 +00:00
for ( i = 0 ; i < 4 ; i ++ ) {
var s = sides [ i ] ;
var cur = el . data ( 'orig_margin-' + s ) ;
if ( cur == null ) {
cur = parseInt ( el . css ( 'margin-' + s ) , 10 ) ;
// Cache the original margin
el . data ( 'orig_margin-' + s , cur ) ;
2011-02-10 04:10:03 +00:00
}
2014-02-10 13:14:38 +00:00
var val = cur * scale ;
if ( s === 'right' ) {
val += w ;
} else if ( s === 'bottom' ) {
val += h ;
}
el . css ( 'margin-' + s , val ) ;
// el.css('outline', '1px solid red');
2010-10-19 17:20:28 +00:00
}
2014-02-10 13:14:38 +00:00
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
var setIconSize = editor . setIconSize = function ( size ) {
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// var elems = $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open');
var sel _toscale = '#tools_top .toolset, #editor_panel > *, #history_panel > *,' +
' #main_button, #tools_left > *, #path_node_panel > *, #multiselected_panel > *,' +
2016-03-11 10:04:11 +00:00
' #g_panel > *, #tool_font_size > *, .tools_flyout' ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var elems = $ ( sel _toscale ) ;
var scale = 1 ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
if ( typeof size === 'number' ) {
2014-02-10 13:14:38 +00:00
scale = size ;
2013-02-15 21:57:35 +00:00
} else {
2014-02-10 13:14:38 +00:00
var icon _sizes = { s : 0.75 , m : 1 , l : 1.25 , xl : 1.5 } ;
scale = icon _sizes [ size ] ;
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . tool _scale = scale ;
2014-02-10 13:14:38 +00:00
setFlyoutPositions ( ) ;
// $('.tools_flyout').each(function() {
// var pos = $(this).position();
// console.log($(this), pos.left+(34 * scale));
// $(this).css({'left': pos.left+(34 * scale), 'top': pos.top+(77 * scale)});
// console.log('l', $(this).css('left'));
// });
// var scale = .75;
var hidden _ps = elems . parents ( ':hidden' ) ;
hidden _ps . css ( 'visibility' , 'hidden' ) . show ( ) ;
scaleElements ( elems , scale ) ;
hidden _ps . css ( 'visibility' , 'visible' ) . hide ( ) ;
// return;
$ . pref ( 'iconsize' , size ) ;
$ ( '#iconsize' ) . val ( size ) ;
// Change icon size
// $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open')
// .find('> svg, > img').each(function() {
// this.setAttribute('width',size_num);
// this.setAttribute('height',size_num);
// });
//
// $.resizeSvgIcons({
// '.flyout_arrow_horiz > svg, .flyout_arrow_horiz > img': size_num / 5,
// '#logo > svg, #logo > img': size_num * 1.3,
// '#tools_bottom .icon_label > *': (size_num === 16 ? 18 : size_num * .75)
// });
// if (size != 's') {
// $.resizeSvgIcons({'#layerbuttons svg, #layerbuttons img': size_num * .6});
// }
// Note that all rules will be prefixed with '#svg_editor' when parsed
var cssResizeRules = {
// '.tool_button,\
// .push_button,\
// .tool_button_current,\
// .push_button_pressed,\
// .disabled,\
// .icon_label,\
// .tools_flyout .tool_button': {
// 'width': {s: '16px', l: '32px', xl: '48px'},
// 'height': {s: '16px', l: '32px', xl: '48px'},
// 'padding': {s: '1px', l: '2px', xl: '3px'}
// },
// '.tool_sep': {
// 'height': {s: '16px', l: '32px', xl: '48px'},
// 'margin': {s: '2px 2px', l: '2px 5px', xl: '2px 8px'}
// },
// '#main_icon': {
// 'width': {s: '31px', l: '53px', xl: '75px'},
// 'height': {s: '22px', l: '42px', xl: '64px'}
// },
'#tools_top' : {
2014-04-17 00:25:02 +00:00
'left' : 50 + $ ( '#main_button' ) . width ( ) ,
2014-02-10 13:14:38 +00:00
'height' : 72
} ,
'#tools_left' : {
'width' : 31 ,
'top' : 74
} ,
'div#workarea' : {
'left' : 38 ,
'top' : 74
}
// '#tools_bottom': {
// 'left': {s: '27px', l: '46px', xl: '65px'},
// 'height': {s: '58px', l: '98px', xl: '145px'}
// },
// '#color_tools': {
// 'border-spacing': {s: '0 1px'},
// 'margin-top': {s: '-1px'}
// },
// '#color_tools .icon_label': {
// 'width': {l:'43px', xl: '60px'}
// },
// '.color_tool': {
// 'height': {s: '20px'}
// },
// '#tool_opacity': {
// 'top': {s: '1px'},
// 'height': {s: 'auto', l:'auto', xl:'auto'}
// },
// '#tools_top input, #tools_bottom input': {
// 'margin-top': {s: '2px', l: '4px', xl: '5px'},
// 'height': {s: 'auto', l: 'auto', xl: 'auto'},
// 'border': {s: '1px solid #555', l: 'auto', xl: 'auto'},
// 'font-size': {s: '.9em', l: '1.2em', xl: '1.4em'}
// },
// '#zoom_panel': {
// 'margin-top': {s: '3px', l: '4px', xl: '5px'}
// },
// '#copyright, #tools_bottom .label': {
// 'font-size': {l: '1.5em', xl: '2em'},
// 'line-height': {s: '15px'}
// },
// '#tools_bottom_2': {
// 'width': {l: '295px', xl: '355px'},
// 'top': {s: '4px'}
// },
// '#tools_top > div, #tools_top': {
// 'line-height': {s: '17px', l: '34px', xl: '50px'}
// },
// '.dropdown button': {
// 'height': {s: '18px', l: '34px', xl: '40px'},
// 'line-height': {s: '18px', l: '34px', xl: '40px'},
// 'margin-top': {s: '3px'}
// },
// '#tools_top label, #tools_bottom label': {
// 'font-size': {s: '1em', l: '1.5em', xl: '2em'},
// 'height': {s: '25px', l: '42px', xl: '64px'}
// },
// 'div.toolset': {
// 'height': {s: '25px', l: '42px', xl: '64px'}
// },
// '#tool_bold, #tool_italic': {
// 'font-size': {s: '1.5em', l: '3em', xl: '4.5em'}
// },
// '#sidepanels': {
// 'top': {s: '50px', l: '88px', xl: '125px'},
// 'bottom': {s: '51px', l: '68px', xl: '65px'}
// },
// '#layerbuttons': {
// 'width': {l: '130px', xl: '175px'},
// 'height': {l: '24px', xl: '30px'}
// },
// '#layerlist': {
// 'width': {l: '128px', xl: '150px'}
// },
// '.layer_button': {
// 'width': {l: '19px', xl: '28px'},
// 'height': {l: '19px', xl: '28px'}
// },
// 'input.spin-button': {
// 'background-image': {l: 'url('images/spinbtn_updn_big.png')', xl: 'url('images/spinbtn_updn_big.png')'},
// 'background-position': {l: '100% -5px', xl: '100% -2px'},
// 'padding-right': {l: '24px', xl: '24px' }
// },
// 'input.spin-button.up': {
// 'background-position': {l: '100% -45px', xl: '100% -42px'}
// },
// 'input.spin-button.down': {
// 'background-position': {l: '100% -85px', xl: '100% -82px'}
// },
// '#position_opts': {
// 'width': {all: (size_num*4) +'px'}
// }
} ;
var rule _elem = $ ( '#tool_size_rules' ) ;
if ( ! rule _elem . length ) {
2014-04-08 01:31:22 +00:00
rule _elem = $ ( '<style id="tool_size_rules"></style>' ) . appendTo ( 'head' ) ;
2014-02-10 13:14:38 +00:00
} else {
rule _elem . empty ( ) ;
}
2014-02-18 15:06:27 +00:00
if ( size !== 'm' ) {
2014-02-10 13:14:38 +00:00
var styleStr = '' ;
$ . each ( cssResizeRules , function ( selector , rules ) {
selector = '#svg_editor ' + selector . replace ( /,/g , ', #svg_editor' ) ;
styleStr += selector + '{' ;
$ . each ( rules , function ( prop , values ) {
var val ;
if ( typeof values === 'number' ) {
val = ( values * scale ) + 'px' ;
} else if ( values [ size ] || values . all ) {
val = ( values [ size ] || values . all ) ;
}
styleStr += ( prop + ':' + val + ';' ) ;
} ) ;
styleStr += '}' ;
} ) ;
//this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')';
var prefix = '-' + uaPrefix . toLowerCase ( ) + '-' ;
styleStr += ( sel _toscale + '{' + prefix + 'transform: scale(' + scale + ');}'
+ ' #svg_editor div.toolset .toolset {' + prefix + 'transform: scale(1); margin: 1px !important;}' // Hack for markers
+ ' #svg_editor .ui-slider {' + prefix + 'transform: scale(' + ( 1 / scale ) + ');}' // Hack for sliders
) ;
rule _elem . text ( styleStr ) ;
}
setFlyoutPositions ( ) ;
} ;
// TODO: Combine this with addDropDown or find other way to optimize
var addAltDropDown = function ( elem , list , callback , opts ) {
var button = $ ( elem ) ;
list = $ ( list ) ;
var on _button = false ;
var dropUp = opts . dropUp ;
if ( dropUp ) {
$ ( elem ) . addClass ( 'dropup' ) ;
}
list . find ( 'li' ) . bind ( 'mouseup' , function ( ) {
if ( opts . seticon ) {
setIcon ( '#cur_' + button [ 0 ] . id , $ ( this ) . children ( ) ) ;
$ ( this ) . addClass ( 'current' ) . siblings ( ) . removeClass ( 'current' ) ;
}
callback . apply ( this , arguments ) ;
} ) ;
$ ( window ) . mouseup ( function ( evt ) {
if ( ! on _button ) {
button . removeClass ( 'down' ) ;
list . hide ( ) ;
list . css ( { top : 0 , left : 0 } ) ;
}
on _button = false ;
} ) ;
2014-02-18 15:06:27 +00:00
// var height = list.height(); // Currently unused
2014-02-10 13:14:38 +00:00
button . bind ( 'mousedown' , function ( ) {
var off = button . offset ( ) ;
if ( dropUp ) {
off . top -= list . height ( ) ;
off . left += 8 ;
} else {
off . top += button . height ( ) ;
}
list . offset ( off ) ;
if ( ! button . hasClass ( 'down' ) ) {
list . show ( ) ;
on _button = true ;
} else {
// CSS position must be reset for Webkit
list . hide ( ) ;
list . css ( { top : 0 , left : 0 } ) ;
}
button . toggleClass ( 'down' ) ;
} ) . hover ( function ( ) {
on _button = true ;
} ) . mouseout ( function ( ) {
on _button = false ;
} ) ;
if ( opts . multiclick ) {
list . mousedown ( function ( ) {
on _button = true ;
} ) ;
}
} ;
2014-02-18 15:06:27 +00:00
var extsPreLang = [ ] ;
var extAdded = function ( win , ext ) {
if ( ! ext ) {
return ;
}
2014-02-10 13:14:38 +00:00
var cb _called = false ;
var resize _done = false ;
var cb _ready = true ; // Set to false to delay callback (e.g. wait for $.svgIcons)
2014-02-18 15:06:27 +00:00
if ( ext . langReady ) {
if ( editor . langChanged ) { // We check for this since the "lang" pref could have been set by storage
var lang = $ . pref ( 'lang' ) ;
ext . langReady ( { lang : lang , uiStrings : uiStrings } ) ;
}
else {
extsPreLang . push ( ext ) ;
}
}
2014-02-10 13:14:38 +00:00
function prepResize ( ) {
if ( resize _timer ) {
clearTimeout ( resize _timer ) ;
resize _timer = null ;
}
if ( ! resize _done ) {
resize _timer = setTimeout ( function ( ) {
resize _done = true ;
2014-02-18 15:06:27 +00:00
setIconSize ( $ . pref ( 'iconsize' ) ) ;
2014-02-10 13:14:38 +00:00
} , 50 ) ;
}
}
var runCallback = function ( ) {
if ( ext . callback && ! cb _called && cb _ready ) {
cb _called = true ;
ext . callback ( ) ;
}
} ;
var btn _selects = [ ] ;
if ( ext . context _tools ) {
$ . each ( ext . context _tools , function ( i , tool ) {
// Add select tool
var html ;
var cont _id = tool . container _id ? ( ' id="' + tool . container _id + '"' ) : '' ;
var panel = $ ( '#' + tool . panel ) ;
// create the panel if it doesn't exist
if ( ! panel . length ) {
panel = $ ( '<div>' , { id : tool . panel } ) . appendTo ( '#tools_top' ) ;
}
// TODO: Allow support for other types, or adding to existing tool
switch ( tool . type ) {
case 'tool_button' :
html = '<div class="tool_button">' + tool . id + '</div>' ;
var div = $ ( html ) . appendTo ( panel ) ;
if ( tool . events ) {
$ . each ( tool . events , function ( evt , func ) {
$ ( div ) . bind ( evt , func ) ;
} ) ;
}
break ;
case 'select' :
html = '<label' + cont _id + '>'
+ '<select id="' + tool . id + '">' ;
$ . each ( tool . options , function ( val , text ) {
2014-04-09 02:25:25 +00:00
var sel = ( val == tool . defval ) ? ' selected' : '' ;
2014-02-10 13:14:38 +00:00
html += '<option value="' + val + '"' + sel + '>' + text + '</option>' ;
} ) ;
2014-04-09 02:25:25 +00:00
html += '</select></label>' ;
2014-02-10 13:14:38 +00:00
// Creates the tool, hides & adds it, returns the select element
var sel = $ ( html ) . appendTo ( panel ) . find ( 'select' ) ;
$ . each ( tool . events , function ( evt , func ) {
$ ( sel ) . bind ( evt , func ) ;
} ) ;
break ;
case 'button-select' :
html = '<div id="' + tool . id + '" class="dropdown toolset" title="' + tool . title + '">'
+ '<div id="cur_' + tool . id + '" class="icon_label"></div><button></button></div>' ;
var list = $ ( '<ul id="' + tool . id + '_opts"></ul>' ) . appendTo ( '#option_lists' ) ;
if ( tool . colnum ) {
list . addClass ( 'optcols' + tool . colnum ) ;
}
// Creates the tool, hides & adds it, returns the select element
var dropdown = $ ( html ) . appendTo ( panel ) . children ( ) ;
btn _selects . push ( {
elem : ( '#' + tool . id ) ,
list : ( '#' + tool . id + '_opts' ) ,
title : tool . title ,
callback : tool . events . change ,
cur : ( '#cur_' + tool . id )
} ) ;
break ;
case 'input' :
html = '<label' + cont _id + '>'
+ '<span id="' + tool . id + '_label">'
+ tool . label + ':</span>'
+ '<input id="' + tool . id + '" title="' + tool . title
2014-04-09 03:44:19 +00:00
+ '" size="' + ( tool . size || '4' ) + '" value="' + ( tool . defval || '' ) + '" type="text"/></label>' ;
2014-02-10 13:14:38 +00:00
// Creates the tool, hides & adds it, returns the select element
// Add to given tool.panel
var inp = $ ( html ) . appendTo ( panel ) . find ( 'input' ) ;
if ( tool . spindata ) {
inp . SpinButton ( tool . spindata ) ;
}
if ( tool . events ) {
$ . each ( tool . events , function ( evt , func ) {
inp . bind ( evt , func ) ;
} ) ;
}
break ;
default :
break ;
}
} ) ;
}
if ( ext . buttons ) {
var fallback _obj = { } ,
placement _obj = { } ,
svgicons = ext . svgicons ,
holders = { } ;
// Add buttons given by extension
$ . each ( ext . buttons , function ( i , btn ) {
var icon , svgicon , tls _id ;
var id = btn . id ;
var num = i ;
// Give button a unique ID
while ( $ ( '#' + id ) . length ) {
id = btn . id + '_' + ( ++ num ) ;
}
if ( ! svgicons ) {
icon = $ ( '<img src="' + btn . icon + '">' ) ;
} else {
fallback _obj [ id ] = btn . icon ;
svgicon = btn . svgicon || btn . id ;
if ( btn . type == 'app_menu' ) {
placement _obj [ '#' + id + ' > div' ] = svgicon ;
} else {
placement _obj [ '#' + id ] = svgicon ;
}
}
var cls , parent ;
// Set button up according to its type
switch ( btn . type ) {
case 'mode_flyout' :
case 'mode' :
cls = 'tool_button' ;
parent = '#tools_left' ;
break ;
case 'context' :
cls = 'tool_button' ;
parent = '#' + btn . panel ;
// create the panel if it doesn't exist
if ( ! $ ( parent ) . length ) {
$ ( '<div>' , { id : btn . panel } ) . appendTo ( '#tools_top' ) ;
}
break ;
case 'app_menu' :
cls = '' ;
parent = '#main_menu ul' ;
break ;
}
var flyout _holder , cur _h , show _btn , ref _data , ref _btn ;
var button = $ ( ( btn . list || btn . type == 'app_menu' ) ? '<li/>' : '<div/>' )
. attr ( 'id' , id )
. attr ( 'title' , btn . title )
. addClass ( cls ) ;
if ( ! btn . includeWith && ! btn . list ) {
2014-02-18 15:06:27 +00:00
if ( 'position' in btn ) {
if ( $ ( parent ) . children ( ) . eq ( btn . position ) . length ) {
$ ( parent ) . children ( ) . eq ( btn . position ) . before ( button ) ;
}
else {
$ ( parent ) . children ( ) . last ( ) . before ( button ) ;
}
2014-02-10 13:14:38 +00:00
} else {
button . appendTo ( parent ) ;
}
if ( btn . type == 'mode_flyout' ) {
// Add to flyout menu / make flyout menu
// var opts = btn.includeWith;
// // opts.button, default, position
ref _btn = $ ( button ) ;
flyout _holder = ref _btn . parent ( ) ;
// Create a flyout menu if there isn't one already
if ( ! ref _btn . parent ( ) . hasClass ( 'tools_flyout' ) ) {
// Create flyout placeholder
tls _id = ref _btn [ 0 ] . id . replace ( 'tool_' , 'tools_' ) ;
show _btn = ref _btn . clone ( )
2014-02-18 15:06:27 +00:00
. attr ( 'id' , tls _id + '_show' )
2014-02-10 13:14:38 +00:00
. append ( $ ( '<div>' , { 'class' : 'flyout_arrow_horiz' } ) ) ;
ref _btn . before ( show _btn ) ;
// Create a flyout div
flyout _holder = makeFlyoutHolder ( tls _id , ref _btn ) ;
flyout _holder . data ( 'isLibrary' , true ) ;
show _btn . data ( 'isLibrary' , true ) ;
}
// ref_data = Actions.getButtonData(opts.button);
placement _obj [ '#' + tls _id + '_show' ] = btn . id ;
// TODO: Find way to set the current icon using the iconloader if this is not default
// Include data for extension button as well as ref button
cur _h = holders [ '#' + flyout _holder [ 0 ] . id ] = [ {
sel : '#' + id ,
fn : btn . events . click ,
icon : btn . id ,
// key: btn.key,
isDefault : true
} , ref _data ] ;
//
// // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
//
// var pos = ('position' in opts)?opts.position:'last';
// var len = flyout_holder.children().length;
//
// // Add at given position or end
// if (!isNaN(pos) && pos >= 0 && pos < len) {
// flyout_holder.children().eq(pos).before(button);
// } else {
// flyout_holder.append(button);
// cur_h.reverse();
// }
} else if ( btn . type == 'app_menu' ) {
button . append ( '<div>' ) . append ( btn . title ) ;
}
}
else if ( btn . list ) {
// Add button to list
button . addClass ( 'push_button' ) ;
$ ( '#' + btn . list + '_opts' ) . append ( button ) ;
if ( btn . isDefault ) {
$ ( '#cur_' + btn . list ) . append ( button . children ( ) . clone ( ) ) ;
svgicon = btn . svgicon || btn . id ;
placement _obj [ '#cur_' + btn . list ] = svgicon ;
}
}
else if ( btn . includeWith ) {
// Add to flyout menu / make flyout menu
var opts = btn . includeWith ;
// opts.button, default, position
ref _btn = $ ( opts . button ) ;
flyout _holder = ref _btn . parent ( ) ;
// Create a flyout menu if there isn't one already
if ( ! ref _btn . parent ( ) . hasClass ( 'tools_flyout' ) ) {
// Create flyout placeholder
tls _id = ref _btn [ 0 ] . id . replace ( 'tool_' , 'tools_' ) ;
show _btn = ref _btn . clone ( )
. attr ( 'id' , tls _id + '_show' )
. append ( $ ( '<div>' , { 'class' : 'flyout_arrow_horiz' } ) ) ;
ref _btn . before ( show _btn ) ;
// Create a flyout div
flyout _holder = makeFlyoutHolder ( tls _id , ref _btn ) ;
}
ref _data = Actions . getButtonData ( opts . button ) ;
if ( opts . isDefault ) {
placement _obj [ '#' + tls _id + '_show' ] = btn . id ;
}
// TODO: Find way to set the current icon using the iconloader if this is not default
// Include data for extension button as well as ref button
2014-04-09 03:44:19 +00:00
cur _h = holders [ '#' + flyout _holder [ 0 ] . id ] = [ {
sel : '#' + id ,
2014-02-10 13:14:38 +00:00
fn : btn . events . click ,
icon : btn . id ,
key : btn . key ,
2014-04-09 03:44:19 +00:00
isDefault : btn . includeWith ? btn . includeWith . isDefault : 0
2014-02-10 13:14:38 +00:00
} , ref _data ] ;
// {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
2014-04-08 13:49:58 +00:00
var pos = ( 'position' in opts ) ? opts . position : 'last' ;
2014-02-10 13:14:38 +00:00
var len = flyout _holder . children ( ) . length ;
// Add at given position or end
if ( ! isNaN ( pos ) && pos >= 0 && pos < len ) {
flyout _holder . children ( ) . eq ( pos ) . before ( button ) ;
} else {
flyout _holder . append ( button ) ;
cur _h . reverse ( ) ;
}
}
if ( ! svgicons ) {
button . append ( icon ) ;
}
if ( ! btn . list ) {
// Add given events to button
$ . each ( btn . events , function ( name , func ) {
if ( name == 'click' && btn . type == 'mode' ) {
if ( btn . includeWith ) {
button . bind ( name , func ) ;
} else {
button . bind ( name , function ( ) {
if ( toolButtonClick ( button ) ) {
func ( ) ;
}
} ) ;
}
if ( btn . key ) {
$ ( document ) . bind ( 'keydown' , btn . key , func ) ;
if ( btn . title ) {
button . attr ( 'title' , btn . title + ' [' + btn . key + ']' ) ;
}
}
} else {
button . bind ( name , func ) ;
}
} ) ;
}
setupFlyouts ( holders ) ;
} ) ;
$ . each ( btn _selects , function ( ) {
addAltDropDown ( this . elem , this . list , this . callback , { seticon : true } ) ;
} ) ;
if ( svgicons ) {
cb _ready = false ; // Delay callback
}
$ . svgIcons ( svgicons , {
2014-02-18 15:06:27 +00:00
w : 24 , h : 24 ,
2014-02-10 13:14:38 +00:00
id _match : false ,
no _img : ( ! svgedit . browser . isWebkit ( ) ) ,
fallback : fallback _obj ,
placement : placement _obj ,
2014-02-18 15:06:27 +00:00
callback : function ( icons ) {
2014-02-10 13:14:38 +00:00
// Non-ideal hack to make the icon match the current size
2014-02-18 15:06:27 +00:00
//if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
if ( $ . pref ( 'iconsize' ) !== 'm' ) {
2014-02-10 13:14:38 +00:00
prepResize ( ) ;
}
cb _ready = true ; // Ready for callback
runCallback ( ) ;
}
} ) ;
}
runCallback ( ) ;
} ;
var getPaint = function ( color , opac , type ) {
// update the editor's fill paint
var opts = { alpha : opac } ;
if ( color . indexOf ( 'url(#' ) === 0 ) {
var refElem = svgCanvas . getRefElem ( color ) ;
if ( refElem ) {
refElem = refElem . cloneNode ( true ) ;
} else {
refElem = $ ( '#' + type + '_color defs *' ) [ 0 ] ;
}
opts [ refElem . tagName ] = refElem ;
} else if ( color . indexOf ( '#' ) === 0 ) {
opts . solidColor = color . substr ( 1 ) ;
} else {
opts . solidColor = 'none' ;
}
return new $ . jGraduate . Paint ( opts ) ;
} ;
$ ( '#text' ) . focus ( function ( ) { textBeingEntered = true ; } ) ;
$ ( '#text' ) . blur ( function ( ) { textBeingEntered = false ; } ) ;
// bind the selected event to our function that handles updates to the UI
svgCanvas . bind ( 'selected' , selectedChanged ) ;
svgCanvas . bind ( 'transition' , elementTransition ) ;
svgCanvas . bind ( 'changed' , elementChanged ) ;
svgCanvas . bind ( 'saved' , saveHandler ) ;
2014-06-01 21:29:54 +00:00
svgCanvas . bind ( 'exported' , exportHandler ) ;
2014-05-22 10:21:29 +00:00
svgCanvas . bind ( 'exportedPDF' , function ( win , data ) {
var exportWindowName = data . exportWindowName ;
if ( exportWindowName ) {
exportWindow = window . open ( '' , exportWindowName ) ; // A hack to get the window via JSON-able name without opening a new one
}
exportWindow . location . href = data . dataurlstring ;
} ) ;
2014-02-10 13:14:38 +00:00
svgCanvas . bind ( 'zoomed' , zoomChanged ) ;
svgCanvas . bind ( 'contextset' , contextChanged ) ;
svgCanvas . bind ( 'extension_added' , extAdded ) ;
svgCanvas . textActions . setInputElem ( $ ( '#text' ) [ 0 ] ) ;
var str = '<div class="palette_item" data-rgb="none"></div>' ;
2014-02-18 15:06:27 +00:00
$ . each ( palette , function ( i , item ) {
2014-02-10 13:14:38 +00:00
str += '<div class="palette_item" style="background-color: ' + item + ';" data-rgb="' + item + '"></div>' ;
} ) ;
$ ( '#palette' ) . append ( str ) ;
// Set up editor background functionality
// TODO add checkerboard as "pattern"
var color _blocks = [ '#FFF' , '#888' , '#000' ] ; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)'];
str = '' ;
$ . each ( color _blocks , function ( ) {
str += '<div class="color_block" style="background-color:' + this + ';"></div>' ;
} ) ;
$ ( '#bg_blocks' ) . append ( str ) ;
var blocks = $ ( '#bg_blocks div' ) ;
var cur _bg = 'cur_background' ;
blocks . each ( function ( ) {
var blk = $ ( this ) ;
blk . click ( function ( ) {
blocks . removeClass ( cur _bg ) ;
$ ( this ) . addClass ( cur _bg ) ;
} ) ;
} ) ;
2014-02-18 15:06:27 +00:00
setBackground ( $ . pref ( 'bkgd_color' ) , $ . pref ( 'bkgd_url' ) ) ;
2014-02-10 13:14:38 +00:00
2014-02-18 15:06:27 +00:00
$ ( '#image_save_opts input' ) . val ( [ $ . pref ( 'img_save' ) ] ) ;
2014-02-10 13:14:38 +00:00
var changeRectRadius = function ( ctl ) {
svgCanvas . setRectRadius ( ctl . value ) ;
} ;
var changeFontSize = function ( ctl ) {
svgCanvas . setFontSize ( ctl . value ) ;
} ;
var changeStrokeWidth = function ( ctl ) {
var val = ctl . value ;
if ( val == 0 && selectedElement && [ 'line' , 'polyline' ] . indexOf ( selectedElement . nodeName ) >= 0 ) {
val = ctl . value = 1 ;
}
svgCanvas . setStrokeWidth ( val ) ;
} ;
var changeRotationAngle = function ( ctl ) {
svgCanvas . setRotationAngle ( ctl . value ) ;
$ ( '#tool_reorient' ) . toggleClass ( 'disabled' , parseInt ( ctl . value , 10 ) === 0 ) ;
} ;
var changeOpacity = function ( ctl , val ) {
if ( val == null ) { val = ctl . value ; }
$ ( '#group_opacity' ) . val ( val ) ;
if ( ! ctl || ! ctl . handle ) {
$ ( '#opac_slider' ) . slider ( 'option' , 'value' , val ) ;
}
svgCanvas . setOpacity ( val / 100 ) ;
} ;
var changeBlur = function ( ctl , val , noUndo ) {
if ( val == null ) { val = ctl . value ; }
$ ( '#blur' ) . val ( val ) ;
var complete = false ;
if ( ! ctl || ! ctl . handle ) {
$ ( '#blur_slider' ) . slider ( 'option' , 'value' , val ) ;
complete = true ;
}
if ( noUndo ) {
svgCanvas . setBlurNoUndo ( val ) ;
} else {
svgCanvas . setBlur ( val , complete ) ;
}
} ;
$ ( '#stroke_style' ) . change ( function ( ) {
svgCanvas . setStrokeAttr ( 'stroke-dasharray' , $ ( this ) . val ( ) ) ;
operaRepaint ( ) ;
} ) ;
$ ( '#stroke_linejoin' ) . change ( function ( ) {
svgCanvas . setStrokeAttr ( 'stroke-linejoin' , $ ( this ) . val ( ) ) ;
operaRepaint ( ) ;
} ) ;
// Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
$ ( 'select' ) . change ( function ( ) { $ ( this ) . blur ( ) ; } ) ;
// fired when user wants to move elements to another layer
var promptMoveLayerOnce = false ;
$ ( '#selLayerNames' ) . change ( function ( ) {
var destLayer = this . options [ this . selectedIndex ] . value ;
var confirmStr = uiStrings . notification . QmoveElemsToLayer . replace ( '%s' , destLayer ) ;
var moveToLayer = function ( ok ) {
if ( ! ok ) { return ; }
promptMoveLayerOnce = true ;
svgCanvas . moveSelectedToLayer ( destLayer ) ;
svgCanvas . clearSelection ( ) ;
populateLayers ( ) ;
} ;
if ( destLayer ) {
if ( promptMoveLayerOnce ) {
moveToLayer ( true ) ;
} else {
$ . confirm ( confirmStr , moveToLayer ) ;
}
}
} ) ;
$ ( '#font_family' ) . change ( function ( ) {
svgCanvas . setFontFamily ( this . value ) ;
} ) ;
$ ( '#seg_type' ) . change ( function ( ) {
svgCanvas . setSegType ( $ ( this ) . val ( ) ) ;
} ) ;
2016-03-14 07:01:42 +00:00
$ ( '#text' ) . bind ( "keyup input" , function ( ) {
2014-02-10 13:14:38 +00:00
svgCanvas . setTextContent ( this . value ) ;
} ) ;
$ ( '#image_url' ) . change ( function ( ) {
setImageURL ( this . value ) ;
} ) ;
$ ( '#link_url' ) . change ( function ( ) {
if ( this . value . length ) {
svgCanvas . setLinkURL ( this . value ) ;
} else {
svgCanvas . removeHyperlink ( ) ;
}
} ) ;
$ ( '#g_title' ) . change ( function ( ) {
svgCanvas . setGroupTitle ( this . value ) ;
} ) ;
$ ( '.attr_changer' ) . change ( function ( ) {
var attr = this . getAttribute ( 'data-attr' ) ;
var val = this . value ;
var valid = svgedit . units . isValidUnit ( attr , val , selectedElement ) ;
if ( ! valid ) {
$ . alert ( uiStrings . notification . invalidAttrValGiven ) ;
this . value = selectedElement . getAttribute ( attr ) ;
return false ;
}
2015-09-27 07:01:04 +00:00
if ( attr !== 'id' && attr !== 'class' ) {
2014-02-10 13:14:38 +00:00
if ( isNaN ( val ) ) {
val = svgCanvas . convertToNum ( attr , val ) ;
} else if ( curConfig . baseUnit !== 'px' ) {
// Convert unitless value to one with given unit
var unitData = svgedit . units . getTypeMap ( ) ;
if ( selectedElement [ attr ] || svgCanvas . getMode ( ) === 'pathedit' || attr === 'x' || attr === 'y' ) {
val *= unitData [ curConfig . baseUnit ] ;
}
}
}
// if the user is changing the id, then de-select the element first
// change the ID, then re-select it with the new ID
if ( attr === 'id' ) {
var elem = selectedElement ;
svgCanvas . clearSelection ( ) ;
elem . id = val ;
svgCanvas . addToSelection ( [ elem ] , true ) ;
} else {
svgCanvas . changeSelectedAttribute ( attr , val ) ;
}
this . blur ( ) ;
} ) ;
// Prevent selection of elements when shift-clicking
$ ( '#palette' ) . mouseover ( function ( ) {
var inp = $ ( '<input type="hidden">' ) ;
$ ( this ) . append ( inp ) ;
inp . focus ( ) . remove ( ) ;
} ) ;
$ ( '.palette_item' ) . mousedown ( function ( evt ) {
// shift key or right click for stroke
var picker = evt . shiftKey || evt . button === 2 ? 'stroke' : 'fill' ;
var color = $ ( this ) . data ( 'rgb' ) ;
var paint ;
// Webkit-based browsers returned 'initial' here for no stroke
if ( color === 'none' || color === 'transparent' || color === 'initial' ) {
color = 'none' ;
paint = new $ . jGraduate . Paint ( ) ;
} else {
paint = new $ . jGraduate . Paint ( { alpha : 100 , solidColor : color . substr ( 1 ) } ) ;
}
paintBox [ picker ] . setPaint ( paint ) ;
2013-02-19 13:17:27 +00:00
svgCanvas . setColor ( picker , color ) ;
2012-10-22 10:47:50 +00:00
2013-02-19 13:17:27 +00:00
if ( color !== 'none' && svgCanvas . getPaintOpacity ( picker ) !== 1 ) {
svgCanvas . setPaintOpacity ( picker , 1.0 ) ;
2010-03-11 21:07:13 +00:00
}
updateToolButtonState ( ) ;
2013-02-15 13:38:55 +00:00
} ) . bind ( 'contextmenu' , function ( e ) { e . preventDefault ( ) ; } ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ ( '#toggle_stroke_tools' ) . on ( 'click' , function ( ) {
$ ( '#tools_bottom' ) . toggleClass ( 'expanded' ) ;
2010-04-01 19:02:36 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-04-01 16:00:50 +00:00
( function ( ) {
2012-10-22 10:47:50 +00:00
var last _x = null , last _y = null , w _area = workarea [ 0 ] ,
2010-04-01 16:00:50 +00:00
panning = false , keypan = false ;
2012-10-22 10:47:50 +00:00
2010-04-01 16:00:50 +00:00
$ ( '#svgcanvas' ) . bind ( 'mousemove mouseup' , function ( evt ) {
2014-01-31 10:55:18 +00:00
if ( panning === false ) { return ; }
2010-04-01 16:00:50 +00:00
w _area . scrollLeft -= ( evt . clientX - last _x ) ;
w _area . scrollTop -= ( evt . clientY - last _y ) ;
2012-10-22 10:47:50 +00:00
2010-04-01 16:00:50 +00:00
last _x = evt . clientX ;
last _y = evt . clientY ;
2012-10-22 10:47:50 +00:00
2014-01-31 10:55:18 +00:00
if ( evt . type === 'mouseup' ) { panning = false ; }
2010-04-01 16:00:50 +00:00
return false ;
} ) . mousedown ( function ( evt ) {
2013-02-15 21:57:35 +00:00
if ( evt . button === 1 || keypan === true ) {
2010-04-01 16:00:50 +00:00
panning = true ;
last _x = evt . clientX ;
last _y = evt . clientY ;
return false ;
}
} ) ;
2012-10-22 10:47:50 +00:00
2010-04-01 16:00:50 +00:00
$ ( window ) . mouseup ( function ( ) {
panning = false ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-04-01 16:00:50 +00:00
$ ( document ) . bind ( 'keydown' , 'space' , function ( evt ) {
svgCanvas . spaceKey = keypan = true ;
evt . preventDefault ( ) ;
} ) . bind ( 'keyup' , 'space' , function ( evt ) {
evt . preventDefault ( ) ;
svgCanvas . spaceKey = keypan = false ;
2010-09-27 18:58:04 +00:00
} ) . bind ( 'keydown' , 'shift' , function ( evt ) {
2013-02-15 21:57:35 +00:00
if ( svgCanvas . getMode ( ) === 'zoom' ) {
2010-09-27 18:58:04 +00:00
workarea . css ( 'cursor' , zoomOutIcon ) ;
}
} ) . bind ( 'keyup' , 'shift' , function ( evt ) {
2013-02-15 21:57:35 +00:00
if ( svgCanvas . getMode ( ) === 'zoom' ) {
2010-09-27 18:58:04 +00:00
workarea . css ( 'cursor' , zoomInIcon ) ;
}
2013-02-15 13:38:55 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . setPanning = function ( active ) {
2013-02-15 13:38:55 +00:00
svgCanvas . spaceKey = keypan = active ;
} ;
} ( ) ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 10:21:55 +00:00
( function ( ) {
2010-03-11 21:07:13 +00:00
var button = $ ( '#main_icon' ) ;
var overlay = $ ( '#main_icon span' ) ;
var list = $ ( '#main_menu' ) ;
var on _button = false ;
var height = 0 ;
var js _hover = true ;
var set _click = false ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
/ *
// Currently unused
2010-03-11 21:07:13 +00:00
var hideMenu = function ( ) {
list . fadeOut ( 200 ) ;
} ;
2014-02-18 15:06:27 +00:00
* /
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( window ) . mouseup ( function ( evt ) {
2013-02-15 21:57:35 +00:00
if ( ! on _button ) {
2010-03-11 21:07:13 +00:00
button . removeClass ( 'buttondown' ) ;
2012-10-22 10:47:50 +00:00
// do not hide if it was the file input as that input needs to be visible
2010-03-11 21:07:13 +00:00
// for its change event to fire
2013-02-15 21:57:35 +00:00
if ( evt . target . tagName != 'INPUT' ) {
2010-03-11 21:07:13 +00:00
list . fadeOut ( 200 ) ;
2013-02-15 21:57:35 +00:00
} else if ( ! set _click ) {
2010-03-11 21:07:13 +00:00
set _click = true ;
$ ( evt . target ) . click ( function ( ) {
2013-02-15 21:57:35 +00:00
list . css ( 'margin-left' , '-9999px' ) . show ( ) ;
2010-03-11 21:07:13 +00:00
} ) ;
}
}
on _button = false ;
2010-07-09 19:09:37 +00:00
} ) . mousedown ( function ( evt ) {
2014-01-31 00:27:46 +00:00
// $('.contextMenu').hide();
2010-08-16 20:26:06 +00:00
var islib = $ ( evt . target ) . closest ( 'div.tools_flyout, .contextMenu' ) . length ;
2014-02-10 10:21:55 +00:00
if ( ! islib ) { $ ( '.tools_flyout:visible,.contextMenu' ) . fadeOut ( 250 ) ; }
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
overlay . bind ( 'mousedown' , function ( ) {
if ( ! button . hasClass ( 'buttondown' ) ) {
// Margin must be reset in case it was changed before;
2013-02-16 16:07:19 +00:00
list . css ( 'margin-left' , 0 ) . show ( ) ;
2013-02-15 21:57:35 +00:00
if ( ! height ) {
2010-03-11 21:07:13 +00:00
height = list . height ( ) ;
}
2013-02-15 21:57:35 +00:00
// Using custom animation as slideDown has annoying 'bounce effect'
2010-03-11 21:07:13 +00:00
list . css ( 'height' , 0 ) . animate ( {
'height' : height
2013-02-16 16:07:19 +00:00
} , 200 ) ;
2010-03-11 21:07:13 +00:00
on _button = true ;
} else {
list . fadeOut ( 200 ) ;
}
2013-02-16 16:07:19 +00:00
button . toggleClass ( 'buttondown buttonup' ) ;
2010-03-11 21:07:13 +00:00
} ) . hover ( function ( ) {
on _button = true ;
} ) . mouseout ( function ( ) {
on _button = false ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
var list _items = $ ( '#main_menu li' ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Check if JS method of hovering needs to be used (Webkit bug)
2010-01-13 18:28:19 +00:00
list _items . mouseover ( function ( ) {
2010-03-11 21:07:13 +00:00
js _hover = ( $ ( this ) . css ( 'background-color' ) == 'rgba(0, 0, 0, 0)' ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
list _items . unbind ( 'mouseover' ) ;
2013-02-15 21:57:35 +00:00
if ( js _hover ) {
2010-03-11 21:07:13 +00:00
list _items . mouseover ( function ( ) {
this . style . backgroundColor = '#FFC' ;
} ) . mouseout ( function ( ) {
this . style . backgroundColor = 'transparent' ;
return true ;
} ) ;
}
} ) ;
} ( ) ) ;
2010-07-26 17:48:02 +00:00
// Made public for UI customization.
2014-02-18 23:57:49 +00:00
// TODO: Group UI functions into a public editor.ui interface.
2014-02-18 15:06:27 +00:00
editor . addDropDown = function ( elem , callback , dropUp ) {
2014-02-10 10:21:55 +00:00
if ( $ ( elem ) . length == 0 ) { return ; } // Quit if called on non-existant element
2010-03-11 21:07:13 +00:00
var button = $ ( elem ) . find ( 'button' ) ;
2011-01-31 15:57:01 +00:00
var list = $ ( elem ) . find ( 'ul' ) . attr ( 'id' , $ ( elem ) [ 0 ] . id + '-list' ) ;
2010-03-11 21:07:13 +00:00
var on _button = false ;
2013-02-15 21:57:35 +00:00
if ( dropUp ) {
2010-03-11 21:07:13 +00:00
$ ( elem ) . addClass ( 'dropup' ) ;
2013-02-18 20:55:04 +00:00
} else {
// Move list to place where it can overflow container
$ ( '#option_lists' ) . append ( list ) ;
2010-03-11 21:07:13 +00:00
}
2011-01-31 15:57:01 +00:00
list . find ( 'li' ) . bind ( 'mouseup' , callback ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( window ) . mouseup ( function ( evt ) {
2013-02-15 21:57:35 +00:00
if ( ! on _button ) {
2010-03-11 21:07:13 +00:00
button . removeClass ( 'down' ) ;
list . hide ( ) ;
}
on _button = false ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
button . bind ( 'mousedown' , function ( ) {
if ( ! button . hasClass ( 'down' ) ) {
2014-02-10 13:14:38 +00:00
if ( ! dropUp ) {
var pos = $ ( elem ) . position ( ) ;
list . css ( {
top : pos . top + 24 ,
left : pos . left - 10
} ) ;
}
2010-04-05 19:53:14 +00:00
list . show ( ) ;
on _button = true ;
} else {
list . hide ( ) ;
}
2013-02-18 20:55:04 +00:00
button . toggleClass ( 'down' ) ;
2010-04-05 19:53:14 +00:00
} ) . hover ( function ( ) {
on _button = true ;
} ) . mouseout ( function ( ) {
on _button = false ;
} ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . addDropDown ( '#font_family_dropdown' , function ( ) {
2010-03-11 21:07:13 +00:00
$ ( '#font_family' ) . val ( $ ( this ) . text ( ) ) . change ( ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . addDropDown ( '#opacity_dropdown' , function ( ) {
2014-02-10 10:21:55 +00:00
if ( $ ( this ) . find ( 'div' ) . length ) { return ; }
2014-02-18 15:06:27 +00:00
var perc = parseInt ( $ ( this ) . text ( ) . split ( '%' ) [ 0 ] , 10 ) ;
2010-03-11 21:07:13 +00:00
changeOpacity ( false , perc ) ;
} , true ) ;
2012-10-22 10:47:50 +00:00
// For slider usage, see: http://jqueryui.com/demos/slider/
2013-02-15 21:57:35 +00:00
$ ( '#opac_slider' ) . slider ( {
2010-03-11 21:07:13 +00:00
start : function ( ) {
$ ( '#opacity_dropdown li:not(.special)' ) . hide ( ) ;
} ,
stop : function ( ) {
$ ( '#opacity_dropdown li' ) . show ( ) ;
$ ( window ) . mouseup ( ) ;
} ,
2013-02-23 19:22:00 +00:00
slide : function ( evt , ui ) {
2010-03-11 21:07:13 +00:00
changeOpacity ( ui ) ;
}
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . addDropDown ( '#blur_dropdown' , $ . noop ) ;
2012-10-22 10:47:50 +00:00
2010-04-28 16:34:02 +00:00
var slideStart = false ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ ( '#blur_slider' ) . slider ( {
2010-04-06 18:40:10 +00:00
max : 10 ,
2013-02-19 13:25:54 +00:00
step : 0.1 ,
2010-04-06 20:16:07 +00:00
stop : function ( evt , ui ) {
2010-04-28 16:34:02 +00:00
slideStart = false ;
2010-04-06 20:16:07 +00:00
changeBlur ( ui ) ;
2010-04-06 18:40:10 +00:00
$ ( '#blur_dropdown li' ) . show ( ) ;
$ ( window ) . mouseup ( ) ;
} ,
2010-04-28 16:34:02 +00:00
start : function ( ) {
slideStart = true ;
} ,
2013-02-23 19:22:00 +00:00
slide : function ( evt , ui ) {
2010-04-28 16:34:02 +00:00
changeBlur ( ui , null , slideStart ) ;
2010-04-06 18:40:10 +00:00
}
} ) ;
2014-02-18 15:06:27 +00:00
editor . addDropDown ( '#zoom_dropdown' , function ( ) {
2010-03-11 21:07:13 +00:00
var item = $ ( this ) ;
2013-02-19 13:25:54 +00:00
var val = item . data ( 'val' ) ;
2013-02-15 21:57:35 +00:00
if ( val ) {
2010-03-11 21:07:13 +00:00
zoomChanged ( window , val ) ;
} else {
2014-03-16 03:32:12 +00:00
changeZoom ( { value : parseFloat ( item . text ( ) ) } ) ;
2010-03-11 21:07:13 +00:00
}
} , true ) ;
2012-10-22 10:47:50 +00:00
2010-04-05 19:53:14 +00:00
addAltDropDown ( '#stroke_linecap' , '#linecap_opts' , function ( ) {
2010-05-24 19:46:32 +00:00
setStrokeOpt ( this , true ) ;
2014-02-10 13:14:38 +00:00
} , { dropUp : true } ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
addAltDropDown ( '#stroke_linejoin' , '#linejoin_opts' , function ( ) {
setStrokeOpt ( this , true ) ;
} , { dropUp : true } ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
addAltDropDown ( '#tool_position' , '#position_opts' , function ( ) {
var letter = this . id . replace ( 'tool_pos' , '' ) . charAt ( 0 ) ;
svgCanvas . alignSelectedElements ( letter , 'page' ) ;
} , { multiclick : true } ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
/ *
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
When a flyout icon is selected
( if flyout ) {
- Change the icon
- Make pressing the button run its stuff
}
- Run its stuff
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
When its shortcut key is pressed
- If not current in list , do as above
, else :
- Just run its stuff
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
* /
// Unfocus text input when workarea is mousedowned.
( function ( ) {
var inp ;
var unfocus = function ( ) {
$ ( inp ) . blur ( ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
$ ( '#svg_editor' ) . find ( 'button, select, input:not(#text)' ) . focus ( function ( ) {
inp = this ;
ui _context = 'toolbars' ;
workarea . mousedown ( unfocus ) ;
} ) . blur ( function ( ) {
ui _context = 'canvas' ;
workarea . unbind ( 'mousedown' , unfocus ) ;
// Go back to selecting text if in textedit mode
if ( svgCanvas . getMode ( ) == 'textedit' ) {
$ ( '#text' ) . focus ( ) ;
2013-10-29 07:07:09 +00:00
}
} ) ;
2014-02-10 13:14:38 +00:00
} ( ) ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickFHPath = function ( ) {
if ( toolButtonClick ( '#tool_fhpath' ) ) {
svgCanvas . setMode ( 'fhpath' ) ;
2010-03-11 21:07:13 +00:00
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickLine = function ( ) {
if ( toolButtonClick ( '#tool_line' ) ) {
svgCanvas . setMode ( 'line' ) ;
2010-03-11 21:07:13 +00:00
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickSquare = function ( ) {
if ( toolButtonClick ( '#tool_square' ) ) {
svgCanvas . setMode ( 'square' ) ;
2010-03-11 21:07:13 +00:00
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickRect = function ( ) {
if ( toolButtonClick ( '#tool_rect' ) ) {
svgCanvas . setMode ( 'rect' ) ;
}
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickFHRect = function ( ) {
if ( toolButtonClick ( '#tool_fhrect' ) ) {
svgCanvas . setMode ( 'fhrect' ) ;
}
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickCircle = function ( ) {
if ( toolButtonClick ( '#tool_circle' ) ) {
svgCanvas . setMode ( 'circle' ) ;
}
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickEllipse = function ( ) {
if ( toolButtonClick ( '#tool_ellipse' ) ) {
svgCanvas . setMode ( 'ellipse' ) ;
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickFHEllipse = function ( ) {
if ( toolButtonClick ( '#tool_fhellipse' ) ) {
svgCanvas . setMode ( 'fhellipse' ) ;
2010-03-11 21:07:13 +00:00
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickImage = function ( ) {
if ( toolButtonClick ( '#tool_image' ) ) {
svgCanvas . setMode ( 'image' ) ;
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickZoom = function ( ) {
if ( toolButtonClick ( '#tool_zoom' ) ) {
svgCanvas . setMode ( 'zoom' ) ;
workarea . css ( 'cursor' , zoomInIcon ) ;
2010-10-27 18:15:28 +00:00
}
2010-10-05 17:13:00 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var zoomImage = function ( multiplier ) {
var res = svgCanvas . getResolution ( ) ;
multiplier = multiplier ? res . zoom * multiplier : 1 ;
// setResolution(res.w * multiplier, res.h * multiplier, true);
$ ( '#zoom' ) . val ( multiplier * 100 ) ;
svgCanvas . setZoom ( multiplier ) ;
zoomDone ( ) ;
updateCanvas ( true ) ;
} ;
var dblclickZoom = function ( ) {
if ( toolButtonClick ( '#tool_zoom' ) ) {
zoomImage ( ) ;
setSelectMode ( ) ;
2010-03-11 21:07:13 +00:00
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickText = function ( ) {
if ( toolButtonClick ( '#tool_text' ) ) {
svgCanvas . setMode ( 'text' ) ;
}
2012-10-22 10:47:50 +00:00
} ;
2014-02-10 13:14:38 +00:00
var clickPath = function ( ) {
if ( toolButtonClick ( '#tool_path' ) ) {
svgCanvas . setMode ( 'path' ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// Delete is a contextual tool that only appears in the ribbon if
// an element has been selected
var deleteSelected = function ( ) {
if ( selectedElement != null || multiselected ) {
svgCanvas . deleteSelectedElements ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var cutSelected = function ( ) {
if ( selectedElement != null || multiselected ) {
svgCanvas . cutSelectedElements ( ) ;
2010-03-11 21:07:13 +00:00
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var copySelected = function ( ) {
if ( selectedElement != null || multiselected ) {
svgCanvas . copySelectedElements ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var pasteInCenter = function ( ) {
var zoom = svgCanvas . getZoom ( ) ;
var x = ( workarea [ 0 ] . scrollLeft + workarea . width ( ) / 2 ) / zoom - svgCanvas . contentW ;
var y = ( workarea [ 0 ] . scrollTop + workarea . height ( ) / 2 ) / zoom - svgCanvas . contentH ;
svgCanvas . pasteElements ( 'point' , x , y ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var moveToTopSelected = function ( ) {
if ( selectedElement != null ) {
svgCanvas . moveToTopSelectedElement ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var moveToBottomSelected = function ( ) {
if ( selectedElement != null ) {
svgCanvas . moveToBottomSelectedElement ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var moveUpDownSelected = function ( dir ) {
if ( selectedElement != null ) {
svgCanvas . moveUpDownSelected ( dir ) ;
2010-03-11 21:07:13 +00:00
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var convertToPath = function ( ) {
if ( selectedElement != null ) {
svgCanvas . convertToPath ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var reorientPath = function ( ) {
if ( selectedElement != null ) {
path . reorient ( ) ;
2012-10-22 10:47:50 +00:00
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var makeHyperlink = function ( ) {
if ( selectedElement != null || multiselected ) {
$ . prompt ( uiStrings . notification . enterNewLinkURL , 'http://' , function ( url ) {
if ( url ) { svgCanvas . makeHyperlink ( url ) ; }
} ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var moveSelected = function ( dx , dy ) {
if ( selectedElement != null || multiselected ) {
if ( curConfig . gridSnapping ) {
// Use grid snap value regardless of zoom level
var multi = svgCanvas . getZoom ( ) * curConfig . snappingStep ;
dx *= multi ;
dy *= multi ;
}
svgCanvas . moveSelectedElements ( dx , dy ) ;
2010-03-11 21:07:13 +00:00
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var linkControlPoints = function ( ) {
$ ( '#tool_node_link' ) . toggleClass ( 'push_button_pressed tool_button' ) ;
2014-02-18 15:06:27 +00:00
var linked = $ ( '#tool_node_link' ) . hasClass ( 'push_button_pressed' ) ;
2014-02-10 13:14:38 +00:00
path . linkControlPoints ( linked ) ;
2010-10-05 17:13:00 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clonePathNode = function ( ) {
if ( path . getNodePoint ( ) ) {
path . clonePathNode ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var deletePathNode = function ( ) {
if ( path . getNodePoint ( ) ) {
path . deletePathNode ( ) ;
2010-03-11 21:07:13 +00:00
}
2014-02-10 13:14:38 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var addSubPath = function ( ) {
2014-02-18 15:06:27 +00:00
var button = $ ( '#tool_add_subpath' ) ;
var sp = ! button . hasClass ( 'push_button_pressed' ) ;
2014-02-10 13:14:38 +00:00
button . toggleClass ( 'push_button_pressed tool_button' ) ;
path . addSubPath ( sp ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var opencloseSubPath = function ( ) {
path . opencloseSubPath ( ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var selectNext = function ( ) {
svgCanvas . cycleElement ( 1 ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var selectPrev = function ( ) {
svgCanvas . cycleElement ( 0 ) ;
} ;
2010-09-09 12:46:34 +00:00
2014-02-10 13:14:38 +00:00
var rotateSelected = function ( cw , step ) {
if ( selectedElement == null || multiselected ) { return ; }
if ( ! cw ) { step *= - 1 ; }
var angle = parseFloat ( $ ( '#angle' ) . val ( ) ) + step ;
svgCanvas . setRotationAngle ( angle ) ;
updateContextPanel ( ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickClear = function ( ) {
var dims = curConfig . dimensions ;
$ . confirm ( uiStrings . notification . QwantToClear , function ( ok ) {
if ( ! ok ) { return ; }
setSelectMode ( ) ;
svgCanvas . clear ( ) ;
svgCanvas . setResolution ( dims [ 0 ] , dims [ 1 ] ) ;
updateCanvas ( true ) ;
zoomImage ( ) ;
populateLayers ( ) ;
updateContextPanel ( ) ;
prepPaints ( ) ;
svgCanvas . runExtensions ( 'onNewDocument' ) ;
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickBold = function ( ) {
svgCanvas . setBold ( ! svgCanvas . getBold ( ) ) ;
updateContextPanel ( ) ;
return false ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickItalic = function ( ) {
svgCanvas . setItalic ( ! svgCanvas . getItalic ( ) ) ;
updateContextPanel ( ) ;
return false ;
} ;
var clickSave = function ( ) {
// In the future, more options can be provided here
var saveOpts = {
2014-02-18 15:06:27 +00:00
'images' : $ . pref ( 'img_save' ) ,
2014-02-10 13:14:38 +00:00
'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' ,
2014-04-08 05:13:54 +00:00
'JPEG' , 'BMP' , 'WEBP' , 'PDF'
2014-02-10 13:14:38 +00:00
] , function ( imgType ) { // todo: replace hard-coded msg with uiStrings.notification.
if ( ! imgType ) {
return ;
}
// Open placeholder window (prevents popup)
2014-05-22 10:21:29 +00:00
var exportWindowName ;
function openExportWindow ( ) {
2014-02-10 13:14:38 +00:00
var str = uiStrings . notification . loadingImage ;
2014-05-22 07:22:57 +00:00
if ( curConfig . exportWindowType === 'new' ) {
editor . exportWindowCt ++ ;
}
2014-05-22 10:21:29 +00:00
exportWindowName = curConfig . canvasName + editor . exportWindowCt ;
2014-04-08 01:31:22 +00:00
exportWindow = window . open (
2014-04-09 06:53:08 +00:00
'data:text/html;charset=utf-8,' + encodeURIComponent ( '<title>' + str + '</title><h1>' + str + '</h1>' ) ,
2014-05-22 07:22:57 +00:00
exportWindowName
2014-04-08 13:49:58 +00:00
) ;
2014-02-10 13:14:38 +00:00
}
2014-05-22 10:21:29 +00:00
if ( imgType === 'PDF' ) {
if ( ! customExportPDF ) {
openExportWindow ( ) ;
}
svgCanvas . exportPDF ( exportWindowName ) ;
}
else {
if ( ! customExportImage ) {
openExportWindow ( ) ;
}
var quality = parseInt ( $ ( '#image-slider' ) . val ( ) , 10 ) / 100 ;
svgCanvas . rasterExport ( imgType , quality , exportWindowName ) ;
}
2014-02-10 13:14:38 +00:00
} , function ( ) {
var sel = $ ( this ) ;
if ( sel . val ( ) === 'JPEG' || sel . val ( ) === 'WEBP' ) {
if ( ! $ ( '#image-slider' ) . length ) {
$ ( '<div><label>Quality: <input id="image-slider" type="range" min="1" max="100" value="92" /></label></div>' ) . appendTo ( sel . parent ( ) ) ; // Todo: i18n-ize label
}
}
else {
$ ( '#image-slider' ) . parent ( ) . remove ( ) ;
}
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// by default, svgCanvas.open() is a no-op.
// it is up to an extension mechanism (opera widget, etc)
// to call setCustomHandlers() which will make it do something
var clickOpen = function ( ) {
svgCanvas . open ( ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickImport = function ( ) {
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickUndo = function ( ) {
if ( undoMgr . getUndoStackSize ( ) > 0 ) {
undoMgr . undo ( ) ;
populateLayers ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickRedo = function ( ) {
if ( undoMgr . getRedoStackSize ( ) > 0 ) {
undoMgr . redo ( ) ;
populateLayers ( ) ;
}
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickGroup = function ( ) {
// group
if ( multiselected ) {
svgCanvas . groupSelectedElements ( ) ;
}
// ungroup
else if ( selectedElement ) {
svgCanvas . ungroupSelectedElement ( ) ;
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickClone = function ( ) {
svgCanvas . cloneSelectedElements ( 20 , 20 ) ;
} ;
2013-02-23 18:56:45 +00:00
2014-02-10 13:14:38 +00:00
var clickAlign = function ( ) {
var letter = this . id . replace ( 'tool_align' , '' ) . charAt ( 0 ) ;
svgCanvas . alignSelectedElements ( letter , $ ( '#align_relative_to' ) . val ( ) ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var clickWireframe = function ( ) {
$ ( '#tool_wireframe' ) . toggleClass ( 'push_button_pressed tool_button' ) ;
workarea . toggleClass ( 'wireframe' ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( supportsNonSS ) { return ; }
var wf _rules = $ ( '#wireframe_rules' ) ;
if ( ! wf _rules . length ) {
2014-04-08 01:31:22 +00:00
wf _rules = $ ( '<style id="wireframe_rules"></style>' ) . appendTo ( 'head' ) ;
2010-07-27 13:37:52 +00:00
} else {
2014-02-10 13:14:38 +00:00
wf _rules . empty ( ) ;
2010-07-27 13:37:52 +00:00
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
updateWireFrame ( ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
$ ( '#svg_docprops_container, #svg_prefs_container' ) . draggable ( { cancel : 'button,fieldset' , containment : 'window' } ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var showDocProperties = function ( ) {
if ( docprops ) { return ; }
docprops = true ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// This selects the correct radio button by using the array notation
2014-02-18 15:06:27 +00:00
$ ( '#image_save_opts input' ) . val ( [ $ . pref ( 'img_save' ) ] ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// update resolution option with actual resolution
var res = svgCanvas . getResolution ( ) ;
if ( curConfig . baseUnit !== 'px' ) {
res . w = svgedit . units . convertUnit ( res . w ) + curConfig . baseUnit ;
res . h = svgedit . units . convertUnit ( res . h ) + curConfig . baseUnit ;
}
$ ( '#canvas_width' ) . val ( res . w ) ;
$ ( '#canvas_height' ) . val ( res . h ) ;
$ ( '#canvas_title' ) . val ( svgCanvas . getDocumentTitle ( ) ) ;
$ ( '#svg_docprops' ) . show ( ) ;
} ;
var showPreferences = function ( ) {
if ( preferences ) { return ; }
preferences = true ;
$ ( '#main_menu' ) . hide ( ) ;
// Update background color with current one
var blocks = $ ( '#bg_blocks div' ) ;
var cur _bg = 'cur_background' ;
2014-02-18 15:06:27 +00:00
var canvas _bg = curPrefs . bkgd _color ;
2014-02-10 13:14:38 +00:00
var url = $ . pref ( 'bkgd_url' ) ;
blocks . each ( function ( ) {
var blk = $ ( this ) ;
var is _bg = blk . css ( 'background-color' ) == canvas _bg ;
blk . toggleClass ( cur _bg , is _bg ) ;
if ( is _bg ) { $ ( '#canvas_bg_url' ) . removeClass ( cur _bg ) ; }
} ) ;
if ( ! canvas _bg ) { blocks . eq ( 0 ) . addClass ( cur _bg ) ; }
if ( url ) {
$ ( '#canvas_bg_url' ) . val ( url ) ;
}
$ ( '#grid_snapping_on' ) . prop ( 'checked' , curConfig . gridSnapping ) ;
$ ( '#grid_snapping_step' ) . attr ( 'value' , curConfig . snappingStep ) ;
$ ( '#grid_color' ) . attr ( 'value' , curConfig . gridColor ) ;
$ ( '#svg_prefs' ) . show ( ) ;
} ;
var hideSourceEditor = function ( ) {
$ ( '#svg_source_editor' ) . hide ( ) ;
editingsource = false ;
$ ( '#svg_source_textarea' ) . blur ( ) ;
} ;
var saveSourceEditor = function ( ) {
if ( ! editingsource ) { return ; }
var saveChanges = function ( ) {
svgCanvas . clearSelection ( ) ;
hideSourceEditor ( ) ;
zoomImage ( ) ;
populateLayers ( ) ;
updateTitle ( ) ;
prepPaints ( ) ;
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
if ( ! svgCanvas . setSvgString ( $ ( '#svg_source_textarea' ) . val ( ) ) ) {
$ . confirm ( uiStrings . notification . QerrorsRevertToSource , function ( ok ) {
if ( ! ok ) { return false ; }
saveChanges ( ) ;
} ) ;
2010-03-11 21:07:13 +00:00
} else {
2014-02-10 13:14:38 +00:00
saveChanges ( ) ;
}
setSelectMode ( ) ;
} ;
var hideDocProperties = function ( ) {
$ ( '#svg_docprops' ) . hide ( ) ;
$ ( '#canvas_width,#canvas_height' ) . removeAttr ( 'disabled' ) ;
$ ( '#resolution' ) [ 0 ] . selectedIndex = 0 ;
2014-02-18 15:06:27 +00:00
$ ( '#image_save_opts input' ) . val ( [ $ . pref ( 'img_save' ) ] ) ;
2014-02-10 13:14:38 +00:00
docprops = false ;
} ;
var hidePreferences = function ( ) {
$ ( '#svg_prefs' ) . hide ( ) ;
preferences = false ;
} ;
var saveDocProperties = function ( ) {
// set title
var newTitle = $ ( '#canvas_title' ) . val ( ) ;
updateTitle ( newTitle ) ;
svgCanvas . setDocumentTitle ( newTitle ) ;
// update resolution
var width = $ ( '#canvas_width' ) , w = width . val ( ) ;
var height = $ ( '#canvas_height' ) , h = height . val ( ) ;
if ( w != 'fit' && ! svgedit . units . isValidUnit ( 'width' , w ) ) {
$ . alert ( uiStrings . notification . invalidAttrValGiven ) ;
width . parent ( ) . addClass ( 'error' ) ;
return false ;
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
width . parent ( ) . removeClass ( 'error' ) ;
if ( h != 'fit' && ! svgedit . units . isValidUnit ( 'height' , h ) ) {
$ . alert ( uiStrings . notification . invalidAttrValGiven ) ;
height . parent ( ) . addClass ( 'error' ) ;
return false ;
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
height . parent ( ) . removeClass ( 'error' ) ;
if ( ! svgCanvas . setResolution ( w , h ) ) {
$ . alert ( uiStrings . notification . noContentToFitTo ) ;
return false ;
}
2014-02-18 15:06:27 +00:00
// Set image save option
$ . pref ( 'img_save' , $ ( '#image_save_opts :checked' ) . val ( ) ) ;
2014-02-10 13:14:38 +00:00
updateCanvas ( ) ;
hideDocProperties ( ) ;
} ;
2014-02-18 15:06:27 +00:00
var savePreferences = editor . savePreferences = function ( ) {
// Set background
2014-02-10 13:14:38 +00:00
var color = $ ( '#bg_blocks div.cur_background' ) . css ( 'background-color' ) || '#FFF' ;
setBackground ( color , $ ( '#canvas_bg_url' ) . val ( ) ) ;
// set language
var lang = $ ( '#lang_select' ) . val ( ) ;
2014-02-18 15:06:27 +00:00
if ( lang !== $ . pref ( 'lang' ) ) {
editor . putLocale ( lang , good _langs ) ;
2014-02-10 13:14:38 +00:00
}
// set icon size
setIconSize ( $ ( '#iconsize' ) . val ( ) ) ;
// set grid setting
curConfig . gridSnapping = $ ( '#grid_snapping_on' ) [ 0 ] . checked ;
curConfig . snappingStep = $ ( '#grid_snapping_step' ) . val ( ) ;
curConfig . gridColor = $ ( '#grid_color' ) . val ( ) ;
curConfig . showRulers = $ ( '#show_rulers' ) [ 0 ] . checked ;
$ ( '#rulers' ) . toggle ( curConfig . showRulers ) ;
if ( curConfig . showRulers ) { updateRulers ( ) ; }
curConfig . baseUnit = $ ( '#base_unit' ) . val ( ) ;
svgCanvas . setConfig ( curConfig ) ;
updateCanvas ( ) ;
hidePreferences ( ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
var resetScrollPos = $ . noop ;
2010-03-11 21:07:13 +00:00
var cancelOverlays = function ( ) {
$ ( '#dialog_box' ) . hide ( ) ;
2010-10-05 17:13:00 +00:00
if ( ! editingsource && ! docprops && ! preferences ) {
2013-02-15 21:57:35 +00:00
if ( cur _context ) {
2010-09-23 19:53:43 +00:00
svgCanvas . leaveContext ( ) ;
}
return ;
2013-02-15 13:38:55 +00:00
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
if ( editingsource ) {
2013-02-15 22:07:05 +00:00
if ( origSource !== $ ( '#svg_source_textarea' ) . val ( ) ) {
2011-01-03 18:45:36 +00:00
$ . confirm ( uiStrings . notification . QignoreSourceChanges , function ( ok ) {
2014-02-10 13:14:38 +00:00
if ( ok ) { hideSourceEditor ( ) ; }
2010-03-11 21:07:13 +00:00
} ) ;
} else {
hideSourceEditor ( ) ;
}
2013-02-15 13:38:55 +00:00
} else if ( docprops ) {
2010-03-11 21:07:13 +00:00
hideDocProperties ( ) ;
2010-10-05 17:13:00 +00:00
} else if ( preferences ) {
hidePreferences ( ) ;
2010-03-11 21:07:13 +00:00
}
2011-02-23 20:06:33 +00:00
resetScrollPos ( ) ;
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-04-23 19:40:09 +00:00
var win _wh = { width : $ ( window ) . width ( ) , height : $ ( window ) . height ( ) } ;
2012-10-22 10:47:50 +00:00
2011-02-23 17:10:21 +00:00
// Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)
2013-02-15 21:57:35 +00:00
if ( svgedit . browser . isIE ( ) ) {
2011-02-23 17:10:21 +00:00
( function ( ) {
2011-02-23 20:06:33 +00:00
resetScrollPos = function ( ) {
2013-02-23 18:56:45 +00:00
if ( workarea [ 0 ] . scrollLeft === 0 && workarea [ 0 ] . scrollTop === 0 ) {
2011-02-23 20:06:33 +00:00
workarea [ 0 ] . scrollLeft = curScrollPos . left ;
workarea [ 0 ] . scrollTop = curScrollPos . top ;
2011-02-23 17:10:21 +00:00
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2011-02-23 20:06:33 +00:00
curScrollPos = {
2011-02-23 17:10:21 +00:00
left : workarea [ 0 ] . scrollLeft ,
top : workarea [ 0 ] . scrollTop
} ;
2012-10-22 10:47:50 +00:00
2011-02-23 20:06:33 +00:00
$ ( window ) . resize ( resetScrollPos ) ;
2014-02-18 23:57:49 +00:00
editor . ready ( function ( ) {
2011-02-23 17:10:21 +00:00
// TODO: Find better way to detect when to do this to minimize
// flickering effect
setTimeout ( function ( ) {
2011-02-23 20:06:33 +00:00
resetScrollPos ( ) ;
2011-02-23 17:10:21 +00:00
} , 500 ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2011-02-23 17:10:21 +00:00
workarea . scroll ( function ( ) {
2011-02-23 20:06:33 +00:00
curScrollPos = {
2011-02-23 17:10:21 +00:00
left : workarea [ 0 ] . scrollLeft ,
top : workarea [ 0 ] . scrollTop
} ;
} ) ;
} ( ) ) ;
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( window ) . resize ( function ( evt ) {
2010-04-23 19:40:09 +00:00
$ . each ( win _wh , function ( type , val ) {
var curval = $ ( window ) [ type ] ( ) ;
2013-02-15 21:57:35 +00:00
workarea [ 0 ] [ 'scroll' + ( type === 'width' ? 'Left' : 'Top' ) ] -= ( curval - val ) / 2 ;
2010-04-23 19:40:09 +00:00
win _wh [ type ] = curval ;
} ) ;
2013-10-07 01:35:01 +00:00
setFlyoutPositions ( ) ;
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-10-01 18:59:12 +00:00
( function ( ) {
workarea . scroll ( function ( ) {
2013-10-13 23:23:08 +00:00
// TODO: jQuery's scrollLeft/Top() wouldn't require a null check
2011-07-07 17:36:58 +00:00
if ( $ ( '#ruler_x' ) . length != 0 ) {
$ ( '#ruler_x' ) [ 0 ] . scrollLeft = workarea [ 0 ] . scrollLeft ;
}
if ( $ ( '#ruler_y' ) . length != 0 ) {
2012-10-22 10:47:50 +00:00
$ ( '#ruler_y' ) [ 0 ] . scrollTop = workarea [ 0 ] . scrollTop ;
2011-07-07 17:36:58 +00:00
}
2010-10-01 18:59:12 +00:00
} ) ;
} ( ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( '#url_notice' ) . click ( function ( ) {
$ . alert ( this . title ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( '#change_image_url' ) . click ( promptImgURL ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// added these event handlers for all the push buttons so they
// behave more like buttons being pressed-in and not images
( function ( ) {
2013-02-15 21:57:35 +00:00
var toolnames = [ 'clear' , 'open' , 'save' , 'source' , 'delete' , 'delete_multi' , 'paste' , 'clone' , 'clone_multi' , 'move_top' , 'move_bottom' ] ;
2010-03-11 21:07:13 +00:00
var all _tools = '' ;
var cur _class = 'tool_button_current' ;
2012-10-22 10:47:50 +00:00
2014-05-08 03:47:14 +00:00
$ . each ( toolnames , function ( i , item ) {
all _tools += ( i ? ',' : '' ) + '#tool_' + item ;
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( all _tools ) . mousedown ( function ( ) {
$ ( this ) . addClass ( cur _class ) ;
} ) . bind ( 'mousedown mouseout' , function ( ) {
$ ( this ) . removeClass ( cur _class ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ ( '#tool_undo, #tool_redo' ) . mousedown ( function ( ) {
2014-02-10 13:14:38 +00:00
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) { $ ( this ) . addClass ( cur _class ) ; }
2013-02-15 21:57:35 +00:00
} ) . bind ( 'mousedown mouseout' , function ( ) {
2010-03-11 21:07:13 +00:00
$ ( this ) . removeClass ( cur _class ) ; }
) ;
} ( ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// switch modifier key in tooltips if mac
// NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta
// in Opera and Chrome
2013-02-18 18:22:00 +00:00
if ( svgedit . browser . isMac ( ) && ! window . opera ) {
2013-02-15 21:57:35 +00:00
var shortcutButtons = [ 'tool_clear' , 'tool_save' , 'tool_source' , 'tool_undo' , 'tool_redo' , 'tool_clone' ] ;
2014-02-10 13:14:38 +00:00
i = shortcutButtons . length ;
2010-03-11 21:07:13 +00:00
while ( i -- ) {
var button = document . getElementById ( shortcutButtons [ i ] ) ;
2013-02-23 18:56:45 +00:00
if ( button ) {
2010-08-21 01:08:24 +00:00
var title = button . title ;
2013-02-15 21:57:35 +00:00
var index = title . indexOf ( 'Ctrl+' ) ;
button . title = [ title . substr ( 0 , index ) , 'Cmd+' , title . substr ( index + 5 ) ] . join ( '' ) ;
2010-08-21 01:08:24 +00:00
}
2010-03-11 21:07:13 +00:00
}
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// TODO: go back to the color boxes having white background-color and then setting
2013-10-13 23:23:08 +00:00
// background-image to none.png (otherwise partially transparent gradients look weird)
2010-03-11 21:07:13 +00:00
var colorPicker = function ( elem ) {
var picker = elem . attr ( 'id' ) == 'stroke_color' ? 'stroke' : 'fill' ;
2014-01-31 00:27:46 +00:00
// var opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
2010-10-12 18:35:45 +00:00
var paint = paintBox [ picker ] . paint ;
2010-03-11 21:07:13 +00:00
var title = ( picker == 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity' ) ;
2014-02-18 15:06:27 +00:00
// var was_none = false; // Currently unused
2012-11-28 02:08:13 +00:00
var pos = elem . offset ( ) ;
2013-02-15 21:57:35 +00:00
$ ( '#color_picker' )
. draggable ( { cancel : '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker' , containment : 'window' } )
2014-04-09 01:33:11 +00:00
. css ( curConfig . colorPickerCSS || { 'left' : pos . left - 140 , 'bottom' : 40 } )
2010-03-11 21:07:13 +00:00
. jGraduate (
2012-10-22 10:47:50 +00:00
{
2010-03-11 21:07:13 +00:00
paint : paint ,
window : { pickerTitle : title } ,
2011-01-07 17:35:05 +00:00
images : { clientPath : curConfig . jGraduatePath } ,
newstop : 'inverse'
2010-03-11 21:07:13 +00:00
} ,
function ( p ) {
paint = new $ . jGraduate . Paint ( p ) ;
2010-10-12 18:35:45 +00:00
paintBox [ picker ] . setPaint ( paint ) ;
svgCanvas . setPaint ( picker , paint ) ;
2010-03-11 21:07:13 +00:00
$ ( '#color_picker' ) . hide ( ) ;
} ,
2013-02-19 15:00:56 +00:00
function ( ) {
2010-03-11 21:07:13 +00:00
$ ( '#color_picker' ) . hide ( ) ;
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
var PaintBox = function ( container , type ) {
2014-02-10 13:14:38 +00:00
var paintColor , paintOpacity ,
cur = curConfig [ type === 'fill' ? 'initFill' : 'initStroke' ] ;
2010-10-12 18:35:45 +00:00
// set up gradients to be used for the buttons
var svgdocbox = new DOMParser ( ) . parseFromString (
2014-02-10 13:14:38 +00:00
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="16.5" height="16.5"' +
' fill="#' + cur . color + '" opacity="' + cur . opacity + '"/>' +
' <defs><linearGradient id="gradbox_"/></defs></svg>' , 'text/xml' ) ;
2010-10-12 18:35:45 +00:00
var docElem = svgdocbox . documentElement ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
docElem = $ ( container ) [ 0 ] . appendChild ( document . importNode ( docElem , true ) ) ;
docElem . setAttribute ( 'width' , 16.5 ) ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
this . rect = docElem . firstChild ;
this . defs = docElem . getElementsByTagName ( 'defs' ) [ 0 ] ;
this . grad = this . defs . firstChild ;
this . paint = new $ . jGraduate . Paint ( { solidColor : cur . color } ) ;
this . type = type ;
this . setPaint = function ( paint , apply ) {
this . paint = paint ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
var fillAttr = 'none' ;
2010-10-12 18:35:45 +00:00
var ptype = paint . type ;
var opac = paint . alpha / 100 ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
switch ( ptype ) {
case 'solidColor' :
2013-02-15 21:57:35 +00:00
fillAttr = ( paint [ ptype ] != 'none' ) ? '#' + paint [ ptype ] : paint [ ptype ] ;
2010-10-12 18:35:45 +00:00
break ;
case 'linearGradient' :
case 'radialGradient' :
this . defs . removeChild ( this . grad ) ;
this . grad = this . defs . appendChild ( paint [ ptype ] ) ;
var id = this . grad . id = 'gradbox_' + this . type ;
2013-02-15 21:57:35 +00:00
fillAttr = 'url(#' + id + ')' ;
2014-02-10 13:14:38 +00:00
break ;
2010-10-12 18:35:45 +00:00
}
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
this . rect . setAttribute ( 'fill' , fillAttr ) ;
this . rect . setAttribute ( 'opacity' , opac ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( apply ) {
2010-10-12 18:35:45 +00:00
svgCanvas . setColor ( this . type , paintColor , true ) ;
svgCanvas . setPaintOpacity ( this . type , paintOpacity , true ) ;
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-10-12 20:09:37 +00:00
this . update = function ( apply ) {
2014-02-10 10:53:51 +00:00
if ( ! selectedElement ) { return ; }
var i , len ;
2010-10-12 20:09:37 +00:00
var type = this . type ;
2014-02-10 10:53:51 +00:00
switch ( selectedElement . tagName ) {
2011-03-09 20:00:49 +00:00
case 'use' :
case 'image' :
case 'foreignObject' :
2012-10-22 10:47:50 +00:00
// These elements don't have fill or stroke, so don't change
2011-03-09 20:00:49 +00:00
// the current value
return ;
case 'g' :
case 'a' :
2010-12-20 21:37:04 +00:00
var gPaint = null ;
2012-10-22 10:47:50 +00:00
2010-12-20 21:37:04 +00:00
var childs = selectedElement . getElementsByTagName ( '*' ) ;
2014-02-10 10:53:51 +00:00
for ( i = 0 , len = childs . length ; i < len ; i ++ ) {
2010-12-20 21:37:04 +00:00
var elem = childs [ i ] ;
var p = elem . getAttribute ( type ) ;
2013-02-15 21:57:35 +00:00
if ( i === 0 ) {
2010-12-20 21:37:04 +00:00
gPaint = p ;
2013-02-15 21:57:35 +00:00
} else if ( gPaint !== p ) {
2010-12-20 21:37:04 +00:00
gPaint = null ;
2010-12-21 14:34:54 +00:00
break ;
2010-12-20 21:37:04 +00:00
}
}
2014-02-10 13:14:38 +00:00
2013-02-15 21:57:35 +00:00
if ( gPaint === null ) {
2010-12-20 21:37:04 +00:00
// No common color, don't update anything
2014-02-10 13:14:38 +00:00
paintColor = null ;
2010-12-20 21:37:04 +00:00
return ;
}
2014-02-10 13:14:38 +00:00
paintColor = gPaint ;
paintOpacity = 1 ;
2011-03-09 20:00:49 +00:00
break ;
default :
2014-02-10 13:14:38 +00:00
paintOpacity = parseFloat ( selectedElement . getAttribute ( type + '-opacity' ) ) ;
2010-12-20 21:37:04 +00:00
if ( isNaN ( paintOpacity ) ) {
paintOpacity = 1.0 ;
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
var defColor = type === 'fill' ? 'black' : 'none' ;
2014-02-10 13:14:38 +00:00
paintColor = selectedElement . getAttribute ( type ) || defColor ;
2010-12-20 21:37:04 +00:00
}
2013-02-15 21:57:35 +00:00
if ( apply ) {
2010-10-12 20:09:37 +00:00
svgCanvas . setColor ( type , paintColor , true ) ;
svgCanvas . setPaintOpacity ( type , paintOpacity , true ) ;
}
2010-12-20 21:37:04 +00:00
2012-10-22 10:47:50 +00:00
paintOpacity *= 100 ;
2010-10-12 20:09:37 +00:00
var paint = getPaint ( paintColor , paintOpacity , type ) ;
// update the rect inside #fill_color/#stroke_color
this . setPaint ( paint ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
this . prep = function ( ) {
var ptype = this . paint . type ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
switch ( ptype ) {
case 'linearGradient' :
case 'radialGradient' :
var paint = new $ . jGraduate . Paint ( { copy : this . paint } ) ;
svgCanvas . setPaint ( type , paint ) ;
2014-02-10 13:14:38 +00:00
break ;
2010-10-12 18:35:45 +00:00
}
2013-02-15 13:38:55 +00:00
} ;
2010-10-12 18:35:45 +00:00
} ;
2012-10-22 10:47:50 +00:00
2010-10-12 18:35:45 +00:00
paintBox . fill = new PaintBox ( '#fill_color' , 'fill' ) ;
paintBox . stroke = new PaintBox ( '#stroke_color' , 'stroke' ) ;
2010-09-15 20:10:43 +00:00
$ ( '#stroke_width' ) . val ( curConfig . initStroke . width ) ;
$ ( '#group_opacity' ) . val ( curConfig . initOpacity * 100 ) ;
2012-10-22 10:47:50 +00:00
2010-09-15 20:10:43 +00:00
// Use this SVG elem to test vectorEffect support
2013-02-15 22:32:35 +00:00
var testEl = paintBox . fill . rect . cloneNode ( false ) ;
2013-02-23 18:56:45 +00:00
testEl . setAttribute ( 'style' , 'vector-effect:non-scaling-stroke' ) ;
2014-02-10 13:50:55 +00:00
supportsNonSS = ( testEl . style . vectorEffect === 'non-scaling-stroke' ) ;
2013-02-15 22:32:35 +00:00
testEl . removeAttribute ( 'style' ) ;
2010-10-12 18:35:45 +00:00
var svgdocbox = paintBox . fill . rect . ownerDocument ;
2010-09-15 20:10:43 +00:00
// Use this to test support for blur element. Seems to work to test support in Webkit
2013-02-16 15:02:26 +00:00
var blurTest = svgdocbox . createElementNS ( svgedit . NS . SVG , 'feGaussianBlur' ) ;
2014-02-10 13:14:38 +00:00
if ( blurTest . stdDeviationX === undefined ) {
2010-09-15 20:10:43 +00:00
$ ( '#tool_blur' ) . hide ( ) ;
2010-04-06 18:40:10 +00:00
}
2013-02-15 22:32:35 +00:00
$ ( blurTest ) . remove ( ) ;
2012-10-22 10:47:50 +00:00
2010-09-27 18:58:04 +00:00
// Test for zoom icon support
( function ( ) {
2013-02-15 22:32:35 +00:00
var pre = '-' + uaPrefix . toLowerCase ( ) + '-zoom-' ;
2010-09-27 18:58:04 +00:00
var zoom = pre + 'in' ;
workarea . css ( 'cursor' , zoom ) ;
2013-02-15 21:57:35 +00:00
if ( workarea . css ( 'cursor' ) === zoom ) {
2010-09-27 18:58:04 +00:00
zoomInIcon = zoom ;
zoomOutIcon = pre + 'out' ;
}
workarea . css ( 'cursor' , 'auto' ) ;
} ( ) ) ;
2010-03-11 21:07:13 +00:00
// Test for embedImage support (use timeout to not interfere with page load)
setTimeout ( function ( ) {
2010-08-20 14:52:55 +00:00
svgCanvas . embedImage ( 'images/logo.png' , function ( datauri ) {
2013-02-15 21:57:35 +00:00
if ( ! datauri ) {
2010-03-11 21:07:13 +00:00
// Disable option
2013-02-15 22:32:35 +00:00
$ ( '#image_save_opts [value=embed]' ) . attr ( 'disabled' , 'disabled' ) ;
2010-03-11 21:07:13 +00:00
$ ( '#image_save_opts input' ) . val ( [ 'ref' ] ) ;
2014-02-18 15:06:27 +00:00
$ . pref ( 'img_save' , 'ref' ) ;
2013-02-15 22:32:35 +00:00
$ ( '#image_opt_embed' ) . css ( 'color' , '#666' ) . attr ( 'title' , uiStrings . notification . featNotSupported ) ;
2009-11-09 18:59:53 +00:00
}
} ) ;
2013-02-15 13:38:55 +00:00
} , 1000 ) ;
2012-10-22 10:47:50 +00:00
2013-02-21 20:34:11 +00:00
$ ( '#fill_color, #tool_fill .icon_label' ) . click ( function ( ) {
2010-04-20 13:21:51 +00:00
colorPicker ( $ ( '#fill_color' ) ) ;
2010-03-11 21:07:13 +00:00
updateToolButtonState ( ) ;
2009-11-09 18:59:53 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-21 20:34:11 +00:00
$ ( '#stroke_color, #tool_stroke .icon_label' ) . click ( function ( ) {
2010-04-20 13:21:51 +00:00
colorPicker ( $ ( '#stroke_color' ) ) ;
2010-03-11 21:07:13 +00:00
updateToolButtonState ( ) ;
2009-11-18 16:50:25 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-04-20 13:21:51 +00:00
$ ( '#group_opacityLabel' ) . click ( function ( ) {
$ ( '#opacity_dropdown button' ) . mousedown ( ) ;
$ ( window ) . mouseup ( ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-04-20 13:21:51 +00:00
$ ( '#zoomLabel' ) . click ( function ( ) {
$ ( '#zoom_dropdown button' ) . mousedown ( ) ;
$ ( window ) . mouseup ( ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-23 19:22:00 +00:00
$ ( '#tool_move_top' ) . mousedown ( function ( evt ) {
2010-03-11 21:07:13 +00:00
$ ( '#tools_stacking' ) . show ( ) ;
evt . preventDefault ( ) ;
} ) ;
2012-10-22 10:47:50 +00:00
$ ( '.layer_button' ) . mousedown ( function ( ) {
2010-03-11 21:07:13 +00:00
$ ( this ) . addClass ( 'layer_buttonpressed' ) ;
} ) . mouseout ( function ( ) {
$ ( this ) . removeClass ( 'layer_buttonpressed' ) ;
} ) . mouseup ( function ( ) {
$ ( this ) . removeClass ( 'layer_buttonpressed' ) ;
} ) ;
2012-10-22 10:47:50 +00:00
$ ( '.push_button' ) . mousedown ( function ( ) {
2010-03-11 21:07:13 +00:00
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
$ ( this ) . addClass ( 'push_button_pressed' ) . removeClass ( 'push_button' ) ;
2009-07-30 22:45:59 +00:00
}
2010-03-11 21:07:13 +00:00
} ) . mouseout ( function ( ) {
$ ( this ) . removeClass ( 'push_button_pressed' ) . addClass ( 'push_button' ) ;
} ) . mouseup ( function ( ) {
$ ( this ) . removeClass ( 'push_button_pressed' ) . addClass ( 'push_button' ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-18 18:02:39 +00:00
// ask for a layer name
2010-03-11 21:07:13 +00:00
$ ( '#layer_new' ) . click ( function ( ) {
2014-02-10 13:14:38 +00:00
var uniqName ,
i = svgCanvas . getCurrentDrawing ( ) . getNumLayers ( ) ;
2010-09-16 14:04:47 +00:00
do {
2014-02-10 13:14:38 +00:00
uniqName = uiStrings . layers . layer + ' ' + ( ++ i ) ;
2011-01-16 23:18:51 +00:00
} while ( svgCanvas . getCurrentDrawing ( ) . hasLayer ( uniqName ) ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 23:17:56 +00:00
$ . prompt ( uiStrings . notification . enterUniqueLayerName , uniqName , function ( newName ) {
2014-02-10 13:14:38 +00:00
if ( ! newName ) { return ; }
2011-01-16 23:18:51 +00:00
if ( svgCanvas . getCurrentDrawing ( ) . hasLayer ( newName ) ) {
2011-01-03 18:45:36 +00:00
$ . alert ( uiStrings . notification . dupeLayerName ) ;
2010-03-11 21:07:13 +00:00
return ;
}
svgCanvas . createLayer ( newName ) ;
updateContextPanel ( ) ;
populateLayers ( ) ;
} ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
function deleteLayer ( ) {
2010-03-11 21:07:13 +00:00
if ( svgCanvas . deleteCurrentLayer ( ) ) {
updateContextPanel ( ) ;
populateLayers ( ) ;
// This matches what SvgCanvas does
// TODO: make this behavior less brittle (svg-editor should get which
// layer is selected from the canvas and then select that one in the UI)
2013-02-15 21:57:35 +00:00
$ ( '#layerlist tr.layer' ) . removeClass ( 'layersel' ) ;
$ ( '#layerlist tr.layer:first' ) . addClass ( 'layersel' ) ;
2009-07-30 22:45:59 +00:00
}
2010-09-16 14:04:47 +00:00
}
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
function cloneLayer ( ) {
2011-01-30 17:11:56 +00:00
var name = svgCanvas . getCurrentDrawing ( ) . getCurrentLayerName ( ) + ' copy' ;
2012-10-22 10:47:50 +00:00
2011-01-03 18:45:36 +00:00
$ . prompt ( uiStrings . notification . enterUniqueLayerName , name , function ( newName ) {
2014-02-10 13:14:38 +00:00
if ( ! newName ) { return ; }
2011-01-16 23:18:51 +00:00
if ( svgCanvas . getCurrentDrawing ( ) . hasLayer ( newName ) ) {
2011-01-03 18:45:36 +00:00
$ . alert ( uiStrings . notification . dupeLayerName ) ;
2010-09-16 14:04:47 +00:00
return ;
}
svgCanvas . cloneLayer ( newName ) ;
updateContextPanel ( ) ;
populateLayers ( ) ;
} ) ;
}
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
function mergeLayer ( ) {
2014-02-10 13:14:38 +00:00
if ( $ ( '#layerlist tr.layersel' ) . index ( ) == svgCanvas . getCurrentDrawing ( ) . getNumLayers ( ) - 1 ) {
return ;
}
2010-09-16 14:04:47 +00:00
svgCanvas . mergeLayer ( ) ;
updateContextPanel ( ) ;
populateLayers ( ) ;
}
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
function moveLayer ( pos ) {
var curIndex = $ ( '#layerlist tr.layersel' ) . index ( ) ;
2011-01-16 23:07:35 +00:00
var total = svgCanvas . getCurrentDrawing ( ) . getNumLayers ( ) ;
2013-02-15 21:57:35 +00:00
if ( curIndex > 0 || curIndex < total - 1 ) {
2010-09-16 14:04:47 +00:00
curIndex += pos ;
2010-03-11 21:07:13 +00:00
svgCanvas . setCurrentLayerPosition ( total - curIndex - 1 ) ;
populateLayers ( ) ;
2009-06-17 17:36:00 +00:00
}
2010-09-16 14:04:47 +00:00
}
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
$ ( '#layer_delete' ) . click ( deleteLayer ) ;
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
$ ( '#layer_up' ) . click ( function ( ) {
moveLayer ( - 1 ) ;
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( '#layer_down' ) . click ( function ( ) {
2010-09-16 14:04:47 +00:00
moveLayer ( 1 ) ;
2010-02-04 19:06:49 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( '#layer_rename' ) . click ( function ( ) {
2014-02-18 15:06:27 +00:00
// var curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
2010-03-11 21:07:13 +00:00
var oldName = $ ( '#layerlist tr.layersel td.layername' ) . text ( ) ;
2013-02-15 21:57:35 +00:00
$ . prompt ( uiStrings . notification . enterNewLayerName , '' , function ( newName ) {
2014-02-10 13:14:38 +00:00
if ( ! newName ) { return ; }
2011-01-16 23:18:51 +00:00
if ( oldName == newName || svgCanvas . getCurrentDrawing ( ) . hasLayer ( newName ) ) {
2011-01-03 18:45:36 +00:00
$ . alert ( uiStrings . notification . layerHasThatName ) ;
2010-03-11 21:07:13 +00:00
return ;
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
svgCanvas . renameCurrentLayer ( newName ) ;
populateLayers ( ) ;
} ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
var SIDEPANEL _MAXWIDTH = 300 ;
2012-03-31 18:02:08 +00:00
var SIDEPANEL _OPENWIDTH = 150 ;
2010-06-09 18:17:58 +00:00
var sidedrag = - 1 , sidedragging = false , allowmove = false ;
2012-10-22 10:47:50 +00:00
2013-02-20 22:28:45 +00:00
var changeSidePanelWidth = function ( delta ) {
var rulerX = $ ( '#ruler_x' ) ;
$ ( '#sidepanels' ) . width ( '+=' + delta ) ;
$ ( '#layerpanel' ) . width ( '+=' + delta ) ;
rulerX . css ( 'right' , parseInt ( rulerX . css ( 'right' ) , 10 ) + delta ) ;
workarea . css ( 'right' , parseInt ( workarea . css ( 'right' ) , 10 ) + delta ) ;
2014-04-09 03:44:19 +00:00
svgCanvas . runExtensions ( 'workareaResized' ) ;
2013-02-20 22:28:45 +00:00
} ;
var resizeSidePanel = function ( evt ) {
2014-02-10 13:14:38 +00:00
if ( ! allowmove ) { return ; }
if ( sidedrag == - 1 ) { return ; }
2010-04-20 15:53:19 +00:00
sidedragging = true ;
2013-02-20 22:28:45 +00:00
var deltaX = sidedrag - evt . pageX ;
var sideWidth = $ ( '#sidepanels' ) . width ( ) ;
if ( sideWidth + deltaX > SIDEPANEL _MAXWIDTH ) {
deltaX = SIDEPANEL _MAXWIDTH - sideWidth ;
sideWidth = SIDEPANEL _MAXWIDTH ;
} else if ( sideWidth + deltaX < 2 ) {
deltaX = 2 - sideWidth ;
sideWidth = 2 ;
2010-04-20 15:53:19 +00:00
}
2014-02-10 13:14:38 +00:00
if ( deltaX == 0 ) { return ; }
2013-02-20 22:28:45 +00:00
sidedrag -= deltaX ;
changeSidePanelWidth ( deltaX ) ;
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
// if width is non-zero, then fully close it, otherwise fully open it
// the optional close argument forces the side panel closed
var toggleSidePanel = function ( close ) {
var w = $ ( '#sidepanels' ) . width ( ) ;
var deltaX = ( w > 2 || close ? 2 : SIDEPANEL _OPENWIDTH ) - w ;
changeSidePanelWidth ( deltaX ) ;
} ;
2010-03-11 21:07:13 +00:00
$ ( '#sidepanel_handle' )
2010-04-20 15:53:19 +00:00
. mousedown ( function ( evt ) {
sidedrag = evt . pageX ;
2013-02-20 22:28:45 +00:00
$ ( window ) . mousemove ( resizeSidePanel ) ;
2010-06-09 18:17:58 +00:00
allowmove = false ;
// Silly hack for Chrome, which always runs mousemove right after mousedown
setTimeout ( function ( ) {
allowmove = true ;
} , 20 ) ;
2010-04-20 15:53:19 +00:00
} )
2010-03-11 21:07:13 +00:00
. mouseup ( function ( evt ) {
2014-02-10 13:14:38 +00:00
if ( ! sidedragging ) { toggleSidePanel ( ) ; }
2010-03-11 21:07:13 +00:00
sidedrag = - 1 ;
sidedragging = false ;
} ) ;
2010-04-20 15:53:19 +00:00
$ ( window ) . mouseup ( function ( ) {
sidedrag = - 1 ;
sidedragging = false ;
2013-02-20 22:28:45 +00:00
$ ( '#svg_editor' ) . unbind ( 'mousemove' , resizeSidePanel ) ;
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2009-11-19 15:09:21 +00:00
populateLayers ( ) ;
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
// function changeResolution(x,y) {
// var zoom = svgCanvas.getResolution().zoom;
// setResolution(x * zoom, y * zoom);
// }
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
var centerCanvas = function ( ) {
// this centers the canvas vertically in the workarea (horizontal handled in CSS)
workarea . css ( 'line-height' , workarea . height ( ) + 'px' ) ;
} ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( window ) . bind ( 'load resize' , centerCanvas ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
function stepFontSize ( elem , step ) {
2014-02-10 13:14:38 +00:00
var orig _val = Number ( elem . value ) ;
2010-03-11 21:07:13 +00:00
var sug _val = orig _val + step ;
var increasing = sug _val >= orig _val ;
2014-02-10 13:14:38 +00:00
if ( step === 0 ) { return orig _val ; }
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( orig _val >= 24 ) {
if ( increasing ) {
2010-03-11 21:07:13 +00:00
return Math . round ( orig _val * 1.1 ) ;
}
2013-02-15 22:32:35 +00:00
return Math . round ( orig _val / 1.1 ) ;
2014-02-10 13:14:38 +00:00
}
if ( orig _val <= 1 ) {
2013-02-15 21:57:35 +00:00
if ( increasing ) {
2012-10-22 10:47:50 +00:00
return orig _val * 2 ;
2010-03-11 21:07:13 +00:00
}
2013-02-15 22:32:35 +00:00
return orig _val / 2 ;
2009-10-14 05:11:51 +00:00
}
2013-02-15 22:32:35 +00:00
return sug _val ;
2009-10-14 05:11:51 +00:00
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
function stepZoom ( elem , step ) {
2014-02-10 13:14:38 +00:00
var orig _val = Number ( elem . value ) ;
if ( orig _val === 0 ) { return 100 ; }
2010-03-11 21:07:13 +00:00
var sug _val = orig _val + step ;
2014-02-10 13:14:38 +00:00
if ( step === 0 ) { return orig _val ; }
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( orig _val >= 100 ) {
2010-03-11 21:07:13 +00:00
return sug _val ;
}
2013-02-15 22:32:35 +00:00
if ( sug _val >= orig _val ) {
return orig _val * 2 ;
}
return orig _val / 2 ;
2009-09-24 18:59:39 +00:00
}
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
// function setResolution(w, h, center) {
// updateCanvas();
// // w-=0; h-=0;
// // $('#svgcanvas').css( { 'width': w, 'height': h } );
// // $('#canvas_width').val(w);
// // $('#canvas_height').val(h);
2012-10-22 10:47:50 +00:00
// //
2014-01-31 00:27:46 +00:00
// // if (center) {
// // var w_area = workarea;
// // var scroll_y = h/2 - w_area.height()/2;
// // var scroll_x = w/2 - w_area.width()/2;
// // w_area[0].scrollTop = scroll_y;
// // w_area[0].scrollLeft = scroll_x;
// // }
// }
2012-10-22 10:47:50 +00:00
2013-02-21 20:34:11 +00:00
$ ( '#resolution' ) . change ( function ( ) {
2010-03-11 21:07:13 +00:00
var wh = $ ( '#canvas_width,#canvas_height' ) ;
2013-02-15 21:57:35 +00:00
if ( ! this . selectedIndex ) {
if ( $ ( '#canvas_width' ) . val ( ) == 'fit' ) {
wh . removeAttr ( 'disabled' ) . val ( 100 ) ;
2010-03-11 21:07:13 +00:00
}
2013-02-15 21:57:35 +00:00
} else if ( this . value == 'content' ) {
wh . val ( 'fit' ) . attr ( 'disabled' , 'disabled' ) ;
2010-03-11 21:07:13 +00:00
} else {
var dims = this . value . split ( 'x' ) ;
$ ( '#canvas_width' ) . val ( dims [ 0 ] ) ;
$ ( '#canvas_height' ) . val ( dims [ 1 ] ) ;
2013-02-15 21:57:35 +00:00
wh . removeAttr ( 'disabled' ) ;
2010-03-11 21:07:13 +00:00
}
2009-10-14 05:11:51 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
//Prevent browser from erroneously repopulating fields
2013-02-15 21:57:35 +00:00
$ ( 'input,select' ) . attr ( 'autocomplete' , 'off' ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Associate all button actions as well as non-button keyboard shortcuts
2014-02-18 15:06:27 +00:00
Actions = ( function ( ) {
2010-03-11 21:07:13 +00:00
// sel:'selector', fn:function, evt:'event', key:[key, preventDefault, NoDisableInInput]
var tool _buttons = [
2013-02-15 21:57:35 +00:00
{ sel : '#tool_select' , fn : clickSelect , evt : 'click' , key : [ 'V' , true ] } ,
{ sel : '#tool_fhpath' , fn : clickFHPath , evt : 'click' , key : [ 'Q' , true ] } ,
{ sel : '#tool_line' , fn : clickLine , evt : 'click' , key : [ 'L' , true ] } ,
{ sel : '#tool_rect' , fn : clickRect , evt : 'mouseup' , key : [ 'R' , true ] , parent : '#tools_rect' , icon : 'rect' } ,
{ sel : '#tool_square' , fn : clickSquare , evt : 'mouseup' , parent : '#tools_rect' , icon : 'square' } ,
{ sel : '#tool_fhrect' , fn : clickFHRect , evt : 'mouseup' , parent : '#tools_rect' , icon : 'fh_rect' } ,
{ sel : '#tool_ellipse' , fn : clickEllipse , evt : 'mouseup' , key : [ 'E' , true ] , parent : '#tools_ellipse' , icon : 'ellipse' } ,
{ sel : '#tool_circle' , fn : clickCircle , evt : 'mouseup' , parent : '#tools_ellipse' , icon : 'circle' } ,
{ sel : '#tool_fhellipse' , fn : clickFHEllipse , evt : 'mouseup' , parent : '#tools_ellipse' , icon : 'fh_ellipse' } ,
{ sel : '#tool_path' , fn : clickPath , evt : 'click' , key : [ 'P' , true ] } ,
{ sel : '#tool_text' , fn : clickText , evt : 'click' , key : [ 'T' , true ] } ,
{ sel : '#tool_image' , fn : clickImage , evt : 'mouseup' } ,
{ sel : '#tool_zoom' , fn : clickZoom , evt : 'mouseup' , key : [ 'Z' , true ] } ,
{ sel : '#tool_clear' , fn : clickClear , evt : 'mouseup' , key : [ 'N' , true ] } ,
2014-02-10 13:14:38 +00:00
{ sel : '#tool_save' , fn : function ( ) {
if ( editingsource ) {
saveSourceEditor ( ) ;
}
else {
clickSave ( ) ;
}
} , evt : 'mouseup' , key : [ 'S' , true ] } ,
2013-02-15 21:57:35 +00:00
{ sel : '#tool_export' , fn : clickExport , evt : 'mouseup' } ,
{ sel : '#tool_open' , fn : clickOpen , evt : 'mouseup' , key : [ 'O' , true ] } ,
{ sel : '#tool_import' , fn : clickImport , evt : 'mouseup' } ,
{ sel : '#tool_source' , fn : showSourceEditor , evt : 'click' , key : [ 'U' , true ] } ,
{ sel : '#tool_wireframe' , fn : clickWireframe , evt : 'click' , key : [ 'F' , true ] } ,
2013-02-18 18:52:07 +00:00
{ sel : '#tool_source_cancel,.overlay,#tool_docprops_cancel,#tool_prefs_cancel' , fn : cancelOverlays , evt : 'click' , key : [ 'esc' , false , false ] , hidekey : true } ,
2013-02-15 21:57:35 +00:00
{ sel : '#tool_source_save' , fn : saveSourceEditor , evt : 'click' } ,
{ sel : '#tool_docprops_save' , fn : saveDocProperties , evt : 'click' } ,
{ sel : '#tool_docprops' , fn : showDocProperties , evt : 'mouseup' } ,
{ sel : '#tool_prefs_save' , fn : savePreferences , evt : 'click' } ,
2013-02-15 22:32:35 +00:00
{ sel : '#tool_prefs_option' , fn : function ( ) { showPreferences ( ) ; return false ; } , evt : 'mouseup' } ,
2013-02-15 21:57:35 +00:00
{ sel : '#tool_delete,#tool_delete_multi' , fn : deleteSelected , evt : 'click' , key : [ 'del/backspace' , true ] } ,
{ sel : '#tool_reorient' , fn : reorientPath , evt : 'click' } ,
{ sel : '#tool_node_link' , fn : linkControlPoints , evt : 'click' } ,
{ sel : '#tool_node_clone' , fn : clonePathNode , evt : 'click' } ,
{ sel : '#tool_node_delete' , fn : deletePathNode , evt : 'click' } ,
{ sel : '#tool_openclose_path' , fn : opencloseSubPath , evt : 'click' } ,
{ sel : '#tool_add_subpath' , fn : addSubPath , evt : 'click' } ,
{ sel : '#tool_move_top' , fn : moveToTopSelected , evt : 'click' , key : 'ctrl+shift+]' } ,
{ sel : '#tool_move_bottom' , fn : moveToBottomSelected , evt : 'click' , key : 'ctrl+shift+[' } ,
{ sel : '#tool_topath' , fn : convertToPath , evt : 'click' } ,
{ sel : '#tool_make_link,#tool_make_link_multi' , fn : makeHyperlink , evt : 'click' } ,
2016-01-20 01:00:59 +00:00
{ sel : '#tool_undo' , fn : clickUndo , evt : 'click' } ,
{ sel : '#tool_redo' , fn : clickRedo , evt : 'click' } ,
2013-02-15 21:57:35 +00:00
{ sel : '#tool_clone,#tool_clone_multi' , fn : clickClone , evt : 'click' , key : [ 'D' , true ] } ,
2014-02-11 01:58:57 +00:00
{ sel : '#tool_group_elements' , fn : clickGroup , evt : 'click' , key : [ 'G' , true ] } ,
2013-02-15 21:57:35 +00:00
{ sel : '#tool_ungroup' , fn : clickGroup , evt : 'click' } ,
{ sel : '#tool_unlink_use' , fn : clickGroup , evt : 'click' } ,
{ sel : '[id^=tool_align]' , fn : clickAlign , evt : 'click' } ,
2010-03-11 21:07:13 +00:00
// these two lines are required to make Opera work properly with the flyout mechanism
2014-01-31 00:27:46 +00:00
// {sel: '#tools_rect_show', fn: clickRect, evt: 'click'},
// {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'},
2013-02-15 21:57:35 +00:00
{ sel : '#tool_bold' , fn : clickBold , evt : 'mousedown' } ,
{ sel : '#tool_italic' , fn : clickItalic , evt : 'mousedown' } ,
{ sel : '#sidepanel_handle' , fn : toggleSidePanel , key : [ 'X' ] } ,
{ sel : '#copy_save_done' , fn : cancelOverlays , evt : 'click' } ,
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Shortcuts not associated with buttons
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
{ key : 'ctrl+left' , fn : function ( ) { rotateSelected ( 0 , 1 ) ; } } ,
{ key : 'ctrl+right' , fn : function ( ) { rotateSelected ( 1 , 1 ) ; } } ,
{ key : 'ctrl+shift+left' , fn : function ( ) { rotateSelected ( 0 , 5 ) ; } } ,
{ key : 'ctrl+shift+right' , fn : function ( ) { rotateSelected ( 1 , 5 ) ; } } ,
2010-03-11 21:07:13 +00:00
{ key : 'shift+O' , fn : selectPrev } ,
{ key : 'shift+P' , fn : selectNext } ,
2010-08-20 19:27:57 +00:00
{ key : [ modKey + 'up' , true ] , fn : function ( ) { zoomImage ( 2 ) ; } } ,
2014-02-10 13:14:38 +00:00
{ key : [ modKey + 'down' , true ] , fn : function ( ) { zoomImage ( 0.5 ) ; } } ,
2010-08-20 19:27:57 +00:00
{ key : [ modKey + ']' , true ] , fn : function ( ) { moveUpDownSelected ( 'Up' ) ; } } ,
2013-02-15 13:38:55 +00:00
{ key : [ modKey + '[' , true ] , fn : function ( ) { moveUpDownSelected ( 'Down' ) ; } } ,
2010-03-11 21:07:13 +00:00
{ key : [ 'up' , true ] , fn : function ( ) { moveSelected ( 0 , - 1 ) ; } } ,
{ key : [ 'down' , true ] , fn : function ( ) { moveSelected ( 0 , 1 ) ; } } ,
{ key : [ 'left' , true ] , fn : function ( ) { moveSelected ( - 1 , 0 ) ; } } ,
{ key : [ 'right' , true ] , fn : function ( ) { moveSelected ( 1 , 0 ) ; } } ,
2014-02-10 13:14:38 +00:00
{ key : 'shift+up' , fn : function ( ) { moveSelected ( 0 , - 10 ) ; } } ,
{ key : 'shift+down' , fn : function ( ) { moveSelected ( 0 , 10 ) ; } } ,
{ key : 'shift+left' , fn : function ( ) { moveSelected ( - 10 , 0 ) ; } } ,
{ key : 'shift+right' , fn : function ( ) { moveSelected ( 10 , 0 ) ; } } ,
{ key : [ 'alt+up' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( 0 , - 1 ) ; } } ,
{ key : [ 'alt+down' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( 0 , 1 ) ; } } ,
{ key : [ 'alt+left' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( - 1 , 0 ) ; } } ,
{ key : [ 'alt+right' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( 1 , 0 ) ; } } ,
{ key : [ 'alt+shift+up' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( 0 , - 10 ) ; } } ,
{ key : [ 'alt+shift+down' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( 0 , 10 ) ; } } ,
{ key : [ 'alt+shift+left' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( - 10 , 0 ) ; } } ,
{ key : [ 'alt+shift+right' , true ] , fn : function ( ) { svgCanvas . cloneSelectedElements ( 10 , 0 ) ; } } ,
2011-01-28 20:11:18 +00:00
{ key : 'A' , fn : function ( ) { svgCanvas . selectAllInCurrentLayer ( ) ; } } ,
// Standard shortcuts
{ key : modKey + 'z' , fn : clickUndo } ,
{ key : modKey + 'shift+z' , fn : clickRedo } ,
{ key : modKey + 'y' , fn : clickRedo } ,
2012-10-22 10:47:50 +00:00
2011-01-28 20:11:18 +00:00
{ key : modKey + 'x' , fn : cutSelected } ,
{ key : modKey + 'c' , fn : copySelected } ,
{ key : modKey + 'v' , fn : pasteInCenter }
2010-03-11 21:07:13 +00:00
] ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Tooltips not directly associated with a single function
var key _assocs = {
'4/Shift+4' : '#tools_rect_show' ,
'5/Shift+5' : '#tools_ellipse_show'
} ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
return {
setAll : function ( ) {
var flyouts = { } ;
2012-10-22 10:47:50 +00:00
2013-10-13 23:23:08 +00:00
$ . each ( tool _buttons , function ( i , opts ) {
2010-03-11 21:07:13 +00:00
// Bind function to button
2014-02-10 13:14:38 +00:00
var btn ;
2013-02-15 21:57:35 +00:00
if ( opts . sel ) {
2014-02-10 13:14:38 +00:00
btn = $ ( opts . sel ) ;
if ( btn . length == 0 ) { return true ; } // Skip if markup does not exist
2013-02-15 13:38:55 +00:00
if ( opts . evt ) {
2013-02-15 22:32:35 +00:00
if ( svgedit . browser . isTouch ( ) && opts . evt === 'click' ) {
opts . evt = 'mousedown' ;
}
2010-03-11 21:07:13 +00:00
btn [ opts . evt ] ( opts . fn ) ;
}
2012-10-22 10:47:50 +00:00
2010-07-14 19:15:44 +00:00
// Add to parent flyout menu, if able to be displayed
2013-02-15 21:57:35 +00:00
if ( opts . parent && $ ( opts . parent + '_show' ) . length != 0 ) {
2010-03-11 21:07:13 +00:00
var f _h = $ ( opts . parent ) ;
2013-02-15 21:57:35 +00:00
if ( ! f _h . length ) {
2010-03-11 21:07:13 +00:00
f _h = makeFlyoutHolder ( opts . parent . substr ( 1 ) ) ;
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
f _h . append ( btn ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( ! $ . isArray ( flyouts [ opts . parent ] ) ) {
2010-03-11 21:07:13 +00:00
flyouts [ opts . parent ] = [ ] ;
}
flyouts [ opts . parent ] . push ( opts ) ;
}
2010-01-29 18:27:26 +00:00
}
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Bind function to shortcut key
2013-02-15 21:57:35 +00:00
if ( opts . key ) {
2010-03-11 21:07:13 +00:00
// Set shortcut based on options
2014-02-18 15:06:27 +00:00
var keyval , disInInp = true , fn = opts . fn , pd = false ;
2013-02-15 21:57:35 +00:00
if ( $ . isArray ( opts . key ) ) {
2010-03-11 21:07:13 +00:00
keyval = opts . key [ 0 ] ;
2014-02-10 13:14:38 +00:00
if ( opts . key . length > 1 ) { pd = opts . key [ 1 ] ; }
if ( opts . key . length > 2 ) { disInInp = opts . key [ 2 ] ; }
2010-03-11 21:07:13 +00:00
} else {
keyval = opts . key ;
}
keyval += '' ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ . each ( keyval . split ( '/' ) , function ( i , key ) {
2010-04-01 17:38:23 +00:00
$ ( document ) . bind ( 'keydown' , key , function ( e ) {
2010-03-11 21:07:13 +00:00
fn ( ) ;
2013-02-15 21:57:35 +00:00
if ( pd ) {
2010-03-11 21:07:13 +00:00
e . preventDefault ( ) ;
}
// Prevent default on ALL keys?
return false ;
} ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Put shortcut in title
2013-02-15 21:57:35 +00:00
if ( opts . sel && ! opts . hidekey && btn . attr ( 'title' ) ) {
2013-02-15 22:07:05 +00:00
var newTitle = btn . attr ( 'title' ) . split ( '[' ) [ 0 ] + ' (' + keyval + ')' ;
2010-03-11 21:07:13 +00:00
key _assocs [ keyval ] = opts . sel ;
// Disregard for menu items
2013-02-15 21:57:35 +00:00
if ( ! btn . parents ( '#main_menu' ) . length ) {
2013-02-15 22:07:05 +00:00
btn . attr ( 'title' , newTitle ) ;
2010-03-11 21:07:13 +00:00
}
}
2010-01-29 18:27:26 +00:00
}
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Setup flyouts
setupFlyouts ( flyouts ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Misc additional actions
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
// Make 'return' keypress trigger the change event
2012-10-22 10:47:50 +00:00
$ ( '.attr_changer, #image_url' ) . bind ( 'keydown' , 'return' ,
2010-03-11 21:07:13 +00:00
function ( evt ) { $ ( this ) . change ( ) ; evt . preventDefault ( ) ; }
) ;
2012-10-22 10:47:50 +00:00
2010-09-24 16:05:46 +00:00
$ ( window ) . bind ( 'keydown' , 'tab' , function ( e ) {
2013-02-15 21:57:35 +00:00
if ( ui _context === 'canvas' ) {
2010-09-24 16:05:46 +00:00
e . preventDefault ( ) ;
selectNext ( ) ;
}
} ) . bind ( 'keydown' , 'shift+tab' , function ( e ) {
2013-02-15 21:57:35 +00:00
if ( ui _context === 'canvas' ) {
2010-09-24 16:05:46 +00:00
e . preventDefault ( ) ;
selectPrev ( ) ;
}
} ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( '#tool_zoom' ) . dblclick ( dblclickZoom ) ;
} ,
setTitles : function ( ) {
2013-10-13 23:23:08 +00:00
$ . each ( key _assocs , function ( keyval , sel ) {
2010-03-11 21:07:13 +00:00
var menu = ( $ ( sel ) . parents ( '#main_menu' ) . length ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
$ ( sel ) . each ( function ( ) {
2014-02-10 13:14:38 +00:00
var t ;
2013-02-15 21:57:35 +00:00
if ( menu ) {
2014-02-10 13:14:38 +00:00
t = $ ( this ) . text ( ) . split ( ' [' ) [ 0 ] ;
2010-03-11 21:07:13 +00:00
} else {
2014-02-10 13:14:38 +00:00
t = this . title . split ( ' [' ) [ 0 ] ;
2010-03-11 21:07:13 +00:00
}
var key _str = '' ;
// Shift+Up
$ . each ( keyval . split ( '/' ) , function ( i , key ) {
var mod _bits = key . split ( '+' ) , mod = '' ;
2013-02-15 21:57:35 +00:00
if ( mod _bits . length > 1 ) {
2010-03-11 21:07:13 +00:00
mod = mod _bits [ 0 ] + '+' ;
key = mod _bits [ 1 ] ;
}
key _str += ( i ? '/' : '' ) + mod + ( uiStrings [ 'key_' + key ] || key ) ;
} ) ;
2013-02-15 21:57:35 +00:00
if ( menu ) {
2010-03-11 21:07:13 +00:00
this . lastChild . textContent = t + ' [' + key _str + ']' ;
} else {
this . title = t + ' [' + key _str + ']' ;
2009-12-29 21:20:45 +00:00
}
2009-12-11 20:35:51 +00:00
} ) ;
} ) ;
2010-03-11 21:07:13 +00:00
} ,
getButtonData : function ( sel ) {
var b ;
$ . each ( tool _buttons , function ( i , btn ) {
2014-02-10 13:14:38 +00:00
if ( btn . sel === sel ) { b = btn ; }
2010-03-11 21:07:13 +00:00
} ) ;
return b ;
}
} ;
2014-02-10 13:14:38 +00:00
} ( ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
Actions . setAll ( ) ;
2012-10-22 10:47:50 +00:00
2010-03-16 19:28:57 +00:00
// Select given tool
2014-02-18 15:06:27 +00:00
editor . ready ( function ( ) {
2010-10-29 13:13:34 +00:00
var tool ,
itool = curConfig . initTool ,
2013-02-15 21:57:35 +00:00
container = $ ( '#tools_left, #svg_editor .tools_flyout' ) ,
pre _tool = container . find ( '#tool_' + itool ) ,
reg _tool = container . find ( '#' + itool ) ;
if ( pre _tool . length ) {
2010-03-16 19:28:57 +00:00
tool = pre _tool ;
2013-02-23 19:22:00 +00:00
} else if ( reg _tool . length ) {
2010-03-16 19:28:57 +00:00
tool = reg _tool ;
} else {
2013-02-15 21:57:35 +00:00
tool = $ ( '#tool_select' ) ;
2010-03-16 19:28:57 +00:00
}
tool . click ( ) . mouseup ( ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( curConfig . wireframe ) {
2010-03-16 19:28:57 +00:00
$ ( '#tool_wireframe' ) . click ( ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( curConfig . showlayers ) {
2010-03-16 19:28:57 +00:00
toggleSidePanel ( ) ;
}
2012-10-22 10:47:50 +00:00
2011-01-12 15:10:01 +00:00
$ ( '#rulers' ) . toggle ( ! ! curConfig . showRulers ) ;
2012-10-22 10:47:50 +00:00
2011-06-24 16:28:34 +00:00
if ( curConfig . showRulers ) {
2012-10-22 10:47:50 +00:00
$ ( '#show_rulers' ) [ 0 ] . checked = true ;
2011-06-24 16:28:34 +00:00
}
2013-02-15 21:57:35 +00:00
if ( curConfig . baseUnit ) {
2010-10-05 17:13:00 +00:00
$ ( '#base_unit' ) . val ( curConfig . baseUnit ) ;
}
2012-10-22 10:47:50 +00:00
2013-02-19 21:07:24 +00:00
if ( curConfig . gridSnapping ) {
$ ( '#grid_snapping_on' ) [ 0 ] . checked = true ;
}
2013-02-15 21:57:35 +00:00
if ( curConfig . snappingStep ) {
2010-09-10 13:23:31 +00:00
$ ( '#grid_snapping_step' ) . val ( curConfig . snappingStep ) ;
}
2013-02-19 21:07:24 +00:00
if ( curConfig . gridColor ) {
$ ( '#grid_color' ) . val ( curConfig . gridColor ) ;
}
2010-03-16 19:28:57 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-16 10:28:17 +00:00
// init SpinButtons
$ ( '#rect_rx' ) . SpinButton ( { min : 0 , max : 1000 , callback : changeRectRadius } ) ;
$ ( '#stroke_width' ) . SpinButton ( { min : 0 , max : 99 , smallStep : 0.1 , callback : changeStrokeWidth } ) ;
2010-03-11 21:07:13 +00:00
$ ( '#angle' ) . SpinButton ( { min : - 180 , max : 180 , step : 5 , callback : changeRotationAngle } ) ;
2013-02-16 10:28:17 +00:00
$ ( '#font_size' ) . SpinButton ( { min : 0.001 , stepfunc : stepFontSize , callback : changeFontSize } ) ;
$ ( '#group_opacity' ) . SpinButton ( { min : 0 , max : 100 , step : 5 , callback : changeOpacity } ) ;
2014-02-10 13:14:38 +00:00
$ ( '#blur' ) . SpinButton ( { min : 0 , max : 10 , step : 0.1 , callback : changeBlur } ) ;
2011-02-23 20:06:33 +00:00
$ ( '#zoom' ) . SpinButton ( { min : 0.001 , max : 10000 , step : 50 , stepfunc : stepZoom , callback : changeZoom } )
2012-10-22 10:47:50 +00:00
// Set default zoom
2011-02-23 20:06:33 +00:00
. val ( svgCanvas . getZoom ( ) * 100 ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ ( '#workarea' ) . contextMenu ( {
2010-08-16 20:26:06 +00:00
menu : 'cmenu_canvas' ,
inSpeed : 0
} ,
function ( action , el , pos ) {
2013-02-15 22:32:35 +00:00
switch ( action ) {
2010-08-16 20:26:06 +00:00
case 'delete' :
deleteSelected ( ) ;
break ;
2010-08-17 18:09:50 +00:00
case 'cut' :
cutSelected ( ) ;
break ;
case 'copy' :
copySelected ( ) ;
break ;
case 'paste' :
svgCanvas . pasteElements ( ) ;
break ;
case 'paste_in_place' :
svgCanvas . pasteElements ( 'in_place' ) ;
break ;
2015-06-16 08:17:52 +00:00
case 'group' :
2014-02-11 02:03:54 +00:00
case 'group_elements' :
2010-09-24 17:44:34 +00:00
svgCanvas . groupSelectedElements ( ) ;
break ;
2012-10-22 10:47:50 +00:00
case 'ungroup' :
svgCanvas . ungroupSelectedElement ( ) ;
2010-09-24 17:44:34 +00:00
break ;
2011-01-28 20:11:18 +00:00
case 'move_front' :
moveToTopSelected ( ) ;
break ;
case 'move_up' :
moveUpDownSelected ( 'Up' ) ;
break ;
2010-08-20 14:52:55 +00:00
case 'move_down' :
2010-08-20 19:27:57 +00:00
moveUpDownSelected ( 'Down' ) ;
2010-08-20 14:52:55 +00:00
break ;
2010-09-27 14:20:20 +00:00
case 'move_back' :
moveToBottomSelected ( ) ;
2010-08-20 14:52:55 +00:00
break ;
2013-02-15 13:38:55 +00:00
default :
2013-02-23 19:22:00 +00:00
if ( svgedit . contextmenu && svgedit . contextmenu . hasCustomHandler ( action ) ) {
2013-02-15 13:38:55 +00:00
svgedit . contextmenu . getCustomHandler ( action ) . call ( ) ;
}
break ;
2010-08-17 18:09:50 +00:00
}
2013-02-15 21:57:35 +00:00
if ( svgCanvas . clipBoard . length ) {
2010-08-17 18:09:50 +00:00
canv _menu . enableContextMenuItems ( '#paste,#paste_in_place' ) ;
2010-08-16 20:26:06 +00:00
}
2013-02-15 22:32:35 +00:00
}
) ;
2012-10-22 10:47:50 +00:00
2010-09-16 14:04:47 +00:00
var lmenu _func = function ( action , el , pos ) {
switch ( action ) {
case 'dupe' :
cloneLayer ( ) ;
break ;
case 'delete' :
deleteLayer ( ) ;
break ;
case 'merge_down' :
mergeLayer ( ) ;
break ;
case 'merge_all' :
svgCanvas . mergeAllLayers ( ) ;
updateContextPanel ( ) ;
populateLayers ( ) ;
break ;
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ ( '#layerlist' ) . contextMenu ( {
2010-09-16 14:04:47 +00:00
menu : 'cmenu_layers' ,
inSpeed : 0
} ,
lmenu _func
) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ ( '#layer_moreopts' ) . contextMenu ( {
2010-09-16 14:04:47 +00:00
menu : 'cmenu_layers' ,
inSpeed : 0 ,
allowLeft : true
} ,
lmenu _func
) ;
2012-10-22 10:47:50 +00:00
2010-08-17 18:09:50 +00:00
$ ( '.contextMenu li' ) . mousedown ( function ( ev ) {
ev . preventDefault ( ) ;
2013-02-15 13:38:55 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2010-08-16 20:26:06 +00:00
$ ( '#cmenu_canvas li' ) . disableContextMenu ( ) ;
2010-08-17 18:09:50 +00:00
canv _menu . enableContextMenuItems ( '#delete,#cut,#copy' ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:46:19 +00:00
window . addEventListener ( 'beforeunload' , function ( e ) {
2012-10-22 10:47:50 +00:00
// Suppress warning if page is empty
2013-02-15 21:57:35 +00:00
if ( undoMgr . getUndoStackSize ( ) === 0 ) {
2014-02-18 15:06:27 +00:00
editor . showSaveWarning = false ;
2010-03-26 17:51:41 +00:00
}
2013-02-16 15:19:20 +00:00
// showSaveWarning is set to 'false' when the page is saved.
2014-02-18 15:06:27 +00:00
if ( ! curConfig . no _save _warning && editor . showSaveWarning ) {
2010-03-26 17:51:41 +00:00
// Browser already asks question about closing the page
2014-02-10 13:45:48 +00:00
e . returnValue = uiStrings . notification . unsavedChanges ; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
2012-10-22 10:47:50 +00:00
return uiStrings . notification . unsavedChanges ;
2010-03-26 17:51:41 +00:00
}
2014-01-31 00:06:50 +00:00
} , false ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . openPrep = function ( func ) {
2010-07-01 20:14:12 +00:00
$ ( '#main_menu' ) . hide ( ) ;
2013-02-15 21:57:35 +00:00
if ( undoMgr . getUndoStackSize ( ) === 0 ) {
2010-07-01 20:14:12 +00:00
func ( true ) ;
} else {
2011-01-03 18:45:36 +00:00
$ . confirm ( uiStrings . notification . QwantToOpen , func ) ;
2010-07-01 20:14:12 +00:00
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
function onDragEnter ( e ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
// and indicator should be displayed here, such as "drop files here"
}
function onDragOver ( e ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
}
function onDragLeave ( e ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
// hypothetical indicator should be removed here
}
2014-02-04 04:08:24 +00:00
// Use HTML5 File API: http://www.w3.org/TR/FileAPI/
2010-03-11 21:07:13 +00:00
// if browser has HTML5 File API support, then we will show the open menu item
2013-10-13 23:23:08 +00:00
// and provide a file input to click. When that change event fires, it will
2010-03-11 21:07:13 +00:00
// get the text contents of the file and send it to the canvas
if ( window . FileReader ) {
2013-02-15 21:57:35 +00:00
var importImage = function ( e ) {
2013-10-12 03:08:26 +00:00
$ . process _cancel ( uiStrings . notification . loadingImage ) ;
2012-10-22 10:47:50 +00:00
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
2013-02-15 21:57:35 +00:00
$ ( '#workarea' ) . removeAttr ( 'style' ) ;
2012-10-22 10:47:50 +00:00
$ ( '#main_menu' ) . hide ( ) ;
2013-02-15 21:57:35 +00:00
var file = ( e . type == 'drop' ) ? e . dataTransfer . files [ 0 ] : this . files [ 0 ] ;
if ( ! file ) {
2014-05-22 23:20:43 +00:00
$ ( '#dialog_box' ) . hide ( ) ;
2013-02-15 21:57:35 +00:00
return ;
}
2014-05-22 10:21:29 +00:00
/ * i f ( f i l e . t y p e = = = ' a p p l i c a t i o n / p d f ' ) { / / T o d o : H a n d l e P D F i m p o r t s
}
else * /
2013-02-15 21:57:35 +00:00
if ( file . type . indexOf ( 'image' ) != - 1 ) {
2014-02-04 04:08:24 +00:00
// Detected an image
// svg handling
2014-02-10 13:14:38 +00:00
var reader ;
2013-02-15 21:57:35 +00:00
if ( file . type . indexOf ( 'svg' ) != - 1 ) {
2014-02-10 13:14:38 +00:00
reader = new FileReader ( ) ;
2013-02-15 21:57:35 +00:00
reader . onloadend = function ( e ) {
2015-07-16 13:45:48 +00:00
var newElement = svgCanvas . importSvgString ( e . target . result , true ) ;
2013-02-15 21:57:35 +00:00
svgCanvas . ungroupSelectedElement ( ) ;
svgCanvas . ungroupSelectedElement ( ) ;
svgCanvas . groupSelectedElements ( ) ;
svgCanvas . alignSelectedElements ( 'm' , 'page' ) ;
svgCanvas . alignSelectedElements ( 'c' , 'page' ) ;
2015-07-16 13:45:48 +00:00
// highlight imported element, otherwise we get strange empty selectbox
svgCanvas . selectOnly ( [ newElement ] ) ;
2014-05-22 23:20:43 +00:00
$ ( '#dialog_box' ) . hide ( ) ;
2013-02-15 21:57:35 +00:00
} ;
reader . readAsText ( file ) ;
2014-05-22 23:20:43 +00:00
}
else {
2013-02-15 21:57:35 +00:00
//bitmap handling
2014-02-10 13:14:38 +00:00
reader = new FileReader ( ) ;
2013-02-15 21:57:35 +00:00
reader . onloadend = function ( e ) {
// let's insert the new image until we know its dimensions
2014-02-10 13:14:38 +00:00
var insertNewImage = function ( width , height ) {
2013-02-15 21:57:35 +00:00
var newImage = svgCanvas . addSvgElementFromJson ( {
element : 'image' ,
attr : {
x : 0 ,
y : 0 ,
width : width ,
height : height ,
id : svgCanvas . getNextId ( ) ,
style : 'pointer-events:inherit'
}
} ) ;
svgCanvas . setHref ( newImage , e . target . result ) ;
svgCanvas . selectOnly ( [ newImage ] ) ;
svgCanvas . alignSelectedElements ( 'm' , 'page' ) ;
svgCanvas . alignSelectedElements ( 'c' , 'page' ) ;
updateContextPanel ( ) ;
2014-05-22 23:20:43 +00:00
$ ( '#dialog_box' ) . hide ( ) ;
2012-10-22 10:47:50 +00:00
} ;
2014-05-22 10:21:29 +00:00
// create dummy img so we know the default dimensions
2013-02-15 21:57:35 +00:00
var imgWidth = 100 ;
var imgHeight = 100 ;
var img = new Image ( ) ;
img . src = e . target . result ;
img . style . opacity = 0 ;
img . onload = function ( ) {
imgWidth = img . offsetWidth ;
imgHeight = img . offsetHeight ;
insertNewImage ( imgWidth , imgHeight ) ;
2012-10-22 10:47:50 +00:00
} ;
2013-02-15 21:57:35 +00:00
} ;
reader . readAsDataURL ( file ) ;
2012-10-22 10:47:50 +00:00
}
}
2013-02-15 13:38:55 +00:00
} ;
2012-10-22 10:47:50 +00:00
workarea [ 0 ] . addEventListener ( 'dragenter' , onDragEnter , false ) ;
workarea [ 0 ] . addEventListener ( 'dragover' , onDragOver , false ) ;
workarea [ 0 ] . addEventListener ( 'dragleave' , onDragLeave , false ) ;
2013-02-15 21:57:35 +00:00
workarea [ 0 ] . addEventListener ( 'drop' , importImage , false ) ;
2012-10-22 10:47:50 +00:00
var open = $ ( '<input type="file">' ) . change ( function ( ) {
2010-03-26 18:55:49 +00:00
var f = this ;
2014-02-18 15:06:27 +00:00
editor . openPrep ( function ( ok ) {
2014-02-10 13:14:38 +00:00
if ( ! ok ) { return ; }
2010-03-26 18:55:49 +00:00
svgCanvas . clear ( ) ;
2014-03-16 03:32:12 +00:00
if ( f . files . length === 1 ) {
2013-10-12 03:08:26 +00:00
$ . process _cancel ( uiStrings . notification . loadingImage ) ;
2010-03-26 18:55:49 +00:00
var reader = new FileReader ( ) ;
reader . onloadend = function ( e ) {
2010-10-08 17:54:45 +00:00
loadSvgString ( e . target . result ) ;
2010-03-26 18:55:49 +00:00
updateCanvas ( ) ;
} ;
reader . readAsText ( f . files [ 0 ] ) ;
}
2010-07-01 20:14:12 +00:00
} ) ;
2009-12-11 20:35:51 +00:00
} ) ;
2013-02-15 21:57:35 +00:00
$ ( '#tool_open' ) . show ( ) . prepend ( open ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
var imgImport = $ ( '<input type="file">' ) . change ( importImage ) ;
$ ( '#tool_import' ) . show ( ) . prepend ( imgImport ) ;
2010-03-11 21:07:13 +00:00
}
2012-10-22 10:47:50 +00:00
2014-01-31 00:27:46 +00:00
// $(function() {
2010-03-11 21:07:13 +00:00
updateCanvas ( true ) ;
2014-01-31 00:27:46 +00:00
// });
2012-10-22 10:47:50 +00:00
2014-02-22 04:08:24 +00:00
// var revnums = "svg-editor.js ($Rev$) ";
// revnums += svgCanvas.getVersion();
// $('#copyright')[0].setAttribute('title', revnums);
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// For Compatibility with older extensions
$ ( function ( ) {
window . svgCanvas = svgCanvas ;
2014-02-18 23:57:49 +00:00
svgCanvas . ready = editor . ready ;
2010-03-11 21:07:13 +00:00
} ) ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . setLang = function ( lang , allStrings ) {
editor . langChanged = true ;
2010-03-11 21:07:13 +00:00
$ . pref ( 'lang' , lang ) ;
$ ( '#lang_select' ) . val ( lang ) ;
2013-02-15 21:57:35 +00:00
if ( ! allStrings ) {
return ;
}
2014-02-18 15:06:27 +00:00
// var notif = allStrings.notification; // Currently unused
2013-02-15 21:57:35 +00:00
// $.extend will only replace the given strings
var oldLayerName = $ ( '#layerlist tr.layersel td.layername' ) . text ( ) ;
var rename _layer = ( oldLayerName == uiStrings . common . layer + ' 1' ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ . extend ( uiStrings , allStrings ) ;
svgCanvas . setUiStrings ( allStrings ) ;
Actions . setTitles ( ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
if ( rename _layer ) {
svgCanvas . renameCurrentLayer ( uiStrings . common . layer + ' 1' ) ;
populateLayers ( ) ;
}
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
// In case extensions loaded before the locale, now we execute a callback on them
if ( extsPreLang . length ) {
while ( extsPreLang . length ) {
var ext = extsPreLang . shift ( ) ;
ext . langReady ( { lang : lang , uiStrings : uiStrings } ) ;
}
}
else {
svgCanvas . runExtensions ( 'langReady' , { lang : lang , uiStrings : uiStrings } ) ;
}
2013-02-15 21:57:35 +00:00
svgCanvas . runExtensions ( 'langChanged' , lang ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
// Update flyout tooltips
setFlyoutTitles ( ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
// Copy title for certain tool elements
var elems = {
'#stroke_color' : '#tool_stroke .icon_label, #tool_stroke .color_block' ,
'#fill_color' : '#tool_fill label, #tool_fill .color_block' ,
'#linejoin_miter' : '#cur_linejoin' ,
'#linecap_butt' : '#cur_linecap'
} ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
$ . each ( elems , function ( source , dest ) {
$ ( dest ) . attr ( 'title' , $ ( source ) [ 0 ] . title ) ;
} ) ;
2012-10-22 10:47:50 +00:00
2013-02-15 21:57:35 +00:00
// Copy alignment titles
$ ( '#multiselected_panel div[id^=tool_align]' ) . each ( function ( ) {
$ ( '#tool_pos' + this . id . substr ( 10 ) ) [ 0 ] . title = this . title ;
} ) ;
2010-01-15 21:33:55 +00:00
} ;
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . ready = function ( cb ) {
2013-02-15 21:57:35 +00:00
if ( ! isReady ) {
2010-03-11 21:07:13 +00:00
callbacks . push ( cb ) ;
} else {
cb ( ) ;
}
} ;
2010-01-15 21:33:55 +00:00
2014-02-18 15:06:27 +00:00
editor . runCallbacks = function ( ) {
2010-03-11 21:07:13 +00:00
$ . each ( callbacks , function ( ) {
this ( ) ;
} ) ;
2013-02-15 21:57:35 +00:00
isReady = true ;
2010-03-11 21:07:13 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . loadFromString = function ( str ) {
editor . ready ( function ( ) {
2010-10-08 17:54:45 +00:00
loadSvgString ( str ) ;
2010-03-11 21:07:13 +00:00
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . disableUI = function ( featList ) {
2014-01-31 00:27:46 +00:00
// $(function() {
// $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove();
// $('#tools_top').css('left', 5);
// });
2011-02-03 14:58:47 +00:00
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . loadFromURL = function ( url , opts ) {
2014-02-04 04:08:24 +00:00
if ( ! opts ) { opts = { } ; }
2010-10-11 12:21:37 +00:00
2010-10-08 18:21:46 +00:00
var cache = opts . cache ;
var cb = opts . callback ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . ready ( function ( ) {
2010-03-11 21:07:13 +00:00
$ . ajax ( {
'url' : url ,
'dataType' : 'text' ,
2010-07-19 15:38:23 +00:00
cache : ! ! cache ,
2013-05-08 17:29:18 +00:00
beforeSend : function ( ) {
2013-10-12 03:08:26 +00:00
$ . process _cancel ( uiStrings . notification . loadingImage ) ;
} ,
2010-10-08 18:21:46 +00:00
success : function ( str ) {
loadSvgString ( str , cb ) ;
} ,
2010-04-23 19:40:09 +00:00
error : function ( xhr , stat , err ) {
2013-02-15 21:57:35 +00:00
if ( xhr . status != 404 && xhr . responseText ) {
2010-10-08 18:21:46 +00:00
loadSvgString ( xhr . responseText , cb ) ;
2010-04-23 19:40:09 +00:00
} else {
2014-02-10 13:14:38 +00:00
$ . alert ( uiStrings . notification . URLloadFail + ': \n' + err , cb ) ;
2010-03-11 21:07:13 +00:00
}
2013-05-08 17:29:18 +00:00
} ,
2013-10-12 03:08:26 +00:00
complete : function ( ) {
$ ( '#dialog_box' ) . hide ( ) ;
}
2010-03-11 21:07:13 +00:00
} ) ;
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . loadFromDataURI = function ( str ) {
editor . ready ( function ( ) {
2014-04-08 13:49:58 +00:00
var base64 = false ;
2014-04-08 01:31:22 +00:00
var pre = str . match ( /^data:image\/svg\+xml;base64,/ ) ;
2014-04-08 13:49:58 +00:00
if ( pre ) {
base64 = true ;
}
else {
pre = str . match ( /^data:image\/svg\+xml(?:;(?:utf8)?)?,/ ) ;
}
if ( pre ) {
pre = pre [ 0 ] ;
}
2014-04-08 01:31:22 +00:00
var src = str . slice ( pre . length ) ;
loadSvgString ( base64 ? Utils . decode64 ( src ) : decodeURIComponent ( src ) ) ;
2010-03-11 21:07:13 +00:00
} ) ;
} ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
editor . addExtension = function ( ) {
2010-03-11 21:07:13 +00:00
var args = arguments ;
2012-10-22 10:47:50 +00:00
2014-02-18 15:06:27 +00:00
// Note that we don't want this on editor.ready since some extensions
2010-09-20 12:49:36 +00:00
// may want to run before then (like server_opensave).
$ ( function ( ) {
2014-02-10 13:14:38 +00:00
if ( svgCanvas ) { svgCanvas . addExtension . apply ( this , args ) ; }
2010-03-11 21:07:13 +00:00
} ) ;
} ;
2009-11-09 18:59:53 +00:00
2014-02-18 15:06:27 +00:00
return editor ;
2014-02-10 13:14:38 +00:00
} ( jQuery ) ) ;
2012-10-22 10:47:50 +00:00
2010-03-11 21:07:13 +00:00
// Run init once DOM is loaded
$ ( svgEditor . init ) ;
2012-10-22 10:47:50 +00:00
2014-02-10 13:14:38 +00:00
} ( ) ) ;