Преглед изворни кода

[editor] [minor] updates and fixes

version-14
Rushabh Mehta пре 11 година
родитељ
комит
e412a37d99
5 измењених фајлова са 74 додато и 272 уклоњено
  1. +0
    -193
      public/js/lib/bootstrap-wysiwyg.js
  2. +1
    -1
      public/js/wn/form/control.js
  3. +68
    -75
      public/js/wn/ui/editor.js
  4. +3
    -1
      public/js/wn/views/communication.js
  5. +2
    -2
      website/doctype/web_page/templates/generators/web_page.html

+ 0
- 193
public/js/lib/bootstrap-wysiwyg.js Прегледај датотеку

@@ -1,193 +0,0 @@
/* http://github.com/mindmup/bootstrap-wysiwyg */
/*global jQuery, $, FileReader*/
/*jslint browser:true*/
jQuery(function ($) {
'use strict';
var readFileIntoDataUrl = function (fileInfo) {
var loader = $.Deferred(),
fReader = new FileReader();

wn.upload.upload_file(fileInfo, {
from_form: 1,
doctype: cur_frm.doctype,
docname: cur_frm.docname
}, function(fileid, filename, r) {
if(!r.exc) {
if(fileid)
cur_frm.attachments.update_attachment(fileid, filename);
loader.resolve(filename);
}
});
return loader.promise();
};
$.fn.cleanHtml = function () {
var html = $(this).html();
html = html && html.replace(/(<br>|\s|<div><br><\/div>|&nbsp;)*$/, '');
// remove custom typography (use CSS!)
html = html && html.replace(/(font-family|font-size|line-height):[^;]*;/g, '');
html = html && html.replace(/<[^>]*(font=['"][^'"]*['"])>/g, function(a,b) { return a.replace(b, ''); });
html = html && html.replace(/\s*style\s*=\s*["']\s*["']/g, '');
return html;
};
$.fn.wysiwyg = function (userOptions) {
var editor = this,
selectedRange,
defaultOptions = {
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+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'
},
options,
updateToolbar = function () {
if (options.activeToolbarClass) {
$(options.toolbarSelector).find('.btn[data-' + options.commandRole + ']').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) {
selection.removeAllRanges();
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);
});
}
});
},
markSelection = function (input, color) {
restoreSelection();
document.execCommand('hiliteColor', 0, color || 'transparent');
saveSelection();
input.data(options.selectionMarker, color);
},
bindToolbar = function (toolbar, options) {
toolbar.find('a[data-' + options.commandRole + ']').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);
}
});
};
options = $.extend({}, defaultOptions, userOptions);
bindHotkeys(options.hotKeys);
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;
};
});

+ 1
- 1
public/js/wn/form/control.js Прегледај датотеку

@@ -876,7 +876,7 @@ wn.ui.form.ControlCode = wn.ui.form.ControlInput.extend({
});

