|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 53 KiB |
@ -1,7 +1,7 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> |
||||
<meta charset="UTF-8" /> |
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1"/> |
||||
<link rel="icon" type="image/png" href="images/logo.png"/> |
||||
<link rel="stylesheet" href="svg-editor.css" type="text/css"/> |
||||
@ -0,0 +1,17 @@ |
||||
/*globals svgEditor*/ |
||||
/* see https://code.google.com/p/svg-edit/wiki/ConfigOptions */ |
||||
svgEditor.setConfig({ |
||||
extensions: [ |
||||
'ext-php_savefile_chamilo.js', |
||||
'ext-eyedropper.js', |
||||
'ext-shapes.js', |
||||
'ext-polygon.js', |
||||
'ext-star.js' |
||||
], |
||||
noStorageOnLoad: 'true', |
||||
selectNew: true, |
||||
no_save_warning: true, |
||||
emptyStorageOnDecline: true, |
||||
iconsize: 'm', |
||||
allowedOrigins: [window.location.origin] // May be 'null' (as a string) when used as a file:// URL
|
||||
}); |
||||
@ -1,203 +1,203 @@ |
||||
// jQuery Context Menu Plugin
|
||||
//
|
||||
// Version 1.01
|
||||
//
|
||||
// Cory S.N. LaViska
|
||||
// A Beautiful Site (http://abeautifulsite.net/)
|
||||
// Modified by Alexis Deveria
|
||||
//
|
||||
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
|
||||
//
|
||||
// Terms of Use
|
||||
//
|
||||
// This plugin is dual-licensed under the GNU General Public License
|
||||
// and the MIT License and is copyright A Beautiful Site, LLC.
|
||||
//
|
||||
if(jQuery)( function() { |
||||
var win = $(window); |
||||
var doc = $(document); |
||||
|
||||
$.extend($.fn, { |
||||
|
||||
contextMenu: function(o, callback) { |
||||
// Defaults
|
||||
if( o.menu == undefined ) return false; |
||||
if( o.inSpeed == undefined ) o.inSpeed = 150; |
||||
if( o.outSpeed == undefined ) o.outSpeed = 75; |
||||
// 0 needs to be -1 for expected results (no fade)
|
||||
if( o.inSpeed == 0 ) o.inSpeed = -1; |
||||
if( o.outSpeed == 0 ) o.outSpeed = -1; |
||||
// Loop each context menu
|
||||
$(this).each( function() { |
||||
var el = $(this); |
||||
var offset = $(el).offset(); |
||||
|
||||
var menu = $('#' + o.menu); |
||||
|
||||
// Add contextMenu class
|
||||
menu.addClass('contextMenu'); |
||||
// Simulate a true right click
|
||||
$(this).bind( "mousedown", function(e) { |
||||
var evt = e; |
||||
$(this).mouseup( function(e) { |
||||
var srcElement = $(this); |
||||
srcElement.unbind('mouseup'); |
||||
if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) { |
||||
e.stopPropagation(); |
||||
// Hide context menus that may be showing
|
||||
$(".contextMenu").hide(); |
||||
// Get this context menu
|
||||
|
||||
if( el.hasClass('disabled') ) return false; |
||||
|
||||
// Detect mouse position
|
||||
var d = {}, x = e.pageX, y = e.pageY; |
||||
|
||||
var x_off = win.width() - menu.width(),
|
||||
y_off = win.height() - menu.height(); |
||||
|
||||
if(x > x_off - 15) x = x_off-15; |
||||
if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF
|
||||
|
||||
// Show the menu
|
||||
doc.unbind('click'); |
||||
menu.css({ top: y, left: x }).fadeIn(o.inSpeed); |
||||
// Hover events
|
||||
menu.find('A').mouseover( function() { |
||||
menu.find('LI.hover').removeClass('hover'); |
||||
$(this).parent().addClass('hover'); |
||||
}).mouseout( function() { |
||||
menu.find('LI.hover').removeClass('hover'); |
||||
}); |
||||
|
||||
// Keyboard
|
||||
doc.keypress( function(e) { |
||||
switch( e.keyCode ) { |
||||
case 38: // up
|
||||
if( !menu.find('LI.hover').length ) { |
||||
menu.find('LI:last').addClass('hover'); |
||||
} else { |
||||
menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); |
||||
if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover'); |
||||
} |
||||
break; |
||||
case 40: // down
|
||||
if( menu.find('LI.hover').length == 0 ) { |
||||
menu.find('LI:first').addClass('hover'); |
||||
} else { |
||||
menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); |
||||
if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover'); |
||||
} |
||||
break; |
||||
case 13: // enter
|
||||
menu.find('LI.hover A').trigger('click'); |
||||
break; |
||||
case 27: // esc
|
||||
doc.trigger('click'); |
||||
break |
||||
} |
||||
}); |
||||
|
||||
// When items are selected
|
||||
menu.find('A').unbind('mouseup'); |
||||
menu.find('LI:not(.disabled) A').mouseup( function() { |
||||
doc.unbind('click').unbind('keypress'); |
||||
$(".contextMenu").hide(); |
||||
// Callback
|
||||
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} ); |
||||
return false; |
||||
}); |
||||
|
||||
// Hide bindings
|
||||
setTimeout( function() { // Delay for Mozilla
|
||||
doc.click( function() { |
||||
doc.unbind('click').unbind('keypress'); |
||||
menu.fadeOut(o.outSpeed); |
||||
return false; |
||||
}); |
||||
}, 0); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
// Disable text selection
|
||||
if( $.browser.mozilla ) { |
||||
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); }); |
||||
} else if( $.browser.msie ) { |
||||
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); }); |
||||
} else { |
||||
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); }); |
||||
} |
||||
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
|
||||
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; }); |
||||
|
||||
}); |
||||
return $(this); |
||||
}, |
||||
|
||||
// Disable context menu items on the fly
|
||||
disableContextMenuItems: function(o) { |
||||
if( o == undefined ) { |
||||
// Disable all
|
||||
$(this).find('LI').addClass('disabled'); |
||||
return( $(this) ); |
||||
} |
||||
$(this).each( function() { |
||||
if( o != undefined ) { |
||||
var d = o.split(','); |
||||
for( var i = 0; i < d.length; i++ ) { |
||||
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled'); |
||||
|
||||
} |
||||
} |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Enable context menu items on the fly
|
||||
enableContextMenuItems: function(o) { |
||||
if( o == undefined ) { |
||||
// Enable all
|
||||
$(this).find('LI.disabled').removeClass('disabled'); |
||||
return( $(this) ); |
||||
} |
||||
$(this).each( function() { |
||||
if( o != undefined ) { |
||||
var d = o.split(','); |
||||
for( var i = 0; i < d.length; i++ ) { |
||||
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled'); |
||||
|
||||
} |
||||
} |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Disable context menu(s)
|
||||
disableContextMenu: function() { |
||||
$(this).each( function() { |
||||
$(this).addClass('disabled'); |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Enable context menu(s)
|
||||
enableContextMenu: function() { |
||||
$(this).each( function() { |
||||
$(this).removeClass('disabled'); |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Destroy context menu(s)
|
||||
destroyContextMenu: function() { |
||||
// Destroy specified context menus
|
||||
$(this).each( function() { |
||||
// Disable action
|
||||
$(this).unbind('mousedown').unbind('mouseup'); |
||||
}); |
||||
return( $(this) ); |
||||
} |
||||
|
||||
}); |
||||
// jQuery Context Menu Plugin
|
||||
//
|
||||
// Version 1.01
|
||||
//
|
||||
// Cory S.N. LaViska
|
||||
// A Beautiful Site (http://abeautifulsite.net/)
|
||||
// Modified by Alexis Deveria
|
||||
//
|
||||
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
|
||||
//
|
||||
// Terms of Use
|
||||
//
|
||||
// This plugin is dual-licensed under the GNU General Public License
|
||||
// and the MIT License and is copyright A Beautiful Site, LLC.
|
||||
//
|
||||
if(jQuery)( function() { |
||||
var win = $(window); |
||||
var doc = $(document); |
||||
|
||||
$.extend($.fn, { |
||||
|
||||
contextMenu: function(o, callback) { |
||||
// Defaults
|
||||
if( o.menu == undefined ) return false; |
||||
if( o.inSpeed == undefined ) o.inSpeed = 150; |
||||
if( o.outSpeed == undefined ) o.outSpeed = 75; |
||||
// 0 needs to be -1 for expected results (no fade)
|
||||
if( o.inSpeed == 0 ) o.inSpeed = -1; |
||||
if( o.outSpeed == 0 ) o.outSpeed = -1; |
||||
// Loop each context menu
|
||||
$(this).each( function() { |
||||
var el = $(this); |
||||
var offset = $(el).offset(); |
||||
|
||||
var menu = $('#' + o.menu); |
||||
|
||||
// Add contextMenu class
|
||||
menu.addClass('contextMenu'); |
||||
// Simulate a true right click
|
||||
$(this).bind( "mousedown", function(e) { |
||||
var evt = e; |
||||
$(this).mouseup( function(e) { |
||||
var srcElement = $(this); |
||||
srcElement.unbind('mouseup'); |
||||
if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) { |
||||
e.stopPropagation(); |
||||
// Hide context menus that may be showing
|
||||
$(".contextMenu").hide(); |
||||
// Get this context menu
|
||||
|
||||
if( el.hasClass('disabled') ) return false; |
||||
|
||||
// Detect mouse position
|
||||
var d = {}, x = e.pageX, y = e.pageY; |
||||
|
||||
var x_off = win.width() - menu.width(),
|
||||
y_off = win.height() - menu.height(); |
||||
|
||||
if(x > x_off - 15) x = x_off-15; |
||||
if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF
|
||||
|
||||
// Show the menu
|
||||
doc.unbind('click'); |
||||
menu.css({ top: y, left: x }).fadeIn(o.inSpeed); |
||||
// Hover events
|
||||
menu.find('A').mouseover( function() { |
||||
menu.find('LI.hover').removeClass('hover'); |
||||
$(this).parent().addClass('hover'); |
||||
}).mouseout( function() { |
||||
menu.find('LI.hover').removeClass('hover'); |
||||
}); |
||||
|
||||
// Keyboard
|
||||
doc.keypress( function(e) { |
||||
switch( e.keyCode ) { |
||||
case 38: // up
|
||||
if( !menu.find('LI.hover').length ) { |
||||
menu.find('LI:last').addClass('hover'); |
||||
} else { |
||||
menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); |
||||
if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover'); |
||||
} |
||||
break; |
||||
case 40: // down
|
||||
if( menu.find('LI.hover').length == 0 ) { |
||||
menu.find('LI:first').addClass('hover'); |
||||
} else { |
||||
menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); |
||||
if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover'); |
||||
} |
||||
break; |
||||
case 13: // enter
|
||||
menu.find('LI.hover A').trigger('click'); |
||||
break; |
||||
case 27: // esc
|
||||
doc.trigger('click'); |
||||
break |
||||
} |
||||
}); |
||||
|
||||
// When items are selected
|
||||
menu.find('A').unbind('mouseup'); |
||||
menu.find('LI:not(.disabled) A').mouseup( function() { |
||||
doc.unbind('click').unbind('keypress'); |
||||
$(".contextMenu").hide(); |
||||
// Callback
|
||||
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} ); |
||||
return false; |
||||
}); |
||||
|
||||
// Hide bindings
|
||||
setTimeout( function() { // Delay for Mozilla
|
||||
doc.click( function() { |
||||
doc.unbind('click').unbind('keypress'); |
||||
menu.fadeOut(o.outSpeed); |
||||
return false; |
||||
}); |
||||
}, 0); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
// Disable text selection
|
||||
if( $.browser.mozilla ) { |
||||
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); }); |
||||
} else if( $.browser.msie ) { |
||||
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); }); |
||||
} else { |
||||
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); }); |
||||
} |
||||
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
|
||||
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; }); |
||||
|
||||
}); |
||||
return $(this); |
||||
}, |
||||
|
||||
// Disable context menu items on the fly
|
||||
disableContextMenuItems: function(o) { |
||||
if( o == undefined ) { |
||||
// Disable all
|
||||
$(this).find('LI').addClass('disabled'); |
||||
return( $(this) ); |
||||
} |
||||
$(this).each( function() { |
||||
if( o != undefined ) { |
||||
var d = o.split(','); |
||||
for( var i = 0; i < d.length; i++ ) { |
||||
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled'); |
||||
|
||||
} |
||||
} |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Enable context menu items on the fly
|
||||
enableContextMenuItems: function(o) { |
||||
if( o == undefined ) { |
||||
// Enable all
|
||||
$(this).find('LI.disabled').removeClass('disabled'); |
||||
return( $(this) ); |
||||
} |
||||
$(this).each( function() { |
||||
if( o != undefined ) { |
||||
var d = o.split(','); |
||||
for( var i = 0; i < d.length; i++ ) { |
||||
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled'); |
||||
|
||||
} |
||||
} |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Disable context menu(s)
|
||||
disableContextMenu: function() { |
||||
$(this).each( function() { |
||||
$(this).addClass('disabled'); |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Enable context menu(s)
|
||||
enableContextMenu: function() { |
||||
$(this).each( function() { |
||||
$(this).removeClass('disabled'); |
||||
}); |
||||
return( $(this) ); |
||||
}, |
||||
|
||||
// Destroy context menu(s)
|
||||
destroyContextMenu: function() { |
||||
// Destroy specified context menus
|
||||
$(this).each( function() { |
||||
// Disable action
|
||||
$(this).unbind('mousedown').unbind('mouseup'); |
||||
}); |
||||
return( $(this) ); |
||||
} |
||||
|
||||
}); |
||||
})(jQuery); |
||||
@ -0,0 +1,6 @@ |
||||
#main_icon { |
||||
width:38px !important; |
||||
} |
||||
#tools_top { |
||||
left: 55px !important; |
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
/*globals $, EmbeddedSVGEdit*/ |
||||
/*jslint vars: true */ |
||||
var initEmbed; |
||||
|
||||
// Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain
|
||||
|
||||
$(function () {'use strict'; |
||||
|
||||
var svgCanvas = null; |
||||
var frame; |
||||
|
||||
initEmbed = function () { |
||||
var doc, mainButton; |
||||
svgCanvas = new EmbeddedSVGEdit(frame); |
||||
// Hide main button, as we will be controlling new, load, save, etc. from the host document
|
||||
doc = frame.contentDocument || frame.contentWindow.document; |
||||
mainButton = doc.getElementById('main_button'); |
||||
mainButton.style.display = 'none'; |
||||
}; |
||||
|
||||
function handleSvgData(data, error) { |
||||
if (error) { |
||||
alert('error ' + error); |
||||
} else { |
||||
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data); |
||||
} |
||||
} |
||||
|
||||
function loadSvg() { |
||||
var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>'; |
||||
svgCanvas.setSvgString(svgexample); |
||||
} |
||||
|
||||
function saveSvg() { |
||||
svgCanvas.getSvgString()(handleSvgData); |
||||
} |
||||
|
||||
function exportPNG() { |
||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; |
||||
|
||||
var exportWindow = window.open( |
||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'), |
||||
'svg-edit-exportWindow' |
||||
); |
||||
svgCanvas.rasterExport('PNG', null, exportWindow.name); |
||||
} |
||||
|
||||
function exportPDF() { |
||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; |
||||
|
||||
/** |
||||
// If you want to handle the PDF blob yourself, do as follows
|
||||
svgCanvas.bind('exportedPDF', function (win, data) { |
||||
alert(data.dataurlstring); |
||||
}); |
||||
svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring)
|
||||
return; |
||||
*/ |
||||
|
||||
var exportWindow = window.open( |
||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'), |
||||
'svg-edit-exportWindow' |
||||
); |
||||
svgCanvas.exportPDF(exportWindow.name); |
||||
} |
||||
|
||||
// Add event handlers
|
||||
$('#load').click(loadSvg); |
||||
$('#save').click(saveSvg); |
||||
$('#exportPNG').click(exportPNG); |
||||
$('#exportPDF').click(exportPDF); |
||||
$('body').append( |
||||
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' + |
||||
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
|
||||
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>' |
||||
) |
||||
); |
||||
frame = document.getElementById('svgedit'); |
||||
}); |
||||
@ -1,11 +1,12 @@ |
||||
<?php |
||||
|
||||
$allowedMimeTypesBySuffix = array( |
||||
'svg' => 'image/svg+xml;charset=utf-8', |
||||
'svg' => 'image/svg+xml;charset=UTF-8', |
||||
'png' => 'image/png', |
||||
'jpeg' => 'image/jpeg', |
||||
'bmp' => 'image/bmp', |
||||
'webp' => 'image/webp' |
||||
'webp' => 'image/webp', |
||||
'pdf' => 'application/pdf' |
||||
); |
||||
|
||||
?> |
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 708 B |
@ -0,0 +1,67 @@ |
||||
/*globals svgEditor*/ |
||||
/* |
||||
Depends on Firefox add-on and executables from https://github.com/brettz9/webappfind
|
||||
|
||||
Todos: |
||||
1. See WebAppFind Readme for SVG-related todos |
||||
*/ |
||||
(function () {'use strict'; |
||||
|
||||
var pathID, |
||||
saveMessage = 'webapp-save', |
||||
readMessage = 'webapp-read', |
||||
excludedMessages = [readMessage, saveMessage]; |
||||
|
||||
window.addEventListener('message', function(e) { |
||||
if (e.origin !== window.location.origin || // PRIVACY AND SECURITY! (for viewing and saving, respectively)
|
||||
(!Array.isArray(e.data) || excludedMessages.indexOf(e.data[0]) > -1) // Validate format and avoid our post below
|
||||
) { |
||||
return; |
||||
} |
||||
var svgString, |
||||
messageType = e.data[0]; |
||||
switch (messageType) { |
||||
case 'webapp-view': |
||||
// Populate the contents
|
||||
pathID = e.data[1]; |
||||
|
||||
svgString = e.data[2]; |
||||
svgEditor.loadFromString(svgString); |
||||
|
||||
/*if ($('#tool_save_file')) { |
||||
$('#tool_save_file').disabled = false; |
||||
}*/ |
||||
break; |
||||
case 'webapp-save-end': |
||||
alert('save complete for pathID ' + e.data[1] + '!'); |
||||
break; |
||||
default: |
||||
throw 'Unexpected mode'; |
||||
} |
||||
}, false); |
||||
|
||||
window.postMessage([readMessage], window.location.origin !== 'null' ? window.location.origin : '*'); // Avoid "null" string error for file: protocol (even though file protocol not currently supported by add-on)
|
||||
|
||||
svgEditor.addExtension('WebAppFind', function() { |
||||
|
||||
return { |
||||
name: 'WebAppFind', |
||||
svgicons: svgEditor.curConfig.extPath + 'executablebuilder-icocreator.svg', |
||||
buttons: [{ |
||||
id: 'webappfind_ico_export', //
|
||||
type: 'app_menu', |
||||
title: 'Export ICO Image back to Disk', |
||||
position: 4, // Before 0-based index position 4 (after the regular "Save Image (S)")
|
||||
events: { |
||||
click: function () { |
||||
if (!pathID) { // Not ready yet as haven't received first payload
|
||||
return; |
||||
} |
||||
window.postMessage([saveMessage, pathID, svgEditor.canvas.getSvgString()], window.location.origin); |
||||
} |
||||
} |
||||
}] |
||||
}; |
||||
}); |
||||
|
||||
}()); |
||||
@ -0,0 +1,474 @@ |
||||
/*globals $, svgEditor, svgedit, svgCanvas, DOMParser*/ |
||||
/*jslint vars: true, eqeq: true, es5: true, todo: true */ |
||||
/* |
||||
* ext-imagelib.js |
||||
* |
||||
* Licensed under the MIT License |
||||
* |
||||
* Copyright(c) 2010 Alexis Deveria |
||||
* |
||||
*/ |
||||
|
||||
svgEditor.addExtension("imagelib", function() {'use strict'; |
||||
|
||||
var uiStrings = svgEditor.uiStrings; |
||||
|
||||
$.extend(uiStrings, { |
||||
imagelib: { |
||||
select_lib: 'Select an image library', |
||||
show_list: 'Show library list', |
||||
import_single: 'Import single', |
||||
import_multi: 'Import multiple', |
||||
open: 'Open as new document' |
||||
} |
||||
}); |
||||
|
||||
var img_libs = [ |
||||
{ |
||||
name: 'Local library (local)', |
||||
url: 'extensions/imagelib/index.php', |
||||
//description: 'Demonstration library for SVG-edit on this server'// Chamilo change this line by below
|
||||
description: 'Course gallery' |
||||
}, |
||||
{ |
||||
name: 'Local library', |
||||
url: 'extensions/imagelib/groups.php', |
||||
//description: 'Demonstration library for SVG-edit on this server'// Chamilo change this line by below
|
||||
description: 'Group gallery' |
||||
}, |
||||
{ |
||||
name: 'Local library', |
||||
url: 'extensions/imagelib/users.php', |
||||
//description: 'Demonstration library for SVG-edit on this server'// Chamilo change this line by below
|
||||
description: 'Personal gallery' |
||||
}, |
||||
{ |
||||
name: 'IAN Symbol Libraries', |
||||
url: 'http://ian.umces.edu/symbols/catalog/svgedit/album_chooser.php', |
||||
description: 'Free library of illustrations' |
||||
} |
||||
]; |
||||
|
||||
function closeBrowser() { |
||||
$('#imgbrowse_holder').hide(); |
||||
} |
||||
|
||||
function importImage(url) { |
||||
var newImage = svgCanvas.addSvgElementFromJson({ |
||||
"element": "image", |
||||
"attr": { |
||||
"x": 0, |
||||
"y": 0, |
||||
"width": 0, |
||||
"height": 0, |
||||
"id": svgCanvas.getNextId(), |
||||
"style": "pointer-events:inherit" |
||||
} |
||||
}); |
||||
svgCanvas.clearSelection(); |
||||
svgCanvas.addToSelection([newImage]); |
||||
svgCanvas.setImageURL(url); |
||||
} |
||||
|
||||
var mode = 's'; |
||||
var multi_arr = []; |
||||
var cur_meta; |
||||
var tranfer_stopped = false; |
||||
var pending = {}; |
||||
var preview, submit; |
||||
|
||||
window.addEventListener("message", function(evt) { |
||||
// Receive postMessage data
|
||||
var response = evt.data; |
||||
|
||||
if (!response || typeof response !== "string") { // Todo: Should namespace postMessage API for this extension and filter out here
|
||||
// Do nothing
|
||||
return; |
||||
} |
||||
try { // This block can be removed if embedAPI moves away from a string to an object (if IE9 support not needed)
|
||||
var res = JSON.parse(response); |
||||
if (res.namespace) { // Part of embedAPI communications
|
||||
return; |
||||
} |
||||
} |
||||
catch (e) {} |
||||
|
||||
var char1 = response.charAt(0); |
||||
var id; |
||||
var svg_str; |
||||
var img_str; |
||||
|
||||
if (char1 != "{" && tranfer_stopped) { |
||||
tranfer_stopped = false; |
||||
return; |
||||
} |
||||
|
||||
if (char1 == '|') { |
||||
var secondpos = response.indexOf('|', 1); |
||||
id = response.substr(1, secondpos-1); |
||||
response = response.substr(secondpos+1); |
||||
char1 = response.charAt(0); |
||||
} |
||||
|
||||
|
||||
// Hide possible transfer dialog box
|
||||
$('#dialog_box').hide(); |
||||
var entry, cur_meta; |
||||
switch (char1) { |
||||
case '{': |
||||
// Metadata
|
||||
tranfer_stopped = false; |
||||
cur_meta = JSON.parse(response); |
||||
|
||||
pending[cur_meta.id] = cur_meta; |
||||
|
||||
var name = (cur_meta.name || 'file'); |
||||
|
||||
var message = uiStrings.notification.retrieving.replace('%s', name); |
||||
|
||||
if (mode != 'm') { |
||||
$.process_cancel(message, function() { |
||||
tranfer_stopped = true; |
||||
// Should a message be sent back to the frame?
|
||||
|
||||
$('#dialog_box').hide(); |
||||
}); |
||||
} else { |
||||
entry = $('<div>' + message + '</div>').data('id', cur_meta.id); |
||||
preview.append(entry); |
||||
cur_meta.entry = entry; |
||||
} |
||||
|
||||
return; |
||||
case '<': |
||||
svg_str = true; |
||||
break; |
||||
case 'd': |
||||
if (response.indexOf('data:image/svg+xml') === 0) { |
||||
var pre = 'data:image/svg+xml;base64,'; |
||||
var src = response.substring(pre.length); |
||||
response = svgedit.utilities.decode64(src); |
||||
svg_str = true; |
||||
break; |
||||
} else if (response.indexOf('data:image/') === 0) { |
||||
img_str = true; |
||||
break; |
||||
} |
||||
// Else fall through
|
||||
default: |
||||
// TODO: See if there's a way to base64 encode the binary data stream
|
||||
// var str = 'data:;base64,' + svgedit.utilities.encode64(response, true);
|
||||
|
||||
// Assume it's raw image data
|
||||
// importImage(str);
|
||||
|
||||
// Don't give warning as postMessage may have been used by something else
|
||||
if (mode !== 'm') { |
||||
closeBrowser(); |
||||
} else { |
||||
pending[id].entry.remove(); |
||||
} |
||||
// $.alert('Unexpected data was returned: ' + response, function() {
|
||||
// if (mode !== 'm') {
|
||||
// closeBrowser();
|
||||
// } else {
|
||||
// pending[id].entry.remove();
|
||||
// }
|
||||
// });
|
||||
return; |
||||
} |
||||
|
||||
switch (mode) { |
||||
case 's': |
||||
// Import one
|
||||
if (svg_str) { |
||||
svgCanvas.importSvgString(response); |
||||
} else if (img_str) { |
||||
importImage(response); |
||||
} |
||||
closeBrowser(); |
||||
break; |
||||
case 'm': |
||||
// Import multiple
|
||||
multi_arr.push([(svg_str ? 'svg' : 'img'), response]); |
||||
var title; |
||||
cur_meta = pending[id]; |
||||
if (svg_str) { |
||||
if (cur_meta && cur_meta.name) { |
||||
title = cur_meta.name; |
||||
} else { |
||||
// Try to find a title
|
||||
var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement; |
||||
title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')'; |
||||
} |
||||
if (cur_meta) { |
||||
preview.children().each(function() { |
||||
if ($(this).data('id') == id) { |
||||
if (cur_meta.preview_url) { |
||||
$(this).html('<img src="' + cur_meta.preview_url + '">' + title); |
||||
} else { |
||||
$(this).text(title); |
||||
} |
||||
submit.removeAttr('disabled'); |
||||
} |
||||
}); |
||||
} else { |
||||
preview.append('<div>'+title+'</div>'); |
||||
submit.removeAttr('disabled'); |
||||
} |
||||
} else { |
||||
if (cur_meta && cur_meta.preview_url) { |
||||
title = cur_meta.name || ''; |
||||
} |
||||
if (cur_meta && cur_meta.preview_url) { |
||||
entry = '<img src="' + cur_meta.preview_url + '">' + title; |
||||
} else { |
||||
entry = '<img src="' + response + '">'; |
||||
} |
||||
|
||||
if (cur_meta) { |
||||
preview.children().each(function() { |
||||
if ($(this).data('id') == id) { |
||||
$(this).html(entry); |
||||
submit.removeAttr('disabled'); |
||||
} |
||||
}); |
||||
} else { |
||||
preview.append($('<div>').append(entry)); |
||||
submit.removeAttr('disabled'); |
||||
} |
||||
|
||||
} |
||||
break; |
||||
case 'o': |
||||
// Open
|
||||
if (!svg_str) {break;} |
||||
svgEditor.openPrep(function(ok) { |
||||
if (!ok) {return;} |
||||
svgCanvas.clear(); |
||||
svgCanvas.setSvgString(response); |
||||
// updateCanvas();
|
||||
}); |
||||
closeBrowser(); |
||||
break; |
||||
} |
||||
}, true); |
||||
|
||||
function toggleMulti(show) { |
||||
|
||||
$('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)}); |
||||
if (!preview) { |
||||
preview = $('<div id=imglib_preview>').css({ |
||||
position: 'absolute', |
||||
top: 45, |
||||
right: 10, |
||||
width: 180, |
||||
bottom: 45, |
||||
background: '#fff', |
||||
overflow: 'auto' |
||||
}).insertAfter('#lib_framewrap'); |
||||
|
||||
submit = $('<button disabled>Import selected</button>') |
||||
.appendTo('#imgbrowse') |
||||
.on("click touchend", function() { |
||||
$.each(multi_arr, function(i) { |
||||
var type = this[0]; |
||||
var data = this[1]; |
||||
if (type == 'svg') { |
||||
svgCanvas.importSvgString(data); |
||||
} else { |
||||
importImage(data); |
||||
} |
||||
svgCanvas.moveSelectedElements(i*20, i*20, false); |
||||
}); |
||||
preview.empty(); |
||||
multi_arr = []; |
||||
$('#imgbrowse_holder').hide(); |
||||
}).css({ |
||||
position: 'absolute', |
||||
bottom: 10, |
||||
right: -10 |
||||
}); |
||||
|
||||
} |
||||
|
||||
preview.toggle(show); |
||||
submit.toggle(show); |
||||
} |
||||
|
||||
function showBrowser() { |
||||
|
||||
var browser = $('#imgbrowse'); |
||||
if (!browser.length) { |
||||
$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>\ |
||||
</div></div>').insertAfter('#svg_docprops'); |
||||
browser = $('#imgbrowse'); |
||||
|
||||
var all_libs = uiStrings.imagelib.select_lib; |
||||
|
||||
var lib_opts = $('<ul id=imglib_opts>').appendTo(browser); |
||||
var frame = $('<iframe/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>'); |
||||
|
||||
var header = $('<h1>').prependTo(browser).text(all_libs).css({ |
||||
position: 'absolute', |
||||
top: 0, |
||||
left: 0, |
||||
width: '100%' |
||||
}); |
||||
|
||||
var cancel = $('<button>' + uiStrings.common.cancel + '</button>') |
||||
.appendTo(browser) |
||||
.on("click touchend", function() { |
||||
$('#imgbrowse_holder').hide(); |
||||
}).css({ |
||||
position: 'absolute', |
||||
top: 5, |
||||
right: -10 |
||||
}); |
||||
|
||||
var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser); |
||||
|
||||
var back = $('<button hidden>' + uiStrings.imagelib.show_list + '</button>') |
||||
.appendTo(leftBlock) |
||||
.on("click touchend", function() { |
||||
frame.attr('src', 'about:blank').hide(); |
||||
lib_opts.show(); |
||||
header.text(all_libs); |
||||
back.hide(); |
||||
}).css({ |
||||
'margin-right': 5 |
||||
}).hide(); |
||||
|
||||
var type = $('<select><option value=s>' + |
||||
uiStrings.imagelib.import_single + '</option><option value=m>' + |
||||
uiStrings.imagelib.import_multi + '</option><option value=o>' + |
||||
uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function() { |
||||
mode = $(this).val(); |
||||
switch (mode) { |
||||
case 's': |
||||
case 'o': |
||||
toggleMulti(false); |
||||
break; |
||||
|
||||
case 'm': |
||||
// Import multiple
|
||||
toggleMulti(true); |
||||
break; |
||||
} |
||||
}).css({ |
||||
'margin-top': 10 |
||||
}); |
||||
|
||||
cancel.prepend($.getSvgIcon('cancel', true)); |
||||
back.prepend($.getSvgIcon('tool_imagelib', true)); |
||||
|
||||
$.each(img_libs, function(i, opts) { |
||||
$('<li>') |
||||
.appendTo(lib_opts) |
||||
.text(opts.name) |
||||
.on("click touchend", function() { |
||||
frame.attr('src', opts.url).show(); |
||||
header.text(opts.name); |
||||
lib_opts.hide(); |
||||
back.show(); |
||||
}).append('<span>' + opts.description + '</span>'); |
||||
}); |
||||
|
||||
} else { |
||||
$('#imgbrowse_holder').show(); |
||||
} |
||||
} |
||||
|
||||
return { |
||||
svgicons: svgEditor.curConfig.extPath + "ext-imagelib.xml", |
||||
buttons: [{ |
||||
id: "tool_imagelib", |
||||
type: "app_menu", // _flyout
|
||||
position: 4, |
||||
title: "Image library", |
||||
events: { |
||||
"mouseup": showBrowser |
||||
} |
||||
}], |
||||
callback: function() { |
||||
|
||||
$('<style>').text('\ |
||||
#imgbrowse_holder {\ |
||||
position: absolute;\ |
||||
top: 0;\ |
||||
left: 0;\ |
||||
width: 100%;\ |
||||
height: 100%;\ |
||||
background-color: rgba(0, 0, 0, .5);\ |
||||
z-index: 5;\ |
||||
}\ |
||||
\ |
||||
#imgbrowse {\ |
||||
position: absolute;\ |
||||
top: 25px;\ |
||||
left: 25px;\ |
||||
right: 25px;\ |
||||
bottom: 25px;\ |
||||
min-width: 300px;\ |
||||
min-height: 200px;\ |
||||
background: #B0B0B0;\ |
||||
border: 1px outset #777;\ |
||||
}\ |
||||
#imgbrowse h1 {\ |
||||
font-size: 20px;\ |
||||
margin: .4em;\ |
||||
text-align: center;\ |
||||
}\ |
||||
#lib_framewrap,\ |
||||
#imgbrowse > ul {\ |
||||
position: absolute;\ |
||||
top: 45px;\ |
||||
left: 10px;\ |
||||
right: 10px;\ |
||||
bottom: 10px;\ |
||||
background: white;\ |
||||
margin: 0;\ |
||||
padding: 0;\ |
||||
}\ |
||||
#imgbrowse > ul {\ |
||||
overflow: auto;\ |
||||
}\ |
||||
#imgbrowse > div {\ |
||||
border: 1px solid #666;\ |
||||
}\ |
||||
#imglib_preview > div {\ |
||||
padding: 5px;\ |
||||
font-size: 12px;\ |
||||
}\ |
||||
#imglib_preview img {\ |
||||
display: block;\ |
||||
margin: 0 auto;\ |
||||
max-height: 100px;\ |
||||
}\ |
||||
#imgbrowse li {\ |
||||
list-style: none;\ |
||||
padding: .5em;\ |
||||
background: #E8E8E8;\ |
||||
border-bottom: 1px solid #B0B0B0;\ |
||||
line-height: 1.2em;\ |
||||
font-style: sans-serif;\ |
||||
}\ |
||||
#imgbrowse li > span {\ |
||||
color: #666;\ |
||||
font-size: 15px;\ |
||||
display: block;\ |
||||
}\ |
||||
#imgbrowse li:hover {\ |
||||
background: #FFC;\ |
||||
cursor: pointer;\ |
||||
}\ |
||||
#imgbrowse iframe {\ |
||||
width: 100%;\ |
||||
height: 100%;\ |
||||
border: 0;\ |
||||
}\ |
||||
').appendTo('head'); |
||||
} |
||||
}; |
||||
}); |
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 725 B After Width: | Height: | Size: 725 B |
@ -0,0 +1,34 @@ |
||||
/*globals $, svgCanvas, svgEditor*/ |
||||
/*jslint regexp:true*/ |
||||
// TODO: Might add support for "exportImage" custom
|
||||
// handler as in "ext-server_opensave.js" (and in savefile.php)
|
||||
|
||||
svgEditor.addExtension("php_savefile_chamilo", { |
||||
callback: function() { |
||||
'use strict'; |
||||
function getFileNameFromTitle () { |
||||
var title = svgCanvas.getDocumentTitle(); |
||||
return $.trim(title); |
||||
} |
||||
var save_svg_action = svgEditor.curConfig.extPath + 'savefile.php'; |
||||
svgEditor.setCustomHandlers({ |
||||
save: function(win, data) { |
||||
var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data, |
||||
filename = getFileNameFromTitle(); |
||||
|
||||
$.post( |
||||
save_svg_action, |
||||
{output_svg: svg, filename: filename} |
||||
).done(function(data) { |
||||
var response = jQuery.parseJSON(data); |
||||
console.log(response.message); |
||||
alert(response.message); |
||||
if (response.url != '') { |
||||
window.top.location.href = response.url; |
||||
} |
||||
} |
||||
); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||