Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 13 of 13
  1. #1
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts

    designMode -- Some Questions

    I am going to be using design mode for my Javascript text editor as it seems to be qite well supported these days (safari/mozilla/ie), but tere are a few problems with it that i need help with. The biggest one is the shortcuts that ie adds, (e.g. ctrl+b for bold, ctrl+i for italic) I am going to be highlighting the code with my own functions and so do not really want them to have too much control over the formatting (I know they can if they wanted to but it is their loss in the end) so it would be nice to be able to disable some of the shortcuts (not the ctrl+c/ctrl+v/ctrl+x ones). The enter key is another problem, for each line they type I want to add a new <li> element (it will be in an <ol>, used for line numbers) and do not like the idea of the browser insert a <p>&nbsb</p>, as I will deal with it myself. Does anyone know if it is possible to over-ride these things?

  • #2
    New Coder
    Join Date
    Jul 2005
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You'd need an event handler on the designMode document to intercept keydown events and filter out ctrl-B, ctrl-I, etc. The event properties of interest are: keyCode, ctrlKey, preventDefault() (for W3C-compliant), returnValue (for IE).

  • #3
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I have managed to do this with a normal document (I attached it to the body). However designMode can only be added to iframes and that is what I am having trouble with. Can anyone tell me how I can generate on the fly an iframe and attach to its body onkeydown(/press) event?
    Why cant the darn w3c do something useful with their time apart from removing and depreciating elements, like make a proper way to have formatted outputs in a textarea.

  • #4
    New Coder
    Join Date
    Jul 2005
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    RTE (designMode) is actually a bit buggy in the current Firefox build, though they are some workarounds (and most of the bugginess is fixed in the Firefox 1.1 alpha builds).

    untested:

    Code:
    var iframe = document.createElement('iframe');
    iframe.onload = function() {
      editorDoc = iframe.contentDocument || iframe.contentWindow.document;
      //Fx workaround: delay modifying editorDoc.body right after iframe onload event
      setTimeout(function() {
        editorDoc.body.innerHTML = initial_text;
        editorDoc.designMode = 'on';
      }, 0);
    
      editorDoc.onkeydown = editorDoc_onkeydown; //where editorDoc_onkeydown is the keydown event handler you defined earlier
    
      iframe = null; //IE mem leak fix
    }
    div.appendChild(iframe); //where div is the element you want to add the iframe to
    Last edited by Maian; 07-18-2005 at 11:52 AM. Reason: fixed workaround code

  • #5
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I came up with something like that, it works in firefox but not in IE. First, designMode does not switch itself On, I think for ie you need to do something like:
    document.getElementByTagName('iframe')[0].contentWindow.document.designMode = 'On'
    I also added some content, which works fine in firefox but nothing happens in IE, I think this is because it is an empty iframe, there is no body. Can anyone help me?

  • #6
    New Coder
    Join Date
    Jul 2005
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    This works:

    Code:
    window.onload = function() {
    	var rteElt = document.createElement('iframe');
    	rteElt.id = 'rte';
    	rteElt.onload = initRTE;
    	rteElt.onloadTimeout = setTimeout(initRTE, 50);
    	document.body.appendChild(rteElt);
    }
    
    function initRTE() {
    	var rteElt = document.getElementById('rte');
    	rteElt.onload = null;
    	clearTimeout(rteElt.onloadTimeout);
    	var rte = rteElt.contentWindow.document;
    	rte.designMode = 'on';
    	setTimeout(function() {
    		rte.body.innerHTML = 'abc';
    		rte.designMode = 'on';
    	}, 0);
    }
    And replace the window.onload thing with something more robust (like using window.addEventListener and window.attachEvent).

  • #7
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thank you very much, but can you help me add a way to read the contents of the iframe? I tried: document.getElementById('rte').contentWindow.document.body.innerHTML but IE gives me an error, and I have also had problems implementing an onkeydown/press handler for the iframe.

  • #8
    New Coder
    Join Date
    Jul 2005
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    When/where did you try that |document.getElementById('rte').contentWindow.document.body.innerHTML|?

    The onkeydown event should be something like this:

    Code:
    function rteOnkeydown(evt) {
      evt = evt || window.event;
      if (evt.keyCode == <lowercase ascii code for whatever letter you want> && evt.ctrlKey) {
        //blah...
        return false;
      }
    }

  • #9
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I am having trouble attaching the onkeydown event to the iframe (I am not sure where to e.g. body/main contentWindow etc).

  • #10
    New Coder
    Join Date
    Jul 2005
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Here you go:

    Code:
    function RTEonload() {
    	//dynamically create RTE iframe
    	var rteElt = document.createElement('iframe');
    	rteElt.id = 'rte';
    	//IE6 bug?: setting iframe onload doesn't work, so use attachEvent
    	if (rteElt.attachEvent)
    		rteElt.attachEvent('onload', RTEinit);
    	else
    		rteElt.onload = RTEinit;
    	//Gecko 1.7 bug: see RTEonunload
    	if (window.addEventListener)
    		window.addEventListener('unload', RTEonunload, false);
    	//add iframe to document
    	document.body.insertBefore(rteElt, document.body.firstChild);
    }
    
    //add RTEonload to window onload event for browsers that support RTE
    if (document.designMode) {
    	if (window.addEventListener)
    		window.addEventListener('load', RTEonload, false);
    	else if (window.attachEvent)
    		window.attachEvent('onload', RTEonload);
    }
    
    function RTEinit() {
    	//IE6 bug?: even if the onload event handlers are removed, toggling on designMode calls those
    	//	event handlers - none of the following will prevent RTEinit from being called twice:
    	//	rteElt.onload = null;
    	//	rteElt.detachEvent('onload', rteElt);
    	//	rteElt.setAttribute('onload', null);
    	//	rteElt.contentWindow.onload = null;
    	//	rteElt.contentWindow.detachEvent('onload', rteElt);
    	//so make sure this function never executes more than once
    	//(this should get rid of some infinite onload loop problems)
    	if (RTEinit.hasRun)
    		return;
    	RTEinit.hasRun = true;
    	var rteElt = document.getElementById('rte');
    	var rteWin = rteElt.contentWindow;
    	var rte = rteWin.document;
    	//toggling on designMode will cause iframe to reload, so null the onload event handler
    	//(as previously mentioned, this doesn't work for IE)
    	//(this should get rid of some infinite onload loop problems)
    	rteElt.onload = null;
    	//IE6 bug?: when enabling designMode for the first time, RTE document is reloaded and all
    	//	changes are discarded, so designMode needs to be enabled before modifying document
    	rte.designMode = 'on';
    	//IE6 bug?: when enabling designMode for the first time, 0-timeout delay is necessary
    	//	to access rte.body (doesn't apply here since designMode isn't enabled yet)
    	//Gecko 1.7 bug: 0-timeout delay is necessary since if designMode is enabled during the
    	//	iframe's onload event, the content of the document is deleted and all changes to the
    	//	iframe's document made in the event handler are discarded, regardless of whether
    	//	designMode is enabled before or after making those changes
    	//note: 0-timeout delay, i.e. setTimeout(x, 0), means that x is executed after the current
    	//	function
    	setTimeout(function() {
    		rte.body.innerHTML = 'abc';
    		//Gecko 1.7 bug: designMode needs to reset (or set if it's off) to 'on' to fix bug 232791
    		//	so enable designMode after setting innerHTML (as opposed to before setting innerHTML)
    		//Gecko 1.8 bug: if designMode is currently on, it's necessary to toggle it off first,
    		//	before setting it to 'on' again to fix bug 232791, but this causes an infinite onload
    		//	loop in IE6 if the RTE iframe was not dynamically created
    		//need browser detect here since these bugs can't be directly detected
    		if (navigator.userAgent.indexOf('Gecko') != -1) {
    			rte.designMode = 'off';
    			rte.designMode = 'on';
    		}
    		//Gecko: onevent properties don't work (e.g. rte.onclick doesn't work)
    		//	so DOM2 events must be used
    		if (rte.addEventListener) {
    			//Gecko: default action of key accelerators (i.e. hotkeys) occurs onkeypress
    			rte.addEventListener('keypress', RTEonkeypress, false);
    		} else if (rte.attachEvent) {
    			//IE: default action of key accelerators occurs onkeydown
    			rte.attachEvent('onkeydown', RTEonkeypress);
    		}
    		//set focus to RTE
    		rteWin.focus();
    	}, 0);
    }
    
    function RTEonunload() {
    	//Gecko 1.7 bug: designMode persists even after leaving the page;
    	//	this shouldn't really affect iframes, but I've seen some strange things, so this is
    	//	one of those "just in case" things
    	var rte = document.getElementById('rte').contentWindow.document;
    	rte.designMode = 'off';
    }
    
    function RTEonkeypress(evt) {
    	evt = evt || window.event;
    	//note: Gecko doesn't support formatting key accelerators, e.g. ctrl-I, ctrl-B (bug 191190)
    	if (evt.ctrlKey) {
    		//IE: keyCode
    		//Gecko: charCode (uses keyCode for keys that aren't characters, e.g. left arrow,
    		//	and for keydown and keyup events)
    		var keyCode = evt.keyCode || evt.charCode;
    		switch (keyCode) {
    			case 67:	//ctrl-c
    			case 86:	//ctrl-v
    			case 88:	//ctrl-x
    				return;
    		}
    		//ctrl-(anything else)
    		if (evt.preventDefault)
    			evt.preventDefault();
    		else
    			evt.returnValue = false;
    	}
    }
    That was quite a bug minefield
    Last edited by Maian; 07-19-2005 at 04:37 PM. Reason: comment typos

  • #11
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thank you ever so much! You are right in that it really is a bug minefield. It should be as simple as setting designmode to 'on' and then adding an onkeydown event handler. I am quite suprised that the W3C has not cleaned this whole area up.

    I have had some problems removing the iframes border, normally I would do frameborder="0", but when I tried rteElt.setAttribute('frameborder', 0); it did not seem to do any thing. In the page I have a <ol> list for the line numbers, however does anyone know how I can stop the user from editing any content out of the <ol> tag?
    Last edited by evilguru; 07-19-2005 at 03:59 PM.

  • #12
    New Coder
    Join Date
    Jul 2005
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    That's a CSS thing. You can do it in the script somewhere:

    Code:
    rteElt.style.border = 'none';
    Or in some CSS stylesheet:

    Code:
    #rte {
      border: none;
    }
    The latter way is probably the best - separation of presentation and logic, and all that

    If you're removing the border, you probably should also remove the padding: |padding: 0;| in the CSS.

    BTW, this RTE feature is a Microsoft extension that Mozilla also happened to implement. W3C had no say in it.

    EDIT:

    Oh yeah, in IE you'll need to set the frameborder and margin* properties to 0:

    Code:
    rteElt.frameBorder = 0;
    rteElt.marginHeight = 0;
    rteElt.marginWidth = 0;
    That code can go in RTEonload.

    Then use CSS to tweak the border and padding to your liking.
    Last edited by Maian; 07-19-2005 at 04:55 PM.

  • #13
    Regular Coder
    Join Date
    Jan 2005
    Posts
    113
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thank you very much. I know that the designMode is not a web standard, but I think that the W3C need to create one for dealing with these kinda of things rather than leaving it to the browser compaines to add.


  •  

    Posting Permissions

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