All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.primefaces.editor.editor.js Maven / Gradle / Ivy

Go to download

PrimeFaces is one of the most popular UI libraries in Java EE Ecosystem and widely used by software companies, world renowned brands, banks, financial institutions, insurance companies, universities and more.

There is a newer version: 14.0.0-RC2
Show newest version
/*!
 CLEditor WYSIWYG HTML Editor v1.4.5
 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.
*/

(function ($) {

    //==============
    // jQuery Plugin
    //==============

    $.cleditor = {

        // Define the defaults used for all new cleditor instances
        defaultOptions: {
            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 " +
                          "style | color highlight removeformat | bullets numbering | outdent " +
                          "indent | alignleft center alignright justify | undo redo | " +
                          "rule image link unlink | cut copy paste pastetext | print source",
            colors:       // colors in the color popup
                          "FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF " +
                          "CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F " +
                          "BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C " +
                          "999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C " +
                          "666 900 C60 C93 990 090 399 33F 60C 939 " +
                          "333 600 930 963 660 060 366 009 339 636 " +
                          "000 300 630 633 330 030 033 006 309 303",
            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 in the font size popup
                          "1,2,3,4,5,6,7",
            styles:       // styles in the style popup
                          [["Paragraph", "

"], ["Header 1", "

"], ["Header 2", "

"], ["Header 3", "

"], ["Header 4", "

"], ["Header 5", "

"], ["Header 6", "
"]], useCSS: true, // use CSS to style HTML when possible (not supported in ie) docType: // Document type contained within the editor '', 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; 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 // separate 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,,|" + "pastetext,Paste as Text,inserthtml,|" + "print,,|" + "source,Show Source" }, // 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 = $([]); // Loop through all matching textareas and create the editors this.each(function (idx, elem) { if (elem.tagName.toUpperCase() === "TEXTAREA") { var data = $.data(elem, CLEDITOR); if (!data) data = new cleditor(elem, options); $result = $result.add(data); } }); // return the new jQuery object return $result; }; //================== // Private Variables //================== var // Misc constants BACKGROUND_COLOR = "backgroundColor", BLURRED = "blurred", BUTTON = "button", BUTTON_NAME = "buttonName", CHANGE = "change", CLEDITOR = "cleditor", CLICK = "click", DISABLED = "disabled", DIV_TAG = "
", FOCUSED = "focused", TRANSPARENT = "transparent", UNSELECTABLE = "unselectable", // Class name constants MAIN_CLASS = "ui-editor ui-widget-content", // main containing div TOOLBAR_CLASS = "ui-editor-toolbar", // toolbar div inside main div GROUP_CLASS = "ui-editor-group", // group divs inside the toolbar div BUTTON_CLASS = "ui-editor-button", // button divs inside group div DISABLED_CLASS = "ui-editor-disabled",// disabled button divs DIVIDER_CLASS = "ui-editor-divider", // divider divs inside group div POPUP_CLASS = "ui-editor-popup", // popup divs inside body LIST_CLASS = "ui-editor-list", // list popup divs inside body COLOR_CLASS = "ui-editor-color", // color popup div inside body PROMPT_CLASS = "ui-editor-prompt", // prompt popup divs inside body MSG_CLASS = "ui-editor-message", // message popup div inside body // 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(ua), // 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 //=============== // 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 editor.options = options = $.extend({}, $.cleditor.defaultOptions, options); // Hide the textarea and associate it with this editor var $area = editor.$area = $(area) .css({ border: "none", margin: 0, padding: 0 }) // Needed for IE6 & 7 (won't work in CSS file) .hide() .data(CLEDITOR, editor) .blur(function () { // Update the iframe when the textarea loses focus updateFrame(editor, true); }); // Create the main container var $main = editor.$main = $(DIV_TAG) .addClass(MAIN_CLASS) .width(options.width) .height(options.height); // Create the toolbar var $toolbar = editor.$toolbar = $(DIV_TAG) .addClass(TOOLBAR_CLASS) .appendTo($main); // Add the first group to the toolbar 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 === "|") { // 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) .appendTo($toolbar); } // Button else { // Get the button definition var button = buttons[buttonName]; // Add a new button to the group var $buttonDiv = $(DIV_TAG) .data(BUTTON_NAME, button.name) .addClass(BUTTON_CLASS) .attr("title", button.title) .bind(CLICK, $.proxy(buttonClick, editor)) .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; else if (button.image) map.backgroundImage = imageUrl(button.image); if (button.stripIndex) map.backgroundPosition = button.stripIndex * -24; $buttonDiv.css(map); // Add the unselectable attribute for ie if (ie) $buttonDiv.attr(UNSELECTABLE, "on"); // Create the popup if (button.popupName) createPopup(button.popupName, options, button.popupClass, button.popupContent, button.popupHover); } }); // Add the main div to the DOM and append the textarea $main.insertBefore($area) .append($area); // Bind the document click event handler if (!documentClickAssigned) { $(document).click(function (e) { // Dismiss all non-prompt popups var $target = $(e.target); if (!$target.add($target.parents()).is("." + PROMPT_CLASS)) hidePopups(); }); documentClickAssigned = true; } // Bind the window resize event when the width or height is auto or % if (/auto|%/.test("" + options.width + options.height)) $(window).bind("resize.cleditor", function () { refresh(editor); }); // Create the iframe and resize the controls refresh(editor); }; //=============== // Public Methods //=============== var fn = cleditor.prototype, // Expose the following private functions as methods on the cleditor object. // The closure compiler will rename the private functions. However, the // exposed method names on the cleditor object will remain fixed. methods = [ ["clear", clear], ["disable", disable], ["execCommand", execCommand], ["focus", focus], ["hidePopups", hidePopups], ["sourceMode", sourceMode, true], ["refresh", refresh], ["select", select], ["selectedHTML", selectedHTML, true], ["selectedText", selectedText, true], ["showMessage", showMessage], ["updateFrame", updateFrame], ["updateTextArea", updateTextArea] ]; $.each(methods, function (idx, method) { fn[method[0]] = function () { var editor = this, args = [editor]; // using each here would cast booleans into objects! for (var x = 0; x < arguments.length; x++) { args.push(arguments[x]); } var result = method[1].apply(editor, args); if (method[2]) return result; 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 change(handler) { 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 //=============== // buttonClick - click event handler for toolbar buttons function buttonClick(e) { var editor = this, buttonDiv = e.target, buttonName = $.data(buttonDiv, BUTTON_NAME), button = buttons[buttonName], popupName = button.popupName, popup = popups[popupName]; // Check if disabled if (editor.disabled || $(buttonDiv).attr(DISABLED) === DISABLED) return; // Fire the buttonClick event var data = { editor: editor, button: buttonDiv, buttonName: buttonName, popup: popup, popupName: popupName, command: button.command, useCSS: editor.options.useCSS }; if (button.buttonClick && button.buttonClick(e, data) === false) return false; // Toggle source if (buttonName === "source") { // Show the iframe if (sourceMode(editor)) { delete editor.range; editor.$area.hide(); editor.$frame.show(); buttonDiv.title = button.title; } // Show the textarea else { editor.$frame.hide(); editor.$area.show(); buttonDiv.title = "Show Rich Text"; } } // Check for rich text mode else if (!sourceMode(editor)) { // Handle popups if (popupName) { var $popup = $(popup); // URL if (popupName === "url") { // Check for selection before showing the link url popup if (buttonName === "link" && selectedText(editor) === "") { showMessage(editor, "A selection is required when inserting a link.", buttonDiv); return false; } // Wire up the submit button click event handler $popup.children(":button") .unbind(CLICK) .bind(CLICK, function () { // Insert the image or link if a url was entered var $text = $popup.find(":text"), url = $.trim($text.val()); if (url !== "") execCommand(editor, data.command, url, null, data.button); // Reset the text, hide the popup and set focus $text.val("http://"); hidePopups(); focus(editor); }); } // Paste as Text else if (popupName === "pastetext") { // Wire up the submit button click event handler $popup.children(":button") .unbind(CLICK) .bind(CLICK, function () { // Insert the unformatted text replacing new lines with break tags var $textarea = $popup.find("textarea"), text = $textarea.val().replace(/\n/g, "
"); if (text !== "") execCommand(editor, data.command, text, null, data.button); // Reset the text, hide the popup and set focus $textarea.val(""); hidePopups(); focus(editor); }); } // Show the popup if not already showing for this button if (buttonDiv !== $.data(popup, BUTTON)) { showPopup(editor, popup, buttonDiv); return false; // stop propagination to document click } // propaginate to document click return; } // Print else if (buttonName === "print") editor.$frame[0].contentWindow.print(); // All other buttons else if (!execCommand(editor, data.command, data.value, data.useCSS, buttonDiv)) return false; } // Focus the editor focus(editor); } // hoverEnter - mouseenter event handler for buttons and popup items function hoverEnter(e) { var $div = $(e.target).closest("div"); $div.css(BACKGROUND_COLOR, $div.data(BUTTON_NAME) ? "#FFF" : "#FFC"); } // hoverLeave - mouseleave event handler for buttons and popup items function hoverLeave(e) { $(e.target).closest("div").css(BACKGROUND_COLOR, "transparent"); } // popupClick - click event handler for popup items function popupClick(e) { var editor = this, popup = e.data.popup, target = e.target; // Check for message and prompt popups if (popup === popups.msg || $(popup).hasClass(PROMPT_CLASS)) return; // Get the button info var buttonDiv = $.data(popup, BUTTON), buttonName = $.data(buttonDiv, BUTTON_NAME), button = buttons[buttonName], command = button.command, value, useCSS = editor.options.useCSS; // Get the command value if (buttonName === "font") // Opera returns the fontfamily wrapped in quotes value = target.style.fontFamily.replace(/"/g, ""); else if (buttonName === "size") { if (target.tagName.toUpperCase() === "DIV") target = target.children[0]; value = target.innerHTML; } else if (buttonName === "style") value = "<" + target.tagName + ">"; else if (buttonName === "color") value = hex(target.style.backgroundColor); else if (buttonName === "highlight") { value = hex(target.style.backgroundColor); if (ie) command = 'backcolor'; else useCSS = true; } // Fire the popupClick event var data = { editor: editor, button: buttonDiv, buttonName: buttonName, popup: popup, popupName: button.popupName, command: command, value: value, useCSS: useCSS }; if (button.popupClick && button.popupClick(e, data) === false) return; // Execute the command if (data.command && !execCommand(editor, data.command, data.value, data.useCSS, buttonDiv)) return false; // Hide the popup and focus the editor hidePopups(); focus(editor); } //================== // Private Functions //================== // checksum - returns a checksum using the Adler-32 method function checksum(text) { var a = 1, b = 0; for (var index = 0; index < text.length; ++index) { a = (a + text.charCodeAt(index)) % 65521; b = (b + a) % 65521; } return (b << 16) | a; } // clear - clears the contents of the editor function clear(editor) { editor.$area.val(""); updateFrame(editor); } // createPopup - creates a popup and adds it to the body function createPopup(popupName, options, popupTypeClass, popupContent, popupHover) { // Check if popup already exists if (popups[popupName]) return popups[popupName]; // Create the popup var $popup = $(DIV_TAG) .hide() .addClass(POPUP_CLASS) .appendTo("body"); // Add the content // Custom popup if (popupContent) $popup.html(popupContent); // Color else if (popupName === "color") { var colors = options.colors.split(" "); if (colors.length < 10) $popup.width("auto"); $.each(colors, function (idx, color) { $(DIV_TAG).appendTo($popup) .css(BACKGROUND_COLOR, "#" + color); }); popupTypeClass = COLOR_CLASS; } // Font else if (popupName === "font") $.each(options.fonts.split(","), function (idx, font) { $(DIV_TAG).appendTo($popup) .css("fontFamily", font) .html(font); }); // Size else if (popupName === "size") $.each(options.sizes.split(","), function (idx, size) { $(DIV_TAG).appendTo($popup) .html('' + size + ''); }); // Style else if (popupName === "style") $.each(options.styles, function (idx, style) { $(DIV_TAG).appendTo($popup) .html(style[1] + style[0] + style[1].replace("<", "Enter URL:

'); popupTypeClass = PROMPT_CLASS; } // Paste as Text else if (popupName === "pastetext") { $popup.html('
'); popupTypeClass = PROMPT_CLASS; } // Add the popup type class name if (!popupTypeClass && !popupContent) popupTypeClass = LIST_CLASS; $popup.addClass(popupTypeClass); // Add the unselectable attribute to all items if (ie) { $popup.attr(UNSELECTABLE, "on") .find("div,font,p,h1,h2,h3,h4,h5,h6") .attr(UNSELECTABLE, "on"); } // Add the hover effect to all items if ($popup.hasClass(LIST_CLASS) || popupHover === true) $popup.children().hover(hoverEnter, hoverLeave); // Add the popup to the array and return it popups[popupName] = $popup[0]; return $popup[0]; } // disable - enables or disables the editor function disable(editor, disabled) { // Update the textarea and save the state if (disabled) { editor.$area.attr(DISABLED, DISABLED); editor.disabled = true; } else { editor.$area.removeAttr(DISABLED); delete editor.disabled; } // Switch the iframe into design mode. // ie6 does not support designMode. // ie7 & ie8 do not properly support designMode="off". try { if (ie) editor.doc.body.contentEditable = !disabled; else editor.doc.designMode = !disabled ? "on" : "off"; } // Firefox 1.5 throws an exception that can be ignored // when toggling designMode from off to on. catch (err) { } // Enable or disable the toolbar buttons refreshButtons(editor); } // execCommand - executes a designMode command function execCommand(editor, command, value, useCSS, button) { // Restore the current ie selection restoreRange(editor); // Set the styling method if (!ie) { if (useCSS === undefined || useCSS === null) useCSS = editor.options.useCSS; editor.doc.execCommand("styleWithCSS", 0, useCSS.toString()); } // Execute the command and check for error var inserthtml = command.toLowerCase() === "inserthtml"; if (ie && inserthtml) { /* Despite having access to pasteHTML, IE8 will produce an 'unspecified error' if it is invoked. The only way to detect this bug is via try catch. */ try{ getRange(editor).pasteHTML(value); } catch(e){ // An empty document needs selection beforehand if(/^\s*$/.test(editor.doc.body.innerText)){ editor.doc.execCommand('selectAll',false, null); } // execCommand is the standard method for contentEditable elements editor.doc.execCommand("Paste", 0, value || null); } } else if (iege11 && inserthtml) { var selection = getSelection(editor), range = selection.getRangeAt(0); range.deleteContents(); range.insertNode(range.createContextualFragment(value)); selection.removeAllRanges(); selection.addRange(range); } else { var success = true, message; try { success = editor.doc.execCommand(command, 0, value || null); } 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 " + command + " command. Try using the keyboard shortcut or context menu instead.", button); else showMessage(editor, (message ? message : "Error executing the " + command + " command."), button); } } // Enable the buttons and update the textarea refreshButtons(editor); updateTextArea(editor, true); return success; } // focus - sets focus to either the textarea or iframe function focus(editor) { setTimeout(function () { if (sourceMode(editor)) editor.$area.focus(); else editor.$frame[0].contentWindow.focus(); refreshButtons(editor); }, 0); } // getRange - gets the current text range object function getRange(editor) { if (ie) return getSelection(editor).createRange(); return getSelection(editor).getRangeAt(0); } // getSelection - gets the current text range object function getSelection(editor) { if (ie) return editor.doc.selection; return editor.$frame[0].contentWindow.getSelection(); } // hex - returns the hex value for the passed in color string function hex(s) { // 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); while (s.length < 6) s = "0" + s; return "#" + s; } // 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 function hidePopups() { $.each(popups, function (idx, popup) { $(popup) .hide() .unbind(CLICK) .removeData(BUTTON); }); } // imagesPath - returns the path to the images folder function imagesPath() { var href = $("link[href*=cleditor]").attr("href"); return href.replace(/^(.*\/)[^\/]+$/, '$1') + "images/"; } // imageUrl - Returns the css url string for a filemane function imageUrl(filename) { return "url(" + imagesPath() + filename + ")"; } // refresh - creates the iframe and resizes the controls function refresh(editor) { var $main = editor.$main, options = editor.options; // Remove the old iframe if (editor.$frame) editor.$frame.remove(); // Create a new iframe var $frame = editor.$frame = $('