SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Member
    Join Date
    Mar 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Working with a Select group and cloneNode in JavaScript

    Hi experts,
    I'm banging my head against the wall on this one and request your assistance.

    I have script that creates a form from another pages form and i'm using the cloneNode method javascript.
    The problem i have is that when I clone the select groups the currently selected option is lost and i am re-setting the selected option using the selectedIndex property and then writing to the new form with innerHTML. This seams to work in IE but not in Firefox/Chrome/Safari. Any suggestions?

    Code JavaScript:
    //construct url to submit to popup window
    function submitFormToPopup(form) { 
     
        var newWin = window.open("","TestWindow","width=700,height=200,modul"); //window.blur();
        var theForm = document.getElementById(form);
        var adhocForm = document.createElement("div");         
     
        newWin.document.write('<html><head><title>Popup</title>');
        //newWin.document.write('</head><body onload="document.getElementById(\'formSubmit\').submit();">');
        newWin.document.write('</head><body>'); 
    	newWin.document.write('<form action="AccountEditConf.php" id="formSubmit" method="GET" style="display: block;">');
     
    	for (var i=0;i<theForm.length;i++) {
    		var newElement = theForm.elements[i].cloneNode(true);
    		if (newElement.type == "select-one") { 
    			newElement.value = theForm.elements[i].value;
    		}
    		adhocForm.appendChild(newElement);
    	}
    	newWin.document.write(adhocForm.innerHTML); 
     
    //    var ad = adhocForm.innerHTML; 
    //    newWin.document.write(adhocForm.innerHTML);
        newWin.document.write('</form>');
        newWin.document.write('</body></html>');
    	newWin.document.close();     
    	window.blur();
    	setTimeout("window.reload()",1600);
        return true; 
     }

  2. #2
    padawan silver trophybronze trophy markbrown4's Avatar
    Join Date
    Jul 2006
    Location
    Victoria, Australia
    Posts
    4,107
    Mentioned
    28 Post(s)
    Tagged
    2 Thread(s)
    Hi,

    Well, there's a few things wrong with that code.
    I have never used cloneNode before, it doesn't seem to have great support.
    cloneNode (JavaScript method)

    You said you were using selectedIndex which is the correct way to set the value of a select list, but it's not in your code.

    You're also getting a form element - then trying to iterate over it with:
    Code:
    for (var i=0;i<theForm.length;i++) {
    I'm surprised that works in any browser. You need to be getting the list of elements from within the form.

    Also, I don't believe the type will ever be "select-one".

    There is almost certainly a better way to be doing that - but I'm still not sure why you are doing what you are doing

  3. #3
    SitePoint Addict bronze trophy AllanP's Avatar
    Join Date
    Sep 2010
    Location
    Australia
    Posts
    298
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    The following script works in all non-IE browsers - I haven't been able to find the right syntax for IE, but this works well in the others.

    The way to do this is to write the body of newWin and then append the clone of the form to it in newWin. If you use the deep method - all child elements of the target element, you can append the whole form in one go. You can do it the other way too - appending the elements one at a time, but it takes three appends, rather than one.

    Code :
    <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
     
    <head>
     
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
    <title>Clone nodes to new window</title>
    <script type="text/javascript">
    <!--
     
     window.onload=function(){ 
        var newWin = window.open("","TestWindow","width=700,height=200,modul"); 
        var theForm = document.forms[0];
       // build html for new window 
        var build='<html>\n<head>\n';
        build+='<style type="text/css">\n body { font-family:arial, helvetica, sans-serif; font-weight:bold; }\n<\/style>\n'; 
        build+='<title>This is the new window<\/title>\n<\/head>\n<body>';
        build+='<p style="color:#F00">This is your new window with a form<\/p>\n';
        build+='<\/body>\n<\/html>\n';
        newWin.document.write(build);
        var newElement = theForm.cloneNode(true);
        newWin.document.body.appendChild(newElement);
        //  
        newWin.document.close();     
     }
    // ---------
    //-->
    </script>
    </head>
     
    <body>
     
    <form name="myForm" method="post" action>
      <p class="a"><input type="text" name="txtB1" value="bbb" size="20"></p>
      <p><input type="text" name="txtB2" value="bbb" size="20"></p>
      <p><input type="text" name="txtB3" value="bbb" size="20"></p>
    </form>
     
    </body>
     
    </html>

  4. #4
    SitePoint Member
    Join Date
    Mar 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by markbrown4 View Post
    Hi,

    Well, there's a few things wrong with that code.
    I have never used cloneNode before, it doesn't seem to have great support.
    cloneNode (JavaScript method)

    You said you were using selectedIndex which is the correct way to set the value of a select list, but it's not in your code.

    You're also getting a form element - then trying to iterate over it with:
    Code:
    for (var i=0;i<theForm.length;i++) {
    I'm surprised that works in any browser. You need to be getting the list of elements from within the form.

    Also, I don't believe the type will ever be "select-one".

    There is almost certainly a better way to be doing that - but I'm still not sure why you are doing what you are doing
    Thanks for the response Mark. You're right i had some issues with this script for sure. It might help to provide some more background to what i'm trying to do here. Essentially I'm using this script to off-load changes to a popup so that the user doesn't have to navigate to another page to change options in their profile. I'm thinking that there is probably a much better way to handle this in Ajax but i'm not skilled in Ajax or Ruby etc.. so this is my work around. I was wondering if there is just a way to dump all the name and value pairs from the form into the windows _GET array and pass that to another page instead but i see how to do that in client side scripting; i see that its fairly easy in PHP but what do you think?

    By the way I wrote this last night and it seams to work in both IE and others with the exception of the password field that is previously created using the createElement("input") method before the user submits:
    Code JavaScript:
    //construct url to submit to popup window
    function submitFormToPopup(form) { 
     
        var newWin = window.open("","TestWindow","width=700,height=200"); //window.blur();
        var theForm = document.getElementById(form);
        var adhocForm = document.createElement("div");
    	var adhocFormIE = document.createElement("div"); 
        newWin.document.write('<html><head><title>Popup</title>');
        newWin.document.write('</head><body onload="document.getElementById(\'formSubmit\').submit();">');
    	//newWin.document.write('</head><body>'); 
    	newWin.document.write('<form action="AccountEditConf.php" id="formSubmit" method="GET" style="display: block;">');
     
    	 	for (var i=0;i<theForm.length;i++) {
    			if ( navigator.appName == "Microsoft Internet Explorer") {
    				var newElement = document.createElement("<input name="+theForm.elements[i].name+">");
    				newElement.setAttribute("value",theForm.elements[i].value);
    				newElement.setAttribute("type","text");
    				adhocForm.appendChild(newElement);
     
    				//alert(newElement);
    				//adhocForm.appendChild(newElement);
    			} else {
    				var newElement = document.createElement("input");
    		//window["newElement" + i] = document.createElement("input");
    		//eval("var newElement" + i + "=document.createElement(\"input\");"); 
    			newElement.setAttribute("type","text");
    			newElement.setAttribute("name",theForm.elements[i].name); 
    			newElement.setAttribute("value",theForm.elements[i].value);
    			adhocForm.appendChild(newElement);
    			//newWin.document.write(newElement.innerHTML); 
    			//document.getElementById("formSubmit").appendChild(window["newElement" + i]); 
    			}
    		}
    		var ad = adhocForm.innerHTML; 
    		newWin.document.write(ad)
     
        newWin.document.write('</form>');
    	newWin.document.write('</body></html>');
    	newWin.document.close();
    	window.blur();
    	setTimeout("window.reload()",1600);
        return true; 
     }

  5. #5
    SitePoint Member
    Join Date
    Mar 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by AllanP View Post
    The following script works in all non-IE browsers - I haven't been able to find the right syntax for IE, but this works well in the others.

    The way to do this is to write the body of newWin and then append the clone of the form to it in newWin. If you use the deep method - all child elements of the target element, you can append the whole form in one go. You can do it the other way too - appending the elements one at a time, but it takes three appends, rather than one.

    Code :
    <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
     
    <head>
     
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
    <title>Clone nodes to new window</title>
    <script type="text/javascript">
    <!--
     
     window.onload=function(){ 
        var newWin = window.open("","TestWindow","width=700,height=200,modul"); 
        var theForm = document.forms[0];
       // build html for new window 
        var build='<html>\n<head>\n';
        build+='<style type="text/css">\n body { font-family:arial, helvetica, sans-serif; font-weight:bold; }\n<\/style>\n'; 
        build+='<title>This is the new window<\/title>\n<\/head>\n<body>';
        build+='<p style="color:#F00">This is your new window with a form<\/p>\n';
        build+='<\/body>\n<\/html>\n';
        newWin.document.write(build);
        var newElement = theForm.cloneNode(true);
        newWin.document.body.appendChild(newElement);
        //  
        newWin.document.close();     
     }
    // ---------
    //-->
    </script>
    </head>
     
    <body>
     
    <form name="myForm" method="post" action>
      <p class="a"><input type="text" name="txtB1" value="bbb" size="20"></p>
      <p><input type="text" name="txtB2" value="bbb" size="20"></p>
      <p><input type="text" name="txtB3" value="bbb" size="20"></p>
    </form>
     
    </body>
     
    </html>
    Thanks Allan,
    This works good in all browsers EXCEPT IE but the reason it doesn't work in IE is because before the user submits the form he clicks a span that creates on the flyer an optional password update field. What i'm finding out now is that IE doesn't work so well with the document.createElement("input"); function because the setAttribute("name","blahblah") doesn't work. I'm working around this by doing
    Code JavaScript:
    document.createElement("<input name=\"blahblah\">");
    but that can't be the right way to do it. maybe you can tell me if there is a better way to commit the user profile changes using ajax or something that wouldn't require the user to have to navigate another page? If you read my previous post i explain that i'm just trying to keep the user from having to go to a confirmation page using a pop-up but the pop-up thing gets annoying after a while.

  6. #6
    padawan silver trophybronze trophy markbrown4's Avatar
    Join Date
    Jul 2006
    Location
    Victoria, Australia
    Posts
    4,107
    Mentioned
    28 Post(s)
    Tagged
    2 Thread(s)
    It's sounds like you are wanting to serialize a form into name/value pairs and submit.
    If you want to do this without submitting the actual form I've used this type of function before, it may not be what you are wanting but could help:
    Code javascript:
    function serialize(els) {
        var values = [];
        for (var i = 0, ii = els.length; i < ii; i++) {
            var input = els[i];
            if (input.tagName == 'SELECT' && input.multiple) {
                for (var j = 0, jj = input.options.length; j < jj; j++) {
                    var option = input.options[j];
                    if (option.selected) {
                        values.push(input.name + '=' + encodeURIComponent(option.value));
                    }
                }
            }
            else if (!(/checkbox|radio/.test(input.type) && !input.checked) && input.type != 'submit') {
                values.push(input.name + '=' + encodeURIComponent(input.value));
            }
        }
        return values.join('&');
    }
    function serializeForm(form) {
    	var els = [],
    		types=['input','select','textarea'];
    	for (var i = 0, ii = types.length; i < ii; i++) {
    		var fields = form.getElementsByTagName(types[i]);
    		for (var j = 0, jj = fields.length; j < jj; j++) {
    			els.push(fields[j]);
    		}
    	}
        return form.action + '?' + serialize(els);
    }
    It takes a form, gets the input,textarea,select elements and puts the name value pairs into a URL as if the form was submitted with the GET method.

  7. #7
    SitePoint Addict bronze trophy AllanP's Avatar
    Join Date
    Sep 2010
    Location
    Australia
    Posts
    298
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    The simple solution is to use a frame page with one of the frames hidden . Here's a typical example:

    <frameset framespacing="0" border="0" frameborder="0" cols="*,100%">
    <frame name="leftPage" target="main" src="leftPage.htm">
    <frame name="main" scrolling="auto" src="main_page.htm">

    Your form is in the main page and the whole of the contents of the form can be stored in the left page, which is hidden. You can then have a success page show in the main page frame and then revert to the form again without losing any of the previously input information.


Tags for this Thread

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
  •