Hi guys,
I am using the Jhtml text editor(jHtmlArea-0.6.0.js) Downloaded from the site(http://jhtmlarea.codeplex.com/). I have made some custom changes like adding more events to it. TEven after that, sometimes after adding text/content the events(onchange,onblur....) does not get triggered and the user looses the content when he tries to save the page. I am attaching the code for the editor with this post. If any of you can correct this issue it would really help me.
This issue happens randomly on all browsers. I think I am missing some key events.
Any help is vey much appreciated
-DotnetRocks
(function ($) {
$.fn.htmlarea = function (opts) {
if (opts && typeof(opts) === "string") {
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i])
}
var htmlarea = jHtmlArea(this[0]);
var f = htmlarea[opts];
if (f) {
return f.apply(htmlarea, args)
}
}
return this.each(function () {
jHtmlArea(this, opts)
})
};
var jHtmlArea = window.jHtmlArea = function (elem, options) {
if (elem.jquery) {
return jHtmlArea(elem[0])
}
if (elem.jhtmlareaObject) {
return elem.jhtmlareaObject
} else {
return new jHtmlArea.fn.init(elem, options)
}
};
jHtmlArea.fn = jHtmlArea.prototype = {
jhtmlarea: "0.6.0",
init: function (elem, options) {
if (elem.nodeName.toLowerCase() === "textarea") {
var opts = $.extend({},
jHtmlArea.defaultOptions, options);
elem.jhtmlareaObject = this;
var textarea = this.textarea = $(elem);
var container = this.container = $("<div/>").addClass("jHtmlArea").width(textarea.width()).insertAfter(textarea);
var toolbar = this.toolbar = $("<div/>").addClass("ToolBar").appendTo(container);
priv.initToolBar.call(this, opts);
var iframe = this.iframe = $("<iframe/>").height(textarea.height());
iframe.width(textarea.width() - ($.browser.msie ? 0 : 4));
var htmlarea = this.htmlarea = $("<div/>").append(iframe);
container.append(htmlarea).append(textarea.hide());
priv.initEditor.call(this, opts);
priv.attachEditorEvents.call(this);
iframe.height(iframe.height() - toolbar.height());
toolbar.width(textarea.width() - 2);
if (opts.loaded) {
opts.loaded.call(this)
}
}
},
dispose: function () {
this.textarea.show().insertAfter(this.container);
this.container.remove();
this.textarea[0].jhtmlareaObject = null
},
execCommand: function (a, b, c) {
this.iframe[0].contentWindow.focus();
this.editor.execCommand(a, b || false, c || null);
this.updateTextArea()
},
ec: function (a, b, c) {
this.execCommand(a, b, c)
},
queryCommandValue: function (a) {
this.iframe[0].contentWindow.focus();
return this.editor.queryCommandValue(a)
},
qc: function (a) {
return this.queryCommandValue(a)
},
getSelectedHTML: function () {
if ($.browser.msie) {
return this.getRange().htmlText
} else {
var elem = this.getRange().cloneContents();
return $("<p/>").append($(elem)).html()
}
},
getSelection: function () {
if ($.browser.msie) {
return this.editor.selection
} else {
return this.iframe[0].contentDocument.defaultView.getSelection()
}
},
getRange: function () {
var s = this.getSelection();
if (!s) {
return null
}
return (s.getRangeAt) ? s.getRangeAt(0) : s.createRange()
},
pasteHTML: function (html) {
this.iframe[0].contentWindow.focus();
var r = this.getRange();
if ($.browser.msie) {
r.pasteHTML(html)
} else if ($.browser.mozilla) {
r.deleteContents();
r.insertNode($((html.indexOf("<") != 0) ? $("<span/>").append(html) : html)[0])
} else {
r.deleteContents();
r.insertNode($(this.iframe[0].contentWindow.document.createElement("span")).append($((html.indexOf("<") != 0) ? "<span>" + html + "</span>" : html))[0])
}
r.collapse(false);
r.select()
},
cut: function () {
this.ec("cut")
},
copy: function () {
this.ec("copy")
},
paste: function () {
this.ec("paste")
},
bold: function () {
this.ec("bold")
},
italic: function () {
this.ec("italic")
},
underline: function () {
this.ec("underline")
},
strikeThrough: function () {
this.ec("strikethrough")
},
image: function (url) {
if ($.browser.msie && !url) {
this.ec("insertImage", true)
} else {
this.ec("insertImage", false, (url || prompt("Image URL:", "http://")))
}
},
removeFormat: function () {
this.ec("removeFormat", false, []);
this.unlink()
},
link: function () {
if ($.browser.msie) {
this.ec("createLink", true)
} else {
this.ec("createLink", false, prompt("Link URL:", "http://"))
}
},
unlink: function () {
this.ec("unlink", false, [])
},
orderedList: function () {
this.ec("insertorderedlist")
},
unorderedList: function () {
this.ec("insertunorderedlist")
},
superscript: function () {
this.ec("superscript")
},
subscript: function () {
this.ec("subscript")
},
h1: function () {
this.heading(1)
},
h2: function () {
this.heading(2)
},
h3: function () {
this.heading(3)
},
h4: function () {
this.heading(4)
},
h5: function () {
this.heading(5)
},
h6: function () {
this.heading(6)
},
heading: function (h) {
this.formatBlock($.browser.msie ? "Heading " + h : "h" + h)
},
indent: function () {
this.ec("indent")
},
outdent: function () {
this.ec("outdent")
},
insertHorizontalRule: function () {
this.ec("insertHorizontalRule", false, "ht")
},
justifyLeft: function () {
this.ec("justifyLeft")
},
justifyCenter: function () {
this.ec("justifyCenter")
},
justifyRight: function () {
this.ec("justifyRight")
},
increaseFontSize: function () {
if ($.browser.msie) {
this.ec("fontSize", false, this.qc("fontSize") + 1)
} else if ($.browser.safari) {
this.getRange().surroundContents($(this.iframe[0].contentWindow.document.createElement("span")).css("font-size", "larger")[0])
} else {
this.ec("increaseFontSize", false, "big")
}
},
decreaseFontSize: function () {
if ($.browser.msie) {
this.ec("fontSize", false, this.qc("fontSize") - 1)
} else if ($.browser.safari) {
this.getRange().surroundContents($(this.iframe[0].contentWindow.document.createElement("span")).css("font-size", "smaller")[0])
} else {
this.ec("decreaseFontSize", false, "small")
}
},
forecolor: function (c) {
this.ec("foreColor", false, c || prompt("Enter HTML Color:", "#"))
},
formatBlock: function (v) {
this.ec("formatblock", false, v || null)
},
showHTMLView: function () {
this.updateTextArea();
this.textarea.show();
this.htmlarea.hide();
$("ul li:not(li:has(a.html))", this.toolbar).hide();
$("ul:not(:has(:visible))", this.toolbar).hide();
$("ul li a.html", this.toolbar).addClass("highlighted")
},
hideHTMLView: function () {
this.updateHtmlArea();
this.textarea.hide();
this.htmlarea.show();
$("ul", this.toolbar).show();
$("ul li", this.toolbar).show().find("a.html").removeClass("highlighted")
},
toggleHTMLView: function () {
(this.textarea.is(":hidden")) ? this.showHTMLView() : this.hideHTMLView()
},
toHtmlString: function () {
return this.editor.body.innerHTML
},
toString: function () {
return this.editor.body.innerText
},
updateTextArea: function () {
this.textarea.val(this.toHtmlString())
},
updateHtmlArea: function () {
this.editor.body.innerHTML = this.textarea.val()
}
};
jHtmlArea.fn.init.prototype = jHtmlArea.fn;
jHtmlArea.defaultOptions = {
toolbar: [
["html"],
["bold", "italic", "underline", "strikethrough", "|", "subscript", "superscript"],
["increasefontsize", "decreasefontsize"],
["orderedlist", "unorderedlist"],
["indent", "outdent"],
["justifyleft", "justifycenter", "justifyright"],
["link", "unlink", "image", "horizontalrule"],
["h1", "h2", "h3", "h4", "h5", "h6"],
["cut", "copy", "paste"]
],
css: null,
toolbarText: {
bold: "Bold",
italic: "Italic",
underline: "Underline",
strikethrough: "Strike-Through",
cut: "Cut",
copy: "Copy",
paste: "Paste",
h1: "Heading 1",
h2: "Heading 2",
h3: "Heading 3",
h4: "Heading 4",
h5: "Heading 5",
h6: "Heading 6",
indent: "Indent",
outdent: "Outdent",
horizontalrule: "Insert Horizontal Rule",
justifyleft: "Left Justify",
justifycenter: "Center Justify",
justifyright: "Right Justify",
increasefontsize: "Increase Font Size",
decreasefontsize: "Decrease Font Size",
forecolor: "Text Color",
link: "Insert Link",
unlink: "Remove Link",
image: "Insert Image",
orderedlist: "Insert Ordered List",
unorderedlist: "Insert Unordered List",
subscript: "Subscript",
superscript: "Superscript",
html: "Show/Hide HTML Source View"
}
};
var priv = {
toolbarButtons: {
strikethrough: "strikeThrough",
orderedlist: "orderedList",
unorderedlist: "unorderedList",
horizontalrule: "insertHorizontalRule",
justifyleft: "justifyLeft",
justifycenter: "justifyCenter",
justifyright: "justifyRight",
increasefontsize: "increaseFontSize",
decreasefontsize: "decreaseFontSize",
html: function (btn) {
this.toggleHTMLView()
}
},
initEditor: function (options) {
var edit = this.editor = this.iframe[0].contentWindow.document;
edit.designMode = 'on';
edit.open();
edit.write(this.textarea.val());
edit.close();
if (options.css) {
var e = edit.createElement('link');
e.rel = 'stylesheet';
e.type = 'text/css';
e.href = options.css;
edit.getElementsByTagName('head')[0].appendChild(e)
}
},
initToolBar: function (options) {
var that = this;
var menuItem = function (className, altText, action) {
return $("<li/>").append($("<a href='javascript:void(0);'/>").addClass(className).attr("title", altText).click(function () {
action.call(that, $(this))
}))
};
function addButtons(arr) {
var ul = $("<ul/>").appendTo(that.toolbar);
for (var i = 0; i < arr.length; i++) {
var e = arr[i];
if ((typeof(e)).toLowerCase() === "string") {
if (e === "|") {
ul.append($('<li class="separator"/>'))
} else {
var f = (function (e) {
var m = priv.toolbarButtons[e] || e;
if ((typeof(m)).toLowerCase() === "function") {
return function (btn) {
m.call(this, btn)
}
} else {
return function () {
this[m]();
this.editor.body.focus()
}
}
})(e.toLowerCase());
var t = options.toolbarText[e.toLowerCase()];
ul.append(menuItem(e.toLowerCase(), t || e, f))
}
} else {
ul.append(menuItem(e.css, e.text, e.action))
}
}
};
if (options.toolbar.length !== 0 && priv.isArray(options.toolbar[0])) {
for (var i = 0; i < options.toolbar.length; i++) {
addButtons(options.toolbar[i])
}
} else {
addButtons(options.toolbar)
}
},
attachEditorEvents: function () {
var t = this;
$(this.editor.body).click(function () {
t.updateTextArea()
});
$(this.editor).keyup(function () {
t.updateTextArea()
});
this.textarea.change(function () {
t.updateHtmlArea()
});
$(this.editor).blur(function () {
t.updateTextArea()
});
$(this.editor.body).blur(function () {
t.updateTextArea()
});
this.textarea.blur(function () {
t.updateTextArea()
})
},
isArray: function (v) {
return v && typeof v === 'object' && typeof v.length === 'number' && typeof v.splice === 'function' && !(v.propertyIsEnumerable('length'))
}
}
})(jQuery);