I have a select with options that have values that are populated with jQuery based on data attributes from divs. When a user select an option, the div with the data attribute that matches the value of the option is displayed. Now I'm trying to create a deep linking option, so when I have a url like https://my-site.com/page/#option-2 the option-2 is preselected in the select and the div with data attribute option-2 is displayed. So far I have this javascript:
$(window).on('load', function() {
let urlHash = window.location.hash.replace('#','');
console.log(urlHash);
if ( urlHash ) {
$('.dropdown').val(urlHash);
$('body').find('.location').removeClass('is-active');
$('body').find(`.location[data-location-hash=${urlHash}]`).addClass('is-active');
}
});
If I enter the url https://my-site.com/page/#option-2 the site goes in infinite loop and never loads without displaying any error in the console.. If I refresh the page while loading, the console.log is displayed with the correct string that I'm expecting, but the .location[data-location-hash=option-2] is not displayed and the option is not selected... I'm using the same code for the change function of the dropdown and is working, but it's not working in the load function.. Is there anything I'm missing?
JSFiddle, if it's of any help:
https://jsfiddle.net/tsvetkokrastev/b0epz1mL/4/
Your site is looping because you are doing a window.location.replace To get the urlHash you should use
$(window).on('load', function() {
var href = location.href; // get the url
var split = href.split("#"); // split the string
let urlHash = split[1]; // get the value after the hash
if ( urlHash ) {
$('.dropdown').val(urlHash);
$('body').find('.location').removeClass('is-active');
$('body').find('.location[data-location-hash='+urlHash+']').addClass('is-active');
}
});
https://codepen.io/darkinfore/pen/MWXWEvM?editors=1111#europe
Solved it by using a function instead of $(window).on('load').. Also added $( window ).on( 'hashchange', function( ) {}); to assure that the js will run again after the hash is changed.
Here is an updated jsfiddle: https://jsfiddle.net/tsvetkokrastev/b0epz1mL/5/
Related
Hi I wrote a code which has local storage applied to the options on the page. The only problem I am having is that I am unable to save the page which the options had searched. As you can see in the js fiddle. The options stay the same as which they were selected even after refresh. But when you click on the search function. It takes you to that image with those options applied. But when you refresh the page it goes back to the original. How would I keep the same display after refresh
This is my code for the local storage, it works for the options but not for the display of what the search has produced.
$('#browsepagebutton').on('click', function() {
$('select').each(function() {
var id = $(this).attr('name');
var value = $(this).find("option:selected").val();
console.log("SetItem : " + id + " with value : " + value)
localStorage.setItem(id, value);
});
});
$(document).ready(function() {
$('select').each(function() {
var id = $(this).attr('name');
if (localStorage.getItem(id) !== null) {
var value = localStorage.getItem(id);
$(this).val(value)
}
});
})
Js fiddle of code https://jsfiddle.net/387tnzoy/4/ (Note the function wont work)
The js fiddle does show the code just so that you can get an idea of what is happening for example. When I apply filters such as animation on life of pi and click the submit button it will only show the life of pi image undreneath the options because it is the only one set with that option. The only problem now is that I want local storage to save that page. So that when I refresh it is still on that display.
$('select option').each(function() {
var id = $(this).attr('name');
if (localStorage.getItem(id) != null && id=='name') {
$(this).attr("selected", "selected");
}
});
You'll just need to run the filtering after populating the options. Note that they will still flash on the screen before the JavaScript is run so you might want to keep them hidden until that.
$(document).ready(function() {
$('select').each(function() {
var id = $(this).attr('name');
var value = localStorage.getItem(id);
$(this).val(value)
});
$('#browsepagebutton').click(); // Add this
})
Updated fiddle: https://jsfiddle.net/387tnzoy/6/
There are multiple issue with your fiddle as described below.
Remove onclick="saveValues()" from Search button.
Check on document ready if localstorage has value than play with your localStorage checking code
Your Year dropdown have similar values for multiple options like <option value="5">2013</option>
<option value="5">2014</option>
<option value="5">2015</option> as you can see same value 5 here
And yes #kaivosukeltaja mentioned you have to click Search if localstorage has value on ready event
I have updated fiddle you can find here
Сan you explain please.
Why returned, only the first data attribute - "link-1.html", even if I click on the second link
<a class="project-link" href="link-1.html" data-url="link-1.html">
<a class="project-link" href="link-2.html" data-url="link-2.html">
var toUrl = $('.project-link').attr('data-url');
$('a').click(function() {
window.location.hash = toUrl;
});
The meaning of such action - my links open through Ajax, but I want to URL displayed in the browser.
I want to make it as behance, if you click on the cards portfolio, they displayed through Ajax in the same window, but it also left open the possibility of direct appeal to the links. That's why I want to URL displayed in the browser address bar
You have to get current target url by this
$('a').click(function() {
var toUrl = $(this).data('url'); // use this as current target
window.location.hash = toUrl;
});
I recommend you to use .data() when you're retrieving data attributes (only) instead of .attr()
Demo
.attr( attributeName )
Returns: String
Description: Get the value
of an attribute for the first element in the set of matched elements.
$('.project-link') matches more than one element. Therefore, $('.project-link').attr('data-url') will return the value of the data-url attribute for the first element in the set.
To solve this you have maintain the context of the clicked element as you get the attribute, and you do this by using the this keyword.
And if you have other event listeners attached to the element already and you do not want them to fire -- although ajax calls will abort when the user is redirected -- you can use event.stopImmediatePropagation():
$('a').on('click', function( event ) {
event.stopImmediatePropagation();
window.location.hash = $(this).data('url'); //this here refers to the element that was clicked.
});
$('a[data-url]').click(function() {
window.location.href = $(this).data("url");
});
You might want to try this:
$('.project-link').click(function(){
window.location.hash = $(this).data('url');
});
I've built a image gallery page using the following plugin found from a codrop article:
http://tympanus.net/Tutorials/ThumbnailGridExpandingPreview/
I've got the gallery working as intended but I would like to add another feature but I'm struggling to figure out and I would really appreciate any help.
Here's a jsfiddle showing a basic version with the open function working:
http://jsfiddle.net/yfmm6q0o/
Using Hash values loaded from external links I would like the page to load and automatically open the preview, depending on the hash value (for example www.page.com#item-2 would open the second item preview).
I was able to set the hash value using:
window.location.hash;
And by using the string replace I was able to add 'loc-' to the hash value and scroll the page to that ID, this worked great but I would like preview section to open as well.
Is there a way to link the hash value to the following function:
function initItemsEvents( $items ) {
$items.on( 'click', 'span.og-close', function() {
hidePreview();
return false;
} ).children( 'a' ).on( 'click', function(e) {
var $item = $( this ).parent();
// check if item already opened
current === $item.index() ? hidePreview() : showPreview( $item );
return false;
} );
}
Meaning if the page loaded with #item-2 hash value it would fire a click event or simulate a click on the second item, opening the preview.
Thanks in advance for any help.
I would set it up along these lines:
Working Demo
jQuery:
$(function() {
// give all of your elements a class and bind a handler to them
$('.myBtns').click(function() {
alert('button ' +$('.myBtns').index($(this))+ ' was clicked using the hash from the url ')
});
// get the hash on load
var hash = window.location.hash.replace(/^.*?(#|$)/,'');
// click one of the elements based on the hash
if(hash!='')$('.myBtns').eq(hash).click();
// bind to hashchange if you want to catch changes while on the page, or leave it out
$(window).bind('hashchange', function(e) {
var hash = e.target.location.hash.replace(/^.*?(#|$)/,'');
$('.myBtns').eq(hash).click();
});
});
HTML
<h3>Navigate to: http://dodsoftware.com/sotests/hash/hashTest.html#0 to see the first button clicked based on the url hash.</h3>
<h3>Navigate to: http://dodsoftware.com/sotests/hash/hashTest.html#1 to see the first button clicked based on the url hash.</h3>
<h3>Navigate to: http://dodsoftware.com/sotests/hash/hashTest.html#2 to see the second button clicked based on the url hash.</h3>
<h3>Navigate to: http://dodsoftware.com/sotests/hash/hashTest.html#3 to see the second button clicked based on the url hash.</h3>
<input type="button" class="myBtns" value="I get clicked by the url's hash"/>
<input type="button" class="myBtns" value="I get clicked by the url's hash"/>
<input type="button" class="myBtns" value="I get clicked by the url's hash"/>
<input type="button" class="myBtns" value="I get clicked by the url's hash"/>
So, you may want to try the following. Please see details as comments in the code.
//Let's say the hash is "#item-2" and always has a >0 number (i.e. #item-1, #item-2 and #item-n) at the end.
var indexFromHash = parseInt("#item-2".split("-").pop(), 10) - 1;
//this would trigger click and invoke
//$items.on( 'click', 'span.og-close', function() { part of your code
$items.eq(indexFromHash).find('span.og-close').trigger("click");
//this would trigger click and invoke
//}).children('a').on('click', function(e) { part of your code
$items.eq(indexFromHash).children('a').trigger("click");
So I'm trying to use ajax to put content into a div, and trying to have it change all internal links before it adds the content so that they will use the funciton and load with ajax instead of navigating to another page. My function is supposed to get the data with ajax, change the href and onclick attributes of the link, then put it into the div... However, all it's doing is changing the href and not adding an onclick attribute at all. Here's what I was using so far:
function loadHTML(url, destination) {
$.get(url, function(data){
html = $(data);
$('a', html).each(function(){
if ( $.isUrlInternal( this.href )){
this.onclick = loadHTML(this.href,"forum_frame"); // I've tried using both a string and just putting the function here, neither seem to work.
this.href = "javascript:void(0)";
}
});
$(destination).html(html);
});
};
Also, I'm using jquery-urlinternal. Just thought that was relevant.
You can get the effect you want with less effort by doing this on your destination element ahead of time:
$(destination).on("click", "A", function(e) {
if ($.isUrlInternal(this.href)) {
e.preventDefault();
loadHTML(this.href, "forum_frame");
}
});
Now any <a> that ends up inside the destination container will be handled automatically, even content added in the future by DOM manipulations.
When setting a function to onclick through js it will not show on the markup as an attribute. However in this case it is not working because the function is not being set correctly. Easy approach to make it work,
....
var theHref=this.href;
this.onclick = function(){loadHTML(theHref,"forum_frame");}
....
simple demo http://jsbin.com/culoviro/1/edit
I have a page with 3 buttons. >Logos >Banners >Footer
When any of these 3 buttons clicked it does jquery post to a page which returns HTML content in response and I set innerhtml of a div from that returned content . I want to do this so that If I clicked Logo and than went to Banner and come back on Logo it should not request for content again as its already loaded when clicked 1st time.
Thanks .
Sounds like to be the perfect candidate for .one()
$(".someItem").one("click", function(){
//do your post and load the html
});
Using one will allow for the event handler to trigger once per element.
In the logic of the click handler, look for the content having been loaded. One way would be to see if you can find a particular element that comes in with the content.
Another would be to set a data- attribute on the elements with the click handler and look for the value of that attribute.
For example:
$(".myElements").click(function() {
if ($(this).attr("data-loaded") == false {
// TODO: Do ajax load
// Flag the elements so we don't load again
$(".myElements").attr("data-loaded", true);
}
});
The benefit of storing the state in the data- attribute is that you don't have to use global variables and the data is stored within the DOM, rather than only in javascript. You can also use this to control script behavior with the HTML output by the server if you have a dynamic page.
try this:
HTML:
logos<br />
banner<br />
footer<br />
<div id="container"></div>
JS:
$(".menu").bind("click", function(event) {
event.stopPropagation();
var
data = $(this).attr("data");
type = $(this).attr("type");
if ($("#container").find(".logos").length > 0 && data == "logos") {
$("#container").find(".logos").show();
return false;
}
var htmlappend = $("<div></div>")
.addClass(type)
.addClass(data);
$("#container").find(".remover-class").remove();
$("#container").find(".hidde-class").hide();
$("#container").append(htmlappend);
$("#container").find("." + data).load("file_" + data + "_.html");
return false;
});
I would unbind the click event when clicked to prevent further load requests
$('#button').click(function(e) {
e.preventDefault();
$('#button').unbind('click');
$('#result').load('ajax/test.html ' + 'someid', function() {
//load callback
});
});
or use one.click which is a better answer than this :)
You could dump the returned html into a variable and then check if the variable is null before doing another ajax call
var logos = null;
var banners = null;
var footer = null;
$(".logos").click(function(){
if (logos == null) // do ajax and save to logos variable
else $("div").html(logos)
});
Mark nailed it .one() will save extra line of codes and many checks hassle. I used it in a similar case. An optimized way to call that if they are wrapped in a parent container which I highly suggest will be:
$('#id_of_parent_container').find('button').one("click", function () {
//get the id of the button that was clicked and do the ajax load accordingly
});