/* * 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.safari.js * Safari specific class and functions. * See the documentation for more info. * * File Authors: * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg) * Scott Lewis (lewiscot a-t gmail dotcom) */ WYMeditor.WymClassSafari = function(wym) { this._wym = wym; this._class = "class"; this._newLine = "\n"; }; WYMeditor.WymClassSafari.prototype.initIframe = function(iframe) { 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 jQuery('html', this._doc).attr('dir', this._options.direction); //init designMode this._doc.designMode = "on"; //init html value this.html(this._wym._html); //pre-bind functions if(jQuery.isFunction(this._options.preBind)) this._options.preBind(this); //bind external events this._wym.bindEvents(); //bind editor keydown events jQuery(this._doc).bind("keydown", this.keydown); //bind editor keyup events jQuery(this._doc).bind("keyup", this.keyup); //post-init functions if(jQuery.isFunction(this._options.postInit)) this._options.postInit(this); //add event listeners to doc elements, e.g. images this.listen(); }; WYMeditor.WymClassSafari.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 || ancestor.tagName.toLowerCase() == WYMeditor.OL || ancestor.tagName.toLowerCase() == WYMeditor.UL) this._doc.execCommand(cmd,'',null); } break; case WYMeditor.INSERT_ORDEREDLIST: case WYMeditor.INSERT_UNORDEREDLIST: this._doc.execCommand(cmd,'',null); //Safari creates lists in e.g. paragraphs. //Find the container, and remove it. var focusNode = this.selected(); var container = this.findUp(focusNode, WYMeditor.MAIN_CONTAINERS); if(container) jQuery(container).replaceWith(jQuery(container).html()); 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 && container.tagName.toLowerCase() == WYMeditor.BODY) this._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); }; /* @name selected * @description Returns the selected container */ WYMeditor.WymClassSafari.prototype.selected = function() { var sel = this._iframe.contentWindow.getSelection(); var node = sel.focusNode; if(node) { if(node.nodeName == "#text") return(node.parentNode); else return(node); } else return(null); }; WYMeditor.WymClassSafari.prototype.addCssRule = function(styles, oCss) { styles.insertRule(oCss.name + " {" + oCss.css + "}", styles.cssRules.length); }; //keydown handler, mainly used for keyboard shortcuts WYMeditor.WymClassSafari.prototype.keydown = function(e) { //'this' is the doc var wym = WYMeditor.INSTANCES[this.title]; if(e.ctrlKey){ if(e.keyCode == 66){ //CTRL+b => STRONG wym._exec(WYMeditor.BOLD); e.preventDefault(); } if(e.keyCode == 73){ //CTRL+i => EMPHASIS wym._exec(WYMeditor.ITALIC); e.preventDefault(); } } else if(e.shiftKey && e.keyCode == 13) { wym._exec('InsertLineBreak'); e.preventDefault(); } }; //keyup handler, mainly used for cleanups WYMeditor.WymClassSafari.prototype.keyup = function(evt) { //'this' is the doc var wym = WYMeditor.INSTANCES[this.title]; wym._selected_image = null; var container = null; if(evt.keyCode == 13 && !evt.shiftKey) { //RETURN key //cleanup

between paragraphs jQuery(wym._doc.body).children(WYMeditor.BR).remove(); //fix PRE bug #73 container = wym.selected(); if(container && container.tagName.toLowerCase() == WYMeditor.PRE) wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); //create P after PRE } if(evt.keyCode != 8 && evt.keyCode != 17 && evt.keyCode != 46 && evt.keyCode != 224 && !evt.metaKey && !evt.ctrlKey) { //NOT BACKSPACE, NOT DELETE, NOT CTRL, NOT COMMAND //text nodes replaced by P container = wym.selected(); var name = container.tagName.toLowerCase(); //fix forbidden main containers if( name == "strong" || name == "b" || name == "em" || name == "i" || name == "sub" || name == "sup" || name == "a" || name == "span" //fix #110 ) name = container.parentNode.tagName.toLowerCase(); if(name == WYMeditor.BODY || name == WYMeditor.DIV) wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); //fix #110 for DIV } }; WYMeditor.WymClassSafari.prototype.openBlockTag = function(tag, attributes) { var attributes = this.validator.getValidTagAttributes(tag, attributes); // Handle Safari 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 = ''; // Should fix #125 - also removed the xhtml() override if(typeof attributes['class'] == 'string') { attributes['class'] = attributes['class'].replace(/apple-style-span/gi, ''); } } } this.output += this.helper.tag(tag, attributes, true); }; WYMeditor.WymClassSafari.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 'sup'; return false; };