I am new to JavaScript and jQuery so let me know if I'm way off base.
I am using the cookie plugin from here: https://github.com/carhartl/jquery-cookie.
I have a page with dynamic links. They send the user to the same page they are already on with some GET information in the URL. I want to be able to highlight the previous link clicked.
My idea was to store the element that is clicked in a cookie and then add a class to that element.
Setting the cookie
$("td.column1").on({
click: function () {
$.cookie('productCookie', this); //How do I store 'this' into the cookie?
}
});
Getting the cookie
var productValue = $.cookie('productCookie');
$(productValue).addClass("select singleselected");
Code without cookies
I know from experience that this line of code worked before I added the links, which is also before the page was being redrawn.
$(this).addClass("select singleselected");
I've tried looking into how the this keyword works but I'm afraid I'm not sure what selector the addClass method is getting or how to get the current element.
Solution Used
function getParameters(geturl, columnNumber) {
var url = geturl,
urlRegExp = new RegExp(url.replace(/\/$/, ''));
$(columnNumber).each(function () {
if (urlRegExp.test(this.href)) {
$(this).addClass("singleselected select");
}
});
}
Check this thread out: jQuery add class .active on menu
The basic idea is that you parse the current url and find the anchor tag that is active based on the url.
If your elements have IDs, you can save the element's ID in a cookie and highlight it on the next pageload. Cookie (and localStorage, for that matter) can only store strings, or things that can be serialized to a string. HTML elements are not serializable.
Cookies hold strings. You will need to store some string-based indicator for which link was clicked.
It could be an id or a row number in your table or something like that. Then, when you read the cookie upon page load, you can find the DOM element that matches that indicator and change it accordingly.
You cannot store a DOM element reference in a cookie as DOM element references are not strings and they are not persistent from one page load to the next. A specific DOM element reference only exists during a given page.
If you show the actual HTML that covers what you want to save, we could make a more specific reference about what would make sense to save in the cookie. If it's a table, perhaps a row/column count (converted to string form). If every link has a unique id, then the easiest is to just store the id.
Related
The idea is pretty simple, yet I cannot figure it out. Basically I want to save an element that was clicked in the sessionStorage. However, this is not easy because sessionStorage only takes strings.
I am attatching a click event to all my navigation buttons. (This does not work of course)
navButtons.addEventListener("click", function () {
sessionStorage['active-nav'] = $(this);
});
How would I save a DOM element and access it later?
EDIT
Basically when the page is reloaded, I want to keep track which element was clicked before and the apply some CSS to it once the new page is loaded. For example changing the background color of that element to orange, etc.
Therefore, I need to somehow save some information about that element in the sessionStorage and access the element/ find the element, once the page is reloaded. I used the approach of adding an Id to all elements and then using the javascript function document.getElementById("test"), to find it. However, there are quite a few navigation elements, so adding Ids to all of them would probably not be the cleanest solution. What would be the best way of solving this wihtout adding Ids to everything?
I'd say you should either:
Store it's id, then use document.querySelector() to reselect it using the stored id.
Produce & store a reverse selector, by using a library such as SimmerJS, then use document.querySelector() to reselect it using the stored selector.
Reverse selectors avoid the need to add explicit ids to all relevant elements.
Here's how reverse selectors work:
window.simmer = window.Simmer.configure({ depth: 10 })
document
.querySelector('.container')
.addEventListener('click', e => {
console.log(simmer(e.target))
})
<script src="https://cdn.jsdelivr.net/npm/simmerjs#0.5.6/dist/simmer.js"></script>
<div class="container">
<div class="left">
<button> Click Me </button>
</div>
<div class="right">
<button> Click Me </button>
</div>
</div>
Then save the produced selector and use it again to reselect the element on page load. No explicit ids needed.
Saving selectors avoids serialising & rehydrating HTML, so you don't loose any event listeners attached to the element, plus they won't take up a lot of storage space in case you plan to do this for a lot of elements.
You can set the sessionStorage value to .outerHTML of the element.
sessionStorage['active-nav'] = this.outerHTML;
If more data than only the HTML is needed you can store a JSON string at sessionStorage, where one of the values is the .outerHTML.
navButtons.addEventListener("click", function () {
sessionStorage.setItem('div', this.outerHTML);
});
Save using the outerHTML property of the element
To get the same element
var element=sessionStorage.getItem('div');
This is my jquery scenario:
User click on div
It triggers an ajax call to save some data on DB
when callback received, we show an update msg <--everything good
until here
Now, when user click on the same element, it shows the information
from the DB, the same should happen with the other divs!
Noticed that when you click, the same text that you saved later is showing up in all the divs!!! it is not refreshing, but the actual source IS showing
the changes!
It looks like only the DOM is not reflecting the changes!
I am trying to put the text in the divs using .text();
All the divs are using the same element id!, I am just updating its data!
Thanks,
Marco
All the divs are using the same element id! - never ever should two elements have the same ID, because it breaks the principles on which HTML is built on and 3rd party libraries rely on.
If you need to target multiple elements use classes.
In case your elements have the class yourClass and you want to set them the text "foo", then
var yourResponseText = "foo";
$('.yourClass').text(yourResponseText);
Especially if you use jQuery - the ID selector is implemented in such way, that when it finds an element with that ID it doesn't look for another - the settings will only affect the first (from the viewpoint of DOM) element. On the other hand, when you're using the class selector, then simply said you're doing a forEach cycle through the elements with that class.
I'm creating a chrome extension that hides a jQuery element on the page when clicked.
I need to store a reference to this element in the chrome.storage API, so when the page is loaded at a later date I can have that element hidden again.
I know the DOM tree is rebuilt on page load, and I'm not sure if this will effect anything. The element could be anything on the page as well, so not necessarily having a class/id name.
What is the best way to go about storing the reference? I'm all out of ideas on how to do this (brand new to JavaScript).
Update
As suggested by Xan, I am now using xPath to store a reference to the element.
//Get the element
var elem = e.target || e.srcElement;
$(elem).click(function () {
xPathOfElem = getElementXPath(elem); //Get xPath of element
updateStorage(xPathOfElem);
$(elem).hide("");
return false;
});
//Store it
function updateStorage(xPathOfElem) {
chrome.storage.sync.set({"element":xPathOfElem} //set xPath to storage
, function (data) {});
};
//Retrieve it on load later
function getStorage() {
chrome.storage.sync.get(null, function (data) {
$(getElementsByXPath(document, data.element)).hide(""); //get and hide element
});
}
window.onload = function () {
getStorage();
};
As Xan mentioned, not a perfect approach if the page isn't static but it does what I need it to
This is a very broad question and the reason is: in general, there is no way you can reliably pinpoint an element on a page, especially if it's dynamic.
There is no "single" solution that works for every page. However, assuming that you can devise a method of pinpointing an element, you should look into DOM XPath.
It's a rich way of describing how to find an element, much more general than class/id name. And it's just a string, so it can easily be stored. Once you have this description, you can find the element using document.evaluate.
The downside is, there is no such thing as "the XPath" of an element. You need to come up with your own method of constructing one for a given element, and like I said to do so automatically is nigh-impossible. You're certainly welcome to try an cover many common cases, but finding a universal solution is hopeless.
P.S. See this question for finding "an XPath" of an element. Again, would only work reliably in a static page.
I'm developing a website that allows users to open multiple pages of the same content in the same browser window via inline 'windows'.
As the content can be repeated multiple times the id's can in turn be the same and therefore I have to "handle" them each so that I can distinguish between these pages.
I currently do this by assigning on load a unique id to the script like so:
var id_key;
function load_page() {
id_key++;
load_script("test.js") //load javascript file
}
//test.js:
$(function () {
var unique_id = id_key;
//adds the `unique id ` to the end of all elements with an id attribute set. ie `mycontainer` becomes `mycontainer_1`
update_ids(unique_id);
$("#mybtn_ " + unique_id).click(function () {
//do stuff
});
}
This works fine most of the time however if multiple pages are loaded too fast the Id tends to get overwritten causing confusion and errors.
I am wondering if there is a better technique of this doing this. I have heard of backbone.js but I am not sure whether that would be helpful in this case.
There are several general approaches to solve this kind of problem:
Load the sub pages in iframes. Each iframe gets it's own ID space. Scripts in all frames can talk to each other via the parent variable as long as all documents were loaded from the same domain.
Don't use any ids. Instead, give each "window" an ID and then locate elements in the window via classes and parent-child relations. Note that an element can have more than one class.
You can then use $(selector, win) to look for elements on a certain window win. The window becomes the "Selector Context" which means jQuery will search only children of the window and nothing else.
At the start of your script, locate all important elements by ID and save them in a JavaScript object. That way, you can access them without using a jQuery selector.
For example, you could select anything with an ID and save it with .data() in the window element. After this setup, all elements would be accessible via $(win).data('id')
You can generate quite good unique ids by concatenating a date and a random number:
new Date().getTime() + Math.random()
While this is by no means perfect, I think in your use case it will suffice.
As Jack mentioned in his comment, you can pass this id to your new window as a get parameter. I once did a whole OS-like interface with this method, and it worked flawlessly.
I have any number of anchor links on a page that need to execute the same block of JavaScript code on click, and that code needs to be associated with one value. There are several of these on each page. I usually use a hidden input to store the value in a one-to-one relationship, but what is the best way to associate several links placed throughout a page with a value?
For example, think of a group of links that reference a product by ID, and all show the same dynamic layer for the product. Now there might be a multiple groups of links for a bunch of products. How do I draw those associations? I'm using Mootools and bind events by class, so I don't want a bunch of inline event function calls that pass arguments.
If your already using Mootools, a good way to do this is using the element's data storage.
window.addEvent('domready', function() {
$$('a.classname').each(function(el) {
el.store('productID', /*get this however you want*/);
el.addEvent('click', function(e) {
var productID = el.retrieve('productID');
}
}
}
And here's one method for getting the productID's (assuming you have control over URL formatting):
<a href='ViewProduct.php?ProductID=7#pid:7'>link</a>
//in your js (above)
var pid = el.get('href').split('#')[1].split(':')[1];
el.store('productID', pid);
Do you want to set the values in your html code? Otherwise, you can dynamically add the values to the dom nodes themselves.
If you want to set them in the html, use a custom attribute if you don't care for standard compliance. If you do care, encode the values as class names or use the lang-attribute and prefix your data with 'x-' so you stay compliant to RFC 1766.