im new to jquery bbq, i've figured out most of the setup so far but i have a little issue. heres the setup.
one page with main nav links on the right
each nav link click will change the body content of the page to its corresponding data (showing and hiding divs) (with bbq)
one of the links shows a div with another set of links that when clicked will set hash B in the url
so first link click
domain.com/dir/#A=page1
second link click
domain.com/dir/#A=page1&B=set1
if i press the back button it goes back to the previous A hash, however the B hash remains in the url.
is there a way to remove the B peram when not on the specific page?
$(window).bind('hashchange', function(e) {
var state = $.bbq.getState('p');
var graphState = $.bbq.getState('n');
var base_title = '{/literal}{$smarty.const.SITE_TITLE}{literal} | Dashboard | ';
$('.profile-nav a').each(function() {
if (!state) {
$('.profile-nav a').each(function() {
$('#' + this.id).removeClass('live active');
document.title = base_title + 'Message Center';
});
$('#m').addClass('live active');
} else if (state == this.id) {
$('#' + this.id).addClass('live active');
document.title = base_title + $(this).text();
} else {
$('#' + this.id).removeClass('live active');
}
});
if (!state) {
$('.tab-content').fadeOut('fast');
$('.message-content').fadeIn('slow');
} else {
$('.tab-content').fadeOut('fast');
clicked = $('#' + state).attr('rel').split(' ')[0];
$('.' + clicked).fadeIn('slow');
}
if (state == 'r') {
if (graphState) {
$('.nick-breakdown').fadeOut('fast');
$('#' + graphState).fadeIn('slow');
document.title = base_title + 'Reports | ' + $('#' + graphState).attr('rel');
} else {
$('.item-breakdown').fadeOut('fast');
$('.nick-breakdown').fadeIn('slow');
document.title = base_title + 'Reports';
}
}
});
I've accomplished the same thing using jsbbq.pushState with merge_mode = 2 instead of just setting the # on the anchor.
Check out the docs here: http://benalman.com/code/projects/jquery-bbq/docs/files/jquery-ba-bbq-js.html#jQuery.bbq.pushState
merge_mode(Number) : Merge behavior defaults to 0 if merge_mode is not
specified (unless a hash string beginning with # is specified, in
which case merge behavior defaults to 2), and is as-follows:
0: params in the params argument will override any params in the current state.
1: any params in the current state will override params in the params argument.
2: params argument will completely replace current state.
So if your link looks like:
mysite.com#A=page1&B=page2 you could call
$.bbq.pushState({'A' : 'pageXYZ'}, 2);
And your doc location would then be:
mysite.com#A=pageXYZ
I got a way easier approach, no plugins needed:
Copy over current hashparameters to a dummy URL AS searchParameters. Now you can treat the hash parameters like search-parameters, edit them with all the functionality of searchparameters (developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) and copy them back afterwards AS hasparameters,
E.g Simple function that set and updates parameters, you could also use '.delete()' instead of '.set' to delete the parameter:
function setOrUpdateHashParameter( hashParameterName, hashParameterValue ) {
let theURL = new URL('https://dummy.com'); // create dummy url
theURL.search = window.location.hash.substring(1); // copy current hash-parameters without the '#' AS search-parameters
theURL.searchParams.set( hashParameterName, hashParameterValue ); // set or update value with the searchParams-API
window.location.hash = theURL.searchParams; // Write back as hashparameters
}
If anyone knows how to format these post properly, feel free to edit it, thanks!
Related
I am using InfiniteScroll:
var infScroll = new InfiniteScroll( '.grid', {
path: function() {
var pageNumber = ( this.loadCount + 1 );
var apiUrlQuery = $('.pagination__next').attr('href') + '&page=' + pageNumber;
return apiUrlQuery;
},
responseType: 'text',
status: '.scroll-status',
history: false
});
But now I need to implement search, so that means I need to refresh the path and the grid. How to do it?
So far what I have done is:
$('.search-events').on('click', function() {
infScroll.destroy();
/* building search query */
$('.grid-item').remove(); //Remove items visually from the grid
var apiUrlQuery = baseUrl + "&" + searchBy + "=" + searchTerm;
$('.pagination__next').attr('href', apiUrlQuery); //Update search url
infScroll.create();
infScroll.isLoading = false;
infScroll.loadNextPage();
})
With this, I am doing a new request using a new URL and get results but they don't get printed on the screen, also I see that the height of the grid is still the same as if I did not remove the grid-items.
Any ideas?
I finally made it work:
$('.search-events').on('click', function() {
msnry.remove($('.grid').find('.grid-item'));
var apiUrlQuery = baseUrl + "&" + searchBy + "=" + searchTerm;
$('.pagination__next').attr('href', apiUrlQuery);
infScroll.isLoading = false;
infScroll.canLoad = true;
infScroll.create();
msnry.layout();
infScroll.loadNextPage();
})
This line removes the elements from the DOM as I did with $('.grid-item').remove(), but also remove it from some internal array that keeps data.
msnry.remove($('.grid').find('.grid-item'));
Also, I removed infScroll.destroy(); because it unbinds from the load method.
The key part is msnry.layout(); this one rebuilds the layout.
Hope it helps someone in the future.
I'm working on a drupal module and it gets images from an API, adds selectable search-filters and generates pagination. If I go to e.g. the 7th pagination page and add a filter that only spans 3 pages it will result in not showing anything at all.
Solution: on upon adding a filter, go back to the 1st page. Now is my problem that that page is an url parameter and the links made by the filter are set to href='#' so basically this page yes.
So I try to debug the javascript that handles the on click:
$('#blabla .filter-url').click(function(e) {
e.preventDefault();
var link = $(e.currentTarget);
console.log(link);
var filter_key = link.data('filter-key');
var filter_value = link.data('filter-value');
// var active = link.hasClass('active');
var filters_input = $('#blabla input[name="filters"]');
var current_filters = JSON.parse(filters_input.val() || '{}');
current_filters.filters = current_filters.filters || [];
var exists = ($.grep(current_filters.filters, function(e, i){
return e.key == filter_key;
}).length);
if (exists) {
//Remove current filter from list
current_filters.filters = $.grep(current_filters.filters, function(e, i){
return e.key != filter_key;
});
link.removeClass('active');
}
// Add current filter to list
current_filters.filters.push({
key: filter_key,
value: filter_value,
});
link.addClass('active');
filters_input.val(JSON.stringify(current_filters));
$('#formname').submit();
});
the link object:
The link object has a {0, context and length} object in which both 0 and context contain multiple instances of the url, which one should I edit?
I just want to manipulate the URL / get parameter page=xxx to be page=0, so it goes back to the 1st page. How to achieve this?
I was searching in the wrong place. At the end of the onclick-function it submits the form. I had to change the action of this form like this:
var old_form_action = $('#formname').attr('action');
var new_form_action = old_form_action.replace(/(page=)[^\&]+/, '$1' + '0');
$('#formname').attr('action', new_form_action);
What I am trying to do is to call a function every time a person scrolls that checks the current class of container and adds +1 to the current value of the current data attribute and then toggles the class relative to the data attribute it is currently changing the class on scroll but giving a "NaN. I am already running this function on click and it works fine.
here is a fiddle.
http://jsfiddle.net/kaL63/1/
This is my function on scroll
var timeout;
$(window).scroll(function() {
if(typeof timeout == "number") {
window.clearTimeout(timeout);
delete timeout;
}
timeout = window.setTimeout( check, 100);
});
My html Looks like this
<div class="container year-1987" data-year-index="1987">
Some Content
</div>
the function I am calling right now that I think should work..
function check(){
var
animationHolder = $('.container'),
currentClass = animationHolder.attr("class").match(/year[\w-]*\b/);
var goToYear = $('.container').data('year-index');
var goToYear2 = parseInt(goToYear,1000) + 1;
animationHolder.toggleClass(currentClass + ' year-' + goToYear2);
animationHolder.attr('data-year-index', goToYear2);
}
My working code on click
$("a").click(function (e) {
e.preventDefault();
var
animationHolder = $('.container'),
currentClass = animationHolder.attr("class").match(/year[\w-]*\b/);
var goToYear = $(this).data('year-index');
animationHolder.toggleClass(currentClass + ' year-' + goToYear);
animationHolder.attr('data-year-index', goToYear);
I rewrote your check method:
function check() {
var $container = $('.container'),
currentYear = $container.data('m-index'),
nextYear = 1 + currentYear;
$container.removeClass('m-' + currentYear).addClass('m-' + nextYear);
$container.data('m-index', nextYear);
}
I made the following changes:
There is no need for the regular expression since we can generate the class name ourselves.
I am not sure why you were originally using two separate data-attributes (m-index and year-index), but I switched them to both match. If you need both of them, some more logic is needed to use year-index after the initial call.
I am now updating m-index via .data() rather than setting a data attribute.
This method seemed to work fine for me.
I have the following url
http://www.domain.com?page=options&tab=general
I want to be able to get to the tab parameter and change it e.g
I have two tabs General & Styles and when I click on styles, I want a hidden field(that has this url as a value) to change so that it reads the same url but with the tabs parameter changed to styles. So it would look like this
http://www.domain.com?page=options&tab=styles
However, this url may not have the parameter tab when the page is loaded so i need to be able to add a parameter to the url query string.
There will be many more tabs so I cannot just replace the text general with styles
Anyone know?
Thanks
var s = "http://www.domain.com?page=options&tab=general"
var queryString = s.substring(s.lastIndexOf("?") + 1);
var newQueryString = $.map(queryString.split("&"), function(pair) {
var p = pair.split("=");
if (p[1] == "general") {
p[1] = "styles";
return p.join("=");
} else {
return pair;
}
}).join("&");
We're working on a music page to list albums, songs and add lyrics.
We have a "View More" below each album, clicking that shows you the song list (using jquery, making a hidden div slide down). We'd like to add a variable to the URL if someone clicks it (or remove it if they "hide") the songs, so that it creates a permalink to that section. If someone passes that it'll automatically show that div open.
So a link should look something like this
http://www.greendayauthority.com/music/catalog.php#album=1039
or
http://www.greendayauthority.com/music.catalog.php?album=1039
(Could someone help me figure out the better way to use this? Between the "#" and "?"
We want to do the same thing for lyrics of individual songs. If someone clicks a song title, it adds another variable to the URL with the song ID.
So if someone clicks a song title it'll then be
http://www.greendayauthority.com/music/catalog.php?album=1039&song=3
We can handle all the code to make all the stuff appear on the page, but I don't know how to add a variable onto the page with javascript, so that if someone wants to link the lyrics to a specific song, they can share that link and when they visit, the proper divs will be shown.
Can someone help point me in the right direction? Any tips on a better way to do this are also welcome.
Thanks!
If you delimit it with a ?, it's a query string, the normal way to put variables onto a page. If you do it with #, it's the hash, and it refers to navigation within a page.
If you use the # you can navigate without refreshing the page. If you add an item to the query string from Javascript (location.href = blah?album=1039), the page will get reloaded. I don't think that's what you want.
In any case, when you click the link to expose the hidden div, don't change location.href. Just make your anchor tag navigate within the page, as in
Here's my try at it:
Required code:
var HashSearch = new function () {
var params;
this.set = function (key, value) {
params[key] = value;
this.push();
};
this.get = function (key, value) {
return params[key];
};
this.keyExists = function (key) {
return params.hasOwnProperty(key);
};
this.push= function () {
var hashBuilder = [], key, value;
for(key in params) if (params.hasOwnProperty(key)) {
key = encodeURIComponent(key), value = encodeURIComponent(params[key]);
hashBuilder.push(key + ( (value !== "undefined") ? '=' + value : "" ));
}
window.location.hash = hashBuilder.join("&");
};
(this.load = function (paramString) {
params = {}
var hashStr = paramString || window.location.hash, hashArray, keyVal
hashStr = hashStr.substring(1);
if (hashStr === "") return;
hashArray = hashStr.split('&');
for(var i = 0; i < hashArray.length; i++) {
keyVal = hashArray[i].split('=');
params[decodeURIComponent(keyVal[0])] = (typeof keyVal[1] != "undefined") ? decodeURIComponent(keyVal[1]) : keyVal[1];
}
})();
};
Init code:
$(function () {
showDiv();
$(".view-more-hash").live('click', function () {
HashSearch.load(this.hash);
showDiv();
});
});
function showDiv() {
if (HashSearch.keyExists('album')) {
var albumDiv = $("#album" + HashSearch.get('album')).show();
if (HashSearch.keyExists('song')) {
albumDiv.find("#album" + HashSearch.get('album') + "song" + HashSearch.get('song')).show()
}
}
}
Your links will look like:
View album
View song
Your content:
<a name="album=2"></a> // auto scroll to location.. not required
<div id="album2">
<div id="album2song3"></div>
</div>