//============================= START OF CLASS ==============================// // CLASS: HtmlBox // //===========================================================================// /** * HtmlBox is a cross-browser widget that replaces the normal textboxes with * rich text area like in OpenOffice Text. It has Ajax support out of the box. * PS. It requires JQuery in order to function. * TODO: Smilies, Undo/Redo, CSS for Safari * * * Copyright@2007-2008 Remiya Solutions All rights reserved! * @author Remiya Solutions * @version 2.8 */ $.fn.htmlbox=function(){ // START: Settings if(undefined===window.glob_ha){glob_ha=[];} // Are more colors set? var colors = (typeof document.htmlbox_colors === 'function')?document.htmlbox_colors():['silver','silver','white','white','yellow','yellow','orange','orange','red','red','green','green','blue','blue','brown','brown','black','black']; var styles = (typeof document.htmlbox_styles === 'function')?document.htmlbox_styles():[['No Styles','','']]; var syntax = (typeof document.htmlbox_syntax === 'function')?document.htmlbox_syntax():[['No Syntax','','']]; var d={ buttons:[], // Buttons //dir:".", // HtmlBox Directory, This is needed for the all components and images to work idir:"/resources/scripts/htmlbox/images/",// HtmlBox Image Directory, This is needed for the images to work images:[], // Images output:"xhtml", // Output css:"body{margin:3px;font-family:verdana;font-size:11px;}p{margin:0px;}", rows:[], // Button rows success:function(data){alert(data);}, // AJAX on success error:function(a,b,c){return this;} // AJAX on error }; if(!$(this).attr("id")){$(this).attr("id","jqha_"+glob_ha.length);d.id="jqha_"+glob_ha.length;glob_ha[glob_ha]=glob_ha;}else{d.id=$(this).attr("id");} if(undefined === glob_ha[d.id]){glob_ha[d.id]=this;} // END: Settings // ------------- PRIVATE METHODS -----------------// //========================= START OF METHOD ===========================// // METHOD: get_selection // //=====================================================================// /** * Returns the selected (X)HTML code * @access private */ var get_selection = function(){ var range; if($.browser.msie){ range = d.iframe.contentWindow.document.selection.createRange(); if (range.htmlText && range.text){return range.htmlText;} }else{ if (d.iframe.contentWindow.getSelection) { var selection = d.iframe.contentWindow.getSelection(); if (selection.rangeCount>0&&window.XMLSerializer){ range=selection.getRangeAt(0); var html=new XMLSerializer().serializeToString(range.cloneContents()); return html; }if (selection.rangeCount > 0) { range = selection.getRangeAt(0); var clonedSelection = range.cloneContents(); var div = document.createElement('div'); div.appendChild(clonedSelection); return div.innerHTML; } } } }; //=====================================================================// // METHOD: get_selection // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: in_array // //=====================================================================// /** * Coppies the PHP in_array function. This is useful for Objects. * @access private */ var in_array=function(o,a){ for (var i in a){ if((i===o)){return true;} } return false; }; //=====================================================================// // METHOD: in_array // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: insert_text // //=====================================================================// /** * Inserts text at the cursor position or selection * @access private */ var insert_text = function(text,start,end){ if($.browser.msie){ if(typeof d.idoc.selection !== "undefined" && d.idoc.selection.type !== "Text" && d.idoc.selection.type !== "None"){start = false;d.idoc.selection.clear();} var sel = d.idoc.selection.createRange();sel.pasteHTML(text); if (text.indexOf("\n") === -1) { if (start === false) {} else { if (typeof start !== "undefined") { sel.moveStart("character", - text.length + start); sel.moveEnd("character", - end); } else { sel.moveStart("character", - text.length); } } sel.select(); } }else{ d.idoc.execCommand("insertHTML", false, text); } }; //=====================================================================// // METHOD: insert_text // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: keyup // //=====================================================================// /** * Keyup event. * @access private */ var keyup = function(e){ // Updating the textarea component, so whenever it is posted it will send all the data var html = $("#1"+d.id).is(":visible")?$("#"+d.id).val():html = d.iframe.contentWindow.document.body.innerHTML; html = (typeof getXHTML === 'function')?getXHTML(html):html; $("#"+d.id).val(html); if(undefined!==d.change){d.change();} }; //=====================================================================// // METHOD: keyup // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: keypress // //=====================================================================// /** * Keypress event. * @access private */ var keypress = function(e){ //var code = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode; //if (code == 13){} }; //=====================================================================// // METHOD: keypress // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: nobubble // //=====================================================================// /** * Stops event bubbling * ATTN: Not used now, but is to be used for code editting in the * Next versions * @access private */ /* var nobubble = function(e){ var evt=window.event? event : e; if($.browser.msie){ evt.returnValue = false;evt.cancelBubble = true;return evt; }else{ evt.stopPropagation();evt.preventDefault();return e; } }; */ //=====================================================================// // METHOD: nobubble // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: style // //=====================================================================// /** * Sets the CSS style to the HtmlBox iframe * @access private */ var style = function(){ // START: HtmlBox Style if( d.idoc.createStyleSheet) { d.idoc.createStyleSheet().cssText=d.css; }else { var css=d.idoc.createElement('link'); css.rel='stylesheet'; css.href='data:text/css,'+escape(d.css); if($.browser.opera){ d.idoc.documentElement.appendChild(css); }else{ d.idoc.getElementsByTagName("head")[0].appendChild(css); } } // END: HtmlBox Style }; //=====================================================================// // METHOD: style // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: wrap_tags // //=====================================================================// /** * Wraps tags around the cursor position or selection * @access private */ var wrap_tags = function(start,end){ var sel = get_selection(); //was broken, changed to test for empty string rather than null //and insert a break instead of nothing. if(sel===""){sel="
";} insert_text(start+sel+end,start.length,end.length); }; //=====================================================================// // METHOD: wrap_tags // //========================== END OF METHOD ============================// // ------------- PRIVATE METHODS -----------------// //========================= START OF METHOD ===========================// // METHOD: init // //=====================================================================// /** * Draws the HtmlBox on the screen * @return this */ this.init = function(is_init){ // START: Timeout to allow creation of DesignMode if(undefined===is_init){setTimeout("glob_ha['"+d.id+"'].init(true)",250);return false;} // END: Timeout to allow creation of DesignMode var w=$(this).css("width");var h=$(this).css("height"); $(this).wrap("
"); // START: Appending toolbar $(this).parent().parent().parent().parent().prepend(toolbar()); $("."+d.id+"_tb").css("background-image","url("+d.idir+"bg_silver.jpg)").css("height","30px"); $("."+d.id+"_tb").find("button").each(function(){ $(this).css("border","1px solid #E9EAEF").css("background","transparent").css("margin","1px 1px 1px 1px").css("padding","1px"); $(this).mouseover(function(){$(this).css("border","1px solid #BFCAFF").css("background","#EFF2FF");}); $(this).mouseout(function(){$(this).css("border","1px solid #E9EAEF").css("background","transparent");}); } ); $("."+d.id+"_tb").find("select").each(function(){ $(this).css("border","1px solid #E9EAEF").css("background","transparent").css("margin","2px 2px 3px 2px"); if($.browser.mozilla){$(this).css("padding","0").css("position","relative").css("top","-2px");} } ); // END: Appending toolbar try { var iframe=document.createElement("IFRAME");// var doc=null; $(iframe).css("width",w).css("height",h).attr("id",d.id+"_html").css("border","0"); $(this).parent().prepend(iframe); // START: Shortcuts for less code d.iframe = iframe; d.idoc = iframe.contentWindow.document; // END: Shortcuts d.idoc.designMode="on"; // START: Insert text // Is there text in the textbox? var text = ($(this).val()==="")?"":$(this).val(); if($.browser.mozilla||$.browser.safari){ //if(text===""){text=" ";} d.idoc.open('text/html', 'replace'); d.idoc.write(text); d.idoc.close(); }else{ if(text!==""){d.idoc.write(text);} } // Needed by browsers other than MSIE to become editable if($.browser.msie===false){iframe.contentWindow.document.body.contentEditable = true;} // END: Insert text // START: HtmlBox Style if(d.css.indexOf("background:")===-1){d.css+="body{background:#EFF4FF;}";} if(d.css.indexOf("background-image:")===-1){ d.css=d.css+"body{background-image:url("+d.idir+"/logod.gif);background-position:top right;background-repeat:no-repeat;}"; } if(d.idoc.createStyleSheet) { setTimeout("glob_ha['"+d.id+"'].set_text(glob_ha['"+d.id+"'].get_html())",10); }else { var css=d.idoc.createElement('link'); css.rel='stylesheet'; css.href='data:text/css,'+escape(d.css); if($.browser.opera){ d.idoc.documentElement.appendChild(css); }else if($.browser.safari){ // No solution. Looking for it }else{ d.idoc.getElementsByTagName("head")[0].appendChild(css); } } // END: HtmlBox Style // START: Adding events if(iframe.contentWindow.document.attachEvent){ iframe.contentWindow.document.attachEvent("onkeyup", keyup); iframe.contentWindow.document.attachEvent("onkeypress", keypress); }else{ iframe.contentWindow.document.addEventListener("keyup",keyup,false); iframe.contentWindow.document.addEventListener("keypress",keypress,false); } $(this).hide(); }catch(e){ alert("This rich text component is not supported by your browser.\n"+e); $(this).show(); } return this; }; //=====================================================================// // METHOD: init // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: change // //=====================================================================// /** * Specifies a function to be executed on text change in the HtmlBox */ this.change=function(fn){d.change=fn;return this;}; //=====================================================================// // METHOD: change // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: remove // //=====================================================================// /** * Removes the HtmlBox instance from the DOM and the globalspace */ this.remove = function(){ glob_ha[d.id]=undefined; $(d.id+"_wrap").remove(); }; //=====================================================================// // METHOD: remove // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: toolbar // //=====================================================================// /** * The toolbar of HtmlBox * @return this */ var toolbar=function(){ var h = ""; for(var k=1;k"; for(var i=0;i<(buttons.length+1);i++){ if(undefined===d.buttons[buttons[i]]){continue;} else if(d.buttons[buttons[i]]==="separator_dots"){h += "";} else if(d.buttons[buttons[i]]==="separator_basic"){h += "";} else if(d.buttons[buttons[i]]==="fontsize"){ h += ""; }else if(d.buttons[buttons[i]]==="fontfamily"){ h += ""; }else if(d.buttons[buttons[i]]==="formats"){ h += ""; }else if(d.buttons[buttons[i]]==="fontcolor"){ h += ""; }else if(d.buttons[buttons[i]]==="highlight"){ h += ""; }else if(d.buttons[buttons[i]]==="styles"){ h += ""; }else if(d.buttons[buttons[i]]==="syntax"){ h += ""; } /* else if(d.buttons[buttons[i]]==="images"){ $().mousemove(function(e){document.x=e.pageX;document.y=e.pageY;}); $(document.body).append(""); $("#images").blur(function(){$(this).hide();}); h += ""; }*/ // Commands var cmds = {"bold":"Bold","center":"Center","code":"View Code","copy":"Copy","cut":"Cut","hr":"Insert Line","hyperlink":"Insert Link","image":"Insert Image","indent":"Indent","italic":"Italic","justify":"Justify","left":"Left","ol":"Numbered List","outdent":"Outdent","paragraph":"Insert Paragraph","paste":"Paste","quote":"Quote","redo":"Redo","removeformat":"Remove Format","right":"Right","strike":"Strikethrough","striptags":"Strip Tags","sub":"Subscript","sup":"Superscript","ul":"Bulleted List","underline":"Underline","undo":"Undo","unlink":"Remove Links"}; if(in_array(d.buttons[buttons[i]],cmds)){h += "";} } h += ""; } return h; }; //=====================================================================// // METHOD: toolbar // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: cmd // //=====================================================================// /** * Executes a user-specified command * @return this */ this.cmd = function(cmd,arg1){ // When user clicks toolbar button make sure it always targets its respective WYSIWYG d.iframe.contentWindow.focus(); // START: Prepare commands if(cmd==="paragraph"){cmd="format";arg1="p";} var cmds = {"center":"justifycenter","hr":"inserthorizontalrule","justify":"justifyfull","left":"justifyleft","ol":"insertorderedlist","right":"justifyright","strike":"strikethrough","sub":"subscript","sup":"superscript","ul":"insertunorderedlist"}; if(in_array(cmd,cmds)){cmd=cmds[cmd];} // END: Prepare commands if(cmd==="code"){ var text = this.get_html(); if($("#"+d.id).is(":visible")){ $("#"+d.id).hide(); $("#"+d.id+"_html").show(); this.set_text(text); }else{ $("#"+d.id).show(); $("#"+d.id+"_html").hide(); this.set_text(text); $("#"+d.id).focus(); } }else if(cmd==="hyperlink"){ d.idoc.execCommand("createlink", false, prompt("Paste Web Address URL Here:")); }else if(cmd==="image"){ d.idoc.execCommand("insertimage", false, prompt("Paste Image URL Here:")); }else if(cmd==="fontsize"){ d.idoc.execCommand(cmd, false,arg1); }else if(cmd==="backcolor"){ if($.browser.msie){ d.idoc.execCommand("backcolor", false,arg1); }else{ d.idoc.execCommand("hilitecolor", false,arg1); } }else if(cmd==="fontcolor"){ d.idoc.execCommand("forecolor", false,arg1); }else if(cmd==="fontname"){ d.idoc.execCommand(cmd, false, arg1); }else if(cmd==="cut"){ if($.browser.msie === false){ alert("Available in IExplore only.\nUse CTRL+X to cut text!"); }else{ d.idoc.execCommand('Cut'); } }else if(cmd==="copy"){ if($.browser.msie === false){ alert("Available in IExplore only.\nUse CTRL+C to copy text!"); }else{ d.idoc.execCommand('Copy'); } }else if(cmd==="paste"){ if($.browser.msie === false){ alert("Available in IExplore only.\nUse CTRL+V to paste text!"); }else{ d.idoc.execCommand('Paste'); } }else if(cmd==="format"){ if(arg1==="pindent"){wrap_tags('

