How can I make this repetitious jQuery less so? - javascript

I have 4 blocks of jQuery that look like this:
$('#aSplashBtn1').click(function(){
$('#divSliderContent div').hide();
$('#divSplash1').fadeIn('slow');
return false;
});
$('#aSplashBtn2').click(function(){
$('#divSliderContent div').hide();
$('#divSplash2').fadeIn('slow');
return false;
});
$('#aSplashBtn3').click(function(){
$('#divSliderContent div').hide();
$('#divSplash3').fadeIn('slow');
return false;
});
$('#aSplashBtn4').click(function(){
$('#divSliderContent div').hide();
$('#divSplash4').fadeIn('slow');
return false;
});
I've tried learning more about javascript arrays and for loops but when I try to implement it into this code it only ends up working for the number 1 block. Could someone show me how they would accomplish optimizing this?

A variation on Sosh's answer
$('#aSplashBtn1').click(hideAndFadeIn('#divSplash1'));
$('#aSplashBtn2').click(hideAndFadeIn('#divSplash2'));
$('#aSplashBtn3').click(hideAndFadeIn('#divSplash3'));
function hideAndFadeIn(splash){
return function() {
$('#divSliderContent div').hide();
$(splash).fadeIn('slow');
return false;
};
}

If the clickable items are siblings, you can do:
$('#aSplashBtn1').siblings().andSelf().click(function(e){
$('#divSliderContent div').hide();
$('#divSplash'+e.target.id.substr(e.target.id.length-1)).fadeIn('slow');
e.preventDefault();
});

var $divSlider = $("#divSliderContent div");
$('*[id^=aSplashBtn]').live('click', function(e){
// Get the number from the id of the clicked element
var id = this.id.match(/^aSplashBtn(\d+)$/)[1];
$divSlider.hide();
$("#divSplash" + id).fadeIn('slow');
// Preferred as opposed to return false
e.preventDefault();
});
This will set a single handler that will match every element with an id that starts with aSplashBtn. Your id's could go as high as you wanted (i.e. #aSpashBtn100) and it would still pair with the correct div#divSplash100.
Also, I cached #divSliderContent div in its own variable since you don't want jQuery to 'look it up' again on each click.

Related

how to check if a ul has a particular li with jQuery?

