jQuery: click add to array and save as cookie - javascript

I have a function set up with the jQuery cookie plugin: https://github.com/carhartl/jquery-cookie, with the click function on .grid-block it stores each data-hook in an array, saves them as a cookie, then these chosen divs are viewable on the /itin/your-itin/ page. Here's a demo I've set up too: http://nealfletcher.co.uk/itin/ If you click on the .grid-block divs, this will add them to your itinerary, then when you navigate to: http://nealfletcher.co.uk/itin/your-itin/ only these divs are viewable and stored as a cookie for x amount of time. This works great, BUT if I then go back to add more divs, these are stored as a cookie, but the previous ones are wiped, I want to keep appending to the array, store it as a cookie, then when you navigate to: http://nealfletcher.co.uk/itin/your-itin/ it will display all your selections, even if they've been added separately. If that makes sense?
jQuery:
$(window).load(function () {
var cfilter = [];
var $container = $('.block-wrap');
$container.imagesLoaded(function () {
$container.isotope({
itemSelector: '.grid-block',
animationEngine: 'best-available',
filter: '.grid-block',
masonry: {
columnWidth: 151
}
});
$(".grid-block").click(function () {
var thing = $(this).attr("data-hook");
var test = "." + thing;
cfilter.push(test);
$.removeCookie('listfilter', {
path: '/itin/your-itin/'
});
// We need to set the cookie only once
// it stays at the url for 7 days
$.cookie("listfilter", cfilter, {
expires: 365,
path: '/itin/your-itin/'
});
});
if ($.cookie("listfilter") !== 'null') {
// console log just for testing
console.log($.cookie());
$('.block-wrap').isotope({
filter: $.cookie("listfilter")
});
return false;
} else {
// !! this part could be refactored
// as you don't really need to check against the url
// when the cookie doesn't exist show all elements
$('.block-wrap').isotope({
filter: ''
});
}
});
});
Any suggestions would be greatly appreciated!

Change var cfilter = []; to var cfilter = $.cookie("listfilter");
This way you load the changed cookie and add to it instead of overwriting it.
Better code practice would be to check if the cookie exists before using it though, but you get my hint.
You made an error in implementing my change:
if ($.cookie("listfilter") !== 'null') {
var cfilter = [];
} else {
var cfilter = $.cookie("listfilter");
}
is wrong, use
if ($.cookie("listfilter")) {
var cfilter = $.cookie("listfilter");
} else {
var cfilter =[];
}

Related

HTML/jQuery Save order

