How can I loop variables with Jquery - javascript

I'm new with Javascript and Jquery and I'm facing a small problem.
I'm trying to make sure that if a given link exists, hovering over this link will bring up a popup with the fadeToggle().
So I wrote this code that works:
if ($('.link-1')) {
$('.link-1').mouseover(function () {
$('.popup-1').fadeToggle();
})
.mouseout(function () {
$('.popup-1').fadeToggle();
})
}
But, instead of repeating it ten times, I wanted to write a loop, like this:
var number = 0;
while (number < 10) {
var popup = '.popup-' + number;
var link = '.link-' + number;
if ($(link)) {
$(link).mouseover(function () {
$(popup).fadeToggle();
})
.mouseout(function () {
$(popup).fadeToggle();
})
}
number++;
}
But it does not work. Could you help me please ?
I thank you in advance !

Based on your comments, I'd recommend this approach.
Add a data attribute to each link that corresponds with the popup you want to fire. This will look something like this:
<a href='#' class='link-1' data-popup='popup-1'> Link </a>
Then add a hover event to ALL links, that performs an action if it has the data type:
//hover event on all links(assumes anchor tags)
$('a').mouseover(function () {
if ($(this).attr('data-popup')) {
let popup = '.' + $(this).attr('data-popup');
$(`${popup}`).fadeToggle();
}})
.mouseout(function () {
if ($(this).attr('data-popup')) {
let popup = '.' + $(this).attr('data-popup');
$(`${popup}`).fadeToggle();
}})
You could also make this a single line function using .hover instead of .mouseover and .mouseout if it fits your use case
**refactoring process is added here:
//start with the original function
$('a').hover(function () {
if ($(this).attr('data-popup')) {
let popup = '.' + $(this).attr('data-popup');
$(`${popup}`).fadeToggle();
}})
//consolidate the enter and exit events using .hover()
$('a').hover(function () {
if ($(this).attr('data-popup')) {
let popup = '.' + $(this).attr('data-popup');
$(`${popup}`).fadeToggle();
}})
//remove the if statement, because the function firing without a pop up won't result in any effect
$('a').hover(function () {
let popup = '.' + $(this).attr('data-popup');
$(`${popup}`).fadeToggle();
})
//substitute the variable directly into the jquery tag
$('a').hover(function () {
$(`'.${$(this).attr('data-popup')}`).fadeToggle();
})
// use an ES6 arrow function to make this a one line function
$('a').hover(() => $(`.${$(this).attr('data-popup')}`).fadeToggle())
//as is, this function won't work, because the arrow function binds the "this" keyword differently.
//Event handlers have an optional parameter that is an event JSON object, so we pass that into the function.
//Because it is a parameter, and is used as a variable we can call event "e" for short
//target is a property of the JSON object 'event' that indicates what specific element is triggering the event
// You can console log "e" to see what other values are baked into the event
$('a').hover((e) => $(`.${$(e.target).attr('data-popup')}`).fadeToggle())
//lastly, because we are using an anonymous arrow function with only one parameter, we can omit the parenthesis around the paremeter
$('a').hover(e => $(`.${$(e.target).attr('data-popup')}`).fadeToggle())
The end result is the one liner below!
$('a').hover(e => $(`.${$(e.target).attr('data-popup')}`).fadeToggle())
Additional info on data attributes can be found here:
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