I am working on the two ul lists. What I need is if someone click on the list item in list1, it will check if the 2nd list contains the clicked element or not. If it does not contain the element then copy it else just return.
What I have done so far is I am moving the elements successfully between the list but if I apply a check on it everything stops working.
Here is the link of jsfiddle.
$().ready(function() {
var classHighlight = 'highlight';
var $thumbs = $('ul li').on("click", function(e) {
//e.preventDefault();
debugger;
$thumbs.removeClass(classHighlight);
$(this).addClass(classHighlight);
});
$('#select1').on("dblclick", "li", function() {
//if($("#select2").has($(this))
//return;
//else
$(this).clone().appendTo('#select2').removeClass('highlight');
});
$('#select2').on("dblclick", "li", function() {
$(this).remove();
});
$('#add').click(function() {
$('#select1.highlight').clone().appendTo('#select2').removeClass(classHighlight);
});
$('#remove').click(function() {
$('#select2.highlight').remove();
});
});
If you un comment the above lines in code everything stop working.
Can any one please help me with this?
Thanks
Try this check:
var check = function(li) {
return $("#select2 li").filter(function(i, li2) {
return $(li2).text() == $(li).text();
}).length > 0;
};
Demo
As you're using clone(), you can't compare the new cloned element using is() or has() with the orignal one, because it is a new element, it isn't the same, as stated in clone's docs:
Create a deep copy of the set of matched elements
So it's a copy.
You have a missing paren.
This if($("#select2").has($(this)) should be this if($("#select2").has($(this))).
Also you can just pass this: if($("#select2").has(this))
And you have to check length: if($("#select2").has(this).length)

jQuery not executing code for new element with new id

I have an image, and when I click on it I want it to change to a different image and change its ID as well. Then when I click on this new image, it reverts back.
$(document).ready(function(){
$("#name_edit").click(function(){
$(this).attr("src", "img/tick.png");
$(this).attr("id","name_confirm");
});
$("#name_confirm").click(function(){
$(this).attr("src", "img/edit.png");
$(this).attr("id","name_edit");
});
});
I have successfully done the first step, going from #name_edit to #name_confirm. However, not the reverse.
How do I go about solving this?
My suspicion is that since I'm using (document).ready, jQuery is preparing itself for elements already on the page. However, the element with the ID name_confirm does not exist until the image is clicked on.
Thanks.
The element that you are working on is always the same...
$(document).ready(function(){
// use just the first id value to find it in the DOM
$("#name_edit").click(function(){
var item = $(this);
var id = item.attr('id');
if(id === 'name_edit') {
return item
.attr("src", "img/tick.png")
.attr("id","name_confirm")
;
}
return item
.attr("src", "img/edit.png")
.attr("id","name_edit")
;
})
;
});
I think you have chosen bad solution for your problem.
1) Why your code doesn't work:
You bind 2 events only 1 time, whne your document loaded. So, jquery finds #name_edit element and bind onclick event on it. But jquery cannot find #name_confirm element, because it doesn't exists on document ready)
In your code you should bind 1 onclick event, but have some attr (for example class for checking your state).
Something like:
<img id="main_image" class="name_edit"/>
<script>
var img_paths = ["img/tick.png", "img/edit.png"]
var img_index = 0;
$("#main_image").click(function(){
if($(this).attr("class") == "name_edit"){
$(this).attr("src", "img/tick.png");
$(this).attr("class","name_confirm");
}
else{
$(this).attr("src", "img/edit.png");
$(this).attr("class","name_edit");
}
});
</script>
Other solutions: You can create 2 images and show/hide them.
Or use styles with background attr. With pseudoclasses or classes.
Also you can store image pathes in array and tick array index on click.
Something like:
var img_paths = ["/content/img1.png", "/content/img2.png"]
var img_index = 0;
$("#main_image").click(function(){
$(this).src = img_paths[img_index];
img_index = !img_index;
})
It is not working because you are referencing the same elements, try this:
(function(window, document, $, undefined){
$("#name_edit").on("click", function(){
var self = $(this);
if(self.attr("id") === "name_edit") {
self.attr("src", "img/tick.png");
self.attr("id", "name_confirm");
} else {
self.attr("src", "img/edit.png");
self.attr("id", "name_edit");
}
});
})(this, this.document, jQuery);
Also for easier to understand code you could use classes like this:
(function(window, document, $, undefined){
$(".name_edit").on("click", function(){
var self = $(this);
if(self.hasClass("name_edit")) {
self.attr("src", "img/tick.png");
self.removeClass("name_edit").addClass("name_confirm");
} else {
self.attr("src", "img/edit.png");
self.removeClass("name_confirm").addClass("name_edit");
}
});
})(this, this.document, jQuery);
To simplify replacing classes you could even add your own $.fn.replaceClass(); like this:
jQuery.fn.replaceClass = function(classA, classB) {
this.removeClass(classA).addClass(classB);
return this;
};
Then use it like this:
(function(window, document, $, undefined){
$(".name_edit").on("click", function(){
var self = $(this);
if(self.hasClass("name_edit")) {
self.attr("src", "img/tick.png");
self.replaceClass("name_edit", "name_confirm");
} else {
self.attr("src", "img/edit.png");
self.replaceClass("name_confirm", "name_edit");
}
});
})(this, this.document, jQuery);
I can confirm what the others said.. the jquery gets run on document ready, but doesn't get updated subsequently - so it basically gets the correct element from the dom, and assigns the click event. It has no event for the name_confirm.
so this code does nothing...
$("#name_confirm").click(function(){
$(this).attr("src", "img/edit.png");
$(this).attr("id","name_edit");
});
See it not work in this instructive jsfiddle
Of course does the id need to change? is it possible to use for example a specific class for the img? then you could make the second click bind on the class instead... for example see this working example, which still changes the src and id...
Try On method:
$(document).on('click', '#name_edit', function(){
$(this).attr("src", "img/tick.png");
$(this).attr("id","name_confirm");
});
$(document).on('click', '#name_confirm', function(){
$(this).attr("src", "img/edit.png");
$(this).attr("id","name_edit");
});

using jquery 'this' to condense code

I try not to ask questions, but I can't figure out what should be very easy. I'm building a site for practice briannabaldwinphotography.com. I'm just trying to condense this so that I could just click on an anchor and it smooth scrolls to a <section> with an id the same name as the anchor. Ex: the 'about' li anchor has an href of #section_three and will scroll to the <section> with an id of section_three. I tried like 10 different variations and it won't work for me. Sort of what I'm looking for would be $(this).attr("href").offest().top}....etc. Here is the code I want to condense. Thanks.
$(function() {
$("[href='#section_three']").on("click", function() {
$("html body").animate({"scrollTop":$("#section_three").offset().top}, 1000);
return false;
});
$("[href='#section_two']").on("click", function() {
$("html body").animate({"scrollTop":$("#section_two").offset().top}, 1000);
return false;
});
$("[href='#section_four']").on("click", function() {
$("html body").animate({"scrollTop":$("#section_four").offset().top}, 1000);
return false;
});
$("[href='#section_one']").on("click", function() {
$("html body").animate({"scrollTop":$("#section_one").offset().top}, 1000);
return false;
});
});
If you use the attribute starts with selector (^=) you can get all elements with an href beginning with "#section_", bind a handler to those, then within the handler use this.href to get the href of the particular element that was clicked:
$(function() {
$("[href^='#section_']").on("click", function() {
$("html body").animate({"scrollTop" : $(this.href).offset().top}, 1000);
return false;
});
});
Note that this.href does the same job as $(this).attr("href"), but more efficiently: no need to create a jQuery object to access a property of the element that you can get to directly.
Since the href in each case matches the target element it makes it fairly simple
$("[href^='#section']").on("click", function() {
var targetSelector = $(this).attr('href');
$("html body").animate({"scrollTop":$(targetSelector).offset().top}, 1000);
return false;
});
If those elements have a common class or better path through parent class and tags you could improve the initial selector performance

Define a function globally in jQuery

I have some simple jQuery code, and it has a problem. The menu handler function doesn't work at all.
var clicked = false;
$(document).ready(function(){
$TemplateMenu= $('<p class="paragraph">texxt</p>');
$('.TemplateMaker').click();
this.menuhandler();
});
});
function menuhandler(){
if(clicked == false){
$(this).after($TemplateMenu);
clicked = true;
}
else{
$TemplateMenu.remove();
clicked = false;
}
For some reason, the function works if I put it directly inside click() like this:
$('.TemplateMaker').click(function(){
if(clicked == false){
$(this).after($TemplateMenu);
clicked = true;
}
else{
$TemplateMenu.remove();
clicked = false;
}
});
});
What is wrong with this code? Did I define the function wrong or do I need something special if the function contain jQuery elements?
Thanks for the help :-)
Edit:
I edit the code to include your guys suggestions, its stile doesn't seem to work.
code:
var clicked = false;
$(document).ready(function(){
$TemplateMenu= $('<p class="paragraph">texxt</p><p class="p2">texxt</p>');
$('.TemplateMaker').click(menuHandler($(this)));
});
function menuHandler(obj){
if(clicked == false){
$(obj).after($TemplateMenu);
clicked = true;
}
else{
$TemplateMenu.remove();
clicked = false;
}}
I notic now that the jquery throw this "event.returnValue is deprecated. Please use the standard event.preventDefault() instead. ", but I don't know how its contact to my script.
$('.TemplateMaker').click();
this.menuhandler();
});
Try replacing this.menuhandler(); with just menuhandler(); as shown below:
$('.TemplateMaker').click();
menuhandler();
});
Edit: In response to your comment. Try using this instead of $(this) in the menuhandler() of your original code.
You probably want the menuHandler function to fire when someone clicks on the button? Then you can simply change your code as follows:
$('.TemplateMaker').click(menuHandler);
Edit:
You basically have two options:
Option1:
You don't have to pass $(this) change your code to this (make sure you remove the parameter in the menuHandler function if you choose this approach):
$(document).ready(function(){
$TemplateMenu= $('<p class="paragraph">texxt</p><p class="p2">texxt</p>');
$('.TemplateMaker').click(menuHandler);
});
Option2:
Or if you want to pass $(this) you can do something like this (keep the parameter in the menuHandler function if you choose this approach):
$(document).ready(function(){
$TemplateMenu= $('<p class="paragraph">texxt</p><p class="p2">texxt</p>');
$('.TemplateMaker').click(function() {
menuHandler($(this));
});
});

how to hide submenu after click

I'm creating a dropdown menu for mobile site
http://gthost.dyndns.org/kudu/en/
when I click on My Account and click on Who we are, submenu still show,,
I Want to hide it after I click on the link.
this is JavaScript code
var $j = jQuery.noConflict();
$j(document).ready(function () {
$j(".account").click(function () {
var X = $j(this).attr('id');
if (X == 1) {
$j(".submenu").hide();
$j(this).attr('id', '0');
} else {
$j(".submenu").show();
$j(this).attr('id', '1');
}
});
//Mouseup textarea false
$j(".submenu").mouseup(function () {
return false
});
$j(".account").mouseup(function () {
return false
});
//Textarea without editing.
$j(document).mouseup(function () {
$j(".submenu").hide();
$j(".account").attr('id', '');
});
});
i would try using:
$('.submenu').css({display:"none"});
instead of .hide();
Two things strike me as odd here.
Why are your ID's integers - valid names start with [a-z_] etc.
Why are you changing the ID? An ID is meant to be a unique identifier and should persist as long as the element does. If you wish to store information about the state of an element within the element itself, then perhaps look into data attributes.
Without seeing your HTML structure everyone is going to be guessing but rather than whatever you are trying to do with the ID's it looks like you could logically use jQuery.toggle:
$j(".account").click(function(){
$j(".submenu").toggle();
});

Categories