[FIX] web: backport of 2331b14

Update the cleditor lib from v1.3.0 to v1.4.4 fixing IE11 issue, opw 614826
This commit is contained in:
Paramjit Singh Sahota 2014-03-04 18:55:34 +05:30 committed by Martin Trigaux
parent 37fe614126
commit aea9c968cd
3 changed files with 138 additions and 127 deletions

View File

@ -6,7 +6,7 @@
.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}
.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
.cleditorPopup {border:solid 1px #999; background-color:white; color:#333333; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
.cleditorList div {padding:2px 4px 2px 4px}
.cleditorList p,
.cleditorList h1,

View File

@ -1,18 +1,13 @@
/**
@preserve CLEditor WYSIWYG HTML Editor v1.3.0
http://premiumsoftware.net/cleditor
/*!
CLEditor WYSIWYG HTML Editor v1.4.4
http://premiumsoftware.net/CLEditor
requires jQuery v1.4.2 or later
Copyright 2010, Chris Landowski, Premium Software, LLC
Dual licensed under the MIT or GPL Version 2 licenses.
*/
// ==ClosureCompiler==
// @compilation_level SIMPLE_OPTIMIZATIONS
// @output_file_name jquery.cleditor.min.js
// ==/ClosureCompiler==
(function($) {
(function ($) {
//==============
// jQuery Plugin
@ -22,7 +17,7 @@
// Define the defaults used for all new cleditor instances
defaultOptions: {
width: 500, // width not including margins, borders or padding
width: 'auto', // width not including margins, borders or padding
height: 250, // height not including margins, borders or padding
controls: // controls to add to the toolbar
"bold italic underline strikethrough subscript superscript | font size " +
@ -46,18 +41,18 @@
[["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
["Header 3", "<h3>"], ["Header 4","<h4>"], ["Header 5","<h5>"],
["Header 6","<h6>"]],
useCSS: false, // use CSS to style HTML when possible (not supported in ie)
useCSS: true, // use CSS to style HTML when possible (not supported in ie)
docType: // Document type contained within the editor
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
docCSSFile: // CSS file used to style the document contained within the editor
"",
bodyStyle: // style to assign to document body contained within the editor
"margin:4px; color:#4c4c4c; font-size:13px; font-family:\"Lucida Grande\",Helvetica,Verdana,Arial,sans-serif; cursor:text"
"margin:4px; font:10pt Arial,Verdana; cursor:text"
},
// Define all usable toolbar buttons - the init string property is
// expanded during initialization back into the buttons object and
// seperate object properties are created for each button.
// separate object properties are created for each button.
// e.g. buttons.size.title = "Font Size"
buttons: {
// name,title,command,popupName (""=use name)
@ -109,7 +104,7 @@
// Loop through all matching textareas and create the editors
this.each(function(idx, elem) {
if (elem.tagName == "TEXTAREA") {
if (elem.tagName.toUpperCase() === "TEXTAREA") {
var data = $.data(elem, CLEDITOR);
if (!data) data = new cleditor(elem, options);
$result = $result.add(data);
@ -129,6 +124,7 @@
// Misc constants
BACKGROUND_COLOR = "backgroundColor",
BLURRED = "blurred",
BUTTON = "button",
BUTTON_NAME = "buttonName",
CHANGE = "change",
@ -136,6 +132,7 @@
CLICK = "click",
DISABLED = "disabled",
DIV_TAG = "<div>",
FOCUSED = "focused",
TRANSPARENT = "transparent",
UNSELECTABLE = "unselectable",
@ -152,12 +149,15 @@
PROMPT_CLASS = "cleditorPrompt", // prompt popup divs inside body
MSG_CLASS = "cleditorMsg", // message popup div inside body
// Test for ie
ie = $.browser.msie,
ie6 = /msie\s6/i.test(navigator.userAgent),
// Browser detection
ua = navigator.userAgent.toLowerCase(),
ie = /msie/.test(ua),
ie6 = /msie\s6/.test(ua),
iege11 = /(trident)(?:.*rv:([\w.]+))?/.test(ua),
webkit = /webkit/.test(ua),
// Test for iPhone/iTouch/iPad
iOS = /iphone|ipad|ipod/i.test(navigator.userAgent),
iOS = /iphone|ipad|ipod/i.test(ua),
// Popups are created once as needed and shared by all editor instances
popups = {},
@ -223,19 +223,26 @@
var $group = $(DIV_TAG)
.addClass(GROUP_CLASS)
.appendTo($toolbar);
// Initialize the group width
var groupWidth = 0;
// Add the buttons to the toolbar
$.each(options.controls.split(" "), function(idx, buttonName) {
if (buttonName === "") return true;
// Divider
if (buttonName == "|") {
if (buttonName === "|") {
// Add a new divider to the group
var $div = $(DIV_TAG)
.addClass(DIVIDER_CLASS)
.appendTo($group);
// Update the group width
$group.width(groupWidth + 1);
groupWidth = 0;
// Create a new group
$group = $(DIV_TAG)
.addClass(GROUP_CLASS)
@ -258,6 +265,10 @@
.appendTo($group)
.hover(hoverEnter, hoverLeave);
// Update the group width
groupWidth += 24;
$group.width(groupWidth + 1);
// Prepare the button image
var map = {};
if (button.css) map = button.css;
@ -295,17 +306,7 @@
// Bind the window resize event when the width or height is auto or %
if (/auto|%/.test("" + options.width + options.height))
$(window).resize(function() {
//Forcefully blurred iframe contentWindow, chrome, IE, safari doesn't trigger blur on window resize and due to which text disappears
var contentWindow = editor.$frame[0].contentWindow;
if(!$.browser.mozilla && contentWindow){
$(contentWindow).trigger('blur');
}
// CHM Note MonkeyPatch: if the DOM is not remove, refresh the cleditor
if(editor.$main.parent().parent().size()) {
refresh(editor);
}
});
$(window).bind('resize.cleditor', function () { refresh(editor); });
// Create the iframe and resize the controls
refresh(editor);
@ -347,13 +348,26 @@
return editor;
};
});
// blurred - shortcut for .bind("blurred", handler) or .trigger("blurred")
fn.blurred = function(handler) {
var $this = $(this);
return handler ? $this.bind(BLURRED, handler) : $this.trigger(BLURRED);
};
// change - shortcut for .bind("change", handler) or .trigger("change")
fn.change = function(handler) {
fn.change = function change(handler) {
console.log('change test');
var $this = $(this);
return handler ? $this.bind(CHANGE, handler) : $this.trigger(CHANGE);
};
// focused - shortcut for .bind("focused", handler) or .trigger("focused")
fn.focused = function(handler) {
var $this = $(this);
return handler ? $this.bind(FOCUSED, handler) : $this.trigger(FOCUSED);
};
//===============
// Event Handlers
//===============
@ -369,7 +383,7 @@
popup = popups[popupName];
// Check if disabled
if (editor.disabled || $(buttonDiv).attr(DISABLED) == DISABLED)
if (editor.disabled || $(buttonDiv).attr(DISABLED) === DISABLED)
return;
// Fire the buttonClick event
@ -387,7 +401,7 @@
return false;
// Toggle source
if (buttonName == "source") {
if (buttonName === "source") {
// Show the iframe
if (sourceMode(editor)) {
@ -418,10 +432,10 @@
var $popup = $(popup);
// URL
if (popupName == "url") {
if (popupName === "url") {
// Check for selection before showing the link url popup
if (buttonName == "link" && selectedText(editor) === "") {
if (buttonName === "link" && selectedText(editor) === "") {
showMessage(editor, "A selection is required when inserting a link.", buttonDiv);
return false;
}
@ -447,7 +461,7 @@
}
// Paste as Text
else if (popupName == "pastetext") {
else if (popupName === "pastetext") {
// Wire up the submit button click event handler
$popup.children(":button")
@ -475,13 +489,13 @@
return false; // stop propagination to document click
}
// propaginate to documnt click
// propaginate to document click
return;
}
// Print
else if (buttonName == "print")
else if (buttonName === "print")
editor.$frame[0].contentWindow.print();
// All other buttons
@ -526,19 +540,19 @@
useCSS = editor.options.useCSS;
// Get the command value
if (buttonName == "font")
if (buttonName === "font")
// Opera returns the fontfamily wrapped in quotes
value = target.style.fontFamily.replace(/"/g, "");
else if (buttonName == "size") {
if (target.tagName == "DIV")
else if (buttonName === "size") {
if (target.tagName.toUpperCase() === "DIV")
target = target.children[0];
value = target.innerHTML;
}
else if (buttonName == "style")
else if (buttonName === "style")
value = "<" + target.tagName + ">";
else if (buttonName == "color")
else if (buttonName === "color")
value = hex(target.style.backgroundColor);
else if (buttonName == "highlight") {
else if (buttonName === "highlight") {
value = hex(target.style.backgroundColor);
if (ie) command = 'backcolor';
else useCSS = true;
@ -572,7 +586,7 @@
//==================
// Private Functions
//==================
// checksum - returns a checksum using the Adler-32 method
function checksum(text)
{
@ -610,7 +624,7 @@
$popup.html(popupContent);
// Color
else if (popupName == "color") {
else if (popupName === "color") {
var colors = options.colors.split(" ");
if (colors.length < 10)
$popup.width("auto");
@ -622,7 +636,7 @@
}
// Font
else if (popupName == "font")
else if (popupName === "font")
$.each(options.fonts.split(","), function(idx, font) {
$(DIV_TAG).appendTo($popup)
.css("fontFamily", font)
@ -630,28 +644,28 @@
});
// Size
else if (popupName == "size")
else if (popupName === "size")
$.each(options.sizes.split(","), function(idx, size) {
$(DIV_TAG).appendTo($popup)
.html("<font size=" + size + ">" + size + "</font>");
.html('<font size="' + size + '">' + size + '</font>');
});
// Style
else if (popupName == "style")
else if (popupName === "style")
$.each(options.styles, function(idx, style) {
$(DIV_TAG).appendTo($popup)
.html(style[1] + style[0] + style[1].replace("<", "</"));
});
// URL
else if (popupName == "url") {
$popup.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');
else if (popupName === "url") {
$popup.html('Enter URL:<br /><input type="text" value="http://" size="35" /><br /><input type="button" value="Submit" />');
popupTypeClass = PROMPT_CLASS;
}
// Paste as Text
else if (popupName == "pastetext") {
$popup.html('Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>');
else if (popupName === "pastetext") {
$popup.html('Paste your content here and click submit.<br /><textarea cols="40" rows="3"></textarea><br /><input type="button" value="Submit" />');
popupTypeClass = PROMPT_CLASS;
}
@ -720,12 +734,12 @@
}
// Execute the command and check for error
var success = true, description;
if (ie && command.toLowerCase() == "inserthtml")
var success = true, message;
if (ie && command.toLowerCase() === "inserthtml")
getRange(editor).pasteHTML(value);
else {
try { success = editor.doc.execCommand(command, 0, value || null); }
catch (err) { description = err.description; success = false; }
catch (err) { message = err.message; success = false; }
if (!success) {
if ("cutcopypaste".indexOf(command) > -1)
showMessage(editor, "For security reasons, your browser does not support the " +
@ -733,13 +747,14 @@
button);
else
showMessage(editor,
(description ? description : "Error executing the " + command + " command."),
(message ? message : "Error executing the " + command + " command."),
button);
}
}
// Enable the buttons
// Enable the buttons and update the textarea
refreshButtons(editor);
updateTextArea(editor, true);
return success;
}
@ -765,19 +780,26 @@
return editor.$frame[0].contentWindow.getSelection();
}
// Returns the hex value for the passed in string.
// hex("rgb(255, 0, 0)"); // #FF0000
// hex("#FF0000"); // #FF0000
// hex("#F00"); // #FF0000
// hex - returns the hex value for the passed in color string
function hex(s) {
var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s),
c = s.split("");
// hex("rgb(255, 0, 0)") returns #FF0000
var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s);
if (m) {
s = ( m[1] << 16 | m[2] << 8 | m[3] ).toString(16);
s = (m[1] << 16 | m[2] << 8 | m[3]).toString(16);
while (s.length < 6)
s = "0" + s;
return "#" + s;
}
return "#" + (s.length == 6 ? s : c[1] + c[1] + c[2] + c[2] + c[3] + c[3]);
// hex("#F00") returns #FF0000
var c = s.split("");
if (s.length === 4)
return "#" + c[1] + c[1] + c[2] + c[2] + c[3] + c[3];
// hex("#FF0000") returns #FF0000
return s;
}
// hidePopups - hides all popups
@ -792,9 +814,8 @@
// imagesPath - returns the path to the images folder
function imagesPath() {
var cssFile = "jquery.cleditor.css",
href = $("link[href$='" + cssFile +"']").attr("href");
return href.substr(0, href.length - cssFile.length) + "images/";
var href = $("link[href*=cleditor]").attr("href");
return href.replace(/^(.*\/)[^\/]+$/, '$1') + "images/";
}
// imageUrl - Returns the css url string for a filemane
@ -813,7 +834,7 @@
editor.$frame.remove();
// Create a new iframe
var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;">')
var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;" />')
.hide()
.appendTo($main);
@ -833,14 +854,14 @@
// Work around for bug in IE which causes the editor to lose
// focus when clicking below the end of the document.
if (ie)
if (ie || iege11)
$doc.click(function() {focus(editor);});
// Load the content
updateFrame(editor);
// Bind the ie specific iframe event handlers
if (ie) {
if (ie || iege11) {
// Save the current user selection. This code is needed since IE will
// reset the selection just after the beforedeactivate event and just
@ -848,19 +869,19 @@
$doc.bind("beforedeactivate beforeactivate selectionchange keypress", function(e) {
// Flag the editor as inactive
if (e.type == "beforedeactivate")
if (e.type === "beforedeactivate")
editor.inactive = true;
// Get rid of the bogus selection and flag the editor as active
else if (e.type == "beforeactivate") {
// Get rid of the bogus selection and flag the editor as active
else if (e.type === "beforeactivate") {
if (!editor.inactive && editor.range && editor.range.length > 1)
editor.range.shift();
delete editor.inactive;
}
// Save the selection when the editor is active
// Save the selection when the editor is active
else if (!editor.inactive) {
if (!editor.range)
if (!editor.range)
editor.range = [];
editor.range.unshift(getRange(editor));
@ -871,22 +892,31 @@
});
// Restore the text range when the iframe gains focus
// Restore the text range and trigger focused event when the iframe gains focus
$frame.focus(function() {
restoreRange(editor);
$(editor).triggerHandler(FOCUSED);
});
// Trigger blurred event when the iframe looses focus
$frame.blur(function() {
$(editor).triggerHandler(BLURRED);
});
}
// Update the textarea when the iframe loses focus
($.browser.mozilla ? $doc : $(contentWindow)).blur(function() {
updateTextArea(editor, true);
});
// Trigger focused and blurred events for all other browsers
else {
$(editor.$frame[0].contentWindow)
.focus(function () { $(editor).triggerHandler(FOCUSED); })
.blur(function () { $(editor).triggerHandler(BLURRED); });
}
// Enable the toolbar buttons as the user types or clicks
// Enable the toolbar buttons and update the textarea as the user types or clicks
$doc.click(hidePopups)
.bind("keyup mouseup", function() {
refreshButtons(editor);
updateTextArea(editor, true);
});
// Show the textarea for iPhone/iTouch/iPad or
@ -899,14 +929,14 @@
var $toolbar = editor.$toolbar,
$group = $toolbar.children("div:last"),
wid = /%/.test("" + options.width) ? options.width : $main.width();
wid = $main.width();
// Resize the toolbar
var hgt = $group.offset().top + $group.outerHeight() - $toolbar.offset().top + 1;
$toolbar.height(hgt);
// Resize the iframe
hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height)) - hgt;
hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height, 10)) - hgt;
$frame.width(wid).height(hgt);
// Resize the textarea. IE6 textareas have a 1px top
@ -927,7 +957,7 @@
function refreshButtons(editor) {
// Webkit requires focus before queryCommandEnabled will return anything but false
if (!iOS && $.browser.webkit && !editor.focused) {
if (!iOS && webkit && !editor.focused) {
editor.$frame[0].contentWindow.focus();
window.focus();
editor.focused = true;
@ -963,14 +993,14 @@
if (enabled === undefined)
enabled = true;
}
else if (((inSourceMode || iOS) && button.name != "source") ||
(ie && (command == "undo" || command == "redo")))
else if (((inSourceMode || iOS) && button.name !== "source") ||
(ie && (command === "undo" || command === "redo")))
enabled = false;
else if (command && command != "print") {
if (ie && command == "hilitecolor")
else if (command && command !== "print") {
if (ie && command === "hilitecolor")
command = "backcolor";
// IE does not support inserthtml, so it's always enabled
if (!ie || command != "inserthtml") {
if (!ie || command !== "inserthtml") {
try {enabled = queryObj.queryCommandEnabled(command);}
catch (err) {enabled = false;}
}
@ -991,8 +1021,12 @@
// restoreRange - restores the current ie selection
function restoreRange(editor) {
if (ie && editor.range)
editor.range[0].select();
if (editor.range) {
if (ie)
editor.range[0].select();
else if (iege11)
getSelection(editor).addRange(editor.range[0]);
}
}
// select - selects all the text in either the textarea or iframe
@ -1084,7 +1118,7 @@
// of potentially heavy updateFrame callbacks.
if (updateFrameCallback) {
var sum = checksum(code);
if (checkForChange && editor.areaChecksum == sum)
if (checkForChange && editor.areaChecksum === sum)
return;
editor.areaChecksum = sum;
}
@ -1100,7 +1134,7 @@
editor.frameChecksum = checksum(html);
// Update the iframe and trigger the change event
if (html != $body.html()) {
if (html !== $body.html()) {
$body.html(html);
$(editor).triggerHandler(CHANGE);
}
@ -1119,7 +1153,7 @@
// of potentially heavy updateTextArea callbacks.
if (updateTextAreaCallback) {
var sum = checksum(html);
if (checkForChange && editor.frameChecksum == sum)
if (checkForChange && editor.frameChecksum === sum)
return;
editor.frameChecksum = sum;
}
@ -1132,7 +1166,7 @@
editor.areaChecksum = checksum(code);
// Update the textarea and trigger the change event
if (code != $area.val()) {
if (code !== $area.val()) {
$area.val(code);
$(editor).triggerHandler(CHANGE);
}

File diff suppressed because one or more lines are too long