Creating elements dynamically and adding functions with different parameters. - javascript

I'm creating anchor tags dynamically and I want them to call a function that has a set parameter for each one.
Example:
<div class="AnchorHolder">
<a onclick="someFunction(1)">someText</a>
<a onclick="someFunction(2)">someText</a>
<a onclick="someFunction(3)">someText</a>
</div>
I've tried
$("#AnchorHolder").append("<a>" + someText + "</a>").click(function (e) {
someFunction(someIntVariable);
});
but instead connects all of the anchors to the IntVariables current value, whereas I wanted the previous ones.
How can I accomplish this?

Well, I would suggest you to try data attributes. As far I know they are made for that porpuse. See:
$("#AnchorHolder").append("<a href='#' data-myvar='" + someIntVariable + "'>" + someText + "</a>");
// Keep the event binding out of any loop, considering the code above will be called more than once...
$("#AnchorHolder").on('click', 'a', function (e) {
alert($(this).data("myvar"));
});
Fiddle

If you just want the click on the new element, tack it onto that element, and not on the #AnchorHolder element:
var newAnchor = $("<a>" + someText + "</a>").click(function (e) {
someFunction(someIntVariable);
});
$("#AnchorHolder").append(newAnchor);
Or, alternatively to get each <a> to call the someFunction with their postion-inside-the-div:
$("#AnchorHolder a").each(function(idx) {
var a = $(this);
a.click(function() { someFunction(idx); });
});

You can always create a html element as following
$('<a>').attr("onclick","fun('hi')").html('Some text').appendTo("#AnchorHolder");
Hope this helps

Related

How to remove div elements from the DOM tree one by one?

