mirror of https://github.com/artf/grapesjs.git
28 changed files with 846 additions and 541 deletions
@ -0,0 +1,40 @@ |
|||||
|
{ |
||||
|
"name": "grapes", |
||||
|
"description": "Open source web template editor", |
||||
|
"version": "0.0.5", |
||||
|
"author": "Artur Arseniev", |
||||
|
"main": [ |
||||
|
"dist/grapes.min.js" |
||||
|
], |
||||
|
"keywords": [ |
||||
|
"grapes", |
||||
|
"wte", |
||||
|
"web template editor", |
||||
|
"site builder", |
||||
|
"newsletter builder", |
||||
|
"wysiwyg", |
||||
|
"template", |
||||
|
"editor" |
||||
|
], |
||||
|
"license": "BSD-3-Clause", |
||||
|
"ignore": [ |
||||
|
"**/.*", |
||||
|
"node_modules", |
||||
|
"bower_components", |
||||
|
"test", |
||||
|
"tests" |
||||
|
], |
||||
|
"dependencies": { |
||||
|
"backbone": "~1.2.3", |
||||
|
"Backbone.Undo": "~0.2.5", |
||||
|
"jquery": "~2.2.0", |
||||
|
"jquery.ui": "~1.11.4", |
||||
|
"keymaster": "~1.6.3", |
||||
|
"requirejs": "~2.1.22", |
||||
|
"requirejs-text": "~2.0.14", |
||||
|
"spectrum": "~1.8.0", |
||||
|
"underscore": "~1.8.3", |
||||
|
"codemirror": "~5.10.0", |
||||
|
"codemirror-formatting": "*" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,209 @@ |
|||||
|
/*jslint browser:true*/ |
||||
|
define(['jquery'], |
||||
|
function ($) { |
||||
|
|
||||
|
var readFileIntoDataUrl = function (fileInfo) { |
||||
|
var loader = $.Deferred(), |
||||
|
fReader = new FileReader(); |
||||
|
fReader.onload = function (e) { |
||||
|
loader.resolve(e.target.result); |
||||
|
}; |
||||
|
fReader.onerror = loader.reject; |
||||
|
fReader.onprogress = loader.notify; |
||||
|
fReader.readAsDataURL(fileInfo); |
||||
|
return loader.promise(); |
||||
|
}; |
||||
|
$.fn.cleanHtml = function () { |
||||
|
var html = $(this).html(); |
||||
|
return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, ''); |
||||
|
}; |
||||
|
$.fn.wysiwyg = function (userOptions) { |
||||
|
var editor = this, |
||||
|
selectedRange, |
||||
|
options, |
||||
|
toolbarBtnSelector, |
||||
|
updateToolbar = function () { |
||||
|
if (options.activeToolbarClass) { |
||||
|
$(options.toolbarSelector).find(toolbarBtnSelector).each(function () { |
||||
|
var command = $(this).data(options.commandRole); |
||||
|
if (document.queryCommandState(command)) { |
||||
|
$(this).addClass(options.activeToolbarClass); |
||||
|
} else { |
||||
|
$(this).removeClass(options.activeToolbarClass); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
execCommand = function (commandWithArgs, valueArg) { |
||||
|
var commandArr = commandWithArgs.split(' '), |
||||
|
command = commandArr.shift(), |
||||
|
args = commandArr.join(' ') + (valueArg || ''); |
||||
|
document.execCommand(command, 0, args); |
||||
|
updateToolbar(); |
||||
|
}, |
||||
|
bindHotkeys = function (hotKeys) { |
||||
|
$.each(hotKeys, function (hotkey, command) { |
||||
|
editor.keydown(hotkey, function (e) { |
||||
|
if (editor.attr('contenteditable') && editor.is(':visible')) { |
||||
|
e.preventDefault(); |
||||
|
e.stopPropagation(); |
||||
|
execCommand(command); |
||||
|
} |
||||
|
}).keyup(hotkey, function (e) { |
||||
|
if (editor.attr('contenteditable') && editor.is(':visible')) { |
||||
|
e.preventDefault(); |
||||
|
e.stopPropagation(); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
getCurrentRange = function () { |
||||
|
var sel = window.getSelection(); |
||||
|
if (sel.getRangeAt && sel.rangeCount) { |
||||
|
return sel.getRangeAt(0); |
||||
|
} |
||||
|
}, |
||||
|
saveSelection = function () { |
||||
|
selectedRange = getCurrentRange(); |
||||
|
}, |
||||
|
restoreSelection = function () { |
||||
|
var selection = window.getSelection(); |
||||
|
if (selectedRange) { |
||||
|
try { |
||||
|
selection.removeAllRanges(); |
||||
|
} catch (ex) { |
||||
|
document.body.createTextRange().select(); |
||||
|
document.selection.empty(); |
||||
|
} |
||||
|
|
||||
|
selection.addRange(selectedRange); |
||||
|
} |
||||
|
}, |
||||
|
insertFiles = function (files) { |
||||
|
editor.focus(); |
||||
|
$.each(files, function (idx, fileInfo) { |
||||
|
if (/^image\//.test(fileInfo.type)) { |
||||
|
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) { |
||||
|
execCommand('insertimage', dataUrl); |
||||
|
}).fail(function (e) { |
||||
|
options.fileUploadError("file-reader", e); |
||||
|
}); |
||||
|
} else { |
||||
|
options.fileUploadError("unsupported-file-type", fileInfo.type); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
markSelection = function (input, color) { |
||||
|
restoreSelection(); |
||||
|
if (document.queryCommandSupported('hiliteColor')) { |
||||
|
document.execCommand('hiliteColor', 0, color || 'transparent'); |
||||
|
} |
||||
|
saveSelection(); |
||||
|
input.data(options.selectionMarker, color); |
||||
|
}, |
||||
|
bindToolbar = function (toolbar, options) { |
||||
|
toolbar.find(toolbarBtnSelector).click(function () { |
||||
|
restoreSelection(); |
||||
|
editor.focus(); |
||||
|
execCommand($(this).data(options.commandRole)); |
||||
|
saveSelection(); |
||||
|
}); |
||||
|
toolbar.find('[data-toggle=dropdown]').click(restoreSelection); |
||||
|
|
||||
|
toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () { |
||||
|
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */ |
||||
|
this.value = ''; |
||||
|
restoreSelection(); |
||||
|
if (newValue) { |
||||
|
editor.focus(); |
||||
|
execCommand($(this).data(options.commandRole), newValue); |
||||
|
} |
||||
|
saveSelection(); |
||||
|
}).on('focus', function () { |
||||
|
var input = $(this); |
||||
|
if (!input.data(options.selectionMarker)) { |
||||
|
markSelection(input, options.selectionColor); |
||||
|
input.focus(); |
||||
|
} |
||||
|
}).on('blur', function () { |
||||
|
var input = $(this); |
||||
|
if (input.data(options.selectionMarker)) { |
||||
|
markSelection(input, false); |
||||
|
} |
||||
|
}); |
||||
|
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () { |
||||
|
restoreSelection(); |
||||
|
if (this.type === 'file' && this.files && this.files.length > 0) { |
||||
|
insertFiles(this.files); |
||||
|
} |
||||
|
saveSelection(); |
||||
|
this.value = ''; |
||||
|
}); |
||||
|
}, |
||||
|
initFileDrops = function () { |
||||
|
editor.on('dragenter dragover', false) |
||||
|
.on('drop', function (e) { |
||||
|
var dataTransfer = e.originalEvent.dataTransfer; |
||||
|
e.stopPropagation(); |
||||
|
e.preventDefault(); |
||||
|
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { |
||||
|
insertFiles(dataTransfer.files); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
/** Disable the editor |
||||
|
* @date 2015-03-19 */ |
||||
|
if(typeof userOptions=='string' && userOptions=='destroy'){ |
||||
|
editor.attr('contenteditable', false).unbind('mouseup keyup mouseout dragenter dragover'); |
||||
|
$(window).unbind('touchend'); |
||||
|
return this; |
||||
|
} |
||||
|
options = $.extend({}, $.fn.wysiwyg.defaults, userOptions); |
||||
|
toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']'; |
||||
|
bindHotkeys(options.hotKeys); |
||||
|
if (options.dragAndDropImages) { |
||||
|
initFileDrops(); |
||||
|
} |
||||
|
bindToolbar($(options.toolbarSelector), options); |
||||
|
editor.attr('contenteditable', true) |
||||
|
.on('mouseup keyup mouseout', function () { |
||||
|
saveSelection(); |
||||
|
updateToolbar(); |
||||
|
}); |
||||
|
$(window).bind('touchend', function (e) { |
||||
|
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0), |
||||
|
currentRange = getCurrentRange(), |
||||
|
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset); |
||||
|
if (!clear || isInside) { |
||||
|
saveSelection(); |
||||
|
updateToolbar(); |
||||
|
} |
||||
|
}); |
||||
|
return this; |
||||
|
}; |
||||
|
$.fn.wysiwyg.defaults = { |
||||
|
hotKeys: { |
||||
|
'ctrl+b meta+b': 'bold', |
||||
|
'ctrl+i meta+i': 'italic', |
||||
|
'ctrl+u meta+u': 'underline', |
||||
|
'ctrl+z meta+z': 'undo', |
||||
|
'ctrl+y meta+y meta+shift+z': 'redo', |
||||
|
'ctrl+l meta+l': 'justifyleft', |
||||
|
'ctrl+r meta+r': 'justifyright', |
||||
|
'ctrl+e meta+e': 'justifycenter', |
||||
|
'ctrl+j meta+j': 'justifyfull', |
||||
|
'shift+tab': 'outdent', |
||||
|
'tab': 'indent' |
||||
|
}, |
||||
|
toolbarSelector: '[data-role=editor-toolbar]', |
||||
|
commandRole: 'edit', |
||||
|
activeToolbarClass: 'btn-info', |
||||
|
selectionMarker: 'edit-focus-marker', |
||||
|
selectionColor: 'darkgrey', |
||||
|
dragAndDropImages: true, |
||||
|
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); } |
||||
|
}; |
||||
|
|
||||
|
return $; |
||||
|
}); |
||||
|
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue