I'm currently using the following code for my read more buttons:
$(document).ready(function() {
$("a.more-link").attr("href", "");
$("a.more-link").attr("onclick", "return false;");
$('.readmore').each(function(index) {
var $link = $(this);
$(".readmore").prependTo('.' + $link.attr("id") + ' > #bottominfo');
});
$('.readmore').click(function() {
var $link = $(this);
if ( $link.attr("alt") == "read more" ) {
$('.' + $link.attr("id") + ' > #maincontent').load($link.attr("title") + ' #mainarticle', function(index) {
$('.' + $link.attr("id") + ' > #maincontent').hide();
$('.' + $link.attr("id") + ' > #maincontent').slideToggle('slow');
});
$('.' + $link.attr("id") + ' > #maincontent').attr("class", $link.attr("id"));
$link.attr('alt','read less');
} else {
$('#'+ $link.attr("id") + ' > .' + $link.attr("id")).hide();
$link.attr('alt','read more');
}
return false;
});
});
The problem I'm having is that if the user double clicks (or more) on the button it calls the function multiple times.
How do I make the button non-clickable until the .load() have finished?
The easiest would be to add a loading class to the link. I have also just done a quick clean up on your code. I didn't look into how it works but i'm sure if you spend a bit more time you can make it a lot more efficient
$(document).ready(function() {
$("a.more-link").attr("href", "")
.attr("onclick", "return false;");
$('.readmore').each(function(index) {
var $link = $(this);
//wouldn't this call all the elements with "readmore" class????
$(".readmore").prependTo('.' + $link.attr("id") + ' > #bottominfo');
});
$('.readmore').click(function() {
var $link = $(this);
//check if it has already been clicked
if($link.hasClass("loading")) return false;
//add the loading class
$link.addClass("loading");
if ( $link.attr("alt") == "read more" ) {
$('.' + $link.attr("id") + ' > #maincontent').load($link.attr("title") + ' #mainarticle', function(index) {
$('.' + $link.attr("id") + ' > #maincontent').hide()
.slideToggle('slow');
//it's done now and we can remove the loading class so we can click it again
$link.removeClass("loading");
}).attr("class", $link.attr("id"));
$link.attr('alt','read less');
} else {
$('#'+ $link.attr("id") + ' > .' + $link.attr("id")).hide();
$link.attr('alt','read more');
//add it here as well
$link.removeClass("loading");
}
return false;
});
});
Tips: I notice you call the same selectors multiple times. Always check the api doc and see what the methods you are calling do return. Most of them do return the element back, so then you can call the next method without $()
Example: $("div").hide().slideToggle('slow');
Could you not just run the function on .load instead?
$(document).load(function() {
$("a.more-link").attr("href", "");
$("a.more-link").attr("onclick", "return false;");
$('.readmore').each(function(index) {
var $link = $(this);
$(".readmore").prependTo('.' + $link.attr("id") + ' > #bottominfo');
});
$('.readmore').click(function() {
var $link = $(this);
if ( $link.attr("alt") == "read more" ) {
$('.' + $link.attr("id") + ' > #maincontent').load($link.attr("title") + ' #mainarticle', function(index) {
$('.' + $link.attr("id") + ' > #maincontent').hide();
$('.' + $link.attr("id") + ' > #maincontent').slideToggle('slow');
});
$('.' + $link.attr("id") + ' > #maincontent').attr("class", $link.attr("id"));
$link.attr('alt','read less');
} else {
$('#'+ $link.attr("id") + ' > .' + $link.attr("id")).hide();
$link.attr('alt','read more');
}
return false;
});
});
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 4 years ago.
I am using jquery to pull in JSON and loop through the results to create a collection of items. Namely, Anchors with a few data attributes. I then am watching those items so that on click I can pull the relevant data attributes and... do things with that data. When I hard code in the anchors with the data, everything works great. When I create them dynamically through the JSON I get nothing, and the page refreshes.
jQuery( document ).ready(function() {
$.getJSON("http://glacier.creativefilterdev.com/wp-json/wp/v2/chocolate?categories=42&per_page=100&order=asc", function(result) {
$.each(result, function(i, item) {
if(item.better_featured_image == null){
} else {
$(".white").append("<a class=\"choc-option\" href=\"\" data-text=\"" + item.title.rendered + ", \" data-img=\"" + item.better_featured_image.media_details.sizes.thumbnail.source_url + "\"><img class=\"chocolate\" src=\"" + item.better_featured_image.media_details.sizes.thumbnail.source_url + "\"><br>" + item.title.rendered + "</a>");
}
});
});
jQuery("a[data-text]").click(function(){
if(howMany < countVar) {
howMany += 1;
var imgurl = jQuery(".single").val();
var structure = jQuery('<div class="single" data-text="'+ jQuery(this).attr('data-text') +'"><img src="'+ jQuery(this).attr('data-img') +'"><a class="delete">-</a></div>');
jQuery('.buildbox').append(structure);
jQuery("#alert").css('display', 'none');
} else {
jQuery("#alert").css('display', 'block');
}
return false;
});
});
I apologize as there is code in there that I haven't explained as that is the "stuff" I'm doing with the data from the anchors.
You can do it like this
jQuery( document ).ready(function() {
$.getJSON("http://glacier.creativefilterdev.com/wp-json/wp/v2/chocolate?categories=42&per_page=100&order=asc", function(result) {
$.each(result, function(i, item) {
if(item.better_featured_image == null){
} else {
$(".white").append("<a class=\"choc-option\" href='' data-text=\"" + item.title.rendered + ", \" data-img=\"" + item.better_featured_image.media_details.sizes.thumbnail.source_url + "\"><img class=\"chocolate\" src=\"" + item.better_featured_image.media_details.sizes.thumbnail.source_url + "\"><br>" + item.title.rendered + "</a>");
}
});
});
$('body').on('click', 'a[data-text]', function(e) {
e.preventDefault();
alert('test');
if(howMany < countVar) {
howMany += 1;
var imgurl = jQuery(".single").val();
var structure = jQuery('<div class="single" data-text="'+ jQuery(this).attr('data-text') +'"><img src="'+ jQuery(this).attr('data-img') +'"><a class="delete">-</a></div>');
jQuery('.buildbox').append(structure);
jQuery("#alert").css('display', 'none');
} else {
jQuery("#alert").css('display', 'block');
}
return false;
});
});
I use 2 different scripts on a webpage - one pure JS, the other jQuery.
The JS script is used for toggling the hamburger menu in mobile view. hamb.onclick shows the menu when clicking on hamburger, menuL.onclick hides the menu when clicking on a menu item. The latter refuses to work when the jQuery script is active (it works when the jQuery script is commented out).
<script>
(function () {
function hasClass(elem, className) {
return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
}
function toggleClass(elem, className) {
var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' ';
if (hasClass(elem, className)) {
while (newClass.indexOf(' ' + className + ' ') >= 0) {
newClass = newClass.replace(' ' + className + ' ', ' ');
}
elem.className = newClass.replace(/^\s+|\s+$/g, '');
} else {
elem.className += ' ' + className;
}
}
var hamb = document.querySelector('.hamburger');
var menuL = document.querySelector('.menuList');
hamb.onclick = function () {
toggleClass(this, 'hamburgerOpen');
toggleClass(menuL, 'menuActive');
};
menuL.onclick = function () {
toggleClass(hamb, 'hamburgerOpen');
toggleClass(menuL, 'menuActive');
};
})();
</script>
The jQuery is used for smooth navigation/scrolling to the anchors of the page:
<script>
function scrollNav() {
$('.menu a').click(function(){
//Toggle Class
$(".active").removeClass("active");
$(this).closest('li').addClass("active");
var theClass = $(this).attr("class");
$('.'+theClass).parent('li').addClass('active');
//Animate
$('html, body').stop().animate({
scrollTop: $( $(this).attr('href') ).offset().top - 160
}, 800);
return false;
});
$('.scrollTop a').scrollTop();
}
scrollNav();
</script>
As i understand it, the jQuery script highjacks the onclick event of the JS script, because they work on the same parent element: ".menu a" and "menuList" (which is the "ul" inside ".menu").
What can i do to get both scripts working together? I'm a beginner and my JavaScript skills are still weak.
If the second script hijacks the event, just move the function into the second script and run it there.
It works!
I am trying to do gallery portfolio with help of masonry and custom click event. I can hide show images with the click event, but when hide show event complete masonry not reset to again.
link
Here is jQuery code:
var pmo = "#p-masonry_outer";
var ppt = "#p-portfolio_typs";
$('' + ppt + ' li span').on('click', function() {
$('' + ppt + ' li span').removeClass('p-active_work');
$(this).addClass('p-active_work');
var WorkRel = $(this).data("cat");
if (WorkRel != "0") {
$("" + pmo + " > div").hide();
$(".p-masonry a").attr('data-lightbox', '');
$("" + pmo + " > div").each(function() {
var WorkAttrStrip = $(this).data('cat');
var WorkAttr = WorkAttrStrip.split(",");
if ($.inArray(WorkRel + "", WorkAttr) !== -1) {
$(this).show;
}
});
var $container = $('.js-masonry');
$container.imagesLoaded(function() {
$container.masonry();
});
} else {
$("" + pmo + " > div").fadeIn("slow");
}
return false;
}
I'm trying to make a website using jquery-1.11.1 where I want a <textarea> to be spawned whenever I click on the link which only shows on mouseenter on a div. But I'm getting an error in my console,
Uncaught ReferenceError: inputdivEditor is not defined (Please ignore JSFiddle errors)
I've absolutely no idea why I'm getting this. Here are my codes,
$(document).ready(function () {
$("[id^=divEditor-]").each(function () {
var content = $(this).html();
var targetID = $(this).attr('id');
var txtID = 'input' + targetID;
$('<textarea id="input' + targetID + '" name="' + txtID + '" >' + content + '</textarea>').insertBefore(this).css('display', 'none');
var button = "<a onclick='activateDivEditor(this, " + txtID + ")' class='custom-edit-button editDiv' id='active" + targetID + "'>Embed Code</a>";
$(this).on('mouseenter', function () {
$(this).prepend($(button));
$(this).css('position', 'relative');
});
$(this).on('mouseleave', function () {
$('.editDiv').remove();
});
});
});
function activateDivEditor(btn, txtId) {
var targetID = $(btn).parent().get(0).id;
var update = "<a onclick='deactivateDivEditor(this, " + txtId + ")' class='custom-edit-button updatediv' id='deactive" + targetID + "'>Update</a>";
var cancel = "<a onclick='cancelactivateDivEditor(this)' class='custom-edit-button cancel' id='cancelactive" + targetID + "'>Cancel</a>";
var targetClass = $('#' + targetID).attr('class');
var targetWidth = $('#' + targetID).width();
$('#' + targetID).css('display', 'none');
$('#input' + targetID).css('display', 'block').css('width', targetWidth - 2).css('height', '125px');
$('#input' + targetID).parent().css('position', 'relative');
$(update).prependTo($('#input' + targetID).parent());
$(cancel).prependTo($('#input' + targetID).parent());
}
JSFiddle Demo
How can I generate a textarea whenever I click on the button link? Need this help badly. Thanks.
I have the following condition in a long function:
if ( shipSet == true ) {
$("#" + shippingFields[i]).style.background = 'gray';
$("#" + shippingFields[i]).className = 'optional';
} else {
$("#" + shippingFields[i]).removeAttribute('style');
$("#" + shippingFields[i]).removeClass('optional');
}
the style lines work fine, whether true or false, but the className and removeClass lines aren't working. Any suggestions? Am I just not using them properly?
Since ("#" + shippingFields[i]) return a jQuery object.
You need to use addClass() and removeClass() instead:
if ( shipSet == true ) {
$("#" + shippingFields[i]).css('background','gray');
$("#" + shippingFields[i]).addClass('optional');
} else {
$("#" + shippingFields[i]).removeAttr('style');
$("#" + shippingFields[i]).removeClass('optional');
}
Also, you can use css() to set the styles of your elements.
You should use addClass (to add class to element) and removeClass (to remove class from element):
$("#" + shippingFields[i]).addClass('optional');
$("#" + shippingFields[i]).removeClass('optional');
if ( shipSet == true ) {
$("#" + shippingFields[i]).css('background','gray');
$("#" + shippingFields[i]).addClass('optional');
} else {
$("#" + shippingFields[i]).removeAttr('style');
$("#" + shippingFields[i]).removeClass('optional');
}
Try this, for adding class name use always $("#attributeID").addClass('ClassName');
if ( shipSet == true ) {
$("#" + shippingFields[i]).css('background','gray');
$("#" + shippingFields[i]).addClass('optional');
} else {
$("#" + shippingFields[i]).removeAttr('style');
$("#" + shippingFields[i]).removeClass('optional');
}