Dynamically create numerous methods in jQuery? - javascript

A number is generated on my page in a hidden text field based on a number of 'pages' that need to be produced.
The plan is to dynamically allow the user to switch between the pages by clicking on numbers (e.g. if we have 3 pages, they can click on 1, 2 or 3 to display each page).
The problem is that the number of pages will vary from run to run, but in order for me to be able to add the page switching functionality in js/jQuery, I need to create a .click() method for each page button.
However because the number of pages isn't a set amount, I need to somehow create these methods dynamically - creating as many as are required, so a .click() function for each page.
$("#page1" ).click(function() {
for(var i = 0; i < tableCount; i++){
$("#usertable" + (i)).hide();
}
$("#usertable1").show();
});
Above is an example of a simple function I wrote that will be executed when the 1st page button is pressed and it iterates through all pages, hides them and then shows the 1st page. However if I have 5 pages, I need to somehow dynamically create a $("#page2" ).click() function and a $("#page3" ).click() function and so on.
Any ideas?

You can use attribute begins with selector
$("[id^=page]").click(function () {
// do stuff
var id = this.id.slice(-1);
for (var i = 0; i < tableCount; i++){
$("#usertable" + i).not("[id$=" id "]").hide();
}
$("#usertable" + id).show();
})

Use of common classes and some attributes will help
<a class="page-link" href="#page1">Page 1</a>
<div id="page1" class="page-content"></div>
Then one click handler works for whole class of links. Within any jQuery event handler this is the element the event occured on
$('.page-link').click(function(){
// hide whole class of content , filter for the one to show
$('.page-content').hide().filter(this.hash).show();
});
Or a bit more verbose for understanding
$('.page-link').click(function(){
var idSelector = $(this).attr('href'); // "#page1"
$('.page-content').hide().filter(idSelector).show();
});

Related

Not able to identify element display values