I'm using the jquery plugin called shapeshift. It's like jqueryui sortable but with better animations. The divs can be dragged and dropped. But I can't seem to figure out how to save their order so that on browser refesh the order remains the same where I left them.
Here is the jsfiddle http://jsfiddle.net/Shikhar_Srivastava/aC367/
$(".container").shapeshift({minColumns: 3});
I'm initiating the plugin as above.
Please help me on my fiddle.
Thanks.
I would create a cookie. So I would first include the jQuery Cookie script (found here: https://github.com/carhartl/jquery-cookie/blob/master/src/jquery.cookie.js), then create the cookies (one for each each .container) each time an element is moved:
/* save cookie */
$('.container').on("ss-drop-complete", function() {
var containerCookieCounter = 0;
$('.container').each(function() {
/* cookie = 12h */
var date = new Date();
date.setTime(date.getTime() + (720 * 60 * 1000));
$.cookie('savepositions' + containerCookieCounter, $(this).html(), { expires: date, path: '/' });
containerCookieCounter += 1;
});
});
Then, before initiating the shapeshift-function, check if there are existing cookies:
/* cookies... */
if ($.cookie('savepositions0')) {
var containerCounter = 0;
$('.container').each(function() {
$(this).html($.cookie('savepositions' + containerCounter));
containerCounter += 1;
});
}
Here is a working fiddle: http://jsfiddle.net/Niffler/FvUcQ/
Only one container
Fiddle
var $con=$(".container").shapeshift({
minColumns: 3
});
function getPos(id){
var p=localStorage[id];
var ro={left:100000,top:-1,unknown:true};
if(p!==undefined) ro=JSON.parse(p);
//alert('get Pos:'+id+' '+JSON.stringify(ro));
return ro;
}
function setPos(id,p){
//alert('set Pos:'+id+' '+JSON.stringify(p));
localStorage[id]=JSON.stringify(p);
}
function arrange(){
var o={};
var con=$(".container:nth-child(1)");
var els=$(".container:nth-child(1) div");
els.each(function(x){
var me=$(this);
var id=me.attr('id');
var o_=o[id]={};
o_.id=me.attr('id');
o_.p=getPos(id);
});
for(var i in o){
var oo=o[i];
var el=$('#'+oo.id);
if(!oo.unknown){
el.css('left',''+oo.p.left+'px');
}
}
}
function savePs(){
var els=$(".container:nth-child(1) div");
els.each(function(){
var me=$(this);
setPos(me.attr('id'),me.position());
});
}
var $con=$(".container:nth-child(1)");
$con.on('ss-rearranged',function(e,selected){
var id=$(selected);
setTimeout(function(){
//var me=$(selected);
savePs();
//setPos(me.attr('id'),me.position());
},500);
});
arrange();
//savePs();
Fiddle
As commenters have suggested, you need to use localStorage to store and retrieve the state, and save that state after the ss-drop-complete event.
Here is the entire JS I used in this updated jsFiddle:
$(function () {
// retrieve from localStorage if there is a saved state
var saved = localStorage.getItem('arrangement');
if (saved) {
populateArrangement($('.container').parent(), JSON.parse(saved));
}
$(".container").shapeshift({
minColumns: 3
}).on('ss-drop-complete', function () {
// get the new arrangement and serialise it to localStorage as a string
var rows = getArrangement();
localStorage.setItem('arrangement', JSON.stringify(rows));
});
// return the data needed to reconstruct the collections as an array of arrays
function getArrangement() {
var rows = [];
$('.container').each(function () {
var elementsInRow = [];
$(this).find('.ss-active-child').each(function () {
elementsInRow.push({
value: parseInt($(this).text(), 10),
colspan: $(this).data('ss-colspan') || 1
});
});
rows.push(elementsInRow);
});
return rows;
}
// use the arrangement to populate the DOM correctly
function populateArrangement(container, newArrangement) {
$(container).find('.container').remove();
$.each(newArrangement, function (index, row) {
var $container = $('<div class="container"></div>');
$container.appendTo(container);
$.each(row, function (index, element) {
var $div = $('<div></div>');
$div.text(element.value);
if (element.colspan > 1)
$div.attr('data-ss-colspan', element.colspan);
$container.append($div);
});
});
}
});
If you have some sort of server side code you can add the order to a hidden field on the ss-drop-complete function and then post this back to the server on post back. You can then just re-output the values back when the page re-renders and you can use this information in any server side code you need.
I've done something similar when working with jquery mobile and ASP.NET to save back to a database the order.
If not, the local storage option could be a good way to go.

Page loading is gradually getting slower using jQuery script

I'm using this jQuery script to show search results. Everything works fine, but when search results have more than one page and I'm browsing pages via paging then every page loading is gradually getting slower. Usually first cca 10 pages loads I get quickly, but next are getting avoiding loading delay. Whole website get frozen for a little while (also loader image), but browser is not yet. What should be the problem?
function editResults(def) {
$('.searchResults').html('<p class=\'loader\'><img src=\'images/loader.gif\' /></p>');
var url = def;
var url = url + "&categories=";
// Parse Categories
$('input[name=chCat[]]').each(function() {
if (this.checked == true) {
url = url + this.value + ",";
}
});
url = url + "&sizes=";
// Parse Sizes
$('input[name=chSize[]]').each(function() {
if (this.checked == true) {
url = url + this.value + ",";
}
});
url = url + "&prices=";
// Parse Prices
$('input[name=chPrice[]]').each(function() {
if (this.checked == true) {
url = url + this.value + ",";
}
});
$('.searchResults').load('results.php'+url);
$('.pageLinks').live("click", function() {
var page = this.title;
editResults("?page="+page);
});
}
$(document).ready(function(){
editResults("?page=1");
// Check All Categories
$('input[name=chCat[0]]').click(function() {
check_status = $('input[name=chCat[0]]').attr("checked");
$('input[name=chCat[]]').each(function() {
this.checked = check_status;
});
});
// Check All Sizes
$('input[name=chSize[0]]').click(function() {
check_status = $('input[name=chSize[0]]').attr("checked");
$('input[name=chSize[]]').each(function() {
this.checked = check_status;
});
});
// Edit Results
$('.checkbox').change(function() {
editResults("?page=1");
});
// Change Type
$(".sort").change(function() {
editResults("?page=1&sort="+$(this).val());
});
});
$('.pageLinks').live("click", function() {
var page = this.title;
editResults("?page="+page);
});
just a wild guess but... wouldn't this piece of code add a new event handler to the click event instead reaplacing the old one with a new one? causing the click to call all the once registered handlers.
you should make the event binding just once
var global_var = '1';
function editResults(def) {
// all your code
global_var = 2; // what ever page goes next
};
$(document).ready(function() {
// all your code ...
$('.pageLinks').live("click", function() {
var page = global_var;
editResults("?page="+page);
});
});

jQuery cookie key value with case statement

Ok, so my code is this so far:
$( document ).ready(function() {
// setup the initial display on page load
var menu_state = $.cookie('atd_gridlist');
// listen for the clicks
$('.gridselect').click(function() {
$.cookie('atd_gridlist', 'grid'); // update (or set) the cookie
$(".grid").css("display", "block");
$(".list").css("display", "none");
});
$('.listselect').click(function() {
$.cookie('atd_gridlist', 'list'); // update (or set) the cookie
$(".grid").css("display", "none");
$(".list").css("display", "block");
});
});
I need to also check to see if the cookie KEY has already been set, I think a case statement would work but I am not sure how to make the case read just the cookie atd_gridlist key values...
If it is gridselect I need to show the grid div and hide the list div, if it is listselect I need it to show the list div and hide the grid div, if it is not set at all, I want grid div loaded by default and hide the list. I also would like to expire the div every 7 days.
Any help in the right direction is appreciated. Thanks!
Would something like this do the job?
$(function() {
var grid = $('.grid');
var list = $('.list');
var stateCookie = 'atd_gridlist';
var SetStateCookie = function(value) {
$.cookie(stateCookie, value, { expires: 7, path: '/' });
}
var ShowByState = function(state) {
state = state || 'grid';
SetStateCookie(state);
if ('grid' === state) {
grid.show();
list.hide();
} else if ('list' === state) {
grid.hide();
list.show();
}
}
$('.gridselect').click(function() {
ShowByState('grid');
});
$('.listselect').click(function() {
ShowByState('list');
});
ShowByState($.cookie(stateCookie));
});

Tablesorter Filter widget stops working after update on all browsers, no error msg

I'm trying to see how I can fix a problem that I'm having with jQuery Tablesoter widget called 'filter', it stops working after the table is updated without any error message and it does this on all web browsers, the other widgets work like zebra and savesort only filter stops working.
here is the code:
<script type="text/javascript" src="tablesorter/OVOjquery-1.10.2.min.js"></script>
<script type="text/javascript" src="tablesorter/OVOjquery.tablesorter.min.js"></script>
<script type="text/javascript" src="tablesorter/OVOjquery.tablesorter.widgets.min.js"></script>
<script type="text/javascript" src="tablesorter/OVOjquery.tablesorter.pager.min.js"></script>
<script type="text/javascript" src="tablesorter/final/toastmessage/jquery.toastmessage-min.js"></script>
<script type="text/javascript" src="tablesorter/qtip/jquery.qtip.min.js"></script>
<!--//c24-->
<script type="text/javascript">
var comper;
function checkSession() {
return $.get("ajaxcontrol.php", function (DblIn) {
console.log('checking for session');
if (DblIn == 1) {
window.location = 'loggedout.php';
}
}).then(updateTable);
}
function checkComper() {
var SvInfo;
var onResponse = function (comperNow) {
if (comper === undefined) {
comper = comperNow;
} else if (comper !== comperNow) {
var Vinfoo;
comper = comperNow;
// returning this $.get will make delay done until this is done.
return $.get("getlastupdate2.php", function (primaryAddType) {
Vinfoo = primaryAddType;
$().toastmessage('showNoticeToast', Vinfoo);
}).then(checkSession);
}
};
$.get('getlastupdate.php').then(onResponse).done(function () {
tid = setTimeout(checkComper, 2000);
});
}
function updateTable() {
return $.get('updatetableNEW.php', function (data) {
console.log('update table');
var $table = $("table.tablesorter");
var $tableContents = $table.find('tbody')
////// var $html = $('<tbody/>').html(data);
$tableContents.replaceWith('<tbody>' + data + '</tbody>')
//$tableContents.replaceWith($html)
$table.trigger("update", [true]);
var currentUrl = document.getElementById("frmcontent").contentWindow.location.href;
var urls = ['indexTOM.php', 'index1.php'],
frame = document.getElementById('frmcontent').contentDocument;
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
if (frame.location.href.indexOf(url) !== -1) {
frame.location.reload()
}
}
$('[title!=""]').qtip({});
});
};
$(function(){
var tid = setTimeout(checkComper, 2000);
$("#append").click(function (e) {
// We will assume this is a user action
e.preventDefault();
updateTable();
});
// define pager options
var pagerOptions = {
// target the pager markup - see the HTML block below
container: $(".pager"),
// output string - default is '{page}/{totalPages}'; possible variables: {page}, {totalPages}, {startRow}, {endRow} and {totalRows}
output: '{startRow} - {endRow} / {filteredRows} ({totalRows})',
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight: true,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows: false,
// go to page selector - select dropdown that sets the current page
cssGoto: '.gotoPage'
};
// Initialize tablesorter
// ***********************
$("table")
.tablesorter({
theme: 'blue',
headerTemplate : '{content} {icon}', // new in v2.7. Needed to add the bootstrap icon!
widthFixed: true,
widgets: ['savesort', 'zebra', 'filter'],
headers: { 8: { sorter: false, filter: false } }
})
// initialize the pager plugin
// ****************************
.tablesorterPager(pagerOptions);
// Delete a row
// *************
$('table').delegate('button.remove', 'click' ,function(){
var t = $('table');
// disabling the pager will restore all table rows
t.trigger('disable.pager');
// remove chosen row
$(this).closest('tr').remove();
// restore pager
t.trigger('enable.pager');
});
// Destroy pager / Restore pager
// **************
$('button:contains(Destroy)').click(function(){
// Exterminate, annhilate, destroy! http://www.youtube.com/watch?v=LOqn8FxuyFs
var $t = $(this);
if (/Destroy/.test( $t.text() )){
$('table').trigger('destroy.pager');
$t.text('Restore Pager');
} else {
$('table').tablesorterPager(pagerOptions);
$t.text('Destroy Pager');
}
return false;
});
// Disable / Enable
// **************
$('.toggle').click(function(){
var mode = /Disable/.test( $(this).text() );
$('table').trigger( (mode ? 'disable' : 'enable') + '.pager');
$(this).text( (mode ? 'Enable' : 'Disable') + 'Pager');
return false;
});
$('table').bind('pagerChange', function(){
// pager automatically enables when table is sorted.
$('.toggle').text('Disable');
});
});
</script>
<!--//c24-->
Maybe the filter widget needs to be reloaded after the table update ?
I first thought that the updated table does not have the correct formatting so I saved the view source as a html file and when I open the page locally the 'filter' (search) works fine, so it cannot be the table (<TD>) formatting or so I think, but what can it be, can anyone please help me I have been trying to get this to work for two weeks now and I'm out of ideas as my knowledge here is limited :( Thanks.
It looks like the plugin needed to know that we made an update and I just needed to trigger the updateAll command.
Like this:
var resort = true, // re-apply the current sort
callback = function(){
// do something after the updateAll method has completed
};
$("table").trigger("updateAll", [ resort, callback ]);
There is a lot of code to wade through, but you might want to try updating the table contents like this:
var $table = $("table.tablesorter");
$table.find('tbody').html(data);
$table.trigger("update", [true]);
I'm only guessing that the replaceWith() function isn't working as intended.
Same problem here.
Short solution: make the filter-select to a filter-match class, then the table will work again.
Long solution: Does anyone have a working example of table sorter combined with ajax pager and filter plugin?

