SitePoint Sponsor

User Tag List

Results 1 to 3 of 3

Hybrid View

  1. #1
    SitePoint Addict xDev's Avatar
    Join Date
    Jul 2003
    Location
    Moncton, New Brunswick, Canada
    Posts
    247
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Undo and Redo Problems: execCommand

    Hi,

    I'm making a js/html editor so I can open, edit and save files on my computer. The editor is a textarea and to view the page I use an embedded iframe to stream the textarea contents to it.

    The problem I'm having is when I click the view button and write the contents to the iframe - the undo and redo stop working. All the other toolbar functions work after a write to the iframe (paste, copy, cut, and save) except the undo and redo.

    I'm not sure why this is happenning, but I have a suspicion its a focus or bubble issue.

    Even if I do an innerHTML event (in the main document or the iframe document), the undo and redo stop working.

    My page is an HTA Application. I can paste the code and maybe someone can tell me what is going on, I'll also supply a zipped version.

    I put 2 buttons at the bottom that only change the z-index of the iframe and textarea for display. This is as a test to show that the undo and redo will continue to work if you press the bottom buttons. The reason is that they don't initiate any stream to iframe, but only change the z-index display properties of the elements.

    I hope my explanation has been clear enough to understand. Any help would be appreciated.

    Code:
    <html xmlns:msie>
    <msie:download id="downloader"
                   style="behavior:url(#default#download)" />
    <head>
    <HTA:APPLICATION 
       ID = "oApp"
       APPLICATIONNAME = "HTA Editor"
       BORDER = "thick"
       CAPTION = "yes"
       ICON = "js.ico"
       SHOWINTASKBAR = "yes"
       SINGLEINSTANCE = "yes"
       SYSMENU = "yes"
       WINDOWSTATE = "normal"
       SCROLL = "no"
       SCROLLFLAT = "yes"
       VERSION = "1.0"
       INNERBORDER = "yes"
       SELECTION = "no"
       MAXIMIZEBUTTON = "yes"
       MINIMIZEBUTTON = "yes"
       NAVIGABLE = "yes"
       CONTEXTMENU = "yes"
       BORDERSTYLE = "normal"
       >
    
    <title>HTA Application: Javascript Editor</title>
    <style type="text/css">
    body { 
    	background:buttonface;
    	border:0px;padding: 0px;
    	margin: 0px;	
    }
    
    textarea {
    	width: 100%; height: 400px;
    	background: #f9f9f9; 
    	font: 13px "courier new", monospaced;
    	position: absolute; 
    	top: 25px; left: 0px;
    	z-index: 20;
    }
    
    #iFrameDisplay 
    {
    	position: absolute; 
    	top: 25px; left: 0px;
    	width: 100%;
    	border: none;
    	height: 400px;
    	z-index: 10;
    }
    
    ul#tabnav {
    	font: bold 11px verdana, arial, sans-serif;
    	list-style-type: none;
    	margin: 0;
    	position: absolute;
    	top: 6px;
    }
    
    ul#tabnav li {
    	float: left;
    	height: 17px;
    	background: url(images/menuBg.gif) repeat-x;
    	margin: 2px 1px;
    	border: 1px solid #91A7B4;
    }
    
    #tabnav a {
    	float: left;
    	display: block;
    	color: #666;
    	text-decoration: none;
    	padding: 2px 4px;
    }
    
    .on {
    	float: left;
    	display: block;
    	background: #f9f9f9;
    	padding: 2px 4px;
    }
    
    #tabnav a:hover {
    	background: #eee;
    	color: #000;
    }
    
    #toolbar {
    			margin: 0;
    			padding: 0;
    			background: transparent;
    			text-align:left;
    			position: absolute;
    			top: 0px; 
    			left: 230px;
    			z-index: 20;
    		  	}
    
    .button 	{
    			background: transparent;
    			border-width: 1px;
    			border-style: solid;
    			border-color: buttonface;
    			margin: -10px 0px;
    			}
    
    .raised	{
    			border-top: 1px solid #f9f9f9;
    			border-left: 1px solid #f9f9f9;
    			border-bottom: 1px solid #999;
    			border-right: 1px solid #999;
    			background: transparent;
    			margin: -10px 0px;
    			}
    
    .pressed	{
    			border-top: 1px solid #999;
    			border-left: 1px solid #999;
    			border-bottom: 1px solid #f9f9f9;
    			border-right: 1px solid #f9f9f9;
    			background: transparent;
    			margin: -10px 0px;
    			}
    .del {
    	color: #999; width: 1px; height: 15px; border: 1px inset; 
    	height: 17px; margin: 5px 2px;
    }
    
    #toolbarDisplay {
    	font: 8pt Verdana, sans-serif; width: 200px; height: 17px;
    	text-align: left; border: 1px inset; padding: 2px; 
    	position: absolute; top: 4px; left: 400px;
    }
    </style>
    
    <script language="JScript">
    function loadFile(fileName) 
    {
    	if (document.all && document.getElementById)
       downloader.startDownload(fileName, displayFile);
    }
    
    function displayFile(text) 
    {
     document.formName.file.value = text;
    }
    
    function CheckTab(el) {
    
      if ((document.all) && (9 == event.keyCode))
      {
       el.selection =document.selection.createRange();
    	el.selection.text = String.fromCharCode(32) + String.fromCharCode(32);
    	event.returnValue = false;
      }
    }
    
    function mouseover() {
    	 var e = event.srcElement;
    	  //toolbarDisplay.innerHTML = e.name;
        if ( e.nodeName != 'IMG' ) return;
    	 e.className = "raised";
    	 
    }
    
    function mouseout() {
    	 var e = event.srcElement;
    	 //toolbarDisplay.innerHTML = "";
        if ( e.nodeName != 'IMG' ) return;
      	 e.className = "button";
    	 
    }
    
    function mousedown() {
    	 var e = event.srcElement;
        if ( e.nodeName != 'IMG' ) return;
      	 e.className = "pressed";
    	 if(e.name == 'save') SaveDocument();
    	 else document.execCommand(e.name);
    }
    
    function mouseup() {
    	 var e = event.srcElement;
        if ( e.nodeName != 'IMG' ) return;
      	 e.className = "raised";
    	 document.formName.file.focus();
    }
    
    function pasteIt()
    {
    	document.formName.file.selection = document.execCommand('Paste');
    }
    
    function SaveDocument()
    {
    	// Setting CancelError to true and using try/catch 
    	// allows the user to click cancel on the save as 
    	// dialog without causing a script error
      	cDialog.CancelError = true;
      	fileTxt = document.formName.file;
      	try{
      		cDialog.Filter="HTM Files (*.htm)|*.htm|"
    		+ "Text Files (*.txt)|*.txt|"
    		+ "JS Files (*.js)|*.js|"
    		+ "CSS Files (*.css)|*.css"
      		cDialog.ShowSave();
      		var fso = new ActiveXObject("Scripting.FileSystemObject");
      		var f = fso.CreateTextFile(cDialog.filename,  true);
      		f.write(fileTxt.value);
      		f.Close();
      		sPersistValue = fileTxt.value;
      	}
      	catch(e){
      		var sCancel = "true";
      		return sCancel;
      	}
    	fileTxt.focus();	
    }
    
    var tabStrs = ["Editor","View Page","Snippets"];
    function tabOn(el, str)
    {
    	var output = "<span class=\"on\">"
    	+ str + "</span>";
    	el.innerHTML = output;
    	switch(str)
    	{
    		case 'Editor':
    		showEditor();
    		break;
    		case 'View Page':
    		showIframe();
    		doc = parent.frames['ifd'].document;
    		doc.write(document.formName.file.value);
    		doc.close();
    		break;
    	}
    	for(var i = 0; i < tabStrs.length; i++)
    	{
    	 if(tabStrs[i] != str)
    	 {
    	 	var element = eval(tabStrs[i].substring(0,1).toLowerCase());
    		element.innerHTML = 
    			'<a href="#">' + tabStrs[i] + '</a>';
    		
    	 }
    	}
    }
    function showEditor()
    {
    	document.getElementById('editor').style.zIndex = '20'; 
    	document.getElementById('iframeDisplay').style.zIndex = '10';
    }
    
    function showIframe(code)
    {
    	document.getElementById('editor').style.zIndex = '10'; 
    	document.getElementById('iframeDisplay').style.zIndex = '20';
    }
    </script>
    </head>
    <body onLoad="document.formName.file.focus();">
    <OBJECT ID="cDialog" WIDTH="0px" HEIGHT="0px"
        CLASSID="CLSID:F9043C85-F6F2-101A-A3C9-08002B2F49FB"
        CODEBASE="http://activex.microsoft.com/controls/vb5/comdlg32.cab">
    </OBJECT>
    <ul id="tabnav">
    	<li id="e" onclick="tabOn(this,'Editor');"><span class="on">Editor</span></li>
    	<li id="v" onclick="tabOn(this,'View Page');"><a href="#">View Page</a></li>
    	<li id="s" onclick="tabOn(this,'Snippets');"><a href="#">Snippets</a></li>
    </ul>
    	<div id="toolbar" onmouseover="mouseover();"
    	 onmouseout="mouseout();"
    	 onmousedown="mousedown();"
    	 onmouseup="mouseup();" 
    	 style="font:7pt verdana, sans-serif;">
    	<img class="button"
    	 onclick="SaveDocument();"
    	 src="images/save.gif"
    	 width="21" height="20"
    	 align="middle"
    	 name="save" alt="save" />
    	<span class="del"></span>
    	<img class="button"
    	 src="images/cut.gif"
    	 width="21" height="20"
    	 align="middle"
    	 name="cut" />
    	<img class="button"
    	 src="images/copy.gif"
    	 width="21" height="20"
    	 align="middle"
    	 name="copy" />
    	<img class="button"
    	 src="images/paste.gif"
    	 width="20" height="21"
    	 align="middle"
    	 name="paste" />
    	<span class="del"></span>
    	<img class="button"
    	 src="images/undo.gif"
    	 width="20" height="21"
    	 align="middle"
    	 name="undo" />
    	<img class="button"
    	 src="images/redo.gif"
    	 width="20" height="21"
    	 align="middle"
    	 name="redo" />
    	 </div>
    <div id="toolbarDisplay"></div>
    <form id="formName" name="formName">
    	<textarea wrap="soft"
    	id="editor" onkeydown="CheckTab(this)"
    	name="file"><html>
    <head>
    <title>Test Page</title>
    <style type="text/css">
    
    </style>
    <script type="text/javascript">
    
    </script>
    </head>
    
    <body>
    
    HTML Markup
    
    </body>
    </html></textarea>
    
    <div style="position: absolute; top: 426px; left: 90%;">
    <input type="button" onclick="document.getElementById('editor').style.zIndex = '20'; 
    	document.getElementById('iframeDisplay').style.zIndex = '10';" value="textarea" />&nbsp;
    <input type="button" onclick="document.getElementById('editor').style.zIndex = '10'; 
    	document.getElementById('iframeDisplay').style.zIndex = '20';" value="iframe" />
    </div>
    </form>
    <iframe id="iframeDisplay" name="ifd"></iframe>
    </body>
    </html>
    ZIP FILE: http://www.xdevdesign.com/hta.zip

    Thanks,
    -xDev

  2. #2
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi xDev,

    Sorry for the late reply.

    I've looked through your post several times - but I'm just not familiar with HTAs. I downloaded it and ran it locally - Very Nice! That's some excellent work there, but I'm afraid I don't have any suggestions.

    Did you make any progress with this problem?

  3. #3
    SitePoint Addict xDev's Avatar
    Join Date
    Jul 2003
    Location
    Moncton, New Brunswick, Canada
    Posts
    247
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MikeFoster
    Hi xDev,

    Sorry for the late reply.

    I've looked through your post several times - but I'm just not familiar with HTAs. I downloaded it and ran it locally - Very Nice! That's some excellent work there, but I'm afraid I don't have any suggestions.

    Did you make any progress with this problem?
    Hi,

    Thanks for the reply. Never made any progress. I had a suggestion from someone in another forum, but that solution would require me to replace the textarea with an iframe. Don't need a wysiwig, just want to be able to apply the execCommands(undo/redo) and code by hand in a textarea.

    The funny thing is that even if I do a simple innerHTML in the main document, the undo/redo stops working as well. I think the undo/redo is very limited and depends on a constant focus on the document. There's not much at MSDN on it either and they say that its not supported - whatever that means

    It's really frustrating, cause I never have any problems finding a solution for programming problems I encounter. Can't find anything at all on google about this either. It seems everyone who's ever used the undo/redo execCommands has done it with an editable iframe, so no one has encountered this peculiar behaviour that I'm getting.

    Thanks,
    -xDev


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •