I have some jQuery code that is quite redundant. I want to refactor it to avoid to duplicate it for every 30 numbers. Each pin-Small ID has a pin-Big ID with the same number. I want to have a code that works for every ID with a higher number (#pin-Small2, #pin-Small3, #pin-Big2, #pin-Big3 and so on ...). It's written in CoffeeScript, but I provide it as a JS version also.
I don't find a start to iterate through these numbers. Can u help me? I would be very thankful if you'd do so, dont't mind if it's in JS or CS. Thanks so much in advance! :)
CoffeeScript
$('#pin-Small1').on
mouseenter: ->
$(#).hide()
$('#pin-Big1').addClass "enabled"
$('#pin-Big1').on
mouseleave: ->
$(#).removeClass "enabled"
$('#pin-Small1').show()
JavaScript
$('#pin-Small1').on({
mouseenter: function() {}
}, $(this).hide(), $('#pin-Big1').addClass("enabled"));
$('#pin-Big1').on({
mouseleave: function() {
$(this).removeClass("enabled");
return $('#pin-Small1').show();
}
});
Seeing your HTML may really help as it could change this answer, but assuming that your HTML looks something like this:
<div id="pin-Small1" class="small" data-related-big-pin="pin-Big1"></div>
<div id="pin-Small2" class="small" data-related-big-pin="pin-Big2"></div>
...
<div id="pin-Big1" class="big" data-related-small-pin="pin-Small1"></div>
<div id="pin-Big2" class="big" data-related-small-pin="pin-Small2"></div>
You could use data attributes like this:
$('.small').on
mouseenter: ->
$(#).hide()
var bigPinId = $(#).data("related-big-pin")
$('#' + bigPinId ).addClass "enabled"
$('.big').on
mouseleave: ->
$(#).removeClass "enabled"
var smallPinId = $(#).data("related-small-pin")
$('#' + smallPinId).show()
So we use classes to bind the mouseenter/mouseleave functions then read data attributes to find which elements they interact with.
Use CSS classes and related selectors... HTML:
<div id="pin-Small1" class="pin"></div>
<div id="pin-Small2" class="pin"></div>
<div id="pin-Small3" class="pin"></div>
jQuery:
$('.pin').each(function() {
// do something with each element, e.g. to hide them all:
$(this).hide();
});
Related
In the HTML code there is a 'href' , is there any posiblity to wrap an A-tag() around it? I'm new to this so please don't be too harsh :)
Note that the jquery is there to find the 'href' of a child inside the div and setting that attritbute to .summary-item-wrapper
HTML:
<div class="summary-item-wrapper" href="www.google.no" id="yui_3_17_2_4_1483527702805_1738"><div>
Jquery:
$(document).ready(function(){
$('body').wrapInner('<div id="support"></div>');
$('#support .sqs-block-summary-v2 .summary-item').each(function () {
var linkto = $(this).find('.summary-title a').attr('href');
$(this).children('.summary-item-wrapper').attr('href', linkto);
});
});
If there are multiple divs on your page you wish to convert, and to remove divs, but to keep all attributes, you can do something like this:
$( "div.summary-item-wrapper" ).each(function() {
$(this).before('<a href=http://'+$(this).attr('href') +'>A link');
$(this).prev().attr('id',$(this).attr('id'));
$(this).prev().addClass($(this).attr('class'));
});
$('div.summary-item-wrapper').remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="summary-item-wrapper" href="www.google.no" id="yui_3_17_2_4_1483527702805_1738">44444444444</div>
<div class="summary-item-wrapper" href="www.google.com" id="yui_3_17_2_4_1483527702805_33333">ttttttttttt</div>
What you want can be done with this:
$('#support .sqs-block-summary-v2 .summary-item-wrapper').wrap(function () {
return '';
});
Also href="google.no" means go to <currentdomain>/google.no, in case you need the google.no use href="https://google.no"
Check JSFiddle.
Please consider the comments on your question too.
have used the following code to remove the style and id attributes from my html, but I would like them to come back once the visitor moves to another element. I'm fairly new to jQuery and have no idea how to achieve that. I would really appreciate somebody's help.
<div class="base" style="background-image: url(img/3.jpg);">
<div id="overlay"></div>
</div>
<script>
$('.base').hover(function(){
$(this).removeAttr('style').children().removeAttr('id');
}, function(){
$(this).addBack();
});
</script>
You have a wrong idea of what addBack() does, anyway the best here might be to use CSS classes.
Something like:
$('.base').hover(function(){
$(this).addClass('myClass');
}, function(){
$(this).removeClass('myClass');
});
Example
The part of the code where you remove the ID is irreversible, so I would find a alternative behaviour/solution there...
Something like this should work :
<div class="base" style="background-image: url(img/3.jpg);">
<div id="overlay"></div>
</div>
<script>
$('.base').hover(function(){
var $this = $(this);
$this.data('style', $this.attr('style')).removeAttr('style').children().each(function(){
var $this = $(this);
$this.data('id', $this.attr('id')).removeAttr('id');
});
}, function(){
var $this = $(this);
$this.attr('style',$this.data('style')).removeData('style').children().each(function(){
var $this = $(this);
$this.attr('id', $this.data('id')).removeData('id');
});
});
</script>
Basically we are storing attribute values in jQuery data arrays. I didn't test it but it should work, I've used this approach more than once..
Updated the code, and here is a working jsfiddle example
As I will have multiple places where this is, I would like to get it to work with a unique data.
Like instead of <a class="snippet_show_answers" href="#">Se svar</a> then maybe something like <a DATA="1" class="snippet_show_answers" href="#">Se svar</a>, which then should run as a part of my script, so that it only handle for the clicked DATA, and not for all of the boxes.
My HTML is this (With multiple of those):
<p class="snippet_answers">Svar: 3 - <span class="green"><a class="snippet_show_answers" href="#">Se svar<img src="images/answerarrow.png" alt="answerarrow" height="14" width="13"></a><a class="snippet_hide_answers" href="#" style="display: none;">Skjul svar<img src="images/answerarrow.png" alt="answerarrow" height="14" width="13"></a></span><hr />
<div class="answers" style="display: none;">
<p>blablabla</p>
</div>
</p>
My JS is this:
$('.snippet_show_answers').live("click", function() {
$('.answers').slideDown("slow");
$('.snippet_show_answers').fadeOut("slow");
$('.snippet_hide_answers').fadeIn("slow");
return false;
});
$('.snippet_hide_answers').live("click", function() {
$('.answers').slideUp("slow");
$('.snippet_hide_answers').fadeOut("slow");
$('.snippet_show_answers').fadeIn("slow");
return false;
});
Hope someone understand me, cause I have seen this method before, but I dont know the name of it, or anything.
Thanks in advanced.
Get a reference to the clicked item's parent element and then find its descendants with the appropriate class:
$('.snippet_show_answers').live("click", function() {
var item = $(this).closest(".snippet_answers");
item.find('.answers').slideDown("slow");
item.find('.snippet_show_answers').fadeOut("slow");
item.find('.snippet_hide_answers').fadeIn("slow");
return false;
});
$('.snippet_hide_answers').live("click", function() {
var item = $(this).closest(".snippet_answers");
item.find('.answers').slideUp("slow");
item.find('.snippet_hide_answers').fadeOut("slow");
item.find('.snippet_show_answers').fadeIn("slow");
return false;
});
Also, if you are using the latest version of jQuery, make sure to change .live() to .on(). .live() was recently deprecated.
I've seen various examples come close to what I am looking for, but none of it seems to describe it how I exactly want it. I am a beginner to jQuery, so explanations welcome.
I'm looking for this to toggle the innerHTML from - to +. Anyone know of a way to do this, efficiently?
jQuery/JavaScript
$(document).ready(function() {
$(".A1").click(function() {
$(".P1").toggle("slow");
$(".A1").html("+");
});
});
HTML
<div class="A1">-</div>
<h2 class="H1">Stuff</h2>
<div class="P1">
Stuffy, Stuffy, Stuffed, Stuffen', Stuffing, Good Luck Stuff
</div>
Thank you, anything relating to switching the inside text of an HTML element shall help. =)
How about adding a class that will let you know the expanded/collapsed status?
$(document).ready(function() {
$(".A1").click(function() {
var $this = $(this);
$(".P1").toggle("slow")
$this.toggleClass("expanded");
if ($this.hasClass("expanded")) {
$this.html("-");
} else {
$this.html("+");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="A1 expanded">-</div>
<h2 class="H1">Stuff</h2>
<div class="P1">
Stuffy, Stuffy, Stuffed, Stuffen', Stuffing, Good Luck Stuff
</div>
Example: http://jsfiddle.net/sGxx4/
$(document).ready(function() {
$(".A1").click(function() {
$(".P1").toggle("slow");
$(".A1").html(($(".A1").html() === "+" ? $(".A1").html("-") : $(".A1").html("+")));
});
});
A bit of explanation: I'm setting $("#A1").html() with the product of the tertiary operator, using it to check for the current value of #A1's text. If it's a +, I set the element's text to -, otherwise, I set it to +.
However, you said "efficiently." To this end, it's important to note that if you're going to use a selector twice or more in the same function, you should store the jQuery object that results from the selector you give in a variable, so you don't have to re-run the selector each time. Here's the code with that modification:
$(document).ready(function() {
$(".A1").click(function() {
var $A1 = $(".A1");
$(".P1").toggle("slow");
$A1.html(($A1.html() === "+" ? $A1.html("-") : $A1.html("+")));
});
});
There's no way to toggle content.
You could check if the $('.P1') is visible, then changing the +/- div according to that.
Something like :
$(document).ready(function() {
$(".A1").click(function() {
$(".P1").toggle("slow", function(){
if($(this).is(':visible'))
$(".A1").html("-")
else
$(".A1").html("+")
});
});
});
Using a callback function (the second argument of the .toggle() method) to do the check will guarantee that you're checking after the animation is complete.
JsFiddle : http://jsfiddle.net/cy8uX/
more shorter version
$(document).ready(function() {
$(".A1").click(function() {
var $self = $(this);
$(".P1").toggle("slow", function ( ) {
$self.html( $self.html() == "-" ? "+" : "-");
});
})
});
Here's a way that uses class names on a parent and CSS rules and doesn't have to change the HTML content and works off a container and classes so you could have multiple ones of these in the same page with only this one piece of code:
HTML:
<div class="container expanded">
<div class="A1">
<span class="minus">-</span>
<span class="plus">+</span>
</div>
<h2 class="H1">Stuff</h2>
<div class="P1">
Stuffy, Stuffy, Stuffed, Stuffen', Stuffing, Good Luck Stuff
</div>
</div>
CSS:
.expanded .plus {display:none;}
.collapsed .minus {display: none;}
Javascript:
$(document).ready(function() {
$(".A1").click(function() {
$(this).closest(".container")
.toggleClass("expanded collapsed")
.find(".P1").slideToggle("slow");
});
});
Working demo: http://jsfiddle.net/jfriend00/MSV4U/
The size of my JavaScript file is getting out of hand because I have hundreds of links, and each one has its own jQuery function even though they all peform basically the same task.
Here's a short excerpt:
$("#link1").click(function ()
{
$(".myDiv").hide();
$("#myDiv1").toggle();
});
$("#link2").click(function ()
{
$(".myDiv").hide();
$("#myDiv2").toggle();
});
$("#link3").click(function ()
{
$(".myDiv").hide();
$("#myDiv3").toggle();
});
Would there be a way to abstract some of this logic so that I have only a single function instead of hundreds that do the same thing?
You can add a class to all the links that do the same thing and act with jQuery on that class.
<a href='whatever' id='link_1' class='toggler'>text</a>
<a href='whatever' id='link_2' class='toggler'>text</a>
jQuery code will be:
$(".toggler").click( function(){
// toggle the divs
var number = $(this).attr("id").split('_')[1];
$(".myDiv").hide();
$("#myDiv"+ number).toggle();
});
The general approach that I use is to use the traversal methods to find related elements rather than using absolute selectors. This will allow you to apply the same code to elements that are similarly configured without any complicated dependencies on the format of the ids, etc. Done correctly it's also reasonably robust against minor changes to the mark up.
For example, say I have a series of links, each followed by a div that will be toggled by clicking on that link. The links each have a particular class so they can easily be referenced.
Toggle
<div>
Some content...
</div>
Toggle
<div>
Other content
</div>
I would then find all the links by class, then use the next method to find the associated div and toggle it's visibility. Note that this is a simple example. You may need to use more complicated traversal mechanisms and filter by element type or class, too, depending on your exact mark up.
$('.linkClass').click( function() {
$(this).next().toggle();
});
What about adding the ID of your target into the href of the link?
<a id="link1" href="#myDiv1" class="toggle">Toggle 1</a><br/>
<a id="link2" href="#myDiv2" class="toggle">Toggle 2</a><br/>
<a id="link3" href="#myDiv3" class="toggle">Toggle 3</a><br/>
Then you could write a single function like so:
$(".toggle").click(function(e) {
e.preventDefault();
$(".myDiv").hide();
$($(this).attr('href')).toggle();
});
Or another approach I've used:
$(".toggle").each(function(i) {
$(this).click(function(e) {
e.preventDefault();
$(".myDiv").hide();
$(".myDiv:eq("+i+")").toggle();
});
});
This one is in the same vein as tvanfosson's idea, using some sort of DOM relationship to link the elements, in this case by assuming that the link elements and the div elements are in the same order on the page.
You can just have each click call an external function and pass in a parameter for the number string.
Ex:
$("#link1").click(toggle("1"));
$("#link2").click(toggle("2"));
function toggle(number) {
$(".myDiv").hide();
$("#myDiv"+number).toggle();
}
function makeToggler(number) {
$('#link' + number).click(function() {
$('.myDiv').hide();
$('#myDiv' + number).toggle();
});
}
makeToggler(1);
makeToggler(2);
makeToggler(3);
You can adapt this to meet your naming standards.
Depending on the structure of your divs and links, there are better ways to do it. If you post the structure of your elements, I'll show you one.
I think this is a simple refactoring
you could define a function as such
function doSomethingTo(thisDiv)
{
$(".myDiv").hide();
$(thisDiv).toggle();
}
and then just reuse it where you need it
$("#link1).click(doSomethingTo(thisDiv));
$("#link2).click(doSomethingTo(thisDiv));
Building on Craig's solution:
$("#link1, #link2").click(toggle(this));
function toggle(obj) {
$(".myDiv").hide();
$("#myDiv" + $(obj).attr("id").replace('link','')).toggle();
}
I change the link become like this (i rename the id to just a number)
<a href='#test1' id='1' class='link'> ... </a>
<a href='#test2' id='2' class='link'> ... </a>
<a href='#test3' id='3' class='link'> ... </a>
and then on js:
$(document).ready(function(){
$('.link').click(function(){
$('.myDiv').hide();
var id = $(this).attr('id'); // take the id
$('#myDiv'+id).toggle();
});
});
throw your makeToggle into a loop?
function makeToggler(number) {
$('#link' + number).click(function() {
$('.myDiv').hide();
$('#myDiv' + number).toggle();
});
}
for(i=1;i>=#;i++) {makeToggler(i);}
then you could even have it count your links for you, something link this?:
function countElementsByClass(className){
var count = 0;
var o = document.getElementsByTagName("a").className;
for(var i=0;i<o.length;i+){
if(o[i].className == "accordion/whatever")
count ++;
}
return count;
}
credit: building on SLaCKS solution