welcome to the web community :-)
My jQuery skills are a bit rusty, but I recall, that there is an Attribute Contains Selector, which you could combine with .each() like so:
$('[class*="link-"]').each(function (index, link) {
$('[class="popup-"' + index + '"]').each(function (_, popup) {
$(link)
.mouseover(function () {
$(popup).fadeToggle();
})
.mouseout(function () {
$(popup).fadeToggle();
})
}
}
The second index is not interesting, that's why I named the argument „_”.
Let me know, whether it still works

If your objects are in order from link-1 to link-10, you can try this method
Loop object that has class "link-[number]" using each function
save number using index + 1
give action to object that have been hovered
so the code will be like this:
$('[class*="link-"]').each(function (index) {
var number = index + 1; //index start from 0, so it need to add + 1
$(this)
.mouseover(function () {
$('[class="popup-' + number+ '"]').fadeToggle();
})
.mouseout(function () {
$('[class="popup-' + number+ '"]').fadeToggle();
})
});
But if your object are not in order from link-1 to link-10, I recommend to use custom data attribute in your HTML code.
Example:
<a class="link-1" data-number="1">test 1</a>
<div class="popup-1" style="display:none">
test 1 popup
</div>
Then change number variable to this code:
var number = $(this).attr("data-number");
It will more save.
Hope it helps.

Related

How make javascript function work only one time

How to make Javascript function work only one time ?
if (window.location.hash) {
$(document).ready(function () {
var id = window.location.hash;
$(id).trigger('click');
});
$('li').click(function () {
$(this).prependTo($(this).parent());
});
}
I need auto-click on that li element which link user comes to website. web.com/#2 (list order - 2 1 3 4 5) , web.com/#4 (list order - 4 1 2 3). but i want than user stay in website with hash url list elements stay in their places then user click for example on 3 list element he must stay and his place so list order (4 1 2 3). I just need change list order by url hash on load page.
I solved it
if (window.location.hash) {
$('li').one('click',function () {
if (!window.run){
$(this).prependTo($(this).parent());
window.run = true;
}
});
$(document).ready(function () {
var id = window.location.hash;
$(id).trigger('click');
});
}
In your particular case the simplest solution is to use .one(), which unbinds the handler after running it the first time:
$('li').one('click',function () { ... }
Another approach is to have the function redefine itself to a no-op after it runs. This can be useful in some cases when there isn't a convenient event handler to unbind:
var oneTimeFunction = function() {
console.log("This will only happen once.");
oneTimeFunction = function() {};
}

jQuery switching between more than two classes

I've already posted a question about jQuery toggle method here
But the problem is that even with the migrate plugin it does not work.
I want to write a script that will switch between five classes (0 -> 1 -> 2 -> 3 -> 4 -> 5).
Here is the part of the JS code I use:
$('div.priority#priority'+id).on('click', function() {
$(this).removeClass('priority').addClass('priority-low');
});
$('div.priority-low#priority'+id).on('click' ,function() {
$(this).removeClass('priority-low').addClass('priority-medium');
});
$('div.priority-medium#priority'+id).on('click', function() {
$(this).removeClass('priority-medium').addClass('priority-normal');
});
$('div.priority-normal#priority'+id).on('click', function() {
$(this).removeClass('priority-normal').addClass('priority-high');
});
$('div.priority-high'+id).on('click', function() {
$(this).removeClass('priority-high').addClass('priority-emergency');
});
$('div.priority-emergency'+id).on('click', function() {
$(this).removeClass('priority-emergency').addClass('priority-low');
});
This is not the first version of the code - I already tried some other things, like:
$('div.priority#priority'+id).toggle(function() {
$(this).attr('class', 'priority-low');
}, function() {
$(this).attr('class', 'priority-medium');
}, function() {
...)
But this time it only toggles between the first one and the last one elements.
This is where my project is: strasbourgmeetings.org/todo
The thing is that your code will hook your handlers to the elements with those classes when your code runs. The same handlers remain attached when you change the classes on the elements.
You can use a single handler and then check which class the element has when the click occurs:
$('div#priority'+id).on('click', function() {
var $this = $(this);
if ($this.hasClass('priority')) {
$this.removeClass('priority').addClass('priority-low');
}
else if (this.hasClass('priority-low')) {
$this.removeClass('priority-low').addClass('priority-medium');
}
else /* ...and so on... */
});
You can also do it with a map:
var nextPriorities = {
"priority": "priority-low",
"priority-low": "priority-medium",
//...and so on...
"priority-emergency": "priority"
};
$('div#priority'+id).on('click', function() {
var $this = $(this),
match = /\bpriority(?:-\w+)?\b/.exec(this.className),
current = match && match[0],
next = nextPriorities[current];
if (current) {
$this.removeClass(current).addClass(next || 'priority');
}
});
[edit: working demo]
Assuming you have 'priority' as the default class already on the element at the initialization phase, this will cycle through the others:
$('div#priority' + id)
.data('classes.cycle', [
'priority',
'priority-low',
'priority-medium',
'priority-normal',
'priority-high',
'priority-emergency'
])
.data('classes.current', 0)
.on('click', function () {
var $this = $(this),
cycle = $this.data('classes.cycle'),
current = $this.data('classes.current');
$this
.removeClass(cycle[current % cycle.length])
.data('classes.current', ++current)
.addClass(cycle[current % cycle.length]);
});
I have tried myself to do this with the sole help of toggleClass() and didn't succeeded.
Try my method that declares an array with your five classes and toggles dynamically through
them.Do adapt to your own names.
//variable for the classes array
var classes=["one","two","three","four","five"];
//add a counter data to your divs to have a counter for the array
$('div#priority').data("counter",0);
$(document).on('click','div#priority',function(){
var $this=$(this);
//the current counter that is stored
var count=$this.data("counter");
//remove the previous class if is there
if(($this).hasClass(classes[count-1])){
$(this).removeClass(classes[count-1]));
}
//check if we've reached the end of the array so to restart from the first class.
//Note:remove the comment on return statement if you want to see the default class applied.
if(count===classes.length){
$this.data("counter",0);
//return;//with return the next line is out of reach so class[0] wont be added
}
$(this).addClass(classes[count++]);
//udpate the counter data
$this.data("counter",count);
});
//If you use toggleClass() instead of addClass() you will toggle off your other classes.Hope is a good answer.

Simple Javascript Calling function not working/don't know how to get it to work

I'm trying to call a function and not the alert and I thought it was as easy as just doing something like this: FunctionsName(); and delete the alert(''); but it's not working for me :(
Can someone please look at the code I have below and tell me what is wrong ?
Thank you so much!!
<script type="text/javascript">
var comper;
function checkComper() {
var onResponse = function(comperNow) {
if (comper === undefined) {
comper = comperNow;
return;
}
if (comper !== comperNow) {
// show a message to the visitor
alert("New Info Added"); // <--*** I WANT TO TAKE THIS OUT AND CALL $("#append").click(function(e)
comper = comperNow;
}
};
$.get('getlastupdate.php', onResponse);
}
var tid = setInterval(checkComper, 2000);
$(function() {
var $table = $("table.tablesorter");
$("#append").click(function(e) {
e.preventDefault();
$.get('updatetable.php', function(data)
{
$table
.find('tbody')
.html('')
.append(data);
$table.trigger("update", [true]);
});
});
/*........ and so on.... */
</script>
What about changin that :
alert("New Info Added");
to that :
$('#append').trigger('click');
It will simulate a click and trigger the function.
One thing important to distinguish:
alert("New Info Added") is a function. Actually, alert() is a function, being passed the parameter "New Info Added".
$('#append').click(function(e) { is not a function, at least, not in the same way. $('#append') is a jQuery selector function, which selects all elements with an id of "append". $('#append').click() is a function that sets a click event on all elements returned in the selector.
What the whole syntax of $('#append').click(function(e) { means is on its own a syntax error. What you're doing is telling the elements found in the selector what their click function should be. But the function(e) { says that it's the start of the code of the function. That line of code isn't complete until the ending }) - the } closing the function declaration and the ) closing the call to click.
So, you can't simply replace alert("New Info Added"), which is a complete function call, with $('#append').click(function(e) {, because it's a syntax error - you haven't completed the function(e) declaration, nor the click function call. You can trigger the click function, as Karl's answer told you. Or, you can use the shortcut:
$('#append').click()
Note that this is a full proper sentence, and can therefore replace the alert.

.append link will not fire onclick function

I've searched around I cannot find the answer to this. In my code, a link is created inside of a div and given an onclick value to pass an argument to a function. I cannot figure out why it will not fire.
var imgCount = 0;
var curImg;
function resetImg(target) {
alert(target);
}
$(".add").click(function () {
imgCount = imgCount + 1;
curImg = "theImg" + imgCount;
//Here we add the remove link
$('#links')
.append('Call Function');
$('.dynamic').css('display', 'block');
});
Here's the fiddle:
http://jsfiddle.net/stewarjs/4UV7A/
I've tried using .click() when creating the link, but the argument being passed needs to be unique to each link. I've tried grabbing $(this).attr("id") but the value comes back undefined.
Thanks for any and all help.
Jeff
Rather than try to mangle HTML into JavaScript, I suggest you use the jQuery methods already available to you.
$('#links')
.append($("<a>").attr('href', '#').on('click', function () { resetImg(curImg);
}).addClass('dynamic').text('Call Function'));
http://jsfiddle.net/ExplosionPIlls/4UV7A/1/
remove javascript: from onclick, it should like like this: onclick="resetImg(\'' + curImg + '\');"
There's always a way to get rid of onclick handlers. Here's how I'd do it:
var image_count = 0;
$('#links').on('click', '.dynamic', function(e) {
e.preventDefault()
alert($(this).data('image'));
});
$('.add').click(function () {
$('<a />', {
'href': '#',
'data-image': 'theImg' + (++image_count),
'class': 'dynamic',
'text': 'Call function'
}).appendTo('#links');
});
Demo: http://jsfiddle.net/4UV7A/4/

Assigning Anchor tag's to call Javascript function dynamically

I am creating list of <span class="infa9span"><img src="/csm/view/include/images/foldericon.png"/><a id="infa9Service">'+servicename+'</a><br/></span> tags dynamically and appending it to a div
Then using the below map to map a tags attribute to some function
var idMap = {
//it can be a lot more
"javaInfo":javaInfo,
/*infa9 product map*/
"infa9PMServer":infa9PMServer,
"infa9Service":infa9Service
};
This is the click Handler
$('#ds-accordion a').click(function(event) {
var elementId=$(this).attr("id");
treeItemClickHandler(elementId);
});
function treeItemClickHandler(id)
{
(idMap[id])(id); //Is this usage called 1st class functions?
}
function infa9Service(id)
{
alert("i got this "+id);
}
Note: I am using Jquery v1.6.3
But when I click on any of the a tags, it calls the function an does all the operation inside the function, but gives an error Object dosen't support this porperty or method in the treeItemClickHandler function.
I would like to know,
How to avoid getting this error?
Is there a more better approach for something like this?
And Is it 1st class functions that I am using (if so where can i learn more about it)?
Thanks.
Update
How can I pass 2nd parameter?
'<span class="infa9span"><img src="/csm/view/include/images/foldericon.png"/><a id="infa9Service" title='+servicename+'>'+servicename+'</a><br/></span>'
$('#ds-accordion a').click(function(event) {
var elementId=$(this).attr("id");
var elementName=$(this).attr("title");
treeItemClickHandler(elementId,elementName);
});
function treeItemClickHandler(id,name)
{
idMap[id](id,name);
}
function infa9Service(id,name)
{
alert(id+", "+name);
}
It gives me infa9Service, undefined
check this out http://jsfiddle.net/ywQMV/4
1)define your functions.
2)define your id map.
html part :
<div id ="ds-accordion">
<span class="infa9span">
<img src="/csm/view/include/images/foldericon.png"/>
<a id="infa9Service" title='+servicename+'>'+servicename+'</a>
<br/>
</span>
js part:
function infa9Service(id, serviceName)
{
alert("i got this "+id +" serviceName : " + serviceName);
}
var idMap = {
"infa9Service":infa9Service
};
$('#ds-accordion a').click(function(event) {
var elementId=$(this).attr("id");
var serviceName = this.title;
treeItemClickHandler(elementId, serviceName);
});
function treeItemClickHandler(id,serviceName)
{
// alert(idMap[id])
(idMap[id])(id,serviceName); //Is this usage called 1st class functions?
}

Categories