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

META-INF.resources.scripts.vendor.plugins.wysiwyg.jquery.wysiwyg.js Maven / Gradle / Ivy

/**
 * WYSIWYG - jQuery plugin 0.97
 * (0.97.2 - From infinity)
 *
 * Copyright (c) 2008-2009 Juan M Martinez, 2010-2011 Akzhan Abdulin and all contributors
 * https://github.com/akzhan/jwysiwyg
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */

/*jslint browser: true, forin: true */

(function ( $ ) {
	"use strict";
	/* Wysiwyg namespace: private properties and methods */

	var console = window.console ? window.console : {
		log: $.noop,
		error: function ( msg ) {
			$.error( msg );
		}
	};
	var supportsProp = (('prop' in $.fn) && ('removeProp' in $.fn));

	function Wysiwyg() {
		// - the item is added by this.ui.appendControls and then appendItem
		// - click triggers this.triggerControl
		// cmd or[key] - designMode exec function name
		// tags - activates control for these tags (@see checkTargets)
		// css - activates control if one of css is applied
		this.controls = {
			bold: {
				groupIndex: 0,
				visible: true,
				tags: ["b", "strong"],
				css: {
					fontWeight: "bold"
				},
				tooltip: "Bold",
				hotkey: {"ctrl": 1, "key": 66}
			},

			copy: {
				groupIndex: 8,
				visible: false,
				tooltip: "Copy"
			},

			createLink: {
				groupIndex: 6,
				visible: true,
				exec: function () {
					var self = this;
					if ( $.wysiwyg.controls && $.wysiwyg.controls.link ) {
						$.wysiwyg.controls.link.init( this );
					} else if ( $.wysiwyg.autoload ) {
						$.wysiwyg.autoload.control( "wysiwyg.link.js", function () {
							self.controls.createLink.exec.apply( self );
						} );
					} else {
						console.error( "$.wysiwyg.controls.link not defined. You need to include wysiwyg.link.js file" );
					}
				},
				tags: ["a"],
				tooltip: "Create link"
			},

			cut: {
				groupIndex: 8,
				visible: false,
				tooltip: "Cut"
			},

			decreaseFontSize: {
				groupIndex: 9,
				visible: false,
				tags: ["small"],
				tooltip: "Decrease font size",
				exec: function () {
					this.decreaseFontSize();
				}
			},

			h1: {
				groupIndex: 7,
				visible: true,
				className: "h1",
				command: ($.browser.msie || $.browser.safari) ? "FormatBlock" : "heading",
				"arguments": ($.browser.msie || $.browser.safari) ? "

" : "h1", tags: ["h1"], tooltip: "Header 1" }, h2: { groupIndex: 7, visible: true, className: "h2", command: ($.browser.msie || $.browser.safari) ? "FormatBlock" : "heading", "arguments": ($.browser.msie || $.browser.safari) ? "

" : "h2", tags: ["h2"], tooltip: "Header 2" }, h3: { groupIndex: 7, visible: true, className: "h3", command: ($.browser.msie || $.browser.safari) ? "FormatBlock" : "heading", "arguments": ($.browser.msie || $.browser.safari) ? "

" : "h3", tags: ["h3"], tooltip: "Header 3" }, highlight: { tooltip: "Highlight", className: "highlight", groupIndex: 1, visible: false, css: { backgroundColor: "rgb(255, 255, 102)" }, exec: function () { var command, node, selection, args; if ( $.browser.msie || $.browser.safari ) { command = "backcolor"; } else { command = "hilitecolor"; } if ( $.browser.msie ) { node = this.getInternalRange().parentElement(); } else { selection = this.getInternalSelection(); node = selection.extentNode || selection.focusNode; while ( node.style === undefined ) { node = node.parentNode; if ( node.tagName && node.tagName.toLowerCase() === "body" ) { return; } } } if ( node.style.backgroundColor === "rgb(255, 255, 102)" || node.style.backgroundColor === "#ffff66" ) { args = "#ffffff"; } else { args = "#ffff66"; } this.editorDoc.execCommand( command, false, args ); } }, html: { groupIndex: 10, visible: false, exec: function () { var elementHeight; if ( this.options.resizeOptions && $.fn.resizable ) { elementHeight = this.element.height(); } if ( this.viewHTML ) { //textarea is shown this.setContent( this.original.value ); $( this.original ).hide(); this.editor.show(); if ( this.options.resizeOptions && $.fn.resizable ) { // if element.height still the same after frame was shown if ( elementHeight === this.element.height() ) { this.element.height( elementHeight + this.editor.height() ); } this.element.resizable( $.extend( true, { alsoResize: this.editor }, this.options.resizeOptions ) ); } this.ui.toolbar.find( "li" ).each( function () { var li = $( this ); if ( li.hasClass( "html" ) ) { li.removeClass( "active" ); } else { li.removeClass( 'disabled' ); } } ); } else { //wysiwyg is shown this.saveContent(); $( this.original ).css( { width: this.element.outerWidth() - 6, height: this.element.height() - this.ui.toolbar.height() - 6, resize: "none" } ).show(); this.editor.hide(); if ( this.options.resizeOptions && $.fn.resizable ) { // if element.height still the same after frame was hidden if ( elementHeight === this.element.height() ) { this.element.height( this.ui.toolbar.height() ); } this.element.resizable( "destroy" ); } this.ui.toolbar.find( "li" ).each( function () { var li = $( this ); if ( li.hasClass( "html" ) ) { li.addClass( "active" ); } else { if ( false === li.hasClass( "fullscreen" ) ) { li.removeClass( "active" ).addClass( 'disabled' ); } } } ); } this.viewHTML = !(this.viewHTML); }, tooltip: "View source code" }, increaseFontSize: { groupIndex: 9, visible: false, tags: ["big"], tooltip: "Increase font size", exec: function () { this.increaseFontSize(); } }, indent: { groupIndex: 2, visible: true, tooltip: "Indent" }, insertHorizontalRule: { groupIndex: 6, visible: true, tags: ["hr"], tooltip: "Insert Horizontal Rule" }, insertImage: { groupIndex: 6, visible: true, exec: function () { var self = this; if ( $.wysiwyg.controls && $.wysiwyg.controls.image ) { $.wysiwyg.controls.image.init( this ); } else if ( $.wysiwyg.autoload ) { $.wysiwyg.autoload.control( "wysiwyg.image.js", function () { self.controls.insertImage.exec.apply( self ); } ); } else { console.error( "$.wysiwyg.controls.image not defined. You need to include wysiwyg.image.js file" ); } }, tags: ["img"], tooltip: "Insert image" }, insertOrderedList: { groupIndex: 5, visible: true, tags: ["ol"], tooltip: "Insert Ordered List" }, insertTable: { groupIndex: 6, visible: true, exec: function () { var self = this; if ( $.wysiwyg.controls && $.wysiwyg.controls.table ) { $.wysiwyg.controls.table( this ); } else if ( $.wysiwyg.autoload ) { $.wysiwyg.autoload.control( "wysiwyg.table.js", function () { self.controls.insertTable.exec.apply( self ); } ); } else { console.error( "$.wysiwyg.controls.table not defined. You need to include wysiwyg.table.js file" ); } }, tags: ["table"], tooltip: "Insert table" }, insertUnorderedList: { groupIndex: 5, visible: true, tags: ["ul"], tooltip: "Insert Unordered List" }, italic: { groupIndex: 0, visible: true, tags: ["i", "em"], css: { fontStyle: "italic" }, tooltip: "Italic", hotkey: {"ctrl": 1, "key": 73} }, justifyCenter: { groupIndex: 1, visible: true, tags: ["center"], css: { textAlign: "center" }, tooltip: "Justify Center" }, justifyFull: { groupIndex: 1, visible: true, css: { textAlign: "justify" }, tooltip: "Justify Full" }, justifyLeft: { visible: true, groupIndex: 1, css: { textAlign: "left" }, tooltip: "Justify Left" }, justifyRight: { groupIndex: 1, visible: true, css: { textAlign: "right" }, tooltip: "Justify Right" }, ltr: { groupIndex: 10, visible: false, exec: function () { var p = this.dom.getElement( "p" ); if ( !p ) { return false; } $( p ).attr( "dir", "ltr" ); return true; }, tooltip: "Left to Right" }, outdent: { groupIndex: 2, visible: true, tooltip: "Outdent" }, paragraph: { groupIndex: 7, visible: false, className: "paragraph", command: "FormatBlock", "arguments": ($.browser.msie || $.browser.safari) ? "

" : "p", tags: ["p"], tooltip: "Paragraph" }, paste: { groupIndex: 8, visible: false, tooltip: "Paste" }, redo: { groupIndex: 4, visible: true, tooltip: "Redo" }, removeFormat: { groupIndex: 10, visible: true, exec: function () { this.removeFormat(); }, tooltip: "Remove formatting" }, rtl: { groupIndex: 10, visible: false, exec: function () { var p = this.dom.getElement( "p" ); if ( !p ) { return false; } $( p ).attr( "dir", "rtl" ); return true; }, tooltip: "Right to Left" }, strikeThrough: { groupIndex: 0, visible: true, tags: ["s", "strike"], css: { textDecoration: "line-through" }, tooltip: "Strike-through" }, subscript: { groupIndex: 3, visible: true, tags: ["sub"], tooltip: "Subscript" }, superscript: { groupIndex: 3, visible: true, tags: ["sup"], tooltip: "Superscript" }, underline: { groupIndex: 0, visible: true, tags: ["u"], css: { textDecoration: "underline" }, tooltip: "Underline", hotkey: {"ctrl": 1, "key": 85} }, undo: { groupIndex: 4, visible: true, tooltip: "Undo" }, code: { visible: true, groupIndex: 6, tooltip: "Code snippet", exec: function () { var range = this.getInternalRange(), common = $( range.commonAncestorContainer ), $nodeName = range.commonAncestorContainer.nodeName.toLowerCase(); if ( common.parent( "code" ).length ) { common.unwrap(); } else { if ( $nodeName !== "body" ) { common.wrap( "" ); } } } }, cssWrap: { visible: false, groupIndex: 6, tooltip: "CSS Wrapper", exec: function () { $.wysiwyg.controls.cssWrap.init( this ); } } }; this.defaults = { html: '

INITIAL_CONTENT
', debug: false, controls: {}, css: {}, events: {}, autoGrow: false, autoSave: true, brIE: true, // http://code.google.com/p/jwysiwyg/issues/detail?id=15 formHeight: 270, formWidth: 440, iFrameClass: null, initialContent: "", maxHeight: 10000, // see autoGrow maxLength: 0, messages: { nonSelection: "Select the text you wish to link" }, toolbarHtml: '', removeHeadings: false, replaceDivWithP: false, resizeOptions: false, rmUnusedControls: false, // https://github.com/akzhan/jwysiwyg/issues/52 rmUnwantedBr: true, // http://code.google.com/p/jwysiwyg/issues/detail?id=11 tableFiller: "Lorem ipsum", initialMinHeight: null, controlImage: { forceRelativeUrls: false }, controlLink: { forceRelativeUrls: false }, plugins: { // placeholder for plugins settings autoload: false, i18n: false, rmFormat: { rmMsWordMarkup: false } }, dialog: "default" }; //these properties are set from control hashes this.availableControlProperties = [ "arguments", "callback", "className", "command", "css", "custom", "exec", "groupIndex", "hotkey", "icon", "tags", "tooltip", "visible" ]; this.editor = null; //jquery iframe holder this.editorDoc = null; this.element = null; this.options = {}; this.original = null; this.savedRange = null; this.timers = []; this.validKeyCodes = [8, 9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46]; this.isDestroyed = false; this.dom = { // DOM related properties and methods ie: { parent: null // link to dom }, w3c: { parent: null // link to dom } }; this.dom.parent = this; this.dom.ie.parent = this.dom; this.dom.w3c.parent = this.dom; this.ui = {}; // UI related properties and methods this.ui.self = this; this.ui.toolbar = null; this.ui.initialHeight = null; // ui.grow this.dom.getAncestor = function ( element, filterTagName ) { filterTagName = filterTagName.toLowerCase(); while ( element && typeof element.tagName != "undefined" && "body" !== element.tagName.toLowerCase() ) { if ( filterTagName === element.tagName.toLowerCase() ) { return element; } element = element.parentNode; } if ( !element.tagName && (element.previousSibling || element.nextSibling) ) { if ( element.previousSibling ) { if ( element.previousSibling.tagName.toLowerCase() == filterTagName ) { return element.previousSibling; } } if ( element.nextSibling ) { if ( element.nextSibling.tagName.toLowerCase() == filterTagName ) { return element.nextSibling; } } } return null; }; this.dom.getElement = function ( filterTagName ) { var dom = this; filterTagName = filterTagName.toLowerCase(); if ( window.getSelection ) { return dom.w3c.getElement( filterTagName ); } else { return dom.ie.getElement( filterTagName ); } }; this.dom.ie.getElement = function ( filterTagName ) { var dom = this.parent, selection = dom.parent.getInternalSelection(), range = selection.createRange(), element; if ( "Control" === selection.type ) { // control selection if ( 1 === range.length ) { element = range.item( 0 ); } else { // multiple control selection return null; } } else { element = range.parentElement(); } return dom.getAncestor( element, filterTagName ); }; this.dom.w3c.getElement = function ( filterTagName ) { var dom = this.parent, range = dom.parent.getInternalRange(), element; if ( !range ) { return null; } element = range.commonAncestorContainer; if ( 3 === element.nodeType ) { element = element.parentNode; } // if startContainer not Text, Comment, or CDATASection element then // startOffset is the number of child nodes between the start of the // startContainer and the boundary point of the Range if ( element === range.startContainer ) { element = element.childNodes[range.startOffset]; } if ( !element.tagName && (element.previousSibiling || element.nextSibling) ) { if ( element.previousSibiling ) { if ( element.previousSibiling.tagName.toLowerCase() == filterTagName ) { return element.previousSibiling; } } if ( element.nextSibling ) { if ( element.nextSibling.tagName.toLowerCase() == filterTagName ) { return element.nextSibling; } } } return dom.getAncestor( element, filterTagName ); }; this.ui.addHoverClass = function () { $( this ).addClass( "wysiwyg-button-hover" ); }; this.ui.appendControls = function () { var ui = this, self = this.self, controls = self.parseControls(), hasVisibleControls = true, // to prevent separator before first item groups = [], controlsByGroup = {}, i, currentGroupIndex, // jslint wants all vars at top of function iterateGroup = function ( controlName, control ) { //called for every group when adding if ( control.groupIndex && currentGroupIndex !== control.groupIndex ) { currentGroupIndex = control.groupIndex; hasVisibleControls = false; } if ( !control.visible ) { return; } if ( !hasVisibleControls ) { ui.appendItemSeparator(); hasVisibleControls = true; } if ( control.custom ) { ui.appendItemCustom( controlName, control ); } else { ui.appendItem( controlName, control ); } }; $.each( controls, function ( name, c ) { //sort by groupIndex var index = "empty"; if ( undefined !== c.groupIndex ) { if ( "" === c.groupIndex ) { index = "empty"; } else { index = c.groupIndex; } } if ( undefined === controlsByGroup[index] ) { groups.push( index ); controlsByGroup[index] = {}; } controlsByGroup[index][name] = c; } ); groups.sort( function ( a, b ) { //just sort group indexes by if ( "number" === typeof (a) && typeof (a) === typeof (b) ) { return (a - b); } else { a = a.toString(); b = b.toString(); if ( a > b ) { return 1; } if ( a === b ) { return 0; } return -1; } } ); if ( 0 < groups.length ) { // set to first index in groups to proper placement of separator currentGroupIndex = groups[0]; } for ( i = 0; i < groups.length; i += 1 ) { $.each( controlsByGroup[groups[i]], iterateGroup ); } }; this.ui.appendItem = function ( name, control ) { var self = this.self, className = control.className || control.command || name || "empty", tooltip = control.tooltip || control.command || name || ""; return $( '
  • ' + (className) + "
  • " ).addClass( className ).attr( "title", tooltip ).hover( this.addHoverClass, this.removeHoverClass ).click(function ( event ) { if ( $( this ).hasClass( "disabled" ) ) { return false; } self.triggerControl.apply( self, [name, control] ); /** * @link https://github.com/akzhan/jwysiwyg/issues/219 */ var $target = $( event.target ); for ( var controlName in self.controls ) { if ( $target.hasClass( controlName ) ) { self.ui.toolbar.find( "." + controlName ).toggleClass( "active" ); self.editorDoc.rememberCommand = true; break; } } this.blur(); self.ui.returnRange(); self.ui.focus(); return true; } ).appendTo( self.ui.toolbar ); }; this.ui.appendItemCustom = function ( name, control ) { var self = this.self, tooltip = control.tooltip || control.command || name || ""; if ( control.callback ) { $( window ).bind( "trigger-" + name + ".wysiwyg", control.callback ); } return $( '
  • ' ).addClass( "custom-command-" + name ).addClass( "wysiwyg-custom-command" ).addClass( name ).attr( "title", tooltip ).hover( this.addHoverClass, this.removeHoverClass ).click(function () { if ( $( this ).hasClass( "disabled" ) ) { return false; } self.triggerControl.apply( self, [name, control] ); this.blur(); self.ui.returnRange(); self.ui.focus(); self.triggerControlCallback( name ); return true; } ).appendTo( self.ui.toolbar ); }; this.ui.appendItemSeparator = function () { var self = this.self; return $( '' ).appendTo( self.ui.toolbar ); }; this.autoSaveFunction = function () { this.saveContent(); }; //called after click in wysiwyg "textarea" this.ui.checkTargets = function ( element ) { var self = this.self; //activate controls $.each( self.options.controls, function ( name, control ) { var className = control.className || control.command || name || "empty", tags, elm, css, el, checkActiveStatus = function ( cssProperty, cssValue ) { var handler; if ( "function" === typeof (cssValue) ) { handler = cssValue; if ( handler( el.css( cssProperty ).toString().toLowerCase(), self ) ) { self.ui.toolbar.find( "." + className ).addClass( "active" ); } } else { if ( el.css( cssProperty ).toString().toLowerCase() === cssValue ) { self.ui.toolbar.find( "." + className ).addClass( "active" ); } } }; if ( "fullscreen" !== className ) { self.ui.toolbar.find( "." + className ).removeClass( "active" ); } //activate by allowed tags if ( control.tags || (control.options && control.options.tags) ) { tags = control.tags || (control.options && control.options.tags); elm = element; while ( elm ) { if ( elm.nodeType !== 1 ) { break; } if ( $.inArray( elm.tagName.toLowerCase(), tags ) !== -1 ) { self.ui.toolbar.find( "." + className ).addClass( "active" ); } elm = elm.parentNode; } } //activate by supposed css if ( control.css || (control.options && control.options.css) ) { css = control.css || (control.options && control.options.css); el = $( element ); while ( el ) { if ( el[0].nodeType !== 1 ) { break; } $.each( css, checkActiveStatus ); el = el.parent(); } } } ); }; this.ui.designMode = function () { var attempts = 3, self = this.self, runner; runner = function ( attempts ) { if ( "on" === self.editorDoc.designMode ) { if ( self.timers.designMode ) { window.clearTimeout( self.timers.designMode ); } // IE needs to reget the document element (this.editorDoc) after designMode was set if ( self.innerDocument() !== self.editorDoc ) { self.ui.initFrame(); } return; } try { self.editorDoc.designMode = "on"; } catch ( e ) { } attempts -= 1; if ( attempts > 0 ) { self.timers.designMode = window.setTimeout( function () { runner( attempts ); }, 100 ); } }; runner( attempts ); }; this.destroy = function () { this.isDestroyed = true; var i, $form = this.element.closest( "form" ); for ( i = 0; i < this.timers.length; i += 1 ) { window.clearTimeout( this.timers[i] ); } // Remove bindings $form.unbind( ".wysiwyg" ); this.element.remove(); $.removeData( this.original, "wysiwyg" ); $( this.original ).show(); return this; }; this.getRangeText = function () { var r = this.getInternalRange(); if ( r.toString ) { r = r.toString(); } else if ( r.text ) { // IE r = r.text; } return r; }; //not used? this.execute = function ( command, arg ) { if ( typeof (arg) === "undefined" ) { arg = null; } this.editorDoc.execCommand( command, false, arg ); }; this.extendOptions = function ( options ) { var controls = {}; /** * If the user set custom controls, we catch it, and merge with the * defaults controls later. */ if ( "object" === typeof options.controls ) { controls = options.controls; delete options.controls; } options = $.extend( true, {}, this.defaults, options ); options.controls = $.extend( true, {}, controls, this.controls, controls ); if ( options.rmUnusedControls ) { $.each( options.controls, function ( controlName ) { if ( !controls[controlName] ) { delete options.controls[controlName]; } } ); } return options; }; this.ui.focus = function () { var self = this.self; self.editor.get( 0 ).contentWindow.focus(); return self; }; this.ui.returnRange = function () { var self = this.self, sel; if ( self.savedRange !== null ) { if ( window.getSelection ) { //non IE and there is already a selection sel = window.getSelection(); if ( sel.rangeCount > 0 ) { sel.removeAllRanges(); } try { sel.addRange( self.savedRange ); } catch ( e ) { console.error( e ); } } else if ( window.document.createRange ) { // non IE and no selection window.getSelection().addRange( self.savedRange ); } else if ( window.document.selection ) { //IE self.savedRange.select(); } self.savedRange = null; } }; this.increaseFontSize = function () { if ( $.browser.mozilla || $.browser.opera ) { this.editorDoc.execCommand( "increaseFontSize", false, null ); } else if ( $.browser.safari ) { var Range = this.getInternalRange(), Selection = this.getInternalSelection(), newNode = this.editorDoc.createElement( "big" ); // If cursor placed on text node if ( true === Range.collapsed && 3 === Range.commonAncestorContainer.nodeType ) { var text = Range.commonAncestorContainer.nodeValue.toString(), start = text.lastIndexOf( " ", Range.startOffset ) + 1, end = (-1 === text.indexOf( " ", Range.startOffset )) ? text : text.indexOf( " ", Range.startOffset ); Range.setStart( Range.commonAncestorContainer, start ); Range.setEnd( Range.commonAncestorContainer, end ); Range.surroundContents( newNode ); Selection.addRange( Range ); } else { Range.surroundContents( newNode ); Selection.removeAllRanges(); Selection.addRange( Range ); } } else { console.error( "Internet Explorer?" ); } }; this.decreaseFontSize = function () { if ( $.browser.mozilla || $.browser.opera ) { this.editorDoc.execCommand( "decreaseFontSize", false, null ); } else if ( $.browser.safari ) { var Range = this.getInternalRange(), Selection = this.getInternalSelection(), newNode = this.editorDoc.createElement( "small" ); // If cursor placed on text node if ( true === Range.collapsed && 3 === Range.commonAncestorContainer.nodeType ) { var text = Range.commonAncestorContainer.nodeValue.toString(), start = text.lastIndexOf( " ", Range.startOffset ) + 1, end = (-1 === text.indexOf( " ", Range.startOffset )) ? text : text.indexOf( " ", Range.startOffset ); Range.setStart( Range.commonAncestorContainer, start ); Range.setEnd( Range.commonAncestorContainer, end ); Range.surroundContents( newNode ); Selection.addRange( Range ); } else { Range.surroundContents( newNode ); Selection.removeAllRanges(); Selection.addRange( Range ); } } else { console.error( "Internet Explorer?" ); } }; this.getContent = function () { if ( this.viewHTML ) { this.setContent( this.original.value ); } return this.events.filter( 'getContent', this.editorDoc.body.innerHTML ); }; /** * A jWysiwyg specific event system. * * Example: * * $("#editor").getWysiwyg().events.bind("getContent", function (orig) { * return "
    "+orgi+"
    "; * }); * * This makes it so that when ever getContent is called, it is wrapped in a div#content. */ this.events = { _events: {}, /** * Similar to jQuery's bind, but for jWysiwyg only. */ bind: function ( eventName, callback ) { if ( typeof (this._events.eventName) !== "object" ) { this._events[eventName] = []; } this._events[eventName].push( callback ); }, /** * Similar to jQuery's trigger, but for jWysiwyg only. */ trigger: function ( eventName, args ) { if ( typeof (this._events.eventName) === "object" ) { var editor = this.editor; $.each( this._events[eventName], function ( k, v ) { if ( typeof (v) === "function" ) { v.apply( editor, args ); } } ); } }, /** * This "filters" `originalText` by passing it as the first argument to every callback * with the name `eventName` and taking the return value and passing it to the next function. * * This function returns the result after all the callbacks have been applied to `originalText`. */ filter: function ( eventName, originalText ) { if ( typeof (this._events[eventName]) === "object" ) { var editor = this.editor, args = Array.prototype.slice.call( arguments, 1 ); $.each( this._events[eventName], function ( k, v ) { if ( typeof (v) === "function" ) { originalText = v.apply( editor, args ); } } ); } return originalText; } }; this.getElementByAttributeValue = function ( tagName, attributeName, attributeValue ) { var i, value, elements = this.editorDoc.getElementsByTagName( tagName ); for ( i = 0; i < elements.length; i += 1 ) { value = elements[i].getAttribute( attributeName ); if ( $.browser.msie ) { /** IE add full path, so I check by the last chars. */ value = value.substr( value.length - attributeValue.length ); } if ( value === attributeValue ) { return elements[i]; } } return false; }; this.getInternalRange = function () { var selection = this.getInternalSelection(); if ( !selection ) { return null; } if ( selection.rangeCount && selection.rangeCount > 0 ) { // w3c return selection.getRangeAt( 0 ); } else if ( selection.createRange ) { // ie return selection.createRange(); } return null; }; this.getInternalSelection = function () { // firefox: document.getSelection is deprecated if ( this.editor.get( 0 ).contentWindow ) { if ( this.editor.get( 0 ).contentWindow.getSelection ) { return this.editor.get( 0 ).contentWindow.getSelection(); } if ( this.editor.get( 0 ).contentWindow.selection ) { return this.editor.get( 0 ).contentWindow.selection; } } if ( this.editorDoc.getSelection ) { return this.editorDoc.getSelection(); } if ( this.editorDoc.selection ) { return this.editorDoc.selection; } return null; }; this.getRange = function () { var selection = this.getSelection(); if ( !selection ) { return null; } if ( selection.rangeCount && selection.rangeCount > 0 ) { // w3c selection.getRangeAt( 0 ); } else if ( selection.createRange ) { // ie return selection.createRange(); } return null; }; this.getSelection = function () { return (window.getSelection) ? window.getSelection() : window.document.selection; }; // :TODO: you can type long string and letters will be hidden because of overflow this.ui.grow = function () { var self = this.self, innerBody = $( self.editorDoc.body ), innerHeight = $.browser.msie ? innerBody[0].scrollHeight : innerBody.height() + 2 + 20, // 2 - borders, 20 - to prevent content jumping on grow minHeight = self.ui.initialHeight, height = Math.max( innerHeight, minHeight ); height = Math.min( height, self.options.maxHeight ); self.editor.attr( "scrolling", height < self.options.maxHeight ? "no" : "auto" ); // hide scrollbar firefox innerBody.css( "overflow", height < self.options.maxHeight ? "hidden" : "" ); // hide scrollbar chrome self.editor.get( 0 ).height = height; return self; }; this.init = function ( element, options ) { var self = this, $form = $( element ).closest( "form" ), newX = (element.width || element.clientWidth || 0), newY = (element.height || element.clientHeight || 0); this.options = this.extendOptions( options ); this.original = element; this.ui.toolbar = $( this.options.toolbarHtml ); if ( $.browser.msie && parseInt( $.browser.version, 10 ) < 8 ) { this.options.autoGrow = false; } if ( newX === 0 && element.cols ) { newX = (element.cols * 8) + 21; } if ( newY === 0 && element.rows ) { newY = (element.rows * 16) + 16; } this.editor = $( window.location.protocol === "https:" ? '' : "" ).attr( "frameborder", "0" ); if ( this.options.iFrameClass ) { this.editor.addClass( this.options.iFrameClass ); } else { this.editor.css( { minHeight: (newY - 6).toString() + "px", // fix for issue 12 ( http://github.com/akzhan/jwysiwyg/issues/issue/12 ) width: (newX > 50) ? (newX - 8).toString() + "px" : "" } ); if ( $.browser.msie && parseInt( $.browser.version, 10 ) < 7 ) { this.editor.css( "height", newY.toString() + "px" ); } } /** * Automagically add id to iframe if textarea has its own when possible * ( http://github.com/akzhan/jwysiwyg/issues/245 ) */ if ( element.id ) { var proposedId = element.id + '-wysiwyg-iframe'; if ( !document.getElementById( proposedId ) ) { this.editor.attr( 'id', proposedId ); } } /** * http://code.google.com/p/jwysiwyg/issues/detail?id=96 */ this.editor.attr( "tabindex", $( element ).attr( "tabindex" ) ); this.element = $( "
    " ).addClass( "wysiwyg" ); if ( !this.options.iFrameClass ) { this.element.css( { width: (newX > 0) ? newX.toString() + "px" : "100%" } ); } $( element ).hide().before( this.element ); this.viewHTML = false; /** * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52 */ this.initialContent = $( element ).val(); this.ui.initFrame(); if ( this.options.resizeOptions && $.fn.resizable ) { this.element.resizable( $.extend( true, { alsoResize: this.editor }, this.options.resizeOptions ) ); } if ( this.options.autoSave ) { $form.bind( "submit.wysiwyg", function () { self.autoSaveFunction(); } ); } $form.bind( "reset.wysiwyg", function () { self.resetFunction(); } ); }; this.ui.initFrame = function () { var self = this.self, stylesheet, growHandler, saveHandler; self.ui.appendControls(); self.element.append( self.ui.toolbar ).append( $( "
    " ).css( { clear: "both" } ) ).append( self.editor ); self.editorDoc = self.innerDocument(); if ( self.isDestroyed ) { return null; } self.ui.designMode(); self.editorDoc.open(); self.editorDoc.write( self.options.html/** * @link http://code.google.com/p/jwysiwyg/issues/detail?id=144 */.replace( /INITIAL_CONTENT/, function () { return self.wrapInitialContent(); } ) ); self.editorDoc.close(); $.wysiwyg.plugin.bind( self ); $( self.editorDoc ).trigger( "initFrame.wysiwyg" ); $( self.editorDoc ).bind( "click.wysiwyg", function ( event ) { self.ui.checkTargets( event.target ? event.target : event.srcElement ); } ); /** * @link https://github.com/akzhan/jwysiwyg/issues/251 */ setInterval( function () { var offset = null; try { var range = self.getInternalRange(); if ( range ) { offset = { range: range, parent: $.browser.msie ? range.parentElement() : range.endContainer.parentNode, width: ($.browser.msie ? range.boundingWidth : range.startOffset - range.endOffset) || 0 }; } } catch ( e ) { console.error( e ); } if ( offset && offset.width == 0 && !self.editorDoc.rememberCommand ) { self.ui.checkTargets( offset.parent ); } }, 400 ); /** * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20 */ $( self.original ).focus( function () { if ( $( this ).filter( ":visible" ).length === 0 ) { return; } self.ui.focus(); } ); $( self.editorDoc ).keydown( function ( event ) { var emptyContentRegex; if ( event.keyCode === 8 ) { // backspace emptyContentRegex = /^<([\w]+)[^>]*>()?<\/\1>$/; if ( emptyContentRegex.test( self.getContent() ) ) { // if content is empty event.stopPropagation(); // prevent remove single empty tag return false; } } self.editorDoc.rememberCommand = false; return true; } ); if ( !$.browser.msie ) { $( self.editorDoc ).keydown( function ( event ) { var controlName; /* Meta for Macs. [email protected] */ if ( event.ctrlKey || event.metaKey ) { for ( controlName in self.controls ) { if ( self.controls[controlName].hotkey && self.controls[controlName].hotkey.ctrl ) { if ( event.keyCode === self.controls[controlName].hotkey.key ) { self.triggerControl.apply( self, [controlName, self.controls[controlName]] ); return false; } } } } return true; } ); } else if ( self.options.brIE ) { $( self.editorDoc ).keydown( function ( event ) { if ( event.keyCode === 13 ) { var rng = self.getRange(); rng.pasteHTML( "
    " ); rng.collapse( false ); rng.select(); return false; } return true; } ); } if ( self.options.plugins.rmFormat.rmMsWordMarkup ) { $( self.editorDoc ).bind( "keyup.wysiwyg", function ( event ) { if ( event.ctrlKey || event.metaKey ) { // CTRL + V (paste) if ( 86 === event.keyCode ) { if ( $.wysiwyg.rmFormat ) { if ( "object" === typeof (self.options.plugins.rmFormat.rmMsWordMarkup) ) { $.wysiwyg.rmFormat.run( self, {rules: { msWordMarkup: self.options.plugins.rmFormat.rmMsWordMarkup }} ); } else { $.wysiwyg.rmFormat.run( self, {rules: { msWordMarkup: { enabled: true }}} ); } } } } } ); } if ( self.options.autoSave ) { $( self.editorDoc ).keydown(function () { self.autoSaveFunction(); } ).keyup(function () { self.autoSaveFunction(); } ).mousedown(function () { self.autoSaveFunction(); } ).bind( $.support.noCloneEvent ? "input.wysiwyg" : "paste.wysiwyg", function () { self.autoSaveFunction(); } ); } if ( self.options.autoGrow ) { if ( self.options.initialMinHeight !== null ) { self.ui.initialHeight = self.options.initialMinHeight; } else { self.ui.initialHeight = $( self.editorDoc ).height(); } $( self.editorDoc.body ).css( "border", "1px solid white" ); // cancel margin collapsing growHandler = function () { self.ui.grow(); }; $( self.editorDoc ).keyup( growHandler ); $( self.editorDoc ).bind( "editorRefresh.wysiwyg", growHandler ); // fix when content height > textarea height self.ui.grow(); } if ( self.options.css ) { if ( String === self.options.css.constructor ) { if ( $.browser.msie ) { stylesheet = self.editorDoc.createStyleSheet( self.options.css ); $( stylesheet ).attr( { "media": "all" } ); } else { stylesheet = $( "" ).attr( { "href": self.options.css, "media": "all", "rel": "stylesheet", "type": "text/css" } ); $( self.editorDoc ).find( "head" ).append( stylesheet ); } } else { self.timers.initFrame_Css = window.setTimeout( function () { $( self.editorDoc.body ).css( self.options.css ); }, 0 ); } } if ( self.initialContent.length === 0 ) { if ( "function" === typeof (self.options.initialContent) ) { self.setContent( self.options.initialContent() ); } else { self.setContent( self.options.initialContent ); } } if ( self.options.maxLength > 0 ) { $( self.editorDoc ).keydown( function ( event ) { if ( $( self.editorDoc ).text().length >= self.options.maxLength && $.inArray( event.which, self.validKeyCodes ) === -1 ) { event.preventDefault(); } } ); } // Support event callbacks $.each( self.options.events, function ( key, handler ) { $( self.editorDoc ).bind( key + ".wysiwyg", function ( event ) { // Trigger event handler, providing the event and api to // support additional functionality. handler.apply( self.editorDoc, [event, self] ); } ); } ); // restores selection properly on focus if ( $.browser.msie ) { // Event chain: beforedeactivate => focusout => blur. // Focusout & blur fired too late to handle internalRange() in dialogs. // When clicked on input boxes both got range = null $( self.editorDoc ).bind( "beforedeactivate.wysiwyg", function () { self.savedRange = self.getInternalRange(); } ); } else { $( self.editorDoc ).bind( "blur.wysiwyg", function () { self.savedRange = self.getInternalRange(); } ); } $( self.editorDoc.body ).addClass( "wysiwyg" ); if ( self.options.events && self.options.events.save ) { saveHandler = self.options.events.save; $( self.editorDoc ).bind( "keyup.wysiwyg", saveHandler ); $( self.editorDoc ).bind( "change.wysiwyg", saveHandler ); if ( $.support.noCloneEvent ) { $( self.editorDoc ).bind( "input.wysiwyg", saveHandler ); } else { $( self.editorDoc ).bind( "paste.wysiwyg", saveHandler ); $( self.editorDoc ).bind( "cut.wysiwyg", saveHandler ); } } /** * XHTML5 {@link https://github.com/akzhan/jwysiwyg/issues/152} */ if ( self.options.xhtml5 && self.options.unicode ) { var replacements = {ne: 8800, le: 8804, para: 182, xi: 958, darr: 8595, nu: 957, oacute: 243, Uacute: 218, omega: 969, prime: 8242, pound: 163, igrave: 236, thorn: 254, forall: 8704, emsp: 8195, lowast: 8727, brvbar: 166, alefsym: 8501, nbsp: 160, delta: 948, clubs: 9827, lArr: 8656, Omega: 937, Auml: 196, cedil: 184, and: 8743, plusmn: 177, ge: 8805, raquo: 187, uml: 168, equiv: 8801, laquo: 171, rdquo: 8221, Epsilon: 917, divide: 247, fnof: 402, chi: 967, Dagger: 8225, iacute: 237, rceil: 8969, sigma: 963, Oslash: 216, acute: 180, frac34: 190, lrm: 8206, upsih: 978, Scaron: 352, part: 8706, exist: 8707, nabla: 8711, image: 8465, prop: 8733, zwj: 8205, omicron: 959, aacute: 225, Yuml: 376, Yacute: 221, weierp: 8472, rsquo: 8217, otimes: 8855, kappa: 954, thetasym: 977, harr: 8596, Ouml: 214, Iota: 921, ograve: 242, sdot: 8901, copy: 169, oplus: 8853, acirc: 226, sup: 8835, zeta: 950, Iacute: 205, Oacute: 211, crarr: 8629, Nu: 925, bdquo: 8222, lsquo: 8216, apos: 39, Beta: 914, eacute: 233, egrave: 232, lceil: 8968, Kappa: 922, piv: 982, Ccedil: 199, ldquo: 8220, Xi: 926, cent: 162, uarr: 8593, hellip: 8230, Aacute: 193, ensp: 8194, sect: 167, Ugrave: 217, aelig: 230, ordf: 170, curren: 164, sbquo: 8218, macr: 175, Phi: 934, Eta: 919, rho: 961, Omicron: 927, sup2: 178, euro: 8364, aring: 229, Theta: 920, mdash: 8212, uuml: 252, otilde: 245, eta: 951, uacute: 250, rArr: 8658, nsub: 8836, agrave: 224, notin: 8713, ndash: 8211, Psi: 936, Ocirc: 212, sube: 8838, szlig: 223, micro: 181, not: 172, sup1: 185, middot: 183, iota: 953, ecirc: 234, lsaquo: 8249, thinsp: 8201, sum: 8721, ntilde: 241, scaron: 353, cap: 8745, atilde: 227, lang: 10216, __replacement: 65533, isin: 8712, gamma: 947, Euml: 203, ang: 8736, upsilon: 965, Ntilde: 209, hearts: 9829, Alpha: 913, Tau: 932, spades: 9824, dagger: 8224, THORN: 222, "int": 8747, lambda: 955, Eacute: 201, Uuml: 220, infin: 8734, rlm: 8207, Aring: 197, ugrave: 249, Egrave: 200, Acirc: 194, rsaquo: 8250, ETH: 208, oslash: 248, alpha: 945, Ograve: 210, Prime: 8243, mu: 956, ni: 8715, real: 8476, bull: 8226, beta: 946, icirc: 238, eth: 240, prod: 8719, larr: 8592, ordm: 186, perp: 8869, Gamma: 915, reg: 174, ucirc: 251, Pi: 928, psi: 968, tilde: 732, asymp: 8776, zwnj: 8204, Agrave: 192, deg: 176, AElig: 198, times: 215, Delta: 916, sim: 8764, Otilde: 213, Mu: 924, uArr: 8657, circ: 710, theta: 952, Rho: 929, sup3: 179, diams: 9830, tau: 964, Chi: 935, frac14: 188, oelig: 339, shy: 173, or: 8744, dArr: 8659, phi: 966, iuml: 239, Lambda: 923, rfloor: 8971, iexcl: 161, cong: 8773, ccedil: 231, Icirc: 206, frac12: 189, loz: 9674, rarr: 8594, cup: 8746, radic: 8730, frasl: 8260, euml: 235, OElig: 338, hArr: 8660, Atilde: 195, Upsilon: 933, there4: 8756, ouml: 246, oline: 8254, Ecirc: 202, yacute: 253, auml: 228, permil: 8240, sigmaf: 962, iquest: 191, empty: 8709, pi: 960, Ucirc: 219, supe: 8839, Igrave: 204, yen: 165, rang: 10217, trade: 8482, lfloor: 8970, minus: 8722, Zeta: 918, sub: 8834, epsilon: 949, yuml: 255, Sigma: 931, Iuml: 207, ocirc: 244}; self.events.bind( "getContent", function ( text ) { return text.replace( /&(?:amp;)?(?!amp|lt|gt|quot)([a-z][a-z0-9]*);/gi, function ( str, p1 ) { if ( !replacements[p1] ) { p1 = p1.toLowerCase(); if ( !replacements[p1] ) { p1 = "__replacement"; } } var num = replacements[p1]; /* Numeric return if ever wanted: return replacements[p1] ? "&#"+num+";" : ""; */ return String.fromCharCode( num ); } ); } ); } $( self.original ).trigger( 'ready.jwysiwyg', [self.editorDoc, self] ); }; this.innerDocument = function () { var element = this.editor.get( 0 ); if ( element.nodeName.toLowerCase() === "iframe" ) { if ( element.contentDocument ) { // Gecko return element.contentDocument; } else if ( element.contentWindow ) { // IE return element.contentWindow.document; } if ( this.isDestroyed ) { return null; } console.error( "Unexpected error in innerDocument" ); /* return ( $.browser.msie ) ? document.frames[element.id].document : element.contentWindow.document // contentDocument; */ } return element; }; this.insertHtml = function ( szHTML ) { var img, range; if ( !szHTML || szHTML.length === 0 ) { return this; } if ( $.browser.msie ) { this.ui.focus(); this.editorDoc.execCommand( "insertImage", false, "#jwysiwyg#" ); img = this.getElementByAttributeValue( "img", "src", "#jwysiwyg#" ); if ( img ) { $( img ).replaceWith( szHTML ); } } else { if ( $.browser.mozilla ) { // @link https://github.com/akzhan/jwysiwyg/issues/50 if ( 1 === $( szHTML ).length ) { range = this.getInternalRange(); range.deleteContents(); range.insertNode( $( szHTML ).get( 0 ) ); } else { this.editorDoc.execCommand( "insertHTML", false, szHTML ); } } else { if ( !this.editorDoc.execCommand( "insertHTML", false, szHTML ) ) { this.editor.focus(); /* :TODO: place caret at the end if (window.getSelection) { } else { } this.editor.focus(); */ this.editorDoc.execCommand( "insertHTML", false, szHTML ); } } } this.saveContent(); return this; }; //check allowed properties this.parseControls = function () { var self = this; $.each( this.options.controls, function ( controlName, control ) { $.each( control, function ( propertyName ) { if ( -1 === $.inArray( propertyName, self.availableControlProperties ) ) { throw controlName + '["' + propertyName + '"]: property "' + propertyName + '" not exists in Wysiwyg.availableControlProperties'; } } ); } ); if ( this.options.parseControls ) { //user callback return this.options.parseControls.call( this ); } return this.options.controls; }; this.removeFormat = function () { if ( $.browser.msie ) { this.ui.focus(); } if ( this.options.removeHeadings ) { this.editorDoc.execCommand( "formatBlock", false, "

    " ); // remove headings } this.editorDoc.execCommand( "removeFormat", false, null ); this.editorDoc.execCommand( "unlink", false, null ); if ( $.wysiwyg.rmFormat && $.wysiwyg.rmFormat.enabled ) { if ( "object" === typeof (this.options.plugins.rmFormat.rmMsWordMarkup) ) { $.wysiwyg.rmFormat.run( this, {rules: { msWordMarkup: this.options.plugins.rmFormat.rmMsWordMarkup }} ); } else { $.wysiwyg.rmFormat.run( this, {rules: { msWordMarkup: { enabled: true }}} ); } } return this; }; this.ui.removeHoverClass = function () { $( this ).removeClass( "wysiwyg-button-hover" ); }; this.resetFunction = function () { this.setContent( this.initialContent ); }; this.saveContent = function () { if ( this.viewHTML ) { return; // no need } if ( this.original ) { var content, newContent; content = this.getContent(); if ( this.options.rmUnwantedBr ) { content = content.replace( /$/, "" ); } if ( this.options.replaceDivWithP ) { newContent = $( "

    " ).addClass( "temp" ).append( content ); newContent.children( "div" ).each( function () { var element = $( this ), p = element.find( "p" ), i; if ( 0 === p.length ) { p = $( "

    " ); if ( this.attributes.length > 0 ) { for ( i = 0; i < this.attributes.length; i += 1 ) { p.attr( this.attributes[i].name, element.attr( this.attributes[i].name ) ); } } p.append( element.html() ); element.replaceWith( p ); } } ); content = newContent.html(); } $( this.original ).val( content ); if ( this.options.events && this.options.events.save ) { this.options.events.save.call( this ); } } return this; }; this.setContent = function ( newContent ) { this.editorDoc.body.innerHTML = newContent; this.saveContent(); return this; }; this.triggerControl = function ( name, control ) { var cmd = control.command || name, //command directly for designMode=on iframe (this.editorDoc) args = control["arguments"] || []; if ( control.exec ) { control.exec.apply( this ); //custom exec function in control, allows DOM changing } else { this.ui.focus(); this.ui.withoutCss(); //disable style="" attr inserting in mozzila's designMode // when click , or got "Access to XPConnect service denied" code: "1011" // in Firefox untrusted JavaScript is not allowed to access the clipboard try { this.editorDoc.execCommand( cmd, false, args ); } catch ( e ) { console.error( e ); } } if ( this.options.autoSave ) { this.autoSaveFunction(); } }; this.triggerControlCallback = function ( name ) { $( window ).trigger( "trigger-" + name + ".wysiwyg", [this] ); }; this.ui.withoutCss = function () { var self = this.self; if ( $.browser.mozilla ) { try { self.editorDoc.execCommand( "styleWithCSS", false, false ); } catch ( e ) { try { self.editorDoc.execCommand( "useCSS", false, true ); } catch ( e2 ) { } } } return self; }; this.wrapInitialContent = function () { var content = this.initialContent, found = content.match( /<\/?p>/gi ); if ( !found ) { return "

    " + content + "

    "; } else { // :TODO: checking/replacing } return content; }; } /* * Wysiwyg namespace: public properties and methods */ $.wysiwyg = { messages: { noObject: "Something goes wrong, check object" }, /** * Custom control support by Alec Gorge ( http://github.com/alecgorge ) */ addControl: function ( object, name, settings ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ), customControl = {}, toolbar; if ( !oWysiwyg ) { return this; } customControl[name] = $.extend( true, {visible: true, custom: true}, settings ); $.extend( true, oWysiwyg.options.controls, customControl ); // render new toolbar toolbar = $( oWysiwyg.options.toolbarHtml ); oWysiwyg.ui.toolbar.replaceWith( toolbar ); oWysiwyg.ui.toolbar = toolbar; oWysiwyg.ui.appendControls(); } ); }, clear: function ( object ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } oWysiwyg.setContent( "" ); } ); }, console: console, // let our console be available for extensions destroy: function ( object ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } oWysiwyg.destroy(); } ); }, "document": function ( object ) { // no chains because of return var oWysiwyg = object.data( "wysiwyg" ); if ( !oWysiwyg ) { return undefined; } return $( oWysiwyg.editorDoc ); }, getContent: function ( object ) { // no chains because of return var oWysiwyg = object.data( "wysiwyg" ); if ( !oWysiwyg ) { return undefined; } return oWysiwyg.getContent(); }, init: function ( object, options ) { return object.each( function () { var opts = $.extend( true, {}, options ), obj; // :4fun: // remove this textarea validation and change line in this.saveContent function // $(this.original).val(content); to $(this.original).html(content); // now you can make WYSIWYG editor on h1, p, and many more tags if ( ("textarea" !== this.nodeName.toLowerCase()) || $( this ).data( "wysiwyg" ) ) { return; } obj = new Wysiwyg(); obj.init( this, opts ); $.data( this, "wysiwyg", obj ); $( obj.editorDoc ).trigger( "afterInit.wysiwyg" ); } ); }, insertHtml: function ( object, szHTML ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } oWysiwyg.insertHtml( szHTML ); } ); }, plugin: { listeners: {}, bind: function ( Wysiwyg ) { var self = this; $.each( this.listeners, function ( action, handlers ) { var i, plugin; for ( i = 0; i < handlers.length; i += 1 ) { plugin = self.parseName( handlers[i] ); $( Wysiwyg.editorDoc ).bind( action + ".wysiwyg", {plugin: plugin}, function ( event ) { $.wysiwyg[event.data.plugin.name][event.data.plugin.method].apply( $.wysiwyg[event.data.plugin.name], [Wysiwyg] ); } ); } } ); }, exists: function ( name ) { var plugin; if ( "string" !== typeof (name) ) { return false; } plugin = this.parseName( name ); if ( !$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method] ) { return false; } return true; }, listen: function ( action, handler ) { var plugin; plugin = this.parseName( handler ); if ( !$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method] ) { return false; } if ( !this.listeners[action] ) { this.listeners[action] = []; } this.listeners[action].push( handler ); return true; }, parseName: function ( name ) { var elements; if ( "string" !== typeof (name) ) { return false; } elements = name.split( "." ); if ( 2 > elements.length ) { return false; } return {name: elements[0], method: elements[1]}; }, register: function ( data ) { if ( !data.name ) { console.error( "Plugin name missing" ); } $.each( $.wysiwyg, function ( pluginName ) { if ( pluginName === data.name ) { console.error( "Plugin with name '" + data.name + "' was already registered" ); } } ); $.wysiwyg[data.name] = data; return true; } }, removeFormat: function ( object ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } oWysiwyg.removeFormat(); } ); }, save: function ( object ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } oWysiwyg.saveContent(); } ); }, selectAll: function ( object ) { var oWysiwyg = object.data( "wysiwyg" ), oBody, oRange, selection; if ( !oWysiwyg ) { return this; } oBody = oWysiwyg.editorDoc.body; if ( window.getSelection ) { selection = oWysiwyg.getInternalSelection(); selection.selectAllChildren( oBody ); } else { oRange = oBody.createTextRange(); oRange.moveToElementText( oBody ); oRange.select(); } }, setContent: function ( object, newContent ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } oWysiwyg.setContent( newContent ); } ); }, triggerControl: function ( object, controlName ) { return object.each( function () { var oWysiwyg = $( this ).data( "wysiwyg" ); if ( !oWysiwyg ) { return this; } if ( !oWysiwyg.controls[controlName] ) { console.error( "Control '" + controlName + "' not exists" ); } oWysiwyg.triggerControl.apply( oWysiwyg, [controlName, oWysiwyg.controls[controlName]] ); } ); }, support: { prop: supportsProp }, utils: { extraSafeEntities: [ ["<", ">", "'", '"', " "], [32] ], encodeEntities: function ( str ) { var self = this, aStr, aRet = []; if ( this.extraSafeEntities[1].length === 0 ) { $.each( this.extraSafeEntities[0], function ( i, ch ) { self.extraSafeEntities[1].push( ch.charCodeAt( 0 ) ); } ); } aStr = str.split( "" ); $.each( aStr, function ( i ) { var iC = aStr[i].charCodeAt( 0 ); if ( $.inArray( iC, self.extraSafeEntities[1] ) && (iC < 65 || iC > 127 || (iC > 90 && iC < 97)) ) { aRet.push( '&#' + iC + ';' ); } else { aRet.push( aStr[i] ); } } ); return aRet.join( '' ); } } }; /** * Unifies dialog methods to allow custom implementations * * Events: * * afterOpen * * beforeShow * * afterShow * * beforeHide * * afterHide * * beforeClose * * afterClose * * Example: * var dialog = new ($.wysiwyg.dialog)($('#idToTextArea').data('wysiwyg'), {"title": "Test", "content": "form data, etc."}); * * dialog.bind("afterOpen", function () { alert('you should see a dialog behind this one!'); }); * * dialog.open(); * * */ $.wysiwyg.dialog = function ( jWysiwyg, opts ) { var theme = (jWysiwyg && jWysiwyg.options && jWysiwyg.options.dialog) ? jWysiwyg.options.dialog : (opts.theme ? opts.theme : "default"), obj = new $.wysiwyg.dialog.createDialog( theme ), that = this, $that = $( that ); this.options = { "modal": true, "draggable": true, "title": "Title", "content": "Content", "width": "auto", "height": "auto", "zIndex": 2000, "open": false, "close": false }; this.isOpen = false; $.extend( this.options, opts ); this.object = obj; // Opens a dialog with the specified content this.open = function () { this.isOpen = true; obj.init.apply( that, [] ); var $dialog = obj.show.apply( that, [] ); $that.trigger( "afterOpen", [$dialog] ); }; this.show = function () { this.isOpen = true; $that.trigger( "beforeShow" ); var $dialog = obj.show.apply( that, [] ); $that.trigger( "afterShow" ); }; this.hide = function () { this.isOpen = false; $that.trigger( "beforeHide" ); var $dialog = obj.hide.apply( that, [] ); $that.trigger( "afterHide", [$dialog] ); }; // Closes the dialog window. this.close = function () { this.isOpen = false; var $dialog = obj.hide.apply( that, [] ); $that.trigger( "beforeClose", [$dialog] ); obj.destroy.apply( that, [] ); $that.trigger( "afterClose", [$dialog] ); }; if ( this.options.open ) { $that.bind( "afterOpen", this.options.open ); } if ( this.options.close ) { $that.bind( "afterClose", this.options.close ); } return this; }; // "Static" Dialog methods. $.extend( true, $.wysiwyg.dialog, { _themes: {}, // sample {"Theme Name": object} _theme: "", // the current theme register: function ( name, obj ) { $.wysiwyg.dialog._themes[name] = obj; }, deregister: function ( name ) { delete $.wysiwyg.dialog._themes[name]; }, createDialog: function ( name ) { return new ($.wysiwyg.dialog._themes[name]); }, getDimensions: function () { var width = document.body.scrollWidth, height = document.body.scrollHeight; if ( $.browser.opera ) { height = Math.max( $( document ).height(), $( window ).height(), document.documentElement.clientHeight ); } return [width, height]; } } ); $( function () { // need access to jQuery UI stuff. if ( jQuery.ui ) { $.wysiwyg.dialog.register( "jqueryui", function () { var that = this; this._$dialog = null; this.init = function () { var abstractDialog = this, content = this.options.content; if ( typeof content === 'object' ) { if ( typeof content.html === 'function' ) { content = content.html(); } else if ( typeof content.toString === 'function' ) { content = content.toString(); } } that._$dialog = $( '
    ' ).attr( 'title', this.options.title ).html( content ); var dialogHeight = this.options.height == 'auto' ? 300 : this.options.height, dialogWidth = this.options.width == 'auto' ? 450 : this.options.width; // console.log(that._$dialog); that._$dialog.dialog( { modal: this.options.modal, draggable: this.options.draggable, height: dialogHeight, width: dialogWidth } ); return that._$dialog; }; this.show = function () { that._$dialog.dialog( "open" ); return that._$dialog; }; this.hide = function () { that._$dialog.dialog( "close" ); return that._$dialog; }; this.destroy = function () { that._$dialog.dialog( "destroy" ); return that._$dialog; }; } ); } $.wysiwyg.dialog.register( "default", function () { var that = this; this._$dialog = null; this.init = function () { var abstractDialog = this, content = this.options.content; if ( typeof content === 'object' ) { if ( typeof content.html === 'function' ) { content = content.html(); } else if ( typeof content.toString === 'function' ) { content = content.toString(); } } that._$dialog = $( '
    ' ).css( {"z-index": this.options.zIndex} ); var $topbar = $( '
    ' + this.options.title + '
    ' ); var $link = $( 'X' ); $link.click( function () { abstractDialog.close(); // this is important it makes sure that is close from the abstract $.wysiwyg.dialog instace, not just locally } ); $topbar.find( '.wysiwyg-dialog-close-wrapper' ).prepend( $link ); var $dcontent = $( '
    ' + content + '
    ' ); that._$dialog.append( $topbar ).append( $dcontent ); // Set dialog's height & width, and position it correctly: var dialogHeight = this.options.height == 'auto' ? 300 : this.options.height, dialogWidth = this.options.width == 'auto' ? 450 : this.options.width; that._$dialog.hide().css( { "width": dialogWidth, "height": dialogHeight, "left": (($( window ).width() - dialogWidth) / 2), "top": (($( window ).height() - dialogHeight) / 3) } ); $( "body" ).append( that._$dialog ); return that._$dialog; }; this.show = function () { // Modal feature: if ( this.options.modal ) { var dimensions = $.wysiwyg.dialog.getDimensions(), wrapper = $( '
    ' ).css( {"width": dimensions[0], "height": dimensions[1]} ); that._$dialog.wrap( wrapper ); } // Draggable feature: if ( this.options.draggable ) { var mouseDown = false; that._$dialog.find( "div.wysiwyg-dialog-topbar" ).bind( "mousedown", function ( e ) { e.preventDefault(); $( this ).css( { "cursor": "move" } ); var $topbar = $( this ), _dialog = $( this ).parents( ".wysiwyg-dialog" ), offsetX = (e.pageX - parseInt( _dialog.css( "left" ), 10 )), offsetY = (e.pageY - parseInt( _dialog.css( "top" ), 10 )); mouseDown = true; $( this ).css( { "cursor": "move" } ); $( document ).bind( "mousemove",function ( e ) { e.preventDefault(); if ( mouseDown ) { _dialog.css( { "top": (e.pageY - offsetY), "left": (e.pageX - offsetX) } ); } } ).bind( "mouseup", function ( e ) { e.preventDefault(); mouseDown = false; $topbar.css( { "cursor": "auto" } ); $( document ).unbind( "mousemove" ).unbind( "mouseup" ); } ); } ); } that._$dialog.show(); return that._$dialog; }; this.hide = function () { that._$dialog.hide(); return that._$dialog; }; this.destroy = function () { // Modal feature: if ( this.options.modal ) { that._$dialog.unwrap(); } // Draggable feature: if ( this.options.draggable ) { that._$dialog.find( "div.wysiwyg-dialog-topbar" ).unbind( "mousedown" ); } that._$dialog.remove(); return that._$dialog; }; } ); } ); // end Dialog $.fn.wysiwyg = function ( method ) { var args = arguments, plugin; if ( "undefined" !== typeof $.wysiwyg[method] ) { // set argument object to undefined args = Array.prototype.concat.call( [args[0]], [this], Array.prototype.slice.call( args, 1 ) ); return $.wysiwyg[method].apply( $.wysiwyg, Array.prototype.slice.call( args, 1 ) ); } else if ( "object" === typeof method || !method ) { Array.prototype.unshift.call( args, this ); return $.wysiwyg.init.apply( $.wysiwyg, args ); } else if ( $.wysiwyg.plugin.exists( method ) ) { plugin = $.wysiwyg.plugin.parseName( method ); args = Array.prototype.concat.call( [args[0]], [this], Array.prototype.slice.call( args, 1 ) ); return $.wysiwyg[plugin.name][plugin.method].apply( $.wysiwyg[plugin.name], Array.prototype.slice.call( args, 1 ) ); } else { console.error( "Method '" + method + "' does not exist on jQuery.wysiwyg.\nTry to include some extra controls or plugins" ); } }; $.fn.getWysiwyg = function () { return this.data( "wysiwyg" ); }; })( jQuery );





    © 2015 - 2024 Weber Informatics LLC | Privacy Policy