jQuery Clone inputs in two forms on the same page? - javascript

I have been trying to get two forms on the same page to work and the only issue i'm having is not getting the clone inputs to work, they seem to conflict with each other due to the div elements.
I have been using this tutorial as a guide:
http://www.9lessons.info/2009/06/submit-multiple-forms-jquery-ajax.html
Here is the code working with one form:
http://jsfiddle.net/yBdTA/
And this is what i want to achieve:
http://jsfiddle.net/c4Uce/
Notice when you click on the second 'Add More' link the first input clones rather than the second.
I know i could duplicate the jQuery function for the clone to match the second form:
$(function(){
var removeLink = ' <a class="remove" href="#" onclick="jQuery(this).parent().slideUp(function(){ jQuery(this).remove() }); return false">remove</a>';
jQuery('a.add').relCopy({ append: removeLink});
});
but i want this to be, how can i call it, dynamic? like the 9lessons guide, i can use PHP to create unique identifiers for the clone elements and want the jQuery to match the ID's,
Hope i made this clear.
Help appreciated.

U can try it , it work to multi form
http://jsfiddle.net/yBdTA/2/
(function($) {
function remove(){
$('.clone').each(function(i){
var input= $(this);
input.find('a.remove').click(function(){
input.remove();
});
});
}
$('form').each(function(i){
var form = $(this);
var removeLink = '<a class="remove" href="#">remove</a>';
var iputclone = form.find('p.clone').append(removeLink);
form.find('a.add').click(function(){
iputclone.clone().insertBefore(this);
remove();
});
});
})(jQuery);
Update :
iputclone.clone().insertBefore(this).find('.input').attr('value','');
//So easy, U can think a object when we start will is ifself, use it next, and next

Related

Select button with jQuery for casperjs

