How do I pass data from a link to a jQuery function? - javascript

$(function(){
$('.tab2').live('click', function() {
$('#coverTextH3').text(data[1].H3)
$('#coverTextP').text(data[1].P)
});
});
Lets say I have a link How do I pass data, the index of an array, to a jQuery function so I do not have to repeat my code, for each index [0]-[7]?
var data = [
{
H3: 'name',
p: 'more'
},
{
H3: 'string',
p: 'more strings'
}]

There are numerous options. If attaching handlers via javascript, I would select basing on element's id or some custom attribute, not the class. So say you have a number of links like this:
Tab 1
Tab 2
Tab 3
javascript in this case would be
$(function(){
$('a[link-number]').live('click', function() {
var index = $(this).attr('link-number') * 1 - 1;
$('#coverTextH3').text(data[index].H3)
$('#coverTextP').text(data[index].P)
});
});
Alternatively, you can attach click handlers right in your a elements declaration:
Tab 1
Tab 1
Tab 1
and define setCover function like this:
function setCover(index) {
$('#coverTextH3').text(data[index].H3)
$('#coverTextP').text(data[index].P)
}
Each of alternatives require changes in your htlm. If for some reason it is not possible, you need to at least now the range of your tabs, which can be quite tricky.

Something similar to this should work:
markup:
<a href="www.link.com" data-index="1" id="link1" />
javascript:
$(function(){
$('#link1').live('click', function() {
var idx = $(this).data('index');
$('#coverTextH3').text(data[idx].H3)
$('#coverTextP').text(data[idx].P)
});
});

if your link IDs correspond to the index order in the array you can do something like this:
example jsfiddle
jQuery:
$(function() {
$('.tab2').live('click', function(e) {
e.preventDefault();
// parse the integer from the ID
// and get the 0-based index (by subtracting 1)
var idx = $(this).attr('id').replace('link', '') * 1 - 1;
$('#coverTextH3').text(data[idx].H3)
$('#coverTextP').text(data[idx].p)
});
});
HTML:
Link 1
Link 2
<h3 id="coverTextH3"></h3>
<p id="coverTextP"></p>

Text
I'm not sure I understand exactly what you're asking. If this doens't fit, please clarify.

Related

javascript - avoid repetable code

I have a page with a button that calls a menu modal. The modal contains two more buttons that call two submenus - one for each button. Watch the pen:
https://codepen.io/t411tocreate/pen/yoxJGO
It actually works. But the current problem is that I re-write a repeatable code to call each submenu:
$('.show-submenu-1').on('click', function () {
$('.submenu-1.offcanvas').addClass('offcanvas--active');
})
$('.show-submenu-2').on('click', function () {
$('.submenu-2.offcanvas').addClass('offcanvas--active');
})
This approach seems to be pretty dumb. I need a solution with less repetition, something like forEach function for arrays:
var menus = [
'.show-submenu-1',
'.show-submenu-2'
];
menus.forEach(function(menu){
$(menu).on('click', function () {
$(`${menu}.offcanvas`).addClass('offcanvas--active');
})
});
Of course, this scenario won't work. How can I make my code DRY?
Use markup:
<div class="submenu" data-index="1">
<div class="submenu" data-index="2">
<button class="show-submenu-button" data-submenu-index="1">
<button class="show-submenu-button" data-submenu-index="2">
Then:
$('.show-submenu-button').on('click', function () {
var index = $(this).attr('data-submenu-index');
$('.submenu[data-index="' + index + '"]').addClass('offcanvas--active');
})
There is little value to using classnames that are so specific that they identify every element on the page individually. Classnames should define a class of elements that behave the same way.
Hi I hope I got the question right but you could use data-attributes for something like this. Just set a general class for .show-submenu and mark their connection to the menus with a number in a data-submenu=x attribute. Where x would be the number in .submenu-x.
And then you do something like this:
Notice that i changed .show-submenu-1 to .show-submenu. Make sure every trigger has this class. Also add a data-submenu=x for every submenu you want to use.
$('.show-submenu').on('click', function () {
var number = $(this).attr("data-submenu");
var selector = '.submenu-' + number + '.offcanvas'
$(selector).addClass('offcanvas--active');
})
So the data-submenu is used to pair the trigger and the modal. This way you can stick to an easy to read html code and a short bit of jquery.
Try this:
var menus = [1, 2];
menus.forEach(index => {
$(`.show-submenu-${index}`).on('click', () => {
$(`.submenu-${index}.offcanvas`).addClass('offcanvas--active');
});
});
You can use this as well.
$('.show-submenu-1, .show-submenu-2').on('click', function (event) {
$(event.target).hasClass('show-submenu-1'){
$('.submenu-1.offcanvas').addClass('offcanvas--active');
}else{
$('.submenu-2.offcanvas').addClass('offcanvas--active');
}
})
it would be better to have your show-submenu-1(as showmenu) and submenu-1(as submenu) in same parent element that allows you to use closest() method and make life easy
for eg:
$('.show-submenu').on('click', function (event) {
$(event.target).closest('.submenu').addClass('offcanvas--active');
})

Javascript Jquery ScrollTop paired elements

Hello I am new to programming so please excuse my ignorance.
I have several elements that when clicked use the ScrollTop jQuery function to scroll to a specified point (in another bootstrap nav-tab). I have about 20 different elements that when clicked do this. I have resorted to writing 20 different functions that look similar to the one below. I'm sure there must be a way to store these pairs and have a single ScrollTop function that calls upon those pairs.
$('#element').click(function(e) {
e.preventDefault();
var target = $('#element2').closest('.tab-pane').attr('id');
showTab(target);
setTimeout(function() {
$('html, body, nav').animate({
scrollTop: $("#element2").offset().top -100
}, 500);
}, 500);
});
So my js file has twenty or so of this function, where "#element" and "#element2" are subbed with "#alpha" "#alpha2", "#beta" "#beta2", etc...
Should I be using an array? a class? Thanks for you time.
See Working Fiddle Here
Yes you can add same class to all element that you want fire click on them, to reduce code see HTML example :
<span class="scrollTop" id="element">element text</span>
<span class="scrollTop" id="alpha">alpha text</span>
<span class="scrollTop" id="beta">beta text</span>
Adding two lignes to javascript code:
JS :
var id = $(this).attr('id'); //Id of clicked item
var scrollToId = '#'+id+"2"; //Id of scrolled to item
After that replace static ids by dynamic ones (scrollToId, id).
FULL JS :
$('.scrollTop').click(function(e) {
e.preventDefault();
var id = $(this).attr('id'); //Id of clicked item
var scrollToId = '#'+id+"2"; //Id of scrolled to item
var target = $(scrollToId).closest('.tab-pane').attr('id');
showTab(target);
setTimeout(function() {
$('html, body, nav').animate({
scrollTop: $(scrollToId).offset().top -100
}, 500);
});
});
Try adding the class "element" to each of the items that have an element id followed by a number - no need to remove the id at this time.
Then, change the selector in your code to be:
$('.element').click(function(e) {
If you use the class name instead of the id, you'll get notified when any item with a class of "element" is clicked.
If you need to make special allowances based on which one it is - in your single function, you could then check which one you're dealing with by checking its id:
$(this).attr('id')
Good Luck!

Shorten jquery script

Sorry for asking, but i am really newbie in jquery.
$(".productTopMenu").click(function() {
$("#breadcrumbs").html("Home / <strong>Product</strong>");
});
$(".downloadTopMenu").click(function() {
$("#breadcrumbs").html("Home / <strong>Download</strong>");
});
this is a breadcrumbs. every .productTopMenu clicked, #breadcrumbs will call the text.
if there is 15 pages, i must put 13 more copies of that script.
how to shorten that script like :
.productTopMenu = Home / <strong>Product</strong>
.downloadTopMenu = "Home / <strong>Download</strong>
the text always called inside #breadcrumbs.
is there a way to shorten this script ?
thanks in advance
any suggestion are welcome.
Something like:
$('[class$="TopMenu"]').click(function() {
$("#breadcrumbs").html("Home / <strong>" + getNameFromClass(this.className)
+ "</strong>");
});
function getNameFromClass(theClass) {
// take substring and make title case here
}
I haven't tested it but this should work:
// your data as an array containing objects
var item = [
{
"selector" : ".productTopMenu",
"label" : "Product"
},
{
"selector" : ".downloadTopMenu",
"label" : "Download"
}
],
i = item.length - 1,
$breadcrumbs = $('#breadcrumbs'); // Dom Cache
while (i >= 0) {
(function (i) {
$(item[i].selector).click(function () {
$breadcrumbs.html('Home / <strong>' + item[i].label + '</strong>');
});
}(i));
}
As everyone else has suggested, take the name from an existing element, and then use common class to hook up the click delegate.
If you haven't got the text as it should appear, you could try outputting it as a data-* attribute...
<a href="#" data-title="Downloads" />Go to Downloads</a>
That way you can control the name separately from everything else, at least.
You can give each of this menu elements the same calls, a unique ID and have a mapping id -> text:
var paths = {
'productTopMenu': "Home / <strong>Product</strong>",
'downloadTopMenu': "Home / <strong>Download</strong>"
};
$('.menuItem').click(function() {
if(paths[this.id]) {
$("#breadcrumbs").html(paths[this.id])
}
});
DEMO
You could also use a data- attribute to store some identifier, it does not have to be the id attribute.
Of course there are other ways. You have to decide how automatic or flexible you want the solution to be.
Try to use .each()

JS: Click one div, change another div value

I have a vote button I created that is contained within a .vote_div. 2 parts: .vote_num for the vote total, and .vote for the vote button. The page has a list of items so I need to make sure when the user clicks .vote, it changes the corresponding .vote_num + 1.
My JS function worked when the .vote actually was the total votes, but now I am seperating the two. How do I grab the right .vote_num on the .vote click?
Thanks!
<script>
$(".vote").click( function() {
var votes = $(this).attr('votes');
$.post(
'{% url vote %}', {
"id":this.id,
}, function(data) {});
this.className = "voted";
$(this).text(parseInt(votes) + 1);
return false;
});
</script>
<div class="vote_div">
<span class="vote_num" votes='{{host.num_votes}}'>{{host.num_votes}}</span>
<span class="vote" id="{{host.user.id}}">Vote</span>
</div>
EDIT & SOLUTION:
Got it working using $(this).parent() :
<script>
$(".vote").click( function() {
var votes = $(this).parent().find('.vote_num').attr('votes');
$.post(
'{% url vote %}', {
"id":this.id,
}, function(data) {});
this.className = "voted";
votes = parseInt(votes) + 1;
$(this).parent().find('.vote_num').text(votes);
return false;
});
</script>
try:
var votes = $(this).parent().find('.vote_num').attr('votes');
It goes to the parent of the clicked div then looks for an element with class vote_num then grabs the votes attributes.
#James answer should work, but this should give you a little more freedom to rearrange the two divs and add other elements so long as they share the parent.
To be even more robust you could do (note the 's' on "parents")
var votes = $(this).parents('.vote_div').find('.vote_num').attr('votes');
This will allow the elements to be nested arbitrarily deep as long as they only have a single parent with a class of `vote_div'.
See: http://api.jquery.com/parent/ , http://api.jquery.com/parents/ , and http://api.jquery.com/find/
if you have multiple class with vote, maybe you should use each()
$(".vote").each(function () {
var current = $(this);
current.click = function () {
// the rest of your function
}
})
Assuming I've understood the question correctly, and also assuming that your vote_num element is always the first element in the vote_div element:
var votes = $(this).siblings().eq(0).attr("votes");
Put this inside your click event handler will get the votes attribute from the first sibling element of the clicked element.
You can make this simpler if you are sure the element in question will always be directly before the clicked element:
var votes = $(this).prev().attr("votes");
var votes = $(this).attr('votes');
'votes' does not belong to class 'vote', it belongs to class 'vote_num'
so the line should be
var votes = $(".vote_num").attr('votes');
$('.vote').click(function(){
var $vote_num_obj = $(this).parent().find('.vote_num');
var new_vote_num = parseInt($vote_num_obj.attr('votes'))+1;
$vote_num_obj.attr('votes', new_vote_num);
$vote_num_obj.html(new_vote_num);
});
Put this script inside $('document').ready(function(){ ..here.. });
I suggest to change votes attribute of your span.vote_num to data-votes and change also the jquery attribute selector, this way it will be standard compliant.

Jquery Selectors for name prefixes in division

In my HTML code I have buttons 1, 2, 3 and 4 for 4 different views. I have some divs named as:
sheet(button id)+some string
So whenever I click on button 2 suppose, I want all the divisions with id=sheet2abc, id=sheet2xyz, etc to become visible and for the rest (i.e. 1, 3 and 4) the dispaly:none property should be set like for sheet1abc, sheet3abc, etc.
How can I do this via jQuery selectors?
KISS. Essentially:
$('[id^=sheet]').hide();
$('[id^=sheet'+num+']').show(); // num is a relevant value, see the example
Working example: http://jsfiddle.net/j4TzA/
I think you want to use wildcards in jQuery selectors.
This shows every div whose id starts with "sheet1":
$('div[id^=sheet1]').each(function() {
$(this).show();
});
And this hides the others:
$('div[id^=sheet]:not([id^=sheet1])').each(function() {
$(this).hide();
});
I created a fiddle to demonstrate that.
Buttons: button 1 and so on
Sheets: <div id="sheet1" class="sheet">sheet 1</div> and so on
jQuery:
$('.button').click(function(event){
event.preventDefault();
$('.sheet').hide();
$('#sheet'+$(this).attr('href')).show();
}
Next time make your question more clear.
You can filter like:
$('button').click(function() {
var $button = $(this);
$('div[id^=sheet]').each(function() {
if((new RegExp("^sheet" + $button.data('id') + ".*$")).test($(this).attr('id'))) {
$(this).show();
} else {
$(this).hide();
}
});
});
Then code buttons like:
<button data-id="1">1</button>

Categories