wn.ui.form.ControlTextEditor = wn.ui.form.ControlCode.extend({
editor_name: "wn.ui.Editor",
editor_name: "bsEditor",
make_input: function() {
this._super();
this.editor.editor.keypress("ctrl+s meta+s", function() {


+ 68
- 75
public/js/wn/ui/editor.js Прегледај датотеку

@@ -6,8 +6,7 @@
// todo
// make it inline friendly

wn.provide("wn.ui");
wn.ui.Editor = Class.extend({
bsEditor = Class.extend({
init: function(options) {
this.options = $.extend(options || {}, this.default_options);
if(this.options.editor) {
@@ -25,7 +24,7 @@ wn.ui.Editor = Class.extend({
var me = this;
this.editor = $(editor);
this.editor.on("click", function() {
if(!this.editing) {
if(!me.editing) {
me.set_editing();
}
}).on("mouseup keyup mouseout", function() {
@@ -50,13 +49,13 @@ wn.ui.Editor = Class.extend({
},
setup_fixed_toolbar: function() {
if(!wn._editor_toolbar) {
wn._editor_toolbar = new wn.ui.EditorToolbar(this.options)
if(!window.bs_editor_toolbar) {
window.bs_editor_toolbar = new bsEditorToolbar(this.options)
}
this.toolbar = wn._editor_toolbar;
this.toolbar = window.bs_editor_toolbar;
},
setup_inline_toolbar: function() {
this.toolbar = new wn.ui.EditorToolbar(this.options, this.wrapper);
this.toolbar = new bsEditorToolbar(this.options, this.wrapper);
},
onhide: function(action) {
this.editing = false;
@@ -171,7 +170,7 @@ wn.ui.Editor = Class.extend({
dataurl = parts[0] + ',' + parts[1];
if(me.options.max_file_size) {
if(dataurl.length > (me.options.max_file_size * 1024 * 1024 * 1.4)) {
wn.msgprint("Max file size (" + me.options.max_file_size + "M) exceeded.");
bs_get_modal("Upload Error", "Max file size (" + me.options.max_file_size + "M) exceeded.").modal("show");
throw "file size exceeded";
}
}
@@ -185,29 +184,24 @@ wn.ui.Editor = Class.extend({
},
set_input: function(value) {
if(this.options.field.inside_change_event)
if(this.options.field && this.options.field.inside_change_event)
return;
this.editor.html(value==null ? "" : value);
}
})

wn.ui.EditorToolbar = Class.extend({
bsEditorToolbar = Class.extend({
init: function(options, parent) {
this.options = options;
this.inline = !!parent;
this.options.toolbar_style = $.extend(this.options.toolbar_style || {},
(this.inline ? this.inline_style : this.fixed_style));
this.options.toolbar_style = $.extend((this.inline ? this.inline_style : this.fixed_style),
this.options.toolbar_style || {});
this.make(parent);
this.toolbar.css(this.options.toolbar_style);
this.setup_image_button();
this.bind_events();
this.bind_touch();

var me = this;
$(document).mousedown(function(e) {
me.clicked = $(e.target);
});
//this.bind_touch();
},
fixed_style: {
position: "fixed",
@@ -215,7 +209,8 @@ wn.ui.EditorToolbar = Class.extend({
padding: "5px",
width: "100%",
height: "45px",
"background-color": "#777"
"background-color": "black",
display: "none"
},
inline_style: {
padding: "5px",
@@ -229,13 +224,13 @@ wn.ui.EditorToolbar = Class.extend({
<div class="btn-group form-group">\
<a class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown" \
title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a>\
<ul class="dropdown-menu">\
<li><a data-edit="formatBlock &lt;p&gt;"><p>Paragraph</p></a></li>\
<li><a data-edit="formatBlock &lt;h1&gt;"><h1>Heading 1</h1></a></li>\
<li><a data-edit="formatBlock &lt;h2&gt;"><h2>Heading 2</h2></a></li>\
<li><a data-edit="formatBlock &lt;h3&gt;"><h3>Heading 3</h3></a></li>\
<li><a data-edit="formatBlock &lt;h4&gt;"><h4>Heading 4</h4></a></li>\
<li><a data-edit="formatBlock &lt;h5&gt;"><h5>Heading 5</h5></a></li>\
<ul class="dropdown-menu" role="menu">\
<li><a href="#" data-edit="formatBlock &lt;p&gt;"><p>Paragraph</p></a></li>\
<li><a href="#" data-edit="formatBlock &lt;h1&gt;"><h1>Heading 1</h1></a></li>\
<li><a href="#" data-edit="formatBlock &lt;h2&gt;"><h2>Heading 2</h2></a></li>\
<li><a href="#" data-edit="formatBlock &lt;h3&gt;"><h3>Heading 3</h3></a></li>\
<li><a href="#" data-edit="formatBlock &lt;h4&gt;"><h4>Heading 4</h4></a></li>\
<li><a href="#" data-edit="formatBlock &lt;h5&gt;"><h5>Heading 5</h5></a></li>\
</ul>\
</div>\
<div class="btn-group form-group">\
@@ -266,7 +261,7 @@ wn.ui.EditorToolbar = Class.extend({
</div>\
<div class="btn-group form-group">\
<a class="btn btn-default btn-small btn-html" title="HTML">\
<i class="icon-wrench"></i></a>\
<i class="icon-code"></i></a>\
<a class="btn btn-default btn-small btn-cancel" data-action="Cancel" title="Cancel">\
<i class="icon-remove"></i></a>\
<a class="btn btn-default btn-small btn-success" data-action="Save" title="Save">\
@@ -308,6 +303,8 @@ wn.ui.EditorToolbar = Class.extend({
},

hide: function(action) {
if(!this.editor)
return;
var me = this;
this.toolbar.css("z-index", 0);
$("body").animate({"padding-top": 0 }, {complete: function() {
@@ -327,16 +324,18 @@ wn.ui.EditorToolbar = Class.extend({
me.editor.focus();
me.execCommand($(this).data(me.options.command_role));
me.save_selection();
// close dropdown
me.toolbar.find('[data-toggle=dropdown]').dropdown("hide");
return false;
});
this.toolbar.find('[data-toggle=dropdown]').click(function() { me.restore_selection() });

// link
this.toolbar.find(".btn-add-link").on("click", function() {
if(!wn._link_editor) {
wn._link_editor = new wn.ui.LinkEditor(me);
if(!window.bs_link_editor) {
window.bs_link_editor = new bsLinkEditor(me);
}
wn._link_editor.show();
window.bs_link_editor.show();
})
// file event
@@ -362,17 +361,17 @@ wn.ui.EditorToolbar = Class.extend({
// edit html
this.toolbar.find(".btn-html").on("click", function() {
if(!wn._html_editor)
wn._html_editor = new wn.ui.HTMLEditor();
if(!window.bs_html_editor)
window.bs_html_editor = new bsHTMLEditor();
wn._html_editor.show(me.editor);
window.bs_html_editor.show(me.editor);
})
},

update: function () {
var me = this;
if (this.options.active_toolbar_class) {
$(this.options.toolbar_selector).find('.btn[data-' + this.options.command_role + ']').each(function () {
if (this.toolbar) {
$(this.toolbar).find('.btn[data-' + this.options.command_role + ']').each(function () {
var command = $(this).data(me.options.command_role);
if (document.queryCommandState(command)) {
$(this).addClass(me.options.active_toolbar_class);
@@ -400,28 +399,8 @@ wn.ui.EditorToolbar = Class.extend({
save_selection: function () {
this.selected_range = this.get_current_range();
this.selected_html = this.get_current_html();
},
get_current_html: function() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
},
restore_selection: function () {
var selection = window.getSelection();
if (this.selected_range) {
@@ -437,30 +416,34 @@ wn.ui.EditorToolbar = Class.extend({
input.data(this.options.selection_marker, color);
},
bind_touch: function() {
var me = this;
$(window).bind('touchend', function (e) {
var isInside = (me.editor.is(e.target) || me.editor.has(e.target).length > 0),
current_range = me.get_current_range(),
clear = current_range && (current_range.startContainer === current_range.endContainer && current_range.startOffset === current_range.endOffset);
if (!clear || isInside) {
me.save_selection();
me.update();
}
});
}
// bind_touch: function() {
// var me = this;
// $(window).bind('touchend', function (e) {
// var isInside = (me.editor.is(e.target) || me.editor.has(e.target).length > 0),
// current_range = me.get_current_range(),
// clear = current_range && (current_range.startContainer === current_range.endContainer && current_range.startOffset === current_range.endOffset);
// if (!clear || isInside) {
// me.save_selection();
// me.update();
// }
// });
// }
});

wn.ui.HTMLEditor = Class.extend({
bsHTMLEditor = Class.extend({
init: function() {
var me = this;
this.modal = wn.get_modal("Edit HTML", '<textarea class="form-control" \
this.modal = bs_get_modal("<i class='icon-code'></i> Edit HTML", '<textarea class="form-control" \
style="height: 400px; width: 100%; font-family: Monaco, Courier New, Fixed; font-size: 11px">\
</textarea><br>\
<button class="btn btn-primary" style="margin-top: 7px;">Save</button>');
this.modal.addClass("wn-ignore-click");
this.modal.find(".btn-primary").on("click", function() {
me.editor.html(me.modal.find("textarea").val());
var html = me.modal.find("textarea").val();
$.each(me.dataurls, function(key, val) {
html = html.replace(key, val);
})
me.editor.html();
me.modal.modal("hide");
});
},
@@ -468,15 +451,23 @@ wn.ui.HTMLEditor = Class.extend({
var me = this;
this.editor = editor;
this.modal.modal("show")
this.modal.find("textarea").html(html_beautify(me.editor.html()));
var html = me.editor.html();
// pack dataurls so that html display is faster
this.dataurls = {}
html = html.replace(/<img\s*src=\s*["\'](data:[^,]*),([^"\']*)["\']/g, function(full, g1, g2) {
var key = g2.slice(0,5) + "..." + g2.slice(-5);
me.dataurls[key] = g1 + "," + g2;
return '<img src="'+g1 + "," + key+'"';
})
this.modal.find("textarea").html(html_beautify(html));
}
});

wn.ui.LinkEditor = Class.extend({
bsLinkEditor = Class.extend({
init: function(toolbar) {
var me = this;
this.toolbar = toolbar;
this.modal = wn.get_modal("Edit HTML", '<div class="form-group">\
this.modal = bs_get_modal("<i class='icon-globe'></i> Insert Link", '<div class="form-group">\
<input type="text" class="form-control" placeholder="http://example.com" />\
</div>\
<div class="checkbox" style="position: static;">\
@@ -507,4 +498,6 @@ wn.ui.LinkEditor = Class.extend({
this.modal.find("input[type=text]").val("");
this.modal.modal("show");
}
})
});

bs_get_modal = wn.get_modal;

+ 3
- 1
public/js/wn/views/communication.js Прегледај датотеку

@@ -136,7 +136,6 @@ wn.views.CommunicationComposer = Class.extend({
make: function() {
var me = this;
this.dialog = new wn.ui.Dialog({
width: 640,
title: wn._("Add Reply") + ": " + (this.subject || ""),
no_submit_on_enter: true,
fields: [
@@ -166,6 +165,9 @@ wn.views.CommunicationComposer = Class.extend({
fieldname:"select_attachments"}
]
});

this.dialog.$wrapper.find("[data-edit='outdent']").remove();
$(document).on("upload_complete", function(event, filename, fileurl) {
if(me.dialog.display) {
var wrapper = $(me.dialog.fields_dict.select_attachments.wrapper);


+ 2
- 2
website/doctype/web_page/templates/generators/web_page.html Прегледај датотеку

@@ -10,9 +10,9 @@
<script>
$(function() {
window.name = "{{ name }}";
if(getCookie("full_name")) {
if(window.logged_in) {
wn.require("js/editor.min.js");
wn.editor = new wn.ui.Editor({
wn.editor = new bsEditor({
editor: $(".web-page-content"),
onsave: function(editor) {
wn.call({


Loading…
Откажи
Сачувај