I want to select a button with casperjs, but my issue is that the button has changing IDsand classes. I can only "identify" the button, based on the text of a span 2 levels done:
<button class="changes-always" id="changes-always-too">
<div class="changes-always2">
<span class="changes-always3">Same text</span>
</div>
</button>
With jQuery I can select the button, by first selecting the span, because it always has the same content.
var span = $('span:contains("Same text")');
var button = span.parent().parent() // there is probably a nice way to do this
I got jQuery loaded by casperjs by including it as clientScripts, my issue is how to correctly get it working with the evaluate(function() as well as use the variables as selectors with casperjs (if that's even possible)
This is how far I got, but then I ran into problems with object and string issues.
casper.then(function() {
var items = this.evaluate(function () {
return $('span:contains("Some text")');
});
console.log(items);
});
Would be great, if someone could point me in the right direction, how to use jQuery as a selector and then let casperjs use it. Thanks many times in advance!
You can also use clickLabel() if the text is unique.
casper.clickLabel("Some text");
This should work for buttons, too.
Another option and still not with jquery should be getting the id's by text and if there are sometimes the same text, grab them out by the index:
...
var x = require('casper').selectXPath;
var buttonIDs;
// get button ID's with specific text by getElementsAttribute with xPath selector
buttonIDs = casper.getElementsAttribute(x("//button[contains(text(),'Some specific text')]"), 'id');
casper.then(function() {
casper.echo(buttonIDs);
});
casper.then(function() {
casper.click("button[id='" + buttonIDs[0] + "']");
});
...

Sending an array in a javascript function with append

So here is the situation, im creating a clickable dynamic table by adding row with a button. Each row have informations and can be clicked (the entire row). I look for a way to send the information of the row I clicked to another js function who will copie the row in another dynamic table. But here is the trick : to create a clickable row, I use the function .append and I create the row in a < a> tag which will use href="function_to_add_the_copied_row" to call the other function.
The problem is I cant find out the good syntax. Any suggestion for syntax or other way to do the trick would be appreciated. Here is my code :
//javascript function to make clickable rows
{
var infos = modules_found[i].split("\\t");
rowNum++;
//word ="'Row number : "+infos[0]+"'";
$(".targets").append('<li> <div class="ui-grid-a"><div class="ui-block-a ui-grid-b"><div class="ui-block-a">'+infos[0]+'</div><div class="ui-block-b">'+infos[1]+'</div><div class="ui-block-c">'+infos[2]+'</div></div><div class="ui-block-b ui-grid-b"><div class="ui-block-a">'+infos[3]+'</div><div class="ui-block-b">'+infos[4]+'</div><div class="ui-block-c">'+infos[5]+'</div></div></div></li>');
}
//javascript function who receive the array and add the copied row
function transferArray(infos)
{
alert("in transferArray function");
$(".copied").append('<li> <div class="ui-grid-a"><div class="ui-block-a ui-grid-b"><div class="ui-block-a">'+infos[0]+'</div><div class="ui-block-b">'+infos[1]+'</div><div class="ui-block-c">'+infos[2]+'</div></div><div class="ui-block-b ui-grid-b"><div class="ui-block-a">'+infos[3]+'</div><div class="ui-block-b">'+infos[4]+'</div><div class="ui-block-c">'+infos[5]+'</div></div></div></li>');
}
Here is a high level approach (assuming you know jQuery): instead of wrapping your row inside A tag, better way is to have register a click event listener on your table (via jQuery APIs and not in HTML). In that click handler you can get the index of row clicked easily (make use of jQuery APIs) and once you have the rowindex, you can easily clone the row and move it to somewhere else.
typically how this is handled - if you are not using some type of javascript library like Angular or Knockout is to just store data in the actual HTML with data attributes. you can make as many data attributes as you want as long as they start with data-
ex.
$(".targets").append('<li data-id="xx" data-name="xx" data-custom=""> <a href="...
then I would recommend using jQuery click handler on every row by giving them all a class , ex.
$(".targets").append('<li class="rowClick" data-id="xx" data-name="xx" data-custom=""> <a href="...
then handle the click like this
$(document).on('click' , 'rowClick' , function(e){
var $this = $(this);
//get data of row clicked
var idClicked = $this.attr('data-id');
var nameClicked = $this.attr('data-name');
// you also have the full HTML of the clicked row if you need to copy somewhere
var rowHtml = $(".copied").append($this);
});
You're already using jQuery , so use it to handle the click and then you have the element clicked as a jQuery object right there . You can use native javascript function to handle the click and pass data like you were , but you already are using jQuery and that will automatically bring in a lot more data for you.
Finally, I used native javascript function since the suggested solution didn't work, even if it looks all legit. So here is what I have done:
(...)
//append the js function
$(".FindTable").append('<li id="addedFindRow"><div class="ui-grid-a"><div class="ui-block-a ui-grid-b"><div class="ui-block-a">'+infos[0]+'</div><div class="ui-block-b">'+infos[1]+'</div><div class="ui-block-c">'+infos[2]+'</div></div><div class="ui-block-b ui-grid-b"><div class="ui-block-a">'+infos[3]+'</div><div class="ui-block-b">'+infos[4]+'</div><div class="ui-block-c">'+infos[5]+'</div></div></div></li>');
}
function copyrow(info0,info1,info2,info3,info4,info5)
{
//use data
}
This is quite heavy, but that will do. Would be more chaotic if there was more parameters thought.

dynamically created form depending on <select> does not work

I'm developing a website which must display particular forms for various products depending on the value that the user selects (in <select>) - so a number various forms are created dynamically in a loop by means of a javascript function (buildform() ). The code does not work, e.g. the forms are not created/appended to the wrappers. I narrowed down the problem where i think the problem relates to a different values for the jquery selectors/div-id's (#ecorpproductwrapper"+ecorp_eprodselectid).
When I use (just as a test) #ecorpproductwrapper" (without the variable ecorp_eprodselectid; see also in code below under ALTERNATIVE WORKS) the code works fine, e.g. the forms are built. I checked by means of the console that the ecorpproductwrapper"+ecorp_eprodselectid values are the same for the div-id's and jquery selectors, so I dont understand what goes wrong?
Pls see the simplified code below:
for(var i=0;i<5;i==){
var ecorp_eprodselectid; //will have various values
//function to build form depending on selected value in <select class= eprodtype"+ecorp_eprodselectid >
$(".eprodtype"+ecorp_eprodselectid).focus(function () {
var previous;
// Store the current value on focus and on change
previous = this.value; //old select value
}).change(function() {
var optionsform = buildform(this.value);
console.log('append form'+optionsform);
//NEXT 2 lines doe NOT WORK
$("#ecorpproductwrapper"+ecorp_eprodselectid).children().remove(); //remove previous form
$("#ecorpproductwrapper"+ecorp_eprodselectid).append(optionsform);
//ALTERNATIVE works: $('#ecorpproductwrapper').children().remove(); //remove previous tariif struct form
//ALTERNATIVE works: $('#ecorpproductwrapper').append(optionsform);
var str = "#ecorpproductwrapper"+ecorp_eprodselectid;
console.log('STRING ECORP PRODUCT APPEND: '+str);
console.log('change eprod val: '+this.value);
previous = this.value;
});//$("").focus(function () {
}//for i
//function to build form
var buildform = function(ecorp_eproductid) {
//some code here
//NEXT LINE does not work:
form += '<td> <div id="ecorpproductwrapper'+ ecorp_eprodselectid+'"> </div> </td> </tr>'; //cell with wrapper for ecorp product info
//ALTERNATIVE WORKS: form += '<td> <div id="ecorpproductwrapper"> </div> </td> </tr>'; //cell with wrapper for ecorp product info
//some code here; returns form
}//function buildform
I think you forgot to add ecorp_eprodselectid in your function.
var buildform = function(ecorp_eprodselectid ) {
Few things we assume concerning given text above:
You know this.value works
console.log shows optionsform have HTML that it should have. Not said in OP but if not, the function does not work. function seems to be missing already var buildform = function(someVar) as noted by buysDB
As I cannot see your code, I would try first clear everything 100% by chaning this:
$("#ecorpproductwrapper"+ecorp_eprodselectid).children().remove();
to:
$("#ecorpproductwrapper"+ecorp_eprodselectid).html("");
Then:
$("#ecorpproductwrapper"+ecorp_eprodselectid).html(optionsform);
No need for append if you have no intention to keep anything in DIV.
If you have text also in (#ecorpproductwrapper"+ecorp_eprodselectid) which is why you use children(), consider selecting the DIV that can be cleared.
If that still does not work, something is left out that needs consideration.

Search submit button in all forms with textareas with jquery

I'm working on a Firefox-plugin which searches a webpage for all textareas and places a warning before the submit button.
my code looks like this
var submitWarning = content.document.createElement("div");
submitWarning.innerHTML = "Fancy Message";
$('textarea', window.content.document).each(function() {
var form = $(this, window.content.document).parents('form:first');
$(form, window.content.document).children('input[type=submit]').each(function() {
form.insertBefore(submitWarning, this);
});
});
if i search all submits with $('input[type=submit]'.each it works fine but since i added the thing with the textarea and the form:first i got problems (nothing happens)
p.s. i use the window.content.document thingy because its a ff-plugin and it won't work nothing without it
You need to change it a bit, like this:
var submitWarning = content.document.createElement("div");
submitWarning.innerHTML = "Fancy Message";
$('textarea', window.content.document)
.closest('form')
.find('input[type=submit]')
.before(submitWarning);
The argument syntax is $(selector, context), when finding the form, first there's .closest() which makes this easier, also when you have an element, you can just use $(this) inside it's .each(), no need to search for it again. Also, you can use .before() to make it easier :)
The :has() selector is the best choice for me. Get rid of your extensive code and use this instead.
var buttons = $("form:has(textarea) input[type=submit]", window.content.document);
$("<div>").html("Fancy Message").insertBefore(buttons);
Try var form = $(this, window.content.document).closest('form');. Not sure if that's the ticket, but it's the first thing off my head.

Question about selecting form children jquery

Again I'm asking question about comment form, I'm making an image website and every image has its own comment form, so when I submit form I do like this :
$('#comment_form').live('submit', function() {
...
So in order to select only this form textearea value I tried using this but I get undefined error here is how I tried :
$('#comment_form').live('submit', function() {
image_comment_text=$(this).closest("#comment_text").val(); //textarea id is comment_text
I tried to used find(), its working but when I submit comments for few images I get comments 2 or 3 times as I should, because find finds all occurrences of textarea with comment_text id .. how can I do this ?
#molf , here is HTML generated by javascript:
var xHTML = "<div class=\"addComment\">";
xHTML += "<form action=\"<?=base_url()?>images/post_comment/" + post + "\" method=\"post\" class=\"comment_form\" name=\"comment_form\">";
xHTML += "<input type=\"hidden\" class=\"comment_post_id\" name=\"comment_post_id\" value=\"" +post + "\"/>";
xHTML += "<textarea class=\"comment\" name=\"comment_text\" rows=\"8\" cols=\"40\"></textarea>";
xHTML += "<input type=\"submit\" name=\"submit\" class=\"post_image_comment\" value=\"Comment\"><span> Don't make it too big!</span>";
xHTML += "</form></div>";
EDIT
When I print to console log the value of textarea I get only one result as I should, now when I try to append the ul comments I get 2 of the same values .. here how it goes ..
<ul class="comments"></ul>
below is the comment form which is not in the document at all, when certain anchor is clicked the form pops out below .comments , when form submits I want to append the comments to add the new comment to list items of existing unordered list comments , here is the whole code :
$('form[name^="comment_form"]').live('submit', function(event) {
r= $(this).find('> .comment').val();
$('<div class="overlay"></div>')
.appendTo('.addComment')
.fadeIn(200, function() {
$('.comments')
.append('<li id="new_append">' + r + '</li>')
.children(':last')
.height($('.comments li:last').height())
.hide()
.slideDown(800, function() {
var bodyHeight = $('html').height();
$('.addComment').fadeOut(500, function() {
$('html').height(bodyHeight);
$('h2#leaveAComment').fadeOut(200, function(){$(this).text('Thank you for your comment!').fadeIn(200)});
});
});
$('html, body').scrollTo( $('#new_append'), 800 );
});
event.preventDefault();
});
EDIT II #patrick
The javascript which loads the comment form is above .. here is HTML :
-------------BEGIN FOR EACH--------------
<div id="image-12" class="image_content">
<img src="..." />
<ul class="comments hidden"> //This is where the comments are appended to <li></li>
</ul>
<div style="float: left; display: block; width: 100%;">
<a id="image_comment-12" class="image_comment" onclick="showComments('12');" href="javascript:;">Add Comment</a>
</div>
<div id="addComment-12">//this is where the comment form loads
</div>
</div>
----------END--- FOR EACH--------- image ...
First of all, change your selector for your form. I think you can select form by name using the id selector, but you're not supposed to duplicate ids on a page, so jQuery live is probably only watching the first form. This is just a guess, though.
Also, it doesn't matter what class/id you use for your textarea. If you're only going to have one textarea per form, you can use the :text selector. When finding children, I like to use the children selector.
$('form[name="comment_form"]').live('submit', function() {
image_comment_text = $(this).find('> :text').val();
});
If you're using name instead of id because you're going to have multiple forms, I would suggest changing the name to comment_form_'image_id', then your selector would be: $('form[name^="comment_form"]')
Notice the ^ which requires the name to start with 'comment_form'. That way, you can have unique form names (comment_form_234, comment_form_235) and still have the desired effect.
Edit:
I looked at your code update, and it looks to me like you're ignoring the context of the current form in your function. For instance, when you use the selector $('.comments').append(... you're appending to all elements on your page which match that selector. In order to retrieve the proper elements, you'll have to always use your selector as $(this).find(' > .comments').append(... which will work within the context of the submitted form.
I took a few minutes to edit your code, I haven't run it or anything, but it should be close to what you're trying to do. I hope it at least gets you started in the right direction:
$('form[name^="comment_form"]').live('submit', function (event) {
r = $(this).find('> .comment').val();
/* get addComment-classed element */
var addComment = $(this).find(' > .addComment:first');
/* get comments-classed element */
var comments = $(this).find(' > .comments:first');
$('<div class="overlay"></div>').appendTo(addComment).fadeIn(200, function () {
/* note comments element, not selector */
$(comments).append('<li id="new_append">' + r + '</li>').children(':last').height(
/* again, element */
$(comments).find(' > li:last').height()).hide().slideDown(800, function () {
var bodyHeight = $('html').height();
/* again, element */
$(addComment).fadeOut(500, function () {
$('html').height(bodyHeight);
$('h2#leaveAComment').fadeOut(200, function () {
$(this).text('Thank you for your comment!').fadeIn(200)
});
});
});
$('html, body').scrollTo($('#new_append'), 800);
});
event.preventDefault();
});
I added comments in the code, but notice that the addComments and comments selectors are 'cached'. If you're going to be accessing these elements multiple times, storing them in a variable before using them will cut back on DOM traversals. This should really solve your comments being added to multiple elements on your page.
How many comment_forms do you have on a each page? For correct HTML you should only have one id='comment_text' and one id='comment_form' per page.
Consider changing your ids to class='comment_text' and finding with .comment_text rather than #comment_text
I think from your latest comments the issue may be the way you are dynamically adding your form/comments textbox to the page.
Once you've entered comments and submitted them do you then remove the form you've dynamically added? I would recommend this as if not I think your DOM structure is getting confused causing the problems you are experiencing.
First, the find() method was the correct way to go if used within the proper context.
Second, it sounds like you are re-using IDs. This is not allowed. An ID can be used only once on a page.
The closest() function searches 'up' from (and including) the DOM element. The find() function searches the content of the element.
EDIT:
I assume the form is being submitted when the user clicks the submit button. I also assume that there's more to your submit() handler than is shown. Is that correct?
Sometimes you need to add $(this).preventDefault(); in order to keep the form from being submitted in your code, as well as by the default behavior of the 'submit' button.
The following does the same thing (essentially) as find(). It will find the item with the .comment_text class within the form being submitted. So it should only grab the value of one item:
image_comment_text=$(".comment_text", this).val();
You are getting duplicate comments because you aren't removing the previous add comment form. Try adding this to the end of your .slideDown callback function:
$(this).remove();
Here is the full submit function, I made a few changes/additions:
I removed the > from the find('.comment') as it isn't necessary
Changed the new append to a class, then removed it after you scroll to it.
Removed the form when complete
Changed the event.preventDefault(); to return false;... this is more of a personal preference than anything.
I hope this helps :)
$('form[name^="comment_form"]').live('submit', function(event) {
r = $(this).find('.comment').val();
$('<div class="overlay"></div>')
.appendTo('.addComment')
.fadeIn(200, function() {
$('.comments')
.append('<li class="new_append">' + r + '</li>')
.children(':last')
.height($('.comments li:last').height())
.hide()
.slideDown(800, function() {
var bodyHeight = $('html').height();
$('.addComment').fadeOut(500, function() {
$('html').height(bodyHeight);
$('h2#leaveAComment').fadeOut(200, function(){$(this).text('Thank you for your comment!').fadeIn(200)});
$(this).remove();
});
});
$('html, body').scrollTo( $('.new_append:last'), 800 );
$('.new_append').removeClass('new_append');
});
return false;
});

Categories