From 38a0ab6797421729ec3f11510bbe34a190662042 Mon Sep 17 00:00:00 2001 From: Chris Landowski Date: Fri, 30 Jul 2010 00:00:00 +0000 Subject: [PATCH] Import 1.2 Additions * Added a $(selector).cleditor(options) method to create cleditor instances the jQuery way. * Added a defaultOptions property to allow option overrides at a global level. * Added a buttons property to provide access the internal button definitions. * Added a useCSS option to force the editor to use CSS to style HTML when possible. * Added a disabled property which is true if the editor is disabled; otherwise false. * Added a disable() method to disable or enable the editor. * Added a change event that is triggered when the contents of the editor have changed. * Added a change() method to simplify the binding of the change event. * Added a clear() method to clear the editor. * Added a execCommand() method to execute design mode commands * Added a hidePopups() method to hide all popups. * Added a showMessage() method to show a popup messages inside the editor. * Added a restoreSelection() method to restore the previous selection after focusing another control. * Added support for custom plugin development. * Added an HTML table plugin. * Added an icon plugin. Deletions * Removed the $.cleditor(id, options) constructor function. * Removed the name option used to name the editor. * Removed all class names from options. * Removed all background-image urls from the css file. Other Changes * All image files are now assumed to be in the images subfolder located in the same folder as the jquery.cleditor.css file. * All javascript alerts have been replaced with popup messages. * All javascript prompts have been replaced with custom popups. * Code optimization and cleanup. * Bug fixes. * For security reasons, some browsers do not support script driven access to the clipboard. When a user clicks the cut, copy or paste buttons on these browsers, a popup message is displayed stating this. Users can still interact with the clipboard using the keyboard and context menus. --- history.txt | 7 - jquery.cleditor.css | 21 +- jquery.cleditor.js | 1158 +++++++++++++++++++++++++++---------------- 3 files changed, 731 insertions(+), 455 deletions(-) delete mode 100644 history.txt diff --git a/history.txt b/history.txt deleted file mode 100644 index a7e39c6..0000000 --- a/history.txt +++ /dev/null @@ -1,7 +0,0 @@ -Version 1.0 (7/11/2010) -* Initial release - -Version 1.1 (7/13/2010) -* The onkeyup and onmouseup events are now used to keep the editor and textarea - in sync. Previously, the onblur event was used and was not consistantly - being fired across all browsers. \ No newline at end of file diff --git a/jquery.cleditor.css b/jquery.cleditor.css index 6e9cdcf..acf0b6f 100644 --- a/jquery.cleditor.css +++ b/jquery.cleditor.css @@ -1,13 +1,14 @@ -.cleditorMain {border:1px solid #999999; padding:0 1px 1px; background-color:white; overflow:hidden} +.cleditorMain {border:1px solid #999999; padding:0 1px 1px; background-color:white} .cleditorMain iframe {border:none; margin:0; padding:0} -.cleditorMain textarea {border:none; margin:0; padding:0; overflow-y:scroll; font:10pt Arial,Verdana; resize:none; /* remove webkit grip */} -.cleditorMain textarea:focus {outline:none /* remove webkit focus border */} -.cleditorToolbar {background:url(images/toolbar.gif) repeat} +.cleditorMain textarea {border:none; margin:0; padding:0; overflow-y:scroll; font:10pt Arial,Verdana; resize:none; outline:none /* webkit grip focus */} .cleditorGroup {float:left; height:26px} +.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0} .cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#ccc} -.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background-image:url(images/buttons.gif)} -.cleditorColors {width:150px; height:105px; border:solid 1px #999999; padding:1px 0 0 1px; background-color:white; position:absolute} -.cleditorColors div {float:left; width:14px; height:14px; margin:0 1px 1px 0; text-align:center; vertical-align:middle; cursor:default} -.cleditorPopup {border:solid 1px #999999; background-color:white; position:absolute; font:10pt Arial,Verdana} -.cleditorPopup div {padding:2px 4px 2px 4px; cursor:default; font:10pt Arial,Verdana} -.cleditorPopup p,h1,h2,h3,h4,h5,h6,font {padding:0; margin:0; background-color:Transparent} +.cleditorPopup {border:solid 1px #999999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:0} +.cleditorList div {padding:2px 4px 2px 4px} +.cleditorList p,h1,h2,h3,h4,h5,h6,font {padding:0; margin:0; background-color:Transparent} +.cleditorColor {width:150px; height:105px; padding:1px 0 0 1px} +.cleditorColor div {float:left; width:14px; height:14px; margin:0 1px 1px 0} +.cleditorPrompt {background-color:#F6F7F9; padding:4px; font-size:8.5pt} +.cleditorPrompt input {font-size:8.5pt} +.cleditorMsg {background-color:#FDFCEE; width:150px; padding:4px; font-size:8.5pt} diff --git a/jquery.cleditor.js b/jquery.cleditor.js index 45e9634..8bb087a 100644 --- a/jquery.cleditor.js +++ b/jquery.cleditor.js @@ -1,81 +1,35 @@ -/*! - * CLEditor - WYSIWYG HTML Editor - * version: 1.1 (7/13/2010) - * @requires jQuery v1.4.2 or later - * - * Copyright 2010, Chris Landowski, Premium Software, LLC - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * CLEditor is a simple lightweight jQuery Rich Text (WYSIWYG) - * HTML editor plugin. - */ - -(function($) { +/** + @preserve CLEditor WYSIWYG HTML Editor v1.2 + http://premiumsoftware.net/cleditor + requires jQuery v1.4.2 or later - //========== - // Constants - //========== - - // Toolbar buttons [image index, title, command, parm] - var buttons = { - bold: [0, "Bold", "bold"], - italic: [1, "Italic", "italic"], - underline: [2, "Underline", "underline"], - strikethrough: [3, "Strikethrough", "strikethrough"], - subscript: [4, "Subscript", "subscript"], - superscript: [5, "Superscript", "superscript"], - font: [6, "Font", "fontname"], - size: [7, "Font Size", "fontsize"], - style: [8, "Style", "formatblock"], - color: [9, "Font Color", "forecolor"], - highlight: [10, "Text Highlight Color", "hilitecolor"], - removeformat: [11, "Remove Formatting", "removeformat"], - bullets: [12, "Bullets", "insertunorderedlist"], - numbering: [13, "Numbering", "insertorderedlist"], - outdent: [14, "Outdent", "outdent"], - indent: [15, "Indent", "indent"], - alignleft: [16, "Align Text Left", "justifyleft"], - center: [17, "Center", "justifycenter"], - alignright: [18, "Align Text Right", "justifyright"], - justify: [19, "Justify", "justifyfull"], - undo: [20, "Undo", "undo"], - redo: [21, "Redo", "redo"], - rule: [22, "Insert Horizontal Rule", "inserthorizontalrule"], - image: [23, 'Insert Image', 'insertimage'], - link: [24, 'Insert Hyperlink', 'createlink'], - unlink: [25, 'Remove Hyperlink', 'unlink'], - cut: [26, "Cut", "cut", 1], - copy: [27, "Copy", "copy", 1], - paste: [28, "Paste", "paste", 1], - print: [29, "Print", "print"], - html: [30, "Show HTML"] - }; + Copyright 2010, Chris Landowski, Premium Software, LLC + Dual licensed under the MIT or GPL Version 2 licenses. +*/ - //========== - // Variables - //========== +// ==ClosureCompiler== +// @compilation_level SIMPLE_OPTIMIZATIONS +// @output_file_name jquery.cleditor.min.js +// ==/ClosureCompiler== - // Popups are created once and shared by all editor instances - var $colorPopup, $fontPopup, $sizePopup, $stylePopup, documentClickAssigned; +(function($) { - //============ - // Constructor - //============ + //============== + // jQuery Plugin + //============== - $.cleditor = function(areaID, options) { + $.cleditor = { - // Define defaults and override with options - settings = $.extend({ - name: "cleditor", // name to use when referencing this editor via javascript + // ● Define the defaults used for all new cleditor instances + defaultOptions: { width: 500, // 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 " + "style | color highlight removeformat | bullets numbering | outdent " + - "indent | alignleft center alignright justify | undo redo | rule image " + - "link unlink | cut copy paste | print html", - colors: // colors listed in the color popup + "indent | alignleft center alignright justify | undo redo | " + + "rule image link unlink | cut copy paste | print html", + colors: // colors in the color popup "FFFFFF FFCCCC FFCC99 FFFF99 FFFFCC 99FF99 99FFFF CCFFFF CCCCFF FFCCFF " + "CCCCCC FF6666 FF9966 FFFF66 FFFF33 66FF99 33FFFF 66FFFF 9999FF FF99FF " + "C0C0C0 FF0000 FF9900 FFCC66 FFFF00 33FF33 66CCCC 33CCFF 6666CC CC66CC " + @@ -83,120 +37,254 @@ "666666 990000 CC6600 CC9933 999900 009900 339999 3333FF 6600CC 993399 " + "333333 660000 993300 996633 666600 006600 336666 000099 333399 663366 " + "000000 330000 663300 663333 333300 003300 003333 000066 330099 330033", - fonts: // font names listed in the font popup + fonts: // font names in the font popup "Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond," + "Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana", - sizes: // sizes listed in the font size popup + sizes: // sizes in the font size popup "1,2,3,4,5,6,7", - styles: // styles listed onafterprint the style popup - [['Paragraph', '

'], ['Header 1', '

'], ['Header 2', '

'], - ['Header 3', '

'], ['Header 4','

'], ['Header 5','

'], - ['Header 6','
']], - mainClass: "cleditorMain", // class name assigned to the main containing div - toolbarClass: "cleditorToolbar", // class name assigned to the toolbar div - groupClass: "cleditorGroup", // class name assigned to each group div in the toolbar div - buttonClass: "cleditorButton", // class name assigned to each button - dividerClass: "cleditorDivider", // class name assigned to each group divider + styles: // styles in the style popup + [["Paragraph", "

"], ["Header 1", "

"], ["Header 2", "

"], + ["Header 3", "

"], ["Header 4","

"], ["Header 5","

"], + ["Header 6","
"]], + useCSS: false, // use CSS to style HTML when possible (not supported in ie) bodyStyle: // style to assign to document body contained within the editor "margin:4px; font:10pt Arial,Verdana; cursor:text" - }, options); + }, + + // ● 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. + // e.g. buttons.size.title = "Font Size" + buttons: { + // name,title,command,popupName (""=use name) + init: + "bold,,|" + + "italic,,|" + + "underline,,|" + + "strikethrough,,|" + + "subscript,,|" + + "superscript,,|" + + "font,,fontname,|" + + "size,Font Size,fontsize,|" + + "style,,formatblock,|" + + "color,Font Color,forecolor,|" + + "highlight,Text Highlight Color,hilitecolor,color|" + + "removeformat,Remove Formatting,|" + + "bullets,,insertunorderedlist|" + + "numbering,,insertorderedlist|" + + "outdent,,|" + + "indent,,|" + + "alignleft,Align Text Left,justifyleft|" + + "center,,justifycenter|" + + "alignright,Align Text Right,justifyright|" + + "justify,,justifyfull|" + + "undo,,|" + + "redo,,|" + + "rule,Insert Horizontal Rule,inserthorizontalrule|" + + "image,Insert Image,insertimage,url|" + + "link,Insert Hyperlink,createlink,url|" + + "unlink,Remove Hyperlink,|" + + "cut,,|" + + "copy,,|" + + "paste,,|" + + "print,,|" + + "html,Show HTML" + }, + + // ● imagesPath - returns the path to the images folder + imagesPath: function() { return imagesPath(); } + + }; + + // ● cleditor - creates a new editor for each of the matched textareas + $.fn.cleditor = function(options) { + + // Create a new jQuery object to hold the results + var $result = $([]); - // Check for IE6 - var ie6 = /msie\s6/.test(navigator.userAgent.toLowerCase()); + // Loop through all matching textareas and create the editors + this.each(function() { + if (this.tagName == "TEXTAREA") { + var data = $(this).data(CLEDITOR); + if (!data) $result = $result.add(new cleditor(this, options)); + else $result = $result.add(data); + } + }); + + // return the new jQuery object + return $result; + + }; + + //================== + // Private Variables + //================== + + var + + // ● Misc constants + BACKGROUND_COLOR = "backgroundColor", + BUTTON = "button", + BUTTON_NAME = BUTTON + "Name", + CHANGE = "change", + CLEDITOR = "cleditor", + CLICK = "click", + COLOR = "color", + DISABLED = "disabled", + DIV_TAG = "
", + FONT = "font", + SIZE = "size", + STYLE = "style", + UNSELECTABLE = "unselectable", + + // ● Class name constants + MAIN_CLASS = CLEDITOR + "Main", // main containing div + TOOLBAR_CLASS = CLEDITOR + "Toolbar", // toolbar div inside main div + GROUP_CLASS = CLEDITOR + "Group", // group divs inside the toolbar div + BUTTON_CLASS = CLEDITOR + "Button", // button divs inside group div + DIVIDER_CLASS = CLEDITOR + "Divider", // divider divs inside group div + POPUP_CLASS = CLEDITOR + "Popup", // popup divs inside body + LIST_CLASS = CLEDITOR + "List", // list popup divs inside body + COLOR_CLASS = CLEDITOR + "Color", // color popup div inside body + PROMPT_CLASS = CLEDITOR + "Prompt", // prompt popup divs inside body + MSG_CLASS = CLEDITOR + "Msg", // message popup div inside body + + // ● Test for internet explorer 6 + ie6 = /msie\s6/i.test(navigator.userAgent), + + // ● Popups are created once as needed and shared by all editor instances + popups = {}, + + // ● Used to prevent the document click event from being bound more than once + documentClickAssigned, + + // ● Local copy of the buttons object + buttons = $.cleditor.buttons; + + //=============== + // Initialization + //=============== - // Hide the textarea used to communicate with the server - var $area = $("#" + areaID) + // ● Expand the buttons.init string back into the buttons object + // and create seperate object properties for each button. + // e.g. buttons.size.title = "Font Size" + $.each(buttons.init.split("|"), function(idx, button) { + var items = button.split(","), name = items[0]; + buttons[name] = { + stripIndex: idx, + name: name, + title: items[1] == "" ? name.charAt(0).toUpperCase() + name.substr(1) : items[1], + command: items[2] == "" ? name : items[2], + popupName: items[3] == "" ? name : items[3] + }; + }); + delete buttons.init; + + //============ + // Constructor + //============ + + // ● cleditor - creates a new editor for the passed in textarea element + cleditor = function(area, options) { + + var editor = this; + + // Get the defaults and override with options + options = $.extend({}, $.cleditor.defaultOptions, options); + + // Prepare the textarea + var $area = $(area) .hide() - .keyup($.proxy(this.updateFrame, this)) - .mouseup($.proxy(this.updateFrame, this)); - - // Create the main div used to contain all editor elements and controls - var $main = $("
") + .data(CLEDITOR, editor) + .bind("keyup mouseup", function() {updateFrame(editor);}); + + // Create the main container and append the textarea + var $main = $(DIV_TAG) + .addClass(MAIN_CLASS) + .width(options.width) + .height(options.height) .insertBefore($area) - .addClass(settings.mainClass) - .width(settings.width) - .height(settings.height); - - // Create the toolbar which consists of - // groups of buttons and dividers. - var $toolbar = $("
") - .appendTo($main) - .addClass(settings.toolbarClass); - - var $group = $("
") - .appendTo($toolbar) - .addClass(settings.groupClass); + .append($area); + + // Create the toolbar + var $toolbar = $(DIV_TAG) + .css({ + backgroundImage: imageUrl("toolbar.gif"), + backgroundRepeat: "repeat" + }) + .prependTo($main); + + // Add the first group to the toolbar + var $group = $(DIV_TAG) + .addClass(GROUP_CLASS) + .appendTo($toolbar); + // Add the buttons to the toolbar var wid = 0; - - $.each(settings.controls.split(" "), $.proxy(function(buttonIDx, buttonID) { + $.each(options.controls.split(" "), function(idx, buttonName) { + if (buttonName == "") return true; // Divider - if (buttonID == "|") { + if (buttonName == "|") { // Add a new divider to the group - var $div = $("
") - .appendTo($group) - .addClass(settings.dividerClass); + var $div = $(DIV_TAG) + .addClass(DIVIDER_CLASS) + .appendTo($group); // Set the group width - wid += $div.width(); - $group.width(wid); + $group.width(wid += $div.width()); // Create a new group - $group = $("
") - .appendTo($toolbar) - .addClass(settings.groupClass); + $group = $(DIV_TAG) + .addClass(GROUP_CLASS) + .appendTo($toolbar); wid = 0; + } // Button - else if (buttons[buttonID]) { + else { + // Get the button definition + var button = buttons[buttonName]; + // Add a new button to the group - var pos = (buttons[buttonID][0]) * -24; - var $btn = $("
") - .appendTo($group) - .addClass(settings.buttonClass) - .attr("title", buttons[buttonID][1]) - .css("background-position", pos + "px") - .bind('click', {buttonID: buttonID}, $.proxy(buttonClick, this)); - - // Update the width - wid += $btn.width(); - $group.width(wid); - - // - if ($.browser.msie) $btn.attr("unselectable", "on"); - - // Create the font popup - if (buttonID == "font" && $fontPopup === undefined) - createFontPopup(); - - // Create the size popup - if (buttonID == "size" && $sizePopup === undefined) - createSizePopup(); - - // Create the style popup - if (buttonID == "style" && $stylePopup === undefined) - createStylePopup(); - - // Create the color popup - if ((buttonID == "color" || buttonID == "highlight") && $colorPopup === undefined) - createColorPopup(); + var $buttonDiv = $(DIV_TAG) + .data(BUTTON_NAME, button.name) + .addClass(BUTTON_CLASS) + .attr("title", button.title) + .bind(CLICK, $.proxy(buttonClick, editor)) + .appendTo($group); + + // Prepare the button image + if (button.css) + $buttonDiv.css(button.css); + else if (button.image) + $buttonDiv.css({backgroundImage: imageUrl(button.image)}); + else + $buttonDiv.css({backgroundImage: imageUrl("buttons.gif")}); + if (button.stripIndex) + $buttonDiv.css({backgroundPosition: button.stripIndex * -24}); + + // Update the group width + $group.width(wid += $buttonDiv.width()); + + // Add the unselectable attribute for ie + if ($.browser.msie) + $buttonDiv.attr(UNSELECTABLE, "on"); + + // Create the popup + if (button.popupName) + createPopup(button.popupName, options, button.popupClass, + button.popupContent, button.popupHover); } - }, this)); + }); // Add the hover effect to all toolbar buttons - $main.find("." + settings.buttonClass).hover( - function() {$(this).css({backgroundColor: "#ffffff"});}, - function() {$(this).css({backgroundColor: "transparent"});} - ); - - // Append the textarea to the main div - $area.appendTo($main); + $toolbar.find("." + BUTTON_CLASS).hover(hoverEnter, hoverLeave); // Create an iframe used for wysiwyg editing var $frame = $('