I have photo gallery type of web page. It is comprised of grid of photo thumbnails, with assigned tags beneath them.
At top of page is a list of all of the tags, formatted as buttons. User can click on one or more tag buttons to filter photos. I am using Isotope js for this filtering. This works fine.
However I want to add new feature that runs after the Isotope filtering that will hide any tag buttons that are not assigned to any of the remaining filtered photos.
My plan was to do following:
identify all visible photos
create array from visible photos' tags
use array to hide any unmatched tags
However, I am having problems identifying visible photos after I click tag buttons and Isotope does its filtering.
It seemed like it would be quite straightforward. Isotope js changes a specified element's display = "none" for the hidden photos. Eg if I inspect the element, I can see hidden elements have display = "none"
I created a 'visibletags' function that is called at end of tag button on click to find elements where display != "none":
$('.filter-button').on('click', function() {
// isotope code here
// isotope hides some photos setting their div's `display = "none"`
visibletags();
}
function visibletags(){
var imgdivs = document.querySelectorAll('.imgdiv');
var showtags = [];
for (var i=0, max=imgdivs.length; i < max; i++) {
if (window.getComputedStyle(imgdivs[i]).display != "none") {
// this should be a div that is not hidden by Isotope js
// so loop through it's tags to build array
// array will be used later to hide unmatched tags
var phototagspans = imgdivs[i].querySelectorAll('.photo-tag');
for (var j=0, max=phototagspans.length; j < max; j++) {
showtags.push(phototagspans[j].className);
}
}
}
}
But I am not able to identify the element's display value. I have tried using window.getComputedStyle(imgdivs[i]).display, imgdivs[i].display and imgdivs[i].style.display
Edited to modify question:
I tested running the 'visibletags()' function as another button on click event that I manually click after the isotope filtering is complete. This successfully gets all photo element display values. So that part of code does work.
So my question now is how to run 'visibletags()' function after the Isotope filtering in a way that it is one complete set of code?
I tried changing the 'visibletags()' function to run as $('.filter-button').mouseup(function() but didn't get filtering results.
Maybe this is now general Javascript question eg how to get on click event's results after they have been rendered?
I'm not familiar with Isotope, but you probably need to use a callback function. Check out this documentation, especially the layoutComplete part: https://isotope.metafizzy.co/events.html
In your case, the result could be something like this:
$('.filter-button').on('click', function() {
// initialize isotope
$isotope.on('layoutComplete', function() {
visibletags();
});
// other isotope code here
}

How to us $.data in a loop to display correctly for each div

When I click a marker on my map, I want to display data from the database associated with that marker. Currently I am doing this for the divs that I create. I am having a problem when I click on a div to open my form under it, I want to load the same data into the form, but currently the only data that will load into each for is the first one that ran through the loop.
Another words, my venue-list div might hold 3 venues for this one location, and I can click on each div and display a form under it, but if "Sally's Salon" is the first div in the list, every form will display "Sally's Salon" instead of their own name. Here is my code:
// initially detach form to be attached to each div on click
var editForm = $('.edit-container').detach();
function fillForm(title, priority) {
$('.venue-input').val(title);
$('.priority-input').val(priority);
}
for(var i = array.length -1; i>=0; i--) {
var prop = array[i].feature.prop
if(prop.title) {
// create variable to hold html
var html = $([
"<div class='venue-item'>",
" <span><strong>Venue Name</strong></span>",
" <span class='venue-name venue-title' data-title=" + prop.title + ">" + prop.title + "</span>",
"<span class='venue-priority' data-priority=" + prop.prioritylevel + "><strong>Priority</strong>" + ' ' + prop.prioritylevel + "</span></div>"].join("\n"));
// append venue item to venue list div with event handler to add form and prefill when clicked
$(html).appendTo('.venue-list').on('click', function() {
$(this).after(editForm);
fillForm($('.venue-title').data('title'), $('.venue-priority').data('priority'));
});
}
any input would be helpful, I've been battling this for a couple days now, not sure if I am even attaching the html elements correctly but I mainly just want to be able to click on one of the html elements I create and then the data gets loaded into the form so it can be manipulated.
You are appending multiple copies of your content, however there are 2 elements using the same id (venue-priority & venue-title) - which should be unique on a web page.
Thereafter, you use jQuery to get those elements, however as jQuery expects id's to be unique, it will just grab the first (or last, im not sure) element with that Id.
The solution is not to use duplicated id's in your markup.
You seem to have a syntax error on line 6. You can view errors in a browser using developer tools in case there are others.
$('#priority-input.val('priority);
should be
$('#priority-input').val('priority');
Actually, if you want to set the value to the value of the parameter, you should use
$('#priority-input').val(priority);
not
$('#priority-input').val('priority');

javascript to add second class to element on click event

I am trying to add a second class to my element on click
Before
<div class="foo1">
<a class="class1" >Text</a>
</div>
After
<div class="foo1">
<a class="class1 class2" >Text</a>
</div>
here are my javascript codes; both of them work:
either this one (thanks to #Shomz)
var elements = document.getElementsByClassName('class1 ');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.className += ' class2';
}
or this one (thanks to #t-j-crowder)
[].forEach.call(document.querySelectorAll(".class1 "), function(element) {
element.className += " class2";
});
Question
The site allows the users to click on class1 and change it to class1 class2 . However, by running these codes, the class1 only temporarily changes to class1 class2, I mean the clicking event is not implemented, it has only visually changed. When the site is reloaded, it is back to the previous state. How to apply a fix to change permanently the class by clicking on it?How to achieve the class changing through a click event and to record this permanently? How can these js codes record this click and change it permanently?
Ok so based upon your comment you need to communicate the change to a server, then when the page loads it needs to request the data back from the server to reflect any stored changes. Theres a number of ways to do this depending on your programming capability, preference in language and compatibility requirements.
The most popular method would likely be a data file that is written dynamically by a php script. When the page is loaded it would generate your content based upon the contents of the datafile on the server(not to be confused with your HTML page). When the user modifies and element your page would call the php script using the AJAX POST method in javascript, then the php script would read the existing datafile, modify it accordingly and save it to the server.
For starters you will need a web server with PHP; if your testing locally MAMP is a good choice for Mac and I believe they now do a windows version as well.
Your would have 3 files( presuming all of your css and js is written in your HTML file):
index.htm
data.js
update.php
Assuming a linear list of div elements, each with a switchable class and child content.
index.htm
<html>
<head>
<script src='datafile.js'></script>
<script>
window.addEventListener('load',onload,false); //register the on load handler
function onload(){
var body = document.getElementsByTagName('body')[0];
var newelement;
for(var i = 0; i < elements.length; i++){
//for each element in the data file
newelement = document.createElement('div');
//create a div element
newelement.innerHTML = elements[i].content;
//place the content within the div
newelement.className = elements[i].class;
//set our classes
body.appendChild(newelement);
//add the div to the body
newelement.addEventListener('click',onclick,false);
//add a click listener to the element
}
}
function onclick(){ //on click function
var elementIndex = elements.indexOf(this); //this will be the element in the callback context
//modify class
postchange(elementIndex,classList);
}
function postchange(element,class){
// new post method
// data = {'element':element,'class':class};
// post data to update.php
}
</head>
<body>
</body>
</html>
data.js
var elements = [
{
"content":'Hello I am div 1',
"class":'classA'
},
{
"content":'Hi, I have been known as div 2... but you can call me Tim',
"class":'classA classB'
}
]
I've left the PHP out, it's not my main language so I don't feel happy improvising any code for you without looking it up and testing it first. That and it shouldn't be too hard for you to find information on POST methods on Stack Overflow.
Similarly I left the POST method in the JS out because the standard JS method is a little overcomplicated. Look up the jQuery POST method which is much more simple, again examples should be easy to find.

Javascript Click on Element by Class

So I am writing a script that can be run on a page but I want to click on this element, unfortunately, it does not have an id to get and I am trying to use the .click() function on it, but it doesn't work, here's what I have, anyone know how to fix it? This is the only element in the class also
var classes = document.getElementsByClassName('rateRecipe btns-one-small');
var Rate = classes[0];
Rate.click();
I'd suggest:
document.querySelector('.rateRecipe.btns-one-small').click();
The above code assumes that the given element has both of those classes; otherwise, if the space is meant to imply an ancestor-descendant relationship:
document.querySelector('.rateRecipe .btns-one-small').click();
The method getElementsByClassName() takes a single class-name (rather than document.querySelector()/document.querySelectorAll(), which take a CSS selector), and you passed two (presumably class-names) to the method.
References:
document.getElementsByClassName().
document.querySelector().
If you want to click on all elements selected by some class, you can use this example (used on last.fm on the Loved tracks page to Unlove all).
var divs = document.querySelectorAll('.love-button.love-button--loved');
for (i = 0; i < divs.length; ++i) {
divs[i].click();
};
With ES6 and Babel (cannot be run in the browser console directly)
[...document.querySelectorAll('.love-button.love-button--loved')]
.forEach(div => { div.click(); })
for exactly what you want (if you know the index of button):
var rate = document.getElementsByClassName('rateRecipe btns-one-small')[0];
rate.click();
or for direct action
document.getElementsByClassName('rateRecipe btns-one-small')[0].click();
with jQuery
$('.rateRecipe .btns-one-small').click(function(){
var vIndex = $('.rateRecipe .btns-one-small').index(this);
//vIndex is the index of buttons out of multiple
//do whatever
//alert($(this).val());//for value
});
class of my button is "input-addon btn btn-default fileinput-exists"
below code helped me
document.querySelector('.input-addon.btn.btn-default.fileinput-exists').click();
but I want to click second button, I have two buttons in my screen so I used querySelectorAll
var elem = document.querySelectorAll('.input-addon.btn.btn-default.fileinput-exists');
elem[1].click();
here elem[1] is the second button object that I want to click.

How to add jquery events to added classes?

I am trying to create an image gallery, I am using numbers instead of left/right arrows. At the moment, I am trying to get it working with only 2 image (i.g 2 numbers)
this is the html . the id page, is the highlighted number
<div class="grid_1 pagelink" id="page"><p>1</p></div>
<div class="grid_1 pagelink"><p>2</p></div>
the first time the page loads, the code below works. so when I click on link 2 the the code bellow runs fine. But then I want the same code to be triggered when I click back on the first link; but when I do that, the page refreshes by ignoring the code bellow:
$('.pagelink').live('click', function(e){
e.preventDefault();
var frame = $(this).text() - 1;
var frames = 240 * frame;
// $('#gal').animate({marginLeft:'500px'},'slow');
$('#gal').animate({marginLeft: "+="+frames+'px'},'slow');
$(this).attr('id', 'page').removeClass('pagelink');
$('#page').addClass('pagelink').removeAttr('id','page');
// $('#book').animate({ left: '50' });
})
I thought that the .live() would do that for me but it is not working.
I hope you could help
thank you
Previous, this is because you are removing the class of link "pagelink" which were used to map the clicked event.
Also, use another class instead of id(#page) to identify the #page link, id might be problem if its already assign to other link. like
$(this).removeClass('pagelink').addClass('page');
$('.page').addClass('pagelink').removeClass('page');
live should work fine. i think you have a bug in your code, and its probably here:
$(this).attr('id', 'page').removeClass('pagelink');
$('#page').addClass('pagelink').removeAttr('id','page');
what exactly are you trying to accomplish with this code?
when you click on page2, the you set the div's id to be page, but now you have 2 elements with an id of page, and when you select that id, you get the first one (ie page1), but you still remove the class pagelink from page2
in other words, the bug is that at some point you will have 2 elements with the same id (and ids must be unique btw) so when you select that id with $('#page') you always get the first one

Categories