views:

173

answers:

4

This is probably a very basic question and I know how to do it using plain DOM but would like to learn the JQuery way of doing it.

After identifying the set of nodes using the appropriate JQuery selector, I would like to append a textarea, Save and Cancel button to each node with appropriate callback functions attached to the buttons to store values into a database. If the database has a value stored already, it should be pre-populated in the textarea. I can handle the back-end interaction parts, I just wanted to know the best practice for doing this sort of thing as far adding/removing form elements.

Thanks

+1  A: 

Simply

$('<your nodes>').append('<textarea name="...">' + textarea_value + '</textarea>');

or using $(html) form:

$('<textarea name="...">' + textarea_value + '</textarea>').appendTo('<your nodes>');

You may also use $().clone method if you need repeating values. Take a look at official docs.

Nikita Prokopov
+3  A: 

Something like this, perhaps:

jQuery(yourNodes).each(function(){

    var self = this,
        loading = $('<div>LOADING</div>').appendTo(self),
        id = self.id.replace(/^edit/,'');

    // Retrieve textarea from server
    jQuery.get('/getDataForTextArea?id=' + id, function(textareaValue){

        loading.remove();

        var textarea = jQuery('<textarea/>')
            .attr('id', 'txt' + id)
            .val(textareaValue)
            .add(
                 jQuery('<button>Save</button>')
                    .attr('id', 'btnSave' + id)
                    .click(function(){ /* Click handler */ })
            )
            .add(
                 jQuery('<button>Cancel</button>')
                    .attr('id', 'btnCancel' + id)
                    .click(function(){
                        /* Remove nodes */
                        tr.remove();
                    })
            );

        var tr = jQuery('<tr colspan="4"><td/></tr>');

        tr.find('td').append(textarea);
        tr.appendTo(self);

    });

});
J-P
+1 Yest this is the right approach!
TheVillageIdiot
I like this answer best since it is the most complete answer for my question (add form elements and callbacks). Followup questions: 1) If my original set of nodes have ids as editN where N is a integer, I would like to give these dynamic nodes txtN, btnSaveN, etc. How can I extract the N? 2) How would the Cancel button remove all these nodes? 3) For layout purposes, I would like to enclose the textarea/save/cancel in a TR/TD (colspan=4), how can I do that?
VANJ
Edited as per your requirements :)
J-P
J-P, you are the best! Let me chew on this. Quick question...Is <button> some special token for JQuery? I thought the markup to create a button is input type="button"?
VANJ
It's a valid HTML element, very similar to `<input type="button"/>` - you can use whichever one you want...
J-P
Didn't know that, thanks! One more question, if you don't mind. Instead of adding all the nodes at once, the document.ready() function should just add a image/link to jQuery(yourNodes) and clicking that should do add all the form elemnents as you showed. How can this be done?I can see why JQuery is such a popular library, it is very powerful once you start to "think" JQuery!
VANJ
jQuery(yourNodes).append(jQuery('<a>Click!</a>').click(function(){...ADD TEXTAREA ETC....}));
J-P
Thanks. I am unclear about something though...Your first example used .each to add the textarea to each matched node. When using jQuery(yourNodes).append(jQuery('<a>Click!</a>').click(), would the .each still be necessary? In other words, does the .click returns the original JQuery object with all my matched nodes or does it return just the newly appended <a> node? In the former case, I would need to use the .each(...) while in the latter case I would need...what?Thanks for all your help, I am really learning a lot about JQuery from this example.
VANJ
Within the click handler, `this` would be equal to a single anchor within a single element within yourNodes, then you can add the textarea and buttons just to that element, so, no, the each() is no necessary. Try this: http://gist.github.com/240115
J-P
Thanks again. In the anchor click handler, you use this.parentNode to access the node matched by the original query. But what if I need to access this node deep inside the code? Would "this" always refer to the original matched node anywhere in the code? Even inside a "each" loop? Speaking of "each", why is this necessary? Doesn't all JQuery code execute for all matched elements anyway? I did read http://www.learningjquery.com/2007/08/what-is-this and http://docs.jquery.com/Core/each but I am not clear on the concepts. Thanks for your patience.
VANJ
We could talk for ages about the need of using `each()` versus just using jQuery methods, but basically, it centers around the need to maintain closure-specific variables, where each iteration of the each loop creates a new function closure, within which we can store variables (such as 'textarea'). In the code I gave you (http://gist.github.com/240115), `this` always refers to the clicked element, whatever it may be, and `this.parentNode` refers to the clicked element's parent.
J-P
I changed var tr = jQuery('<tr colspan="4"><td/></tr>'); tovar tr = jQuery('<tr><td colspan="4"/></tr>'); See http://screencast.com/t/YjlmZjg4N2ItThe newly created TR doesn't seem to close the previous TR and so renders on the same row almost as if it is a TD and not a TR! Any idea why?
VANJ
Sorry, I get it now. You were right, the TR needs the colspan. Just changing tr.appendTo(self); to tr.insertAfter(self); and changing the initial .append() to .after() does what I need. Thanks a lot for your help, I really appreciate it.
VANJ
One more problem...when "mynodes" returns just 1 node, everything works fine. But when it returns multiple nodes, the Click link gets added after all of them, but clicking on it does nothing, no errors either. It is as if the click handler is not getting properly attached. Any ideas? Thanks
VANJ
Looks like I need to use .each() after all. One more question, if you are still around. Clicking the link once adds the textarea and buttons. But while they are visible, clicking it again shouldn't add more elements. How is this sort of thing done?Thanks
VANJ
A: 

As far as appending textarea, buttons to selected nodes @Nikita Prokopov's answer will do the trick. But as you want to add callbacks and back-end interactions, the best way to do will be to write a plugin.

TheVillageIdiot
OK how would I do that?
VANJ
A: 

Nikita Prokopov..answered the question. I have been working with jquery for a little while and this is what I have discovered.

Always give actions a name like so:

var SubmitText = $('#form-text-idNumber').submit(function {
                       //do stuff here
                       return false;
                  }

Dont do this:

$('#form-text-idNumber').submit(function {
                       //do stuff here
                       return false;
                  }

if you give your actions a variable it will not interfere with other similar forms on the page

Just give all of your actions and sections a variable and you should be good.

Luke101