i have function including while loop in my function first process is completed but not gone again in click event
$('body').on('click', 'button.expandcollapse', function() {
// var currenttrid = $("tr.selected").attr("data-id");
var parentid = $(".selected").data("id");
var parrentid = (parentid) - 1;
var rowclick = parseInt($(this).closest('tr').attr('data-id'));
var currentid = rowclick + 1;
if ($("tr[data-id='" + parrentid + "'] > td:first-child button").hasClass("expandcollapse")) {
var parentleft = $("tr[data-id='" + rowclick + "']> td:first-child").css("padding-left");
while (true) {
var chiledtrleft = $("tr[data-id='" + currentid + "']> td:first-child").css("padding-left");
if (chiledtrleft <= parentleft) {
break;
}
$("tr[data-id='" + currentid + "']").hide();
currentid = currentid + 1;
}
$("span", this).text
} else {
var parentleft = $("tr[data-id='" + rowclick + "']> td:first-child").css("padding-left");
while (true) {
var chiledtrleft = $("tr[data-id='" + currentid + "']> td:first-child").css("padding-left");
if (chiledtrleft <= parentleft) {
break;
}
$("tr[data-id='" + currentid + "']").show();
currentid = currentid + 1;
}
$("button").removeClass("expandcollapse");
$("span", this).text("-");
}
i want again it comes to click event
now the else condition is continuously working but i want go to the click event after one step completd
In the end of the function You are doing
$("button").removeClass("expandcollapse");
So since there is no button with class expandcollapse . It does not get triggered for second time
Checkout this Demo . Your code goes something like this , and dont work on second click.
So better plan a logic first before implementing.
You can use this selector to make it work (only and only if you are not adding the button dynamically)
$("button.expandcollapse").click(function(){
Working Demo
if dynamic then use your selector with this change for your second last line of code
$(this).removeClass("expandcollapse");
Suggestion : Better Use different class for .removeClass() at last . Why do you want to remove the same class with which you are triggering the event. Please use some other class for other functionalities in click function.
Related
When a new button is created it isn't being picked up by the rest of the code
var topics = ["dog", "cat", "pangolin", "snake", "bird", "emu", "cow", "hedgehog"]
$(document).ready(function () {
$("#btnAddSubmit").click(function() {
var newAnimal = $("#addInput").val();
topics.push(newAnimal);
newAnimal = newAnimal.toLowerCase();
$("#buttons").append('<button id="gif' + newAnimal + '">' + newAnimal + '</button>');
});
$("button").click(function() {
var currentGif = this.id;
if (this.id != "submit") {
currentGif = currentGif.replace("gif", "");
currentGif = currentGif.toLowerCase();
var topicNum = topics.indexOf(currentGif);
var myUrl = "https://api.giphy.com/v1/gifs/search?q=" + topics[topicNum] + "&api_key=oaPF55NglUdAyYKwDZ0KtuSumMrwDAK9&limit=15";
$.ajax({
method: "GET",
url: myUrl,
}).then(function(response) {
console.log(currentGif);
console.log(response);
$("#gifLocation").empty();
var gifURL = response.data[0].images.fixed_width.url;
console.log(response.data.length);
var gifNum = response.data.length
for (var i = 0; i < gifNum; i++) {
$("#gifLocation").append('<div id=gifDiv' + i + '></div>');
gifURL = response.data[i].images.fixed_width.url;
var gifRateId = "gifRate" + i;
var ratingLocString = '<p id="' + gifRateId + '"></p>'
var ratingLoc = $(ratingLocString);
var rating = response.data[i].rating;
var gifRating = "Rating: " + rating;
$("#gifDiv" + i).append(ratingLoc);
$("#" + gifRateId).text(gifRating);
var gifId = "gif" + i;
var gifImage = $('<img class=gif id=' + gifId + '>');
gifImage.attr("src", gifURL);
$("#gifDiv" + i).append(gifImage);
}
});
console.log(currentGif);
}
});
});
What I'm trying to do is when the user creates a new button, that button will then work like the premade buttons. The premade buttons are supposed to display a few gifs.
What is happening is that after I create the new button, clicking on that button won't even console log the id of that new button.
Your event listener $("#btnAddSubmit").click worked only with already created buttons. That is means your new buttons will be without this listener. If you want to add listeners to the new buttons, you must do something like:
// We are create event listener as a function for convenient use
var onButtonClick = function () {
var currentGif = this.id;
if (this.id != "submit") {
currentGif = currentGif.replace("gif", "");
// Your code here...
}
}
$("#btnAddSubmit").click(function() {
var newAnimal = $("#addInput").val();
topics.push(newAnimal);
newAnimal = newAnimal.toLowerCase();
$("#buttons").append('<button id="gif' + newAnimal + '">' + newAnimal + '</button>');
// We are remove all button's listeners and at once add new
$("button").off('click').on('click', onButtonClick);
});
// And this code will add your listener as it was originally
$("button").off('click').on('click', onButtonClick);
Be cearful if your buttons have another event listeners. If it exists, you connot use .off(). In that case is correct way will be add listener for a new specific button's id.
Based on your question and the js code provided, i guess this is because the newly added button doesn't get the event.
All events are attached to the dom on page load. The new buttons that are injected to the DOM doesn't get the events. jQuery already did the bindings to DOM elements before the new code was injected. To solve this you have to use '.on() method in jQuery
Something like this
$(document).on('click','your_button_class_here',function(){
dosomething();
});
You're using the ready callback, so all of this runs when the DOM is ready. However, you don't actually create the new button until this ready callback has already run! So when you try to add callbacks with $("button").click(function(){}), you are trying to add that callback to all the buttons on the DOM... but some of the buttons you want to add it to do not exist yet. They won't exists until that first button's click callback is executed! So the first button you make will have the callback attached, but the new ones will not.
Maybe try something like this? I expect something will be wrong with how the value of this works on your click callback, but I think it's a nudge in the right direction.
$(document).ready(function () {
$("#btnAddSubmit").click(function () {
var newAnimal = $("#addInput").val();
topics.push(newAnimal);
newAnimal = newAnimal.toLowerCase();
$("#buttons").append('<button id="gif' + newAnimal + '">' + newAnimal + '</button>');
// be wary of what the value of `this` refers to! it might refer to
// the `this` of the scope in which it was defined!
function gifCallback() {
var currentGif = this.id;
if (this.id != "submit") {
currentGif = currentGif.replace("gif", "");
currentGif = currentGif.toLowerCase();
var topicNum = topics.indexOf(currentGif);
var myUrl = "https://api.giphy.com/v1/gifs/search?q=" + topics[topicNum] + "&api_key=oaPF55NglUdAyYKwDZ0KtuSumMrwDAK9&limit=15";
$.ajax({
method: "GET",
url: myUrl,
}).then(function (response) {
console.log(currentGif);
console.log(response);
$("#gifLocation").empty();
var gifURL = response.data[0].images.fixed_width.url;
console.log(response.data.length);
var gifNum = response.data.length
for (var i = 0; i < gifNum; i++) {
$("#gifLocation").append('<div id=gifDiv' + i + '></div>');
gifURL = response.data[i].images.fixed_width.url;
var gifRateId = "gifRate" + i;
var ratingLocString = '<p id="' + gifRateId + '"></p>'
var ratingLoc = $(ratingLocString);
var rating = response.data[i].rating;
var gifRating = "Rating: " + rating;
$("#gifDiv" + i).append(ratingLoc);
$("#" + gifRateId).text(gifRating);
var gifId = "gif" + i;
var gifImage = $('<img class=gif id=' + gifId + '>');
gifImage.attr("src", gifURL);
$("#gifDiv" + i).append(gifImage);
}
});
console.log(currentGif);
}
};
// reference the new button by its ID and add your desired callback
$("#gif").click(gifCallback)
});
});
I've been stuck with this for several days and I can't solve it.
I've done it with jQuery with no problem, but I need it in pure JS.
This is how my list is generated.
function get_friends(items){
if(items != undefined){
if (items.length != 0){
var html_friends_list = "";
for(var count = 0; count < items.length; count++){
if(items[count].subscription == "both"){
var display_name = Strophe.getNodeFromJid(items[count].jid);
html_friends_list = html_friends_list + "<li style='font-size:19px' id='open_chat-" + items[count].jid + "'>" + "<a href='chat-js/index.html'>" + display_name + "<span class='block-list-label' id='" + items[count].jid + "_unread_messages" + "'>0</span><span class='block-list-label' id='" + items[count].jid + "_change_status" + "'></span></a></li>";
}
}
document.getElementById("friends-list").innerHTML = html_friends_list;
As a said I want to save the value of the text and the id of any li element clicked.
Regards
you haven't specified whether this is for a specific list or just any li on your page. The below will log the id and innerHTML components of any li on the page. Perhaps you may need to update the querySelector for your particular use case.
var list = document.querySelectorAll('li');
Array.prototype.slice.call(list).forEach(function(listItem){
listItem.addEventListener('click', function(e){
console.log(this.id);
console.log(this.innerHTML);
});
});
Here's a JSFiddle which I think demonstrates what you are trying to achieve.
Jsfiddle
Combination of james' answer and working example.
function get_friends(items) {
if (items != undefined) {
if (items.length != 0) {
var html_friends_list = "<ul>";
for (var count = 0; count < items.length; count++) {
if (items[count].subscription == "both") {
html_friends_list = html_friends_list + "<li id='open_chat-" + items[count].jid + "'>"+ items[count].display_name +"</li>";
}
}
html_friends_list = html_friends_list + '</ul>'
document.getElementById("friends-list").innerHTML = html_friends_list;
}
}
}
Note: you should trigger prototype after your dom element created.
I'm using the .each function to hide/show columns of a table. But the problem is that the code is very slow in IE. After searching on internet I saw that could be because of my .each() function and $(this).
For more information why I'm using this code, you can look at this post: Hide/show column
This is my old code:
include JQuery.min.js on page
javascript:
$(function () {
$('table th').each(function (_id, _value) {
if(_id > 2){
if($(this).find("a").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$(this).find("a").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(_id + 1) + '),table th:nth-of-type(' + parseInt(_id + 1) + ')').toggle();
e.preventDefault();
});
}
else{
if($(this).find("div").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$(this).find("div").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(_id + 1) + '),table th:nth-of-type(' + parseInt(_id + 1) + ')').toggle();
e.preventDefault();
});
}
}
}
});
});
HTML:
<div id="togglers">Show/Hide columns<br/></div>
I tried to convert my javascript with this code (Source: jQuery very slow in IE), but I think there is still a problem with my i(or _id) and _value...
$(function () {
var items = $('table th');
var $currentItem;
for (var i = 0, j = items.length; i < j; i++) {
$currentItem = $(items[i]); // in place of $(this)
function (i, _value) {
if(i > 2){
if($currentItem.find("a").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$currentItem.find("a").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(i + 1) + '),table th:nth-of-type(' + parseInt(i + 1) + ')').toggle();
e.preventDefault();
});
}
else{
if($currentItem.find("div").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$currentItem.find("div").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(i + 1) + '),table th:nth-of-type(' + parseInt(i + 1) + ')').toggle();
e.preventDefault();
});
}
}
}
}
}
});
It's possible that I need to use other code. Any suggestion is welcome! Tnx.
Performance issue has nothing to do with .each. DOM is tens of times slower than any way to iterate collection you choose.
Instead of iterating table on every toggle you can make CSS do it for you. Demo.
$(function() {
var togglers = $('#togglers'), //cache toggler ref
addToggler = function(idx, text) {
togglers.append('<span class="toggler" data-id="'
+ idx + '">' + text + '</span>');
},
table = $('#table'), //cache table ref
columns = 0;
//generate styles for 100 columns table :)
(function generateStyleSheet(len){
var styles = [], i = 0;
for(; i < len; i++) {
styles.push('.hide-' + i + ' .column-' + i + ' {display: none;}') ;
}
$('<style>' + styles.join('\n') + '</style>').appendTo(document.body);
}(100))
//bind on click once using event delegation
togglers.on('click', '.toggler', function(e){
var id = $(e.target).toggleClass('pressed').data('id');
table.toggleClass('hide-' + id);
});
//generate all togglers and count em
table.find('th').each(function(idx, header){
header = $(header);
addToggler(idx, header.text()); //make toggler
header.addClass('column-' + idx); //add class column-i
columns++;
});
//add column-i class to tds
table.find('td').each(function(idx, td) {
$(td).addClass('column-' + (idx%columns));
});
});
Please go to: www.designedbychristian.com/template_2
(so far being tested in chrome)
When you click design a bunch of thumbnails appear.
I am trying to use the .each selector to get the src of the image. I want to take that value and apply it to a div that will appear when clicked. (I know how to program that part)
My problem is when I click the thumb nail my alert is giving me the value of all of the thumbnails.
my code is this:
function spawnImages() {
N = 1
for (i = 1; i <= 9; i++) {
var gal = document.getElementById('gallary')
var newDIV = '<img onclick="imageView()" src="images2/image' + N + '.jpg" class="thumb-nail imageNumber' + N + '"/>'
$('.gallary').prepend(newDIV)
var min = 3;
var max = 70;
var s = Math.floor(Math.random() * (max - min + 1)) + min;
var test = $(('.imageNumber' +N)).css("left", s + "%")
var min = 3;
var max = $(this).height();
var max = 70;
var s = Math.floor(Math.random() * (max - min + 1)) + min;
var test = $(('.imageNumber' + N)).css("top", s + "%")
var min = -45;
var max = 45;
var s = Math.floor(Math.random() * (max - min + 1)) + min;
var test = $(('.imageNumber' + N)).css("-webkit-transform", "rotate(" + s + "deg)")
var test = $(('.imageNumber' + N)).css("transform", "rotate(" + s + "deg)")
var test = $(('.imageNumber' + N)).css("-ms-transform", "rotate(" + s + "deg)")
N++
}
}
function imageView() {
$(".thumb-nail").each(function () {
var imageSrc = $(this).attr('src');
alert($(this).attr('src'));
//$('.images').css("background-image", "url("+imageSrc+")");
//$('.images').css("background-size", "cover");
//$('.blackForeground').css("visibility", "visible");
//$('.images').css("visibility", "visible");
})
};
Just use jquery event handlers, get rid of the onclick call in your html and just add this in your javascript.
$(".thumb-nail").on('click', function(){
var imageSrc = $(this).attr('src');
alert($(this).attr('src'));
//$('.images').css("background-image", "url("+imageSrc+")");
//$('.images').css("background-size", "cover");
//$('.blackForeground').css("visibility", "visible");
//$('.images').css("visibility", "visible");
});
EDIT: didn't think about the images being created dynamically, Popnoodles answer is the right one
pass clicked element reference like this:
var newDIV = '<img onclick="imageView(this)" src="images2/image' + N + '.jpg" class="thumb-nail imageNumber' + N + '"/>'
Function:
function imageView(element) {
var imageSrc = $(element).attr('src');
alert($(element).attr('src'));
}
This is exactly how the jQuery API describes the .each() method:
Iterate over a jQuery object, executing a function for each matched element.
When you called $('.thumb-nail') it returned ALL of the elements with the class thumb-nail in a jQuery object. Then when you called .each( function() {} ) on that object, the loop iterated over all of the returned elements.
The easiest way to handle click events in jQuery, is to use the .on() method, as others have pointed out in their answers.
Also, as #Popnoodles mentioned, since these elements are created dynamically, you may need to run your $().on() call explicitly after these elements are created. For that reason, you might wrap it into your spawnImages() function, rather than putting it inside $() as #Popnoodles indicates (i.e. not $( $(element).on('click',function(){}), as $( ) is equivalent to $(document).ready.
The simplest change is this
// send this element to the function
var newDIV = '<img onclick="imageView(this)" src="images2/image' + N + '.jpg" class="thumb-nail imageNumber' + N + '"/>'
function imageView(el) {
var imageSrc = $(el).attr('src');
alert($(el).attr('src'));
};
But it's nice to do things in a more standard fashion...
First get rid of this onclick="imageView()"
var newDIV = '<img src="images2/image' + N + '.jpg" class="thumb-nail imageNumber' + N + '"/>'
Since these elements are created dynamically you will need to bind the click event to document or another ancestor that exists, and delegate to each ".thumb-nail".
You also need to run this procedure only when dom is ready ($(function(){...});).
$(function(){
$(document).on('click', ".thumb-nail", function () {
var imageSrc = $(this).attr('src');
alert($(this).attr('src'));
//$('.images').css("background-image", "url("+imageSrc+")");
//$('.images').css("background-size", "cover");
//$('.blackForeground').css("visibility", "visible");
//$('.images').css("visibility", "visible");
});
});
This is my all script, I know this is long, but just one line is important and I add all it for insurance:
//Add new Addable div
$('.AddNewE').click(function () {
var RemoveAddableButton = $('<input type="button" class="RemoveE button red" value="remove" />');
$(RemoveAddableButton).click(function () {
$(this).closest('.Addable').remove();
});
var TargetId = $(this).attr('id');
TargetId = TargetId.substring(3);
var Target = $('.Addable#' + TargetId + ':first');
var Count = $('.Addable#' + TargetId).size();
var CloneTarget = $(Target).clone();
CloneTarget.find('input').val('');
CloneTarget.insertAfter('.Addable#' + TargetId + ':last'); // ***importantOne
var TargetName = $(Target).find('input').attr('name');
if (Count == 1) {
var CloneName = TargetName + '[1]';
TargetName = TargetName + '[0]';
$(Target).find('input').attr('name', TargetName);
$(Target).find('span[class*="field-validation"]').attr('data-valmsg-for', TargetName);
$(CloneTarget).find('input').attr('name', CloneName);
$(CloneTarget).append($(RemoveAddableButton));
if ($(CloneTarget).find('span[class*="field-validation"]').size() > 0) {
$(CloneTarget).find('span[class*="field-validation"]').remove();
$(CloneTarget).append(
$('<span class="field-validation-valid invalid-side-note" data-valmsg-replace="true" data-valmsg-for="' + CloneName + '"></span>')
);
}
} else {
var indx = TargetName.length - 3;
var CloneTargetName = TargetName.substring(0, indx);
CloneTargetName = CloneTargetName + '[' + Count + ']';
$(CloneTarget).find('input').attr('name', CloneTargetName);
$(CloneTarget).append($(RemoveAddableButton));
if ($(CloneTarget).find('span[class*="field-validation"]').size() > 0) {
$(CloneTarget).find('span[class*="field-validation"]').remove();
$(CloneTarget).append(
$('<span class="field-validation-valid invalid-side-note" data-valmsg-replace="true" data-valmsg-for="' + CloneTargetName + '"></span>')
);
}
}
(function ($) {
$.fn.updateValidation = function () {
var form = this.closest("form").removeData("validator").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
return this;
};
})(jQuery);
$(Target).updateValidation();
$(CloneTarget).updateValidation();
});
If I click the .AddNewE button then a new div added, but as my script I want to add this new div to the end of the divs so I use
CloneTarget.insertAfter('.Addable#' + TargetId + ':last');
but always the new div added as a second div it means always the :first and :last div is same and is first one also I checked by:
$('.Addable#' + TargetId).css('border', '');
$('.Addable#' + TargetId + ':last').css('border', '3px dotted green');
$('.Addable#' + TargetId + ':first').css('border', '3px dotted red');
So where is the problem? why the jQuery can't recognize last div ?
The problem is in the jQuery selector: $('.Addable#' + TargetId + ':last')
It is not valid HTML when you have multiple elements with the same id (#TargetId). ID is unique and you're not supposed to have more than 1 element with the same ID.
The jQuery selector assumes you use valid correct HTML markups, so it doesn't bother to collect all your elements with that ID. As soon as jQuery found the first element in the DOM with that ID, it stops and appends your new element right after that.
Try updating your jQuery selectors to simply: $('.Addable:first') and $('.Addable:last') and see if it works.