/* * WYMeditor : what you see is What You Mean web-based editor * Copyright (c) 2005 - 2009 Jean-Francois Hovinne, http://www.wymeditor.org/ * Dual licensed under the MIT (MIT-license.txt) * and GPL (GPL-license.txt) licenses. * * For further information visit: * http://www.wymeditor.org/ * * File Name: * jquery.wymeditor.mozilla.js * Gecko specific class and functions. * See the documentation for more info. * * File Authors: * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg) * Volker Mische (vmx a-t gmx dotde) * Bermi Ferrer (wymeditor a-t bermi dotorg) * Frédéric Palluel-Lafleur (fpalluel a-t gmail dotcom) */ WYMeditor.WymClassMozilla = function(wym) { this._wym = wym; this._class = "class"; this._newLine = "\n"; }; WYMeditor.WymClassMozilla.prototype.initIframe = function(iframe) { var wym = this; this._iframe = iframe; this._doc = iframe.contentDocument; //add css rules from options var styles = this._doc.styleSheets[0]; var aCss = eval(this._options.editorStyles); this.addCssRules(this._doc, aCss); this._doc.title = this._wym._index; //set the text direction $('html', this._doc).attr('dir', this._options.direction); //add error class to body if the containing iframe has an error class $('.fieldWithErrors iframe').contents().find('body').addClass('fieldWithErrors'); //init html value this.html(this._wym._html); //init designMode this.enableDesignMode(); //pre-bind functions if($.isFunction(this._options.preBind)) this._options.preBind(this); //bind external events this._wym.bindEvents(); //bind editor keydown events $(this._doc).bind("keydown", this.keydown); //bind editor keyup events $(this._doc).bind("keyup", this.keyup); //bind editor paste events $(this._doc).bind("paste", this.intercept_paste); //bind editor focus events (used to reset designmode - Gecko bug) $(this._doc).bind("focus", function (){ // Fix scope wym.enableDesignMode.call(wym); }); //post-init functions if($.isFunction(this._options.postInit)) this._options.postInit(this); //add event listeners to doc elements, e.g. images this.listen(); }; /* @name html * @description Get/Set the html value */ WYMeditor.WymClassMozilla.prototype.html = function(html) { if(typeof html === 'string') { //disable designMode try { this._doc.designMode = "off"; } catch(e) { }; //replace em by i and strong by bold //(designMode issue) html = html.replace(/]*)>/gi, "") .replace(/<\/em>/gi, "") .replace(/]*)>/gi, "") .replace(/<\/strong>/gi, ""); //update the html body $(this._doc.body).html(html); //re-init designMode this.enableDesignMode(); } else { return($(this._doc.body).html()); } }; WYMeditor.WymClassMozilla.prototype._exec = function(cmd,param) { if(!this.selected()) return(false); switch(cmd) { case WYMeditor.INDENT: case WYMeditor.OUTDENT: var focusNode = this.selected(); var sel = this._iframe.contentWindow.getSelection(); var anchorNode = sel.anchorNode; if(anchorNode.nodeName == "#text") { anchorNode = anchorNode.parentNode; } focusNode = this.findUp(focusNode, WYMeditor.BLOCKS); anchorNode = this.findUp(anchorNode, WYMeditor.BLOCKS); if(focusNode && focusNode == anchorNode && focusNode.tagName.toLowerCase() == WYMeditor.LI) { var ancestor = focusNode.parentNode.parentNode; if(focusNode.parentNode.childNodes.length > 1 || $.inArray(ancestor.tagName.toLowerCase(), [WYMeditor.OL, WYMeditor.UL]) > -1) { this._doc.execCommand(cmd,'',null); } } break; default: if(param) this._doc.execCommand(cmd,'',param); else this._doc.execCommand(cmd,'',null); } //set to P if parent = BODY var container = this.selected(); if(container.tagName.toLowerCase() == WYMeditor.BODY) { this._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); } }; /* @name selected * @description Returns the selected container */ WYMeditor.WymClassMozilla.prototype.selected = function(upgrade_text_nodes) { if (upgrade_text_nodes == null || upgrade_text_nodes.toString() != "true") { upgrade_text_nodes = false; } var sel = this._iframe.contentWindow.getSelection(); var node = sel.focusNode; if(node) { if(node.nodeName == "#text"){ if (upgrade_text_nodes && sel.toString().length > 0) { actual_node = null; parent_node = sel.focusNode.parentNode; if (parent_node != null) { for (i=0;i STRONG wym._exec(WYMeditor.BOLD); return false; } if(e.keyCode == 73){ //CTRL+i => EMPHASIS wym._exec(WYMeditor.ITALIC); return false; } } else if(e.keyCode == 13) { if(!e.shiftKey){ //fix PRE bug #73 container = wym.selected(); if(container && container.tagName.toLowerCase() == WYMeditor.PRE) { e.preventDefault(); wym.insert('

'); } } } }; //keyup handler, mainly used for cleanups WYMeditor.WymClassMozilla.prototype.keyup = function(e) { //'this' is the doc if ((wym = WYMeditor.INSTANCES[this.title]) != null) { wym._selected_image = null; $(wym._iframe).contents().find('.selected_by_wym').removeClass('selected_by_wym'); var container = null; if(e.keyCode == 13 && !e.shiftKey) { //RETURN key - cleanup

between paragraphs $(wym._doc.body).children(WYMeditor.BR).remove(); //fix PRE bug #73 if((container = wym.selected()) && container.tagName.toLowerCase() == WYMeditor.PRE) { wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); //create P after PRE } } else if(($.inArray(e.keyCode, [8, 17, 46, 224]) == -1) && !e.metaKey && !e.ctrlKey) { //NOT BACKSPACE, NOT DELETE, NOT CTRL, NOT COMMAND //text nodes replaced by P wym.format_block(); } } }; WYMeditor.WymClassMozilla.prototype.enableDesignMode = function() { if(this._doc.designMode == "off") { try { this._doc.designMode = "on"; this._doc.execCommand("styleWithCSS", '', false); } catch(e) { } } }; WYMeditor.WymClassMozilla.prototype.openBlockTag = function(tag, attributes) { var attributes = this.validator.getValidTagAttributes(tag, attributes); // Handle Mozilla styled spans if (tag === 'span' && attributes.style) { var new_tag = this.getTagForStyle(attributes.style); if (new_tag) { tag = new_tag; this._tag_stack.pop(); this._tag_stack.push(tag); attributes.style = ''; } } this.output += this.helper.tag(tag, attributes, true); }; WYMeditor.WymClassMozilla.prototype.getTagForStyle = function(style) { if(/bold/.test(style)) return 'strong'; if(/italic/.test(style)) return 'em'; if(/sub/.test(style)) return 'sub'; if(/super/.test(style)) return 'super'; return false; };