JavaScript - Word Count Wysiwyg
I've downloaded a simple wysiwyg script from the internet, however I want to add a wordcounter to it. The main idea is that the amount of words is refreshed every time a new character is entered. However I haven't got a clue on how to implement this,
I've used javascript a lot a few years ago.. but this is out of my league. So I'm hoping someone can help me with this. The html file: Quote: <html> <head> <style type="text/css">@import url('SimpleTextEditor.css');</style> <script src="SimpleTextEditor.js"></script> <script type="text/javascript"> function countWords(){ document.form1.wordcount.value = document.form1.inputString.value.split(' ').length + '/300 words'; if (document.form1.inputString.value.split(' ').length >= 50){ document.getElementById("wordcount").style.color = "red"; }else{ document.getElementById("wordcount").style.color = "black"; } } </script> </head> <body> <form name="form1" method="post"> <div style="height:34px;width:750px;margin-bottom:5px;background-image:url('mainbar.png');background-repeat:no-repeat; "><input style="margin-top:6px;margin-left:25px;" name="wordcount" type="text" value="" size="6"></div> <textarea name="inputString" id="inputString" cols="70" rows="4" onkeyup='countWords();'></textarea> <br> <script> var ste = new SimpleTextEditor("inputString", "ste"); ste.cssFile = 'test.css'; ste.charset = 'iso-8859-1'; ste.init(); </script> <input type="submit" value="submit" onclick="ste.submit();"> </form> </body> </html> The javascript file: Quote: function SimpleTextEditor(id, objectId) { if (!id || !objectId) { alert("SimpleTextEditor.constructor(id, objectId) failed, two arguments are required"); } var self = this; this.id = id; this.objectId = objectId; this.frame; this.viewSource = false; this.path = ""; // with slash at the end this.cssFile = ""; this.charset = "iso-8859-1"; this.editorHtml = ""; this.frameHtml = ""; this.textareaValue = ""; this.browser = { "ie": Boolean(document.body.currentStyle), "gecko" : (navigator.userAgent.toLowerCase().indexOf("gecko") != -1) }; this.init = function() { if (document.getElementById && document.createElement && document.designMode && (this.browser.ie || this.browser.gecko)) { // EDITOR if (!document.getElementById(this.id)) { alert("SimpleTextEditor "+this.objectId+".init() failed, element '"+this.id+"' does not exist"); return; } this.textareaValue = document.getElementById(this.id).value; var ste = document.createElement("div"); document.getElementById(this.id).parentNode.replaceChild(ste, document.getElementById(this.id)); ste.id = this.id+"-ste"; ste.innerHTML = this.editorHtml ? this.editorHtml : this.getEditorHtml(); // BUTTONS var buttons = ste.getElementsByTagName("td"); for (var i = 0; i < buttons.length; ++i) { if (buttons[i].className == "button") { buttons[i].id = this.id+'-button-'+i; buttons[i].onmouseover = function() { this.className = "button-hover"; } buttons[i].onmouseout = function() { this.className = this.className.replace(/button-hover(\s)?/, "button"); } buttons[i].onclick = function(id) { return function() { this.className = "button-hover button-click"; setTimeout(function(){ document.getElementById(id).className = document.getElementById(id).className.replace(/(\s)?button-click/, ""); }, 100); } }(buttons[i].id); } } // FRAME if (this.browser.ie) { this.frame = frames[this.id+"-frame"]; } else if (this.browser.gecko) { this.frame = document.getElementById(this.id+"-frame").contentWindow; } this.frame.document.designMode = "on"; this.frame.document.open(); this.frame.document.write(this.frameHtml ? this.frameHtml : this.getFrameHtml()); this.frame.document.close(); insertHtmlFromTextarea(); } }; function lockUrls(s) { if (self.browser.gecko) { return s; } return s.replace(/href=["']([^"']*)["']/g, 'href="simpletexteditor://simpletexteditor/$1"'); } function unlockUrls(s) { if (self.browser.gecko) { return s; } return s.replace(/href=["']simpletexteditor:\/\/simpletexteditor\/([^"']*)["']/g, 'href="$1"'); } function insertHtmlFromTextarea() { try { self.frame.document.body.innerHTML = lockUrls(self.textareaValue); } catch (e) { setTimeout(insertHtmlFromTextarea, 10); } } this.getEditorHtml = function() { var html = ""; html += '<input type="hidden" id="'+this.id+'" name="'+this.id+'" value="">'; html += '<table class="ste" cellspacing="0" cellpadding="0">'; html += '<tr><td class="bar"><table id="'+this.id+'-buttons" cellspacing="0" cellpadding="0"><tr>'; //html += '<td><select onchange="'+this.objectId+'.execCommand(\'formatblock\', this.value);this.selectedIndex=0;"><option value=""></option><option value="<h1>">Heading 1</option><option value="<h2>">Heading 2</option><option value="<h3>">Heading 3</option><option value="<p>">Paragraph</option><option value="<pre>">Preformatted</option></select></td>'; //html += '<td><div class="separator"></div></td>'; html += '<td class="button"><img src="'+this.path+'images/bold.gif" width="20" height="20" alt="Bold" title="Bold" onclick="'+this.objectId+'.execCommand(\'bold\')"></td>'; html += '<td class="button"><img src="'+this.path+'images/italic.gif" width="20" height="20" alt="Italic" title="Italic" onclick="'+this.objectId+'.execCommand(\'italic\')"></td>'; html += '<td class="button"><img src="'+this.path+'images/underline.gif" width="20" height="20" alt="Underline" title="Underline" onclick="'+this.objectId+'.execCommand(\'underline\')"></td>'; html += '<td><div class="separator"></div></td>'; html += '<td class="button"><img src="'+this.path+'images/left.gif" width="20" height="20" alt="Align Left" title="Align Left" onclick="'+this.objectId+'.execCommand(\'justifyleft\')"></td>'; html += '<td class="button"><img src="'+this.path+'images/center.gif" width="20" height="20" alt="Center" title="Center" onclick="'+this.objectId+'.execCommand(\'justifycenter\')"></td>'; html += '<td class="button"><img src="'+this.path+'images/right.gif" width="20" height="20" alt="Align Right" title="Align Right" onclick="'+this.objectId+'.execCommand(\'justifyright\')"></td>'; html += '<td><div class="separator"></div></td>'; html += '<td class="button"><img src="'+this.path+'images/ol.gif" width="20" height="20" alt="Ordered List" title="Ordered List" onclick="'+this.objectId+'.execCommand(\'insertorderedlist\')"></td>'; html += '<td class="button"><img src="'+this.path+'images/ul.gif" width="20" height="20" alt="Unordered List" title="Unordered List" onclick="'+this.objectId+'.execCommand(\'insertunorderedlist\')"></td>'; html += '<td><div class="separator"></div></td>'; html += '<td class="button"><img src="'+this.path+'images/outdent.gif" width="20" height="20" alt="Outdent" title="Outdent" onclick="'+this.objectId+'.execCommand(\'outdent\')"></td>'; html += '<td class="button"><img src="'+this.path+'images/indent.gif" width="20" height="20" alt="Indent" title="Indent" onclick="'+this.objectId+'.execCommand(\'indent\')"></td>'; //html += '<td><div class="separator"></div></td>'; //html += '<td class="button"><img src="'+this.path+'images/link.gif" width="20" height="20" alt="Insert Link" title="Insert Link" onclick="'+this.objectId+'.execCommand(\'createlink\')"></td>'; //html += '<td class="button"><img src="'+this.path+'images/image.gif" width="20" height="20" alt="Insert Image" title="Insert Image" onclick="'+this.objectId+'.execCommand(\'insertimage\')"></td>'; //html += '<td><div class="separator"></div></td>'; //html += '<td class="button"><img src="'+this.path+'images/help.gif" width="20" height="20" alt="Help" title="Help" onclick="'+this.objectId+'.openWindow(\''+this.path+'help.html\', \'300\', \'300\')"></td>'; html += '</tr></table></td></tr>'; html += '<tr><td class="frame"><iframe id="'+this.id+'-frame" frameborder="0"></iframe></td></tr>'; html += '<tr><td class="source"><input id="'+this.id+'-viewSource" type="checkbox" onclick="'+this.objectId+'.toggleSource()"> View Source</td></tr>'; html += '</table>'; return html; }; this.getFrameHtml = function() { var html = ""; html += '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'; html += '<html><head>'; html += '<meta http-equiv="Content-Type" content="text/html; charset='+this.charset+'">'; html += '<title>SimpleTextEditor frame</title>'; html += '<style type="text/css">pre { background-color: #eeeeee; padding: 0.75em 1.5em; border: 1px solid #dddddd; }</style>'; if (this.cssFile) { html += '<link rel="stylesheet" type="text/css" href="'+this.cssFile+'">'; } html += '<style type="text/css">html,body { cursor: text; } body { margin: 0.5em; padding: 0; }</style>'; html += '</head><body></body></html>'; return html; }; this.openWindow = function(url, width, height) { var x = (screen.width/2-width/2); var y = (screen.height/2-height/2); window.open(url, "", "scrollbars=yes,width="+width+",height="+height+",screenX="+(x)+",screenY="+y+",left="+x+",top=" +y); }; this.toggleSource = function() { var html, text; if (this.browser.ie) { if (!this.viewSource) { html = this.frame.document.body.innerHTML; this.frame.document.body.innerText = unlockUrls(html); document.getElementById(this.id+"-buttons").style.visibility = "hidden"; this.viewSource = true; } else { text = this.frame.document.body.innerText; this.frame.document.body.innerHTML = lockUrls(text); document.getElementById(this.id+"-buttons").style.visibility = "visible"; this.viewSource = false; } } else if (this.browser.gecko) { if (!this.viewSource) { html = document.createTextNode(this.frame.document.body.innerHTML); this.frame.document.body.innerHTML = ""; this.frame.document.body.appendChild(html); document.getElementById(this.id+"-buttons").style.visibility = "hidden"; this.viewSource = true; } else { html = this.frame.document.body.ownerDocument.createRange(); html.selectNodeContents(this.frame.document.body); this.frame.document.body.innerHTML = html.toString(); document.getElementById(this.id+"-buttons").style.visibility = "visible"; this.viewSource = false; } } document.getElementById(this.id+"-viewSource").checked = this.viewSource ? "checked" : ""; document.getElementById(this.id+"-viewSource").blur(); }; this.execCommand = function(cmd, value) { if (cmd == "createlink" && !value) { var url = prompt("Enter URL:", ""); if (url) { this.frame.focus(); this.frame.document.execCommand("unlink", false, null); if (this.browser.ie) this.frame.document.execCommand(cmd, false, "simpletexteditor://simpletexteditor/"+url); else if (this.browser.gecko) this.frame.document.execCommand(cmd, false, url); this.frame.focus(); } } else if (cmd == "insertimage" && !value) { var imageUrl = prompt("Enter Image URL:", ""); if (imageUrl) { this.frame.focus(); this.frame.document.execCommand(cmd, false, imageUrl); this.frame.focus(); } } else { this.frame.focus(); this.frame.document.execCommand(cmd, false, value); this.frame.focus(); } }; this.isOn = function() { return Boolean(this.frame); }; this.getContent = function() { try { return unlockUrls(this.frame.document.body.innerHTML); } catch(e) { alert("SimpleTextEditor "+this.objectId+".getContent() failed"); } }; this.submit = function() { if (this.isOn()) { if (this.viewSource) { this.toggleSource(); } document.getElementById(this.id).value = this.getContent(); } }; } As you can see there are a few lines I wrote myself in the HTML file, but they didn't do the trick. Similar TutorialsI found a nice script online that will count words. Problem is, I need it to also count each DIGIT (0-9) as a seperate word, whether the numbers are seperated by a space or not. I've searched this forum to no avail. Can anyone help me or show me how to do this, here is the original script: Code: <!-- TWO STEPS TO INSTALL WORD COUNT: 1. Copy the coding into the HEAD of your HTML document 2. Add the last code into the BODY of your HTML document --> <!-- STEP ONE: Paste this code into the HEAD of your HTML document --> <HEAD> <SCRIPT LANGUAGE="JavaScript"> <!-- Original: Shawn Seley --> <!-- This script and many more are available free online at --> <!-- The JavaScript Source!! http://javascript.internet.com --> <!-- Begin function CountWords (this_field, show_word_count, show_char_count) { if (show_word_count == null) { show_word_count = true; } if (show_char_count == null) { show_char_count = false; } var char_count = this_field.value.length; var fullStr = this_field.value + " "; var initial_whitespace_rExp = /^[^A-Za-z0-9]+/gi; var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, ""); var non_alphanumerics_rExp = rExp = /[^A-Za-z0-9]+/gi; var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " "); var splitString = cleanedStr.split(" "); var word_count = splitString.length -1; if (fullStr.length <2) { word_count = 0; } if (word_count == 1) { wordOrWords = " word"; } else { wordOrWords = " words"; } if (char_count == 1) { charOrChars = " character"; } else { charOrChars = " characters"; } if (show_word_count & show_char_count) { alert ("Word Count:\n" + " " + word_count + wordOrWords + "\n" + " " + char_count + charOrChars); } else { if (show_word_count) { alert ("Word Count: " + word_count + wordOrWords); } else { if (show_char_count) { alert ("Character Count: " + char_count + charOrChars); } } } return word_count; } // End --> </script> </HEAD> <!-- STEP TWO: Copy this code into the BODY of your HTML document --> <BODY> <form> <textarea cols=40 rows=5 name=x> </textarea> <br> <input type=button value="Count Words" OnClick ="CountWords(this.form.x, true, true);"> </form> <p><center> <font face="arial, helvetica" size"-2">Free JavaScripts provided<br> by <a href="http://javascriptsource.com">The JavaScript Source</a></font> </center><p> <!-- Script Size: 2.04 KB --> Hi all i have a question... In my below code, I need to get rid of the radio option in my file. Count pure words and Count everything as words Also if i specify some content in the input box, it shows all the word count in the output box. I need only few mentioned words to be dispalyed instead For example, if i give input as below in the input box "Java allows you to play online games, chat with people around the world, calculate your mortgage interest, and in view images in 3D, just to name a few. It's also integral to the intranet applications and and other e-business solutions that are the foundation of corporate computing." I need only to display the count of Java , yours , in , and so that i output will be Java - 1 yours - 0 in - 2 and - 3 Can someone help me out in this please... Thanks a lot!!!:) Html Code ======================================================= Code: <html> <head> <title> Word Count </title> <script language = "JavaScript"> function process1 (count) { // for words m=new Array(10000); m1=new Array(10000); N=new Array (10000); for (i=0;i<=1;i++) // which is chosen { if (count=1) { ch=i; } } A=count.message.value; // original message B=""; A=" " + A+" "; A=A.toUpperCase(); // changes all alphas to Upper case if (ch==0) // get rid of everything but apha's { condense1(count); } else { lesscondense(count); } for (i=1;i<=A.length;i++) // trims leading spaces and multiple spaces { if ((!(A.charAt(i)==" ")) || (!(A.charAt(i-1)==" "))) {B=B + A.charAt(i); } } //count.result1.value=B; B=B+" "; // makes sure there is a space at end k=0; str=" "; for (i=0;i<=B.length;i++) { k1=B.indexOf(str,k); if (k1==-1) //end of string B { Numwords=i-1; break; } m[i+1]=B.substring(k,k1); // places all the words into an array m k=k1+1; } //count.result1.value=B; C=""; NN=0; for (i=1;i<=Numwords; i++) // Numwords is total number of words { if (!(m[i]=="")) // only looks at m1 words that have not been processed before (not empty) { NN=NN+1; //unique word stored in m1 array m1[NN]=m[i]; N[NN]=1; // initialize counter for word for (j=i+1;j<=Numwords+1;j++) //counts and makes m1 elements with unique word empty. { if (m1[NN]==m[j]) { N[NN]=N[NN]+1; m[j]=""; } } } } C=C+"Unique:" + NN+" Total:" + Numwords+"\n"; C=C+"Freq.\tWord\n"; for (i=1;i<=NN;i++) // sets up C for showing { C=C + N[i]+ "\t" + m1[i] + "\n"; } count.result1.value=C; } function condense1(count) { // allows only alpha's and spaces for choice 1 C=""; for (i=0;i<=A.length-1;i++) { k=A.charCodeAt(i); if (((k>64) && (k<91)) || (k==32)) { C=C+A.charAt(i); } else { C=C+" "; } } A=C; //count.result1.value=B; } function lesscondense(count) { // allows all characters from space on C=""; for (i=0;i<=A.length-1;i++) { k=A.charCodeAt(i); if (k>31) { C=C+A.charAt(i); } else { C=C+" "; } } A=C; } //======================================== function letters1(count) { // counting characters upto unicode #255 mN=new Array(5000); for (i=0;i<=1;i++) // which is chosen { if ( count.radio2[i].checked) { ch1=i; } } A=count.message.value; T=0; for (i=0;i<=5000;i++) // initialize Array mN to 0 { mN[i]=0; } for (i=0;i<=A.length-1;i++) // k is character and counted in mN[k] { k=A.charCodeAt(i); mN[k]=mN[k]+1; } //count.result1.value=E; D=""; D=D+"Freq.\tLetter\n" if (ch1==0) // shows only alpha's and total number of letters T { for (i=65; i<91;i++) { if (!(mN[i]==0)) { D=D + mN[i] + "\t"+ String.fromCharCode(i) + "\n"; T=T+mN[i]; } } for (i=97;i<=122;i++) { if (!(mN[i]==0)) { D=D+mN[i]+"\t"+String.fromCharCode(i)+"\n"; T=T+mN[i]; } } } else // shows all characters from space (32) to unicode 255 { for (i=32; i<=255;i++) { if (!(mN[i]==0)) { D=D + mN[i] + "\t"+ String.fromCharCode(i) + "\n"; T=T+mN[i]; } } } count.result1.value=D; count.total.value=T; count.wordav.value=Math.round(T/Numwords*10000)/10000; // rounds off } //-- End </script> </head> <body> <form name ="count"><a name="Word_Counter"></a><font size="+1"><p> Count pure words<input type="radio" name="radio1" value="1" CHECKED> Count everything as words <input type ="radio" name="radio1" value="0"><br> <br> <table border="0" cellPadding="1" cellSpacing="1"> <tr> <td><input id="button1" name="button1" onclick="process1(document.count)" style="height: 24px; width: 165px; font-weight: bold" type="button" value="COUNT WORDS"></td> <strong><font face="Arial" color="#000080">Input your text into the box below:</font></strong><br><textarea cols=33 name=message rows=12 style="background-color: #ffffff; font-size: 10pt" wrap=PHYSICAL></textarea> <textarea cols=33 name=result1 rows=12 style="font-size: 10pt; font-family: Arial" wrap=PHYSICAL>WORD COUNT OUTPUT BOX</textarea> <br><table border=0 cellPadding=1 cellSpacing=1> <input type="reset" value="Reset" name="B1"> </body> </html> ======================================================= Hi Guys, I have a javascript, which counts the specified words.. I want javascript to count some of the html tags and symbols when i enter a html code in the textarea.. - the below searchwords are not functioning properly. http://(space) http:/(space) etc... (no spaces are searching) - www. (.(dot) is not searching, also when i enter wwww(4 times) in the textarea it shows www. as count 1) - i can't enter the below symbols in searchwords array [ < ' ? I thank once again Bullant for helping me on the below script... But i am trying to fix my above issue and i couldn't.. :( Please help me out guys... Here is my Code... Code: <html> <head> <title>Word Count</title> <script type = "text/javascript"> function searchForWords(){ document.getElementById('resultsContainer').innerHTML = ''; var txt = document.getElementById('txtMsg').value; var strWords = document.getElementById('txtSearchWords').value; var searchWordsTokens = strWords.split(' '); var searchWords = ['href','LINK_ID','mailto','src="','src= ','src =','.jpg','.gif','.png','www','www.','http','http:// ','http:/ ','http: ','http ',' http',' "','@','amp;','TBD']; for(i=0; i < searchWordsTokens.length; i++){ if(searchWordsTokens[i].length > 0){searchWords.push(searchWordsTokens[i]);} //remove spaces between words } var results = [],matches; for(i=0; i < searchWords.length; i++){ var regex = new RegExp('\\b'+searchWords[i]+'\\b','gi'); matches = txt.match(regex); results[searchWords[i]] = (matches)? matches.length : 0; } //output results var str = ''; for(var i in results){ str += i+'--'+results[i]+'<br />'; } document.getElementById('resultsContainer').innerHTML = str; } window.onload=function(){ document.getElementById('form_submit').onclick=searchForWords; } </script> </head> <body> <table> <tr><td align="center"> <form id="contact_form"><h4>Paste your HTML Code he </h4> <p><label class="form_label" for='message'></label> <textarea rows="20" cols="60" id="txtMsg"></textarea> </p> <div> <input type="text" id="txtSearchWords"/> </div> <p><input id='form_submit' type="button" value="Check for Counts"></p> <div><p><input id='form_submit' type="reset" value="Clear"></p></div> <div id="resultsContainer"></div> </form><br /></td> </table> </body> </html> Sorry about the title, I didn't know what else to use to describe my problem. Basically, I'm generating a random word with a function; then I'm trying to pass this word down to another function. The problem is, when I pass the word, it changes each time (due to it being randomly generated originally). I'm only calling the function once (via button click), but I'm also calling the function in my code lower down to retrieve the returned variable; and the function seems to be running again and returning a new word from my array. Here's a snippet of my code: Code: function ranNum(){ var ranNum = Math.round(Math.random()*10); var chosenWord = wordArray[ranNum]; return chosenWord; } function makeBoxes(x){ //remove children when new word is chosen var hM = document.getElementById("hangMan"); while(hM.firstChild){ hM.removeChild(hM.firstChild); } var chosenWord = ranNum(x); var wL = chosenWord.length; //create box for length of letters in word var i = 0; for(i=0;i<wL;i++){ var cBoxes = document.createElement("div"); cBoxes.className = "letterBoxes"; cBoxes.innerHTML = chosenWord.charAt(i); hangMan.appendChild(cBoxes); } return chosenWord; } function checkLetter(y){ var chosenWord = makeBoxes(y); alert(chosenWord); } So I generate a word with one button; now I need to be able to work with said word in my checkLetter() function. The word changes however. Any help would be greatly received. i have this code Code: function blockformat(tag) { if(document.selection){ var Editor = document.getElementById('iView').contentWindow.document; var range = Editor.selection.createRange(); if (range.pasteHTML) { var content=Editor.selection.createRange().htmlText; content1="<"+tag+">"+content+"</"+tag+">"; range.pasteHTML(content1); } } else if (window.getSelection) { var Editor = document.getElementById('iView').contentWindow; var range = Editor.getSelection().getRangeAt(0); content1="<"+tag+">"+range+"</"+tag+">"; getIFrameDocument('iView').execCommand('insertHTML',false, content1); } } the code get tag like "div" and insert into my wysiwyg the text that marked between the got tags. to example blockformat('div'); not in my wysiwyg iframe there is " <div>blabla</div>" now i want that if i clicked again the tags are remove like a execcommand if i click bold one time its make the text bold and second time its remove the bold tnx ... Hey, as i'm nearly finished writing my own wysiwyg editor, i need help to get it working in IE. So here is the Editor i hope you want to help me. Morri I am trying to create a WYSIWYG editor for my site, but seeing as how every browser gives different results when using the execcommand method, I am trying to do my own insertions instead. What I would like to do is create an iframe with designMode On to enable editing of the frame, but when someone does a command to bold text, I want to make a method which enters <b>Some Highlighted Text</b> into the frame where the user highlighted so it would appear bold and the source would have the <b> tags. My issue is I have been unsuccessful in learning how to take the selected text within an iframe and surround it with tags. I was able to accomplish this in Internet Explorer using this code: Code: //iFrame is the object handling the frame var text = iframe.document.selection.createRange().text; var obj = iframe.document.selection.createRange(); obj.text = '<i>' + text + '</i>'; Except the resulting text would actually have the <i> tags appear, and the source would be: Code: <i>Some Text</i> Pretty retarded if you ask me since in no way did I want it to convert the tags into entities. Anyway, if anyone could please direct me to a method in which I can successfully take selected text within the iframe and surround it with HTML tags in such a way that the formatting will actually show, I would be very grateful ^_^. I use http://www.openwebware.com/ wysiwyg editor. It is necessary to change something in it, but I do not know how? When the inserted image in the editor, and then changes the image size, stretches the image in an editor, I want to record a change image size, without editor in <input type='text'> field. Is there any idea how to bring? Thanks! Hey, i'm building my own wyiwyg-editor, and all works very good, exept getting the current focused element, i mean i wan't to show a path where the user is, and this function came out: Code: wysiwyg.getPath = function(i) { if(wysiwyg.getMode(i) == 'source') return; curr = document.getElementById('wysiwyg_frame_' + i).contentWindow.document; sel = curr.selection; if(sel == undefined) return; if (sel.type=="Control") { // control selection range = sel.createRange(); if (range.length==1) { elem = range.item(0); } else { // multiple control selection return; } } else { range = sel.createRange(); elem = range.parentElement(); } p = elem.tagName; while(elem == elem.parentNode && elem.tagName != 'BODY'){ p = elem + ' > ' + p; } document.getElementById('wysiwg_path_' + i).innerHTML = p; } unfortunaly sel is always undefined, how can i fix it? i hope you can help me Morri Hi All, Having a real problem with IE losing focus when clicking outside the wysiwyg iframe. This works fine in Firefox, Chrome, Safari, Opera. Code: <html> <head></head> <body> <script type="text/javascript"> function initializeEditor() { contentEditor.document.designMode='on'; } function insertHTML1() { var html = "<em><u>Some Text</u></em><p>2. Select this text<p><strong></u>Some text</strong>"; document.contentEditor.focus(); range = contentEditor.document.selection.createRange(); document.contentEditor.focus(); range.pasteHTML(html); } function insertHTML2() { var html = "<strong>INSERTED TEXT</strong>"; document.contentEditor.focus(); range = contentEditor.document.selection.createRange(); document.contentEditor.focus(); range.pasteHTML(html); } </script> <iframe name="contentEditor" id="contentEditor" onLoad="initializeEditor();"></iframe> <p><input type="button" value="1. Click Here" onClick="insertHTML1()"> <p><input type="text" value="3. Click Here"> <p><input type="button" value="4. Click Here" onClick="insertHTML2()"> </body> </html> To demonstrate, first follow steps 1, 2 and 4. This works fine! Introduce step 3, clicking in a field outside the iframe and focus is lost. Appreciate any help!! Thanks WYSIWYG editor for PHPBB3. As far as I'm aware only unofficial MODS exist, and one has the impression they are fraught with bugs. I need a polished free opensource solution. I was really hopeful there was an official WYSIWYG, but I haven't found it yet if there is one. Can anyone confirm? Hi! I am trying to use a very simpe wysiwyg-editor. It works fine, except i don't know how to proces the data from the iframe. I simply cant make use of the text written. Code: <html> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <script type="text/javascript"> function Init() { document.getElementById("rte").contentWindow.document.designMode = "On"; } function doBold() { document.getElementById("rte").contentWindow.document.execCommand('bold', false, null); } function doItalic() { document.getElementById("rte").contentWindow.document.execCommand('italic', false, null); } function doURL() { var mylink = prompt("Enter a URL:", "http://"); if ((mylink != null) && (mylink != "")) { document.getElementById('rte').contentWindow.document.execCommand("CreateLink",false,mylink); } } function doImage() { myimg = prompt('Enter Image URL:', 'http://'); document.getElementById('rte').contentWindow.document.execCommand('InsertImage', false, myimg); } </script> </head> <body onLoad="Init();"> <input type="submit" name="btnBold" value="bold" on id="btnBold" onClick="doBold();"> <input type="submit" name="btnItalic" id="btnItalic" value="italic" onClick="doItalic();"> <input type="submit" name="btnURL" id="btnURL" value="URL" onClick="doURL();"> <input type="submit" name="btnImg" id="btnImg" value="Image" onClick="doImage();"> <br> <form action="process.php" method="post"> <iframe name="rte" id="rte"><textarea name="areal"></textarea> </iframe> <br> <input type="submit" value="Submit"></form> </body> </html> Most editors seem use this iframe-thing, without telling how to send the information by a form. Ok, so the code below will open a DIV under the iframe when right-clicking inside the iframe. The DIV will display the mouse coords where it was clicked. This works in IE, but I can't get it to work in Mozilla (FF, Saf, Op, Chr). Any help appreciated! Code: <html> <body> <script language="JavaScript"> function initialise() { if (navigator.appName == "Microsoft Internet Explorer") { editorContent.document.designMode='on'; editorContent.document.attachEvent("oncontextmenu", showContextMenu); editorContent.document.attachEvent("onclick", hideContextMenu); } else { document.getElementById("editorContent").contentDocument.designMode='on'; editorContent.document.addEventListener("contextmenu", showContextMenu, true); editorContent.document.addEventListener("click", hideContextMenu, true); } } function showContextMenu() { if (navigator.appName == "Microsoft Internet Explorer") { var editorContentWin = document.getElementById('editorContent').contentWindow; var mousex = editorContentWin.event.clientX; var mousey = window.screenTop + editorContentWin.event.clientY; } else { /***************************************/ /* WHAT TO DO HERE TO WORK IN MOZILLA? */ /***************************************/ } document.getElementById("contextMenu").style.visibility = 'visible'; document.getElementById("contextMenu").style.display = ''; document.getElementById("contextMenu").innerHTML = 'X: '+mousex+' Y: '+mousey; if (navigator.appName != "Microsoft Internet Explorer") { document.stopPropagation(); document.preventDefault(); } return false; } function hideContextMenu() { document.getElementById("contextMenu").style.visibility = 'hidden'; document.getElementById("contextMenu").style.display = 'none'; } </script> <iframe id="editorContent" name="editorContent" width="400" height="400" frameborder="1" onLoad="initialise();"></iframe> <div id="contextMenu" style="width: 100px; height: 20px; border: 1px solid black; background-color: yellow; visibility: hidden; display: none"></div> </body> </html> Hi all, I have a small message board with TinyMCE (WYSIWYG) editor integrated into it. It works fine for everything except when someone tries to post code... especially content with the < or > characters. For example, a person may try to post an example of how to make red text in HTML. But when he does this: <span style="color:#ff0000;">Hello</span> Of course it comes out like this: Hello Or C code... #include <stdio.h> gets stripped off as INVALID HTML! So, I ended up making a Javascript filter that pre-processes pasted data and turns all < characters into "‹" and all > into "›" characters. BTW, those two characters look very similar to < and >. They look like this: ‹ and › so that, for example: ‹span style="color:#ff0000;"›Hello‹/span› is NOT interpreted as HTML. Similarly, I pre-convert <br /> to "↵" which is a little "down/left/arrow" symbol that is on most ENTER keys on a keyboard. After converting all the < and > characters, I then restore the ↵ back to <br /> (I do this to preserve the < and > in the br!). The resulting text is posted verbatim as a message, but if it's placed in a CODEBOX, then the codebox does an "onfocus="fix-it-back" meaning that the codebox innerHTML is converted back to < and > characters so it can be selected and copied as real code. All this seems to me to be complicated and convoluted. My gut tells me there is a simpler, better way to do it. Any suggestions or ideas please? Will be appreciated! Thanks! -- Roger Ok, so I'm working on a What-You-See-Is-What-You-Get editor, and it works flawlessly - with standards. I'm trying to work out bugs it has with IE, this one is particularly tricky: When the page loads, the editor should be inialized, and the inner HTML of the body of the iframe should set to specified text. This seems to work fine in standards-compliant browsers - Webkit, Firefox. But nothing is written to the body when when the page loads in IE, here's the gist of the code for reference: Code: function loadText(){ document.getElementById("edit").contentWindow.document.body.innerHTML = "predefined text"; } window.onload = loadText; The oddest part, is if I come from a new page to the editor in IE, the text doesn't appear. But when I refresh in IE, the text appears for a split second and disappears. Any help on this matter is greatly appreciated! I am allowing my customers to use a rich text editor (wysiwyg) on a jsp page to create snippets of HTML code that can be used to describe their items. When they want to add an image, table or custom tag (something we wrote), they are presented with a properties box created using javascript on the same page just below the editor. Upon clicking 'Insert' button on the properties box, I use javascript to create an HTML string with the tag information and insert the string into the edited page where the cursor was. The problem is that I can't seem to find a reliable way to know where the cursor was. More information: I am a C programmer who morphed to a Java programmer who knows some javascript. The JSP page looks like this: -------------------------------------------------------------------- Some text and text fields for some basic information -------------------------------------------------------------------- The javascript wysiwyg editor -------------------------------------------------------------------- The properties box (changes depending on the type of item being inserted) -------------------------------------------------------------------- Submit button, etc. for the page (so the information can be persisted) I have tried: 1. Seven days of searching the web for helpful hints. 2. Using a popup window to get the properties (doesn't work because in IE7, closing the popup also kills the session... I need to use some of the beans on the main window on the popup.) 3. Processing onMouseDown and onKeyDown events storing the element information in a global variable so I could use it later to know the point of insertion. (Has not been reliable and the arrow keys present real problems with where the cursor ends up as that is different from where it was pressed.) I am frustrated because I don't seem to be gaining on the problem. I suspect it is because I have missed something very simple. Does anyone have any ideas? Thanks in advance. Carl I would like to add a Lightbox like image display function to TinyMCE. What is a good approach in the regard, integration or extension? Thank for your input in advance. I have a WYSIWYG text area and I want to insert combo-box' value at current cursor location of the WYSIWYG text area. I have a simple textarea where the value is inserting on combo-box clicking. But when I do integrate both files, the functionality wont work. I have both scripting files..
Hi ! I would need to select whole word (same thing as when you double click a word) just by single clicking on it, or by positioning the cursor above the word(any letter of a word). Then i would need to manipulate the selection(to change selected text to some other text). The outcome would be an editor with a possibility to change selected word (to add diacritical marks to selected word). I've been googling for this for long time and can't find an answer. It can be connected to range object that is not the same in IE a firefox - but i did not manage to make it work. Or is my approach wrong ? Do you have any idea how to do this? Thank you in advance ! Tomas I am trying to transform a set of two radio buttons in a stack of two labels, one blue and on gray representing, respectively, the selected radio and the unselected one. Clicking on this stack will change which of the labels is blue (and which of the radio buttons is checked). It works well but it breaks down in an ugly manner when the two labels aren't of the same width. The best way to see what I mean is to try the test page I made out on your own server or to navigate here to see the page in action. The comments in the source code and actual content explain pretty much what I am aiming for and what the problems are. Also, this is an attempt at accessibility and graceful degradation, so any remarks concerning those issues are most welcome. Code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>word stacks</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <style type="text/css"> .stackContainer { line-height: 2em; /* Prevents the stackBottom from overlaping the second line of text found in the stack container, should there be a second line. */ } .stack { display: inline-block; /* prevent the block options to induce line breaks in your text */ line-height: 1; /* Have the 2 options verticaly close to each other */ position: relative; /* Moves the lines to be in between*/ top: 0.5em; white-space: nowrap; /* prevent line breaks */ } .stackTop, .stackBottom { display: block; /* Stack the options on top of each other */ } /* The following is extra for presentation */ .stackSelected /* Represents the chosen value */ { color: #009; } .stackUnselected /* Represents the other option */ { color: #777; } .stack { cursor: pointer; } p { margin: 3em; } </style> <?php function createWordStack($name, $value1, $value2) { // Set default values (by default, $value1 is checked and not $value2) $firstChecked = "checked=\"checked\" "; $secondChecked = ""; if(isset($_POST[$name])) // One value was chosen { if($_POST[$name] == $value2) // Not default value { $firstChecked = ""; $secondChecked = "checked=\"checked\" "; } // else fall back to default value } // else fall back to default value // Write out the html echo("<span class=\"stack\"> <label for=\"" . $name . "\"> <input type=\"radio\" name=\"" . $name . "\" value=\"" . $value1 . "\" " . $firstChecked . "/>" . $value1 . " </label> <label for=\"" . $name . "\"> <input type=\"radio\" name=\"" . $name . "\" value=\"" . $value2 . "\" " . $secondChecked . "/>" . $value2 . " </label> </span>"); } ?> <script type="text/javascript"> // It is recommended to use this function only if stacks have been created with the php function createStack and if these stacks are contained in an element of class stackContainer function makeStacks() { var forms = document.getElementsByTagName("form"); // Find all forms var nb_forms = forms.length; for(var i = 0; i < nb_forms; ++i) { if(forms[i].className.indexOf("stackContainer") != -1) // If it's a stackContainer { var spans = forms[i].getElementsByTagName("span"); // Find all spans var nb_spans = spans.length; for(var j = 0; j < nb_spans; ++j) { if(spans[j].className.indexOf("stack") != -1) // If it's a stack { var labels = spans[j].getElementsByTagName("label"); // Find all labels var nb_labels = labels.length; if(nb_labels == 2) // Only works with two labels! { labels[0].className += " stackTop"; labels[1].className += " stackBottom"; for(var k = 0; k < nb_labels; ++k) { var inputs = labels[k].getElementsByTagName("input"); // Find all inputs var nb_inputs = inputs.length; if(nb_inputs == 1 && inputs[0].type == "radio") // Only works with one radio button per label! { inputs[0].style.display = "none"; // Hide radio button labels[k].className += (inputs[0].checked)?" stackSelected":" stackUnselected"; } } } // add onclick listener to invert which radio button is checked and invert which label appears on top spans[j].onclick = function() { var labels = this.getElementsByTagName("label"); // Find all labels // We already know that there are only two labels, from earlier! for(var l = 0; l < 2; ++l) { // Invert className from stackTop to stackBottom (or vice-versa) if(labels[l].className.match(/stackSelected/)) { labels[l].className = labels[l].className.replace(/stackSelected/, "stackUnselected"); } else if(labels[l].className.match(/stackUnselected/)) { labels[l].className = labels[l].className.replace(/stackUnselected/, "stackSelected"); } } // Change which of the radios is checked var inputs = labels[0].getElementsByTagName("input"); // Find all inputs from first label // We already know that there is a single label and that it is a radio, from earlier! if(!inputs[0].checked) // If this one is not checked, check it to change which of the radios is checked { inputs[0].checked = true; } else { var inputs = labels[1].getElementsByTagName("input"); // Find all inputs from second label // We already know that there is a single label and that it is a radio, from earlier! if(!inputs[0].checked) // If this one is not checked, check it to change which of the radios is checked { inputs[0].checked = true; } // else there is something wrong as none of the radios are checked! } } } } } } } window.onload = makeStacks; </script> </head> <body> <h1>Word stacks</h1> <h2>How it works</h2> <ol> <li>PHP transforms<br /> <code><?php createWordStack("name","one","two"); ?></code><br /> into<br /> <code> <pre> <span class="stack"> <label for="name"> <input type="radio" name="name" value="one" />one </label> <label for="name"> <input type="radio" name="name" value="two" checked="checked" />two </label> </span> </pre> </code> </li> <li> javascript hides the radio buttons, applies class declarations to the labels and adds an onclick event listener to the<br /> <code> <span class="stack"> </code> </li> </ol> <h2 id="example">Example</h2> <form action="<?php echo($_SERVER['PHP_SELF'] . "#example"); ?>" class="stackContainer" method="post"> <p>Choose between <?php createWordStack("name","one","two"); ?> options.</p> <input type="submit" value="Test that the radio buttons hidden behind this still work" /> </form> <h3>print_r($_POST)</h3> <pre> <?php print_r($_POST); ?> </pre> <form class="stackContainer"> <h2>Known issues</h2> <p> This technique <?php createWordStack("no_matter","absolutely does not","does"); ?> look good with two different sizes of `words`, <?php createWordStack("no_matter2","no matter","although this depends"); ?> in which order they appear. If looks better when the longer word is above the other though. Plus, the way it breaks makes it unreadable when the longer word is on the bottom if the remainder of the text needs to span many lines. </p> <p> Another problem is when the bottom word <?php createWordStack("no_matter3","is","isn't"); ?> longer than the top word but actually consists of a single word. It cannot wrap and therefore interferes with the following text. </p> <p> <?php createWordStack("no_matter4","It really becomes unusable and quite ugly if the top word happens to wrap and span over two or more lines. Of course, the first know issue shown above is enough to understand that THIS known issue doesn't mean a thing if it is the bottom that is too long as it will span over many lines no matter what since it is limited by the width of the shorter word above..","It still works"); ?> .. and so, all in all, it is better to avoid long words altogether. </p> <p> Now, just to illustrate what I am saying above.. <?php createWordStack("no_matter5","Look at this ****!","It really becomes unusable and quite ugly if the top word happens to wrap and span over two or more lines. Of course, the first know issue shown above is enough to understand that THIS known issue doesn't mean a thing if it is the bottom that is too long as it will span over many lines no matter what since it is limited by the width of the shorter word above.."); ?> .. and so, all in all, it is better to avoid long words altogether. </p> <h2>Notes</h2> <p> At least, the next paragraph <?php createWordStack("no_matter6","isn't","is"); ?> pushed down too far. </p> <p> <?php createWordStack("no_matter7","It works","It doesn't work"); ?> when I put the stackBottom BEFORE the stackTop, so I could also call them stackChosen and stackAlternate and just change the className in order to choose one or the other. This is what the javascript used to do when you click on the stack: if the label is of class stackTop, it changes it to stackBottom, and vice-versa. Now, only the colour is changed.. </p> </form> </body> </html> I'm sorry, I know this is no way of asking a question, but I just don't know how else to phrase it. I did put much effort in making this test page as clear as possible. Thanks in advance |