Here is my example.
By clicking the add button, I add a user card. "Clear button" removes all cards. How to remove cards one by one clicking on the "close" icon in each card?
HTML file
<div class="header">
<button id="clear" class="button clear">Clear</button>
<button id="button" class="button add">Add user</button>
</div>
<div id="content">
</div>
JS file
var root = 'https://jsonplaceholder.typicode.com';
var index = 0;
$.ajax({
url: root + '/posts/1/comments',
method: 'GET'
}).then(function(data) {
$("#button").click(function() {
var notificationMessage = "Oops, there are no more user cards to display";
if (index >= data.length ) {
return alert(notificationMessage);
}
$("#content").append('<div id="card"><div class="title"><div class="image"></div><div id="name">'
+ data[index].name + '</div><span id="close"></span></div><div id="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
index++;
// remove all cards from a list and return index equally [0], to be able add user card again.
$("#clear").click(function() {
$("#card").remove();
index = 0;
});
});
});
//How to remove card by clicking on the close button?
have you try to use class in card element?
because id selector only get first matching element
$.ajax({
url: root + '/posts/1/comments',
method: 'GET'
}).then(function(data) {
$("#button").click(
function() {
var notificationMassage = "Oops, there are no more user cards to display";
if (index >= data.length ) {
return alert(notificationMassage);
}
$("#content").append('<div class="card"><div class="title"><div class="image"></div><div class="name">'
+ data[index].name + '</div><span class="close"></span></div><div class="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
index++;
// remove all cards from a list and return index equally [0], to be able add user card again.
$("#clear").click(function() {
$("#content").html('');
index = 0;
});
});
to remove one by one add this code
// remove one cards from a list.
$("#content").on("click", ".close", function() {
$(this).closest('div.card').remove();
});
First of all you need to change id to to class.
And here is solution:
codepen.io/ivanchuda/pen/xRjyJp
First of all, ids should be unique. I recommend changing yours into classes.
$("#content").append('<div class="card"><div class="title"><div class="image"></div><div class="name">'
+ data[index].name + '</div><span class="close"></span></div><div id="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
Now that we have all close icons with class close, we can add the following listener for all .close buttons to remove only the card which contains them.
$(document).on('click', '.close', function(){
$(this).closest('.card').remove(); // remove only closest '.card'
});
First off, I would change the ID on the divs to class instead since you are generating multiple cards. IDs should be unique. Then I would change the code to add one more line to your close-span:
<span class="close" onclick="$(this).parent().parent().remove()"></span>
Try like this
See the updated codeopen
Change the id to class .And match with parent() of parent()
on() more important
$(document).on("click",".close",function() {
$(this).parent().parent().remove()
});
You can use this code to implement what you want:
$("body").on("click", ".close", function(e) {
$(this).closest('.card').remove();
});
Note: Remember that use only single ID on a single page, instead use classes to make it work
See this CodePen
// jQuery on() method description
.on( events [, selector ] [, data ], handler )
See more about jQuery's on() method.
Hope this helps!
The short and not elegant answer is:
$("#content").on("click", "span[id=close]", function() {
$(this).closest("div[id=card]").remove();
});
This should work, but you need to do a better job than this. Your HTML is invalid, since id is expected to be unique and you use the very same id for different items. You could use classes instead, or make sure that the identifier is unique. Note that your SEO will instantly improve if you make your HTML valid. If you use classes instead of not-unique ids, then the script above will change to this one:
//content is unique, therefore it can remain an id
$("#content").on("click", "span.close", function() {
$(this).closest("div.card").remove();
});

Javascript append + click remove them

I got a question, what I have already solved, but it's just so annoying.
I have a js code, which is putting down some html code when a button is pushed with "append", and with that code I'm giving an id to an x button, and an id to the container element. I wanted to use these id-s to identify them with a click function, to remove the html code:
var num = 0;
$('.button').click(funcion(){
num++;
var code = '\
<div class="container" id="text' + num + '">\
<div id="x' + num + '">\
x\
</div>\
Some stuff\
</div>\
';
$('.puthere').append(code);
$('#x' + num).click(function(){
$('#text' + num).remove();
});
});
Now the annoying part is the click function on the x. What I would expect is, that this code would work somehow like this:
1st click on the "button" class element should give this code:
$('#x1').click(function(){
$('#text1').remove();
});
after 2nd click I should have this:
$('#x1').click(function(){
$('#text1').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
instead what I'm getting after the 2nd click is this:
$('#x1').click(function(){
$('#text2').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
so it's always the last element what the x buttons want to remove. My question is, why can my "num" variable stay "1" at the #x1, but not at the #text1?
My solution was to address the parent element instead:
$('#x' + num).click(function(){
$(this).parent('.container').remove();
});
I know, that there is the "live" function too, what I could use, and I wouldn't need to mess with id-s, but that just seems more heavy. Is that correct? Or I'm overcomplicating things too much without making it more efficent?
It's because num is global and you access it after you create second button. To fix this you can wrap your code with anonymouse self executing function:
(function(num) {
$('#x' + num).click(function(){
$('#text' + num).remove();
});
})(num);
or better use only one click
$('.parent').on('click', '.container > div', function() {
$(this).parent().remove();
});

Variable Interpolation in Jquery code inside for loop

I have some code, http://jsfiddle.net/hucw940s/
which has a for loop.
before
<div id="container">
</div>
after
for (i = 1; i < 4; i++){
var showMe = $('<a href=# id="link' + i + '">')
.append('click').click(function(){ alert('You clicked num: ' + i) });
$('#container').append(
$('<div id="div'+i+'">').append('this is div number: ' + i).append(showMe)
);
}
so the links are generated with id=link1, link2, link3 etc, and the divs appended are the same, however the onclick code seems to put the var i in after the event, so on clicking any link they say "you clicked number 4"
How can I make this use the i from the clicked link inside the function that is called on click?
What you are experiencing is the expected behavior based on your code.
However, what you are actually trying to do is pass in event data to your click function. This can be accomplished like this:
for (i = 1; i < 4; i++) {
var showMe = $('<a href=# id="link' + i + '">').append('click')
.click({value: i}, function (e) { alert('You clicked num: ' + e.data.value) });
$('#container').append($('<div id="div' + i + '">').append('this is div number: ' + i).append(showMe));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
</div>
First, you have to assign the event data, so we pass in an object
{value: i} before we pass in the handler function.
Then, in the handler function, we assign the variable e to the
event, so we can access the data attribute.
Finally, you access the value that was passed in by referencing
e.data.value.
You can add as many event data objects as you want and reference them by name this way.
The reason your code is not working as you are expecting is because the variable i is already equal to 3 by the time the click event happens, since the for loop completes before you are able to click any of the links.
Hope this helps give you a better understanding of why your code is behaving the way it is and what you can do to fix it.
Store the id in a data-attribute.
Updated jsFiddle

Very simple jQuery spoiler functionality half works

I have implemented a really simple jQuery spoiler functionality using the following code:
HTML:
<a href="" onclick="return false" class="spoiler" content="spoiled content">
Reveal spoiler
</a>
jQuery / Javascript:
$('a.spoiler').click(function(){
$text = "" + $(this).attr("content") + "";
$(this).replaceWith($text);
});
Basically, I just want the spoiler's content attribute to swap with the text in between the tags. It works for the first click, however it does not swap back when clicked again.
Is there any way for me to implement this in a way where it will indefinitely swap the content?
Thanks!
Simply use
$('a.spoiler').click(function(){
var text = $(this).text();
var content = $(this).attr("content");
$(this).text(content).attr("content", text)
});
DEMO
Otherwise, You need to use Event Delegation using .on() delegated-events approach as you are using replaceWith which is remove elemnent with which event was binded.
$(document).on('click','a.spoiler',function(){
$text = "" + $(this).attr("content") + "";
$(this).replaceWith($text);
});
DEMO
You can use this
$('a.spoiler').click(function () {
$(this).text(function (_, t) {
return t.trim() == "Reveal spoiler" ? $(this).attr('content') : "Reveal spoiler";
});
});
DEMO
Change your code to-
$(document).on('click','a.spoiler',function(){
$text = "" + $(this).attr("content") + "";
$(this).replaceWith($text);
});
If new HTML is being injected into the page,use delegated events to attach an event handler
Edit-
DEMO
$('a.spoiler').click(function(){
$text = $(this).attr("content")
$(this).attr("content",$(this).text()).text($text);
});

What are my options to get all the necessary data using javascript and/or jQuery for the following scenario?

I'm not sure how to best word this, so I'll give it a shot and hopefully revise it as it comes to me.
Using javascript/jQuery, let's say I want to get some data from a clicked element to a function for processing. A couple of options:
OPTION 1:
$('.classOfInterest').click(function() {
// How can I get 'a' and 'b'?
var c = $(this).hasClass('cExists');
});
<a class="cExists classOfInterest" />
OPTION 2:
function processClick(string a, string b) {
// How can I get a reference to the calling element, similar to $(this) in the event handler?
var c; // here I want to determine whether the calling element has class 'cExists'
}
<a class="cExists" href="javascript:processClick('a', 'b')" />
Option 1 is the more jQuery-ish way to accomplish what you're trying to do. You can get a and b by making them attributes of the link:
$('.classOfInterest').click(function() {
// How can I get 'a' and 'b'?
var c = $(this).hasClass('cExists');
alert(this.attr('a') + ' ' + this. attr('b'));
});
<a class="cExists classOfInterest" a="hi" b="mom" />
JS:
function processClick(id, a, b) {
$(id).click(function() {
var c = $(this).hasClass('cExists');
alert(a + ' ' + b);
});
}
HTML:
<script type="text/javascript">processClick("foo123", "a", "b")</script>
<a class="cExists" id="foo123" href="#">
Another option if you want to avoid the inline js inside the html is to do something like the following.
JS:
$(function() {
$('cExists').click(function() {
var c = $(this).hasClass('cExists');
var a = $(this).attr('title').split(":")[0];
var b = $(this).attr('title').split(":")[1];
alert(a + ' ' + b);
});
});
HTML:
<a class="cExists" href="#" title="foo:bar">
But this way you'll be exposing the a and b variables on the element's title.
If you're looking for a standards-compliant solution, you might consider using a data URI, e.g.
foo
To get the data, read out the href attribute and use split() to extract the comma-separated values. Remember to prevent the default action via preventDefault() or return false when handling the click event - otherwise, browsers will try to download the data or just fail.

Categories