','

');} else if(arg1!==""){d.idoc.execCommand('formatBlock', false, "<"+arg1+">");} }else if(cmd==="striptags"){ var sel = get_selection(); sel = sel.replace(/(<([^>]+)>)/ig,""); insert_text(sel); }else if(cmd==="quote"){ wrap_tags('
Quote
','

'); }else if(cmd==="styles"){ wrap_tags(styles[arg1][1],styles[arg1][2]); }else if(cmd==="syntax"){ wrap_tags(syntax[arg1][1],syntax[arg1][2]); }else{ d.idoc.execCommand(cmd, false, null); } //Setting the changed text to textearea if($("#"+d.id).is(":visible")===false){ $("#"+d.id).val(this.get_html()); } }; //=====================================================================// // METHOD: cmd // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: get_text // //=====================================================================// /** * Returns the text without tags of the HtmlBox * @return this */ this.get_text = function(){ // Is textbox visible? if($("#"+d.id).is(":visible")){ return $("#"+d.id).val(); } // Iframe is visible var text; if($.browser.msie){ text = d.iframe.contentWindow.document.body.innerText; }else{ var html = d.iframe.contentWindow.document.body.ownerDocument.createRange(); html.selectNodeContents(d.iframe.contentWindow.document.body); text = html; } return text; }; //=====================================================================// // METHOD: get_text // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: set_text // //=====================================================================// /** * Sets the text as a content of the HtmlBox * @return this */ this.set_text = function(txt){ var text = (undefined===txt)?"":txt; // Is textarea visible? Writing to it. if($("#"+d.id).is(":visible")){ $("#"+d.id).val(text); }else{ // Textarea not visible. write to iframe if($.browser.mozilla||$.browser.safari){ //if($.trim(text)===""){text=" ";} d.idoc.open('text/html', 'replace'); d.idoc.write(text); d.idoc.close(); }else{ d.idoc.body.innerHTML = ""; if(text!==""){d.idoc.write(text);} } d.idoc.body.contentEditable = true; style(); // Setting the CSS style for the iframe } return this; }; //=====================================================================// // METHOD: set_text // //========================== END OF METHOD ============================// //=====================================================================// // METHOD: dir // //========================== END OF METHOD ============================// /** * Sets the image directory of the HtmlBox */ //this.dir = function(dir){d.dir=$.trim(dir);return this;}; //=====================================================================// // METHOD: dir // //========================== END OF METHOD ============================// //=====================================================================// // METHOD: idir // //========================== END OF METHOD ============================// /** * Sets the image directory of the HtmlBox */ this.idir = function(dir){d.idir=$.trim(dir);return this;}; //=====================================================================// // METHOD: idir // //========================== END OF METHOD ============================// //=====================================================================// // METHOD: set_style // //========================== END OF METHOD ============================// /** * Sets the CSS style to be used by the HtmlBox */ this.set_style = function(css){d.css=css;return this;}; //=====================================================================// // METHOD: set_style // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: get_html // //=====================================================================// /** * Returns the (X)HTML content of the HtmlBox * @return this */ this.get_html = function(){ var html; if($("#"+d.id).is(":visible")){ html = $("#"+d.id).val(); }else{ html = d.iframe.contentWindow.document.body.innerHTML; } if(typeof getXHTML === 'function'){ return getXHTML(html); }else{return html;} }; //=====================================================================// // METHOD: get_html // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: button // //=====================================================================// /** * Sets which button to be shown at the top of HtmlBox * @param String the name of the button * @param Integer the row at whic the button is to be placed * @return this */ this.button = function(name,row){ d.buttons[d.buttons.length]=name; if(undefined===row){ if(undefined===d.rows[1]){d.rows[1]="";} d.rows[1]=d.rows[1]+","+(d.buttons.length-1); }else{ if(undefined===d.rows[row]){d.rows[row]="";} d.rows[row]=d.rows[row]+","+(d.buttons.length-1); } return this; }; //=====================================================================// // METHOD: button // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: separator // //=====================================================================// /** * Adds a separator image to the toolbar * @param String "basic" or "dots" * @return this; */ this.separator = function(type,row){ if(undefined===type){type="basic";} this.button("separator_"+type,row); return this; }; //=====================================================================// // METHOD: separator // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: post // //=====================================================================// /** * Posts the form data to the specified URL using Ajax * @param String the URL to post to * @param String the text to be posted, default the (X)HTML text * @return this; */ this.post=function(url,data){ if(undefined===data){data=this.get_html();} data=(d.id+"="+data); $.ajax({type: "POST", data: data,url: url,dataType: "html",error:d.error,success:d.success}); }; //=====================================================================// // METHOD: post // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: get // //=====================================================================// /** * Gets the form data to the specified URL using Ajax * @param String the URL to get to * @param String the text to be posted, default the (X)HTML text * @return this; */ this.get=function(url,data){ if(undefined===data){data=this.get_html();} data=(d.id+"="+data); $.ajax({type: "GET", data: data,url: url,dataType: "html",error:d.error,success:d.success}); }; //=====================================================================// // METHOD: get // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: success // //=====================================================================// /** * Specifies what is to be executed on successful Ajax POST or GET */ this.success=function(fn){d.success=fn;return this;}; //=====================================================================// // METHOD: success // //========================== END OF METHOD ============================// //========================= START OF METHOD ===========================// // METHOD: error // //=====================================================================// /** * Specifies what is to be executed on error Ajax POST or GET */ this.error=function(fn){d.error=fn;return this;}; //=====================================================================// // METHOD: error // //========================== END OF METHOD ============================// return this; }; //===========================================================================// // CLASS: HtmlBox // //============================== END OF CLASS ===============================//