Trying to get my slideshow plugin to infinitely loop (by going back to the first state)

I wrote a slideshow plugin, but for some reason maybe because I've been working on it all day, I can't figure out exactly how to get it to go back to state one, once it's reached the very last state when it's on auto mode.
I'm thinking it's an architectual issue at this point, because basically I'm attaching the amount to scroll left to (negatively) for each panel (a panel contains 4 images which is what is currently shown to the user). The first tab should get: 0, the second 680, the third, 1360, etc. This is just done by calculating the width of the 4 images plus the padding.
I have it on a setTimeout(function(){}) currently to automatically move it which works pretty well (unless you also click tabs, but that's another issue). I just want to make it so when it's at the last state (numTabs - 1), to animate and move its state back to the first one.
Code:
(function($) {
var methods = {
init: function(options) {
var settings = $.extend({
'speed': '1000',
'interval': '1000',
'auto': 'on'
}, options);
return this.each(function() {
var $wrapper = $(this);
var $sliderContainer = $wrapper.find('.js-slider-container');
$sliderContainer.hide().fadeIn();
var $tabs = $wrapper.find('.js-slider-tabs li a');
var numTabs = $tabs.size();
var innerWidth = $wrapper.find('.js-slider-container').width();
var $elements = $wrapper.find('.js-slider-container a');
var $firstElement = $elements.first();
var containerHeight = $firstElement.height();
$sliderContainer.height(containerHeight);
// Loop through each list element in `.js-slider-tabs` and add the
// distance to move for each "panel". A panel in this example is 4 images
$tabs.each(function(i) {
// Set amount to scroll for each tab
if (i === 1) {
$(this).attr('data-to-move', innerWidth + 20); // 20 is the padding between elements
} else {
$(this).attr('data-to-move', innerWidth * (i) + (i * 20));
}
});
// If they hovered on the panel, add paused to the data attribute
$('.js-slider-container').hover(function() {
$sliderContainer.attr('data-paused', true);
}, function() {
$sliderContainer.attr('data-paused', false);
});
// Start the auto slide
if (settings.auto === 'on') {
methods.auto($tabs, settings, $sliderContainer);
}
$tabs.click(function() {
var $tab = $(this);
var $panelNum = $(this).attr('data-slider-panel');
var $amountToMove = $(this).attr('data-to-move');
// Remove the active class of the `li` if it contains it
$tabs.each(function() {
var $tab = $(this);
if ($tab.parent().hasClass('active')) {
$tab.parent().removeClass('active');
}
});
// Add active state to current tab
$tab.parent().addClass('active');
// Animate to panel position
methods.animate($amountToMove, settings);
return false;
});
});
},
auto: function($tabs, settings, $sliderContainer) {
$tabs.each(function(i) {
var $amountToMove = $(this).attr('data-to-move');
setTimeout(function() {
methods.animate($amountToMove, settings, i, $sliderContainer);
}, i * settings.interval);
});
},
animate: function($amountToMove, settings, i, $sliderContainer) {
// Animate
$('.js-slider-tabs li').eq(i - 1).removeClass('active');
$('.js-slider-tabs li').eq(i).addClass('active');
$('#js-to-move').animate({
'left': -$amountToMove
}, settings.speed, 'linear', function() {});
}
};
$.fn.slider = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
return false;
}
};
})(jQuery);
$(window).ready(function() {
$('.js-slider').slider({
'speed': '10000',
'interval': '10000',
'auto': 'on'
});
});​
The auto and animate methods are where the magic happens. The parameters speed is how fast it's animated and interval is how often, currently set at 10 seconds.
Can anyone help me figure out how to get this to "infinitely loop", if you will?
Here is a JSFiddle
It would probably be better to let go of the .each() and setTimeout() combo and use just setInterval() instead. Using .each() naturally limits your loop to the length of your collection, so it's better to use a looping mechanism that's not, and that you can break at any point you choose.
Besides, you can readily identify the current visible element by just checking for .active, from what I can see.
You'd probably need something like this:
setInterval(function () {
// do this check here.
// it saves you a function call and having to pass in $sliderContainer
if ($sliderContainer.attr('data-paused') === 'true') { return; }
// you really need to just pass in the settings object.
// the current element you can identify (as mentioned),
// and $amountToMove is derivable from that.
methods.animate(settings);
}, i * settings.interval);
// ...
// cache your slider tabs outside of the function
// and just form a closure on that to speed up your manips
var slidertabs = $('.js-slider-tabs');
animate : function (settings) {
// identify the current tab
var current = slidertabs.find('li.active'),
// and then do some magic to determine the next element in the loop
next = current.next().length >= 0 ?
current.next() :
slidertabs.find('li:eq(0)')
;
current.removeClass('active');
next.addClass('active');
// do your stuff
};
The code is not optimized, but I hope you see where I'm getting at here.

Categories