Cookies or localstorage is best way? - javascript

I have some javascript, in which i need either cookies or localstorage to ensure variables aren't lost.
I'm a beginner and i'm not sure which is best to use, but i know both do sort of the same thing.
Basically, i need whatever the javascript is doing to be stored and even when user logs out / logs in, between any amount of days this is still being saved.
Can someone help?
<script>
$(document).ready(function() {
$("input").click(function(e) {
e.preventDefault();
var $challenge_div = $(this).parent().parent();
$challenge_div.data("finish", "false");
$challenge_div.removeClass("show").addClass("hide");
var $challenge_list = $("div[class='hide']");
$.each($challenge_list, function() {
var new_challenge = $(this);
if (new_challenge.data("finish") == false) {
new_challenge.removeClass("hide").addClass("show");
return false;
}
});
if ($("div[class='show']").length == 0) {
$("#message p").html("You finished all your challenges !");
}
});
});
</script>

I'm a beginner and i'm not sure which is best to use, but i know both do sort of the same thing.
Actually, they do very different things.
Cookies are for sending information back and forth between the server and client on every HTTP request.
Web storage is for storing information in the client (only).
For your use case, web storage would be the right thing to use, since you only want the information client-side. It also has a reasonable API (unlike cookies). You can store a string:
localStorage.setItem("key", "value");
// or
localStorage.key = "value"; // See warning below
// or
localStorage["key"] = "value"; // See warning below
(I'd recommend using the setItem method instead of directly assigning to a property on localStorage, so there's no chance of your conflicting with any of localStorage's methods!)
...and get it back later, even in the user left the page entirely and came back:
var x = localStorage.getItem("key");
// or
var x = localStorage.key; // See warning above
// or
var x = localStorage["key"]; // See warning above
console.log(x); // "value"
And remove it if you want:
localStorage.removeItem("key");
Often, it makes sense to use JSON to store your client-side information, by using some kind of settings object and storing it by converting it to JSON:
localStorage.setItem("settings", JSON.stringify(settings));
...and using JSON.parse when getting it (back):
var settings = JSON.parse(localStorage.getItem("settings"));
if (!settings) {
// It wasn't there, set defaults
settings = {/*...*/};
}

I'm not sure which is best to use, but I know both do sort of the same thing.
Not really. A key difference in Cookies and Local Storage is that cookies will be sent along with every server request you make.[1]
Requesting some data using AJAX, cookies will be included in the request.
Navigating to a new page, cookies will be included in the request.
So the disadvantage is that you are transferring additional data to the server every time you make a request. More so if you are storing a lot of data into the cookies.
Local storage is merely kept in the browser (until you clear it explicitly), but it is not sent along with every request.
The decision is simple, if you require that data available to the server with request parameters, you should use cookies, else use local storage.
One more thing, from what you are saying, it seems like you intend to store the user's progress in a game. Keep in mind that both cookie and local storage are accessible to the user. So they can tamper with that data if they want.
If it is critical to prevent user's from changing the data, you must store the data on the server instead.
Do read: JavaScript: client-side vs. server-side validation
[1]. This may not be entirely true with HTTP2 but that's a different topic.

Related

Javascript: compare previous url with current one

Requirement:
Compare the previous url with the current one and do some action.
Problem:
The document.referrer is still same after the page refresh.
Question:
Is there an elegant way of comparing urls other then storing a cookie or session?
In case someone will be interested how I resolved my problem:
// store the current url
window.onbeforeunload = function(e) {
window.localStorage.setItem("current-url", window.location.href);
};
// read
var urlReferrer = window.localStorage.getItem("current-url");
// do something
if (urlReferrer != window.location.href)
JavaScript never does anything in an 'elegant' way. It's going to be tricky generally just using javascript, especially if you are expecting this to not change after a page refresh.
While I would suggest either cookies or local storage, your other alternative is saving the "state" of the page using a back-end programming language.

Javascript > form results to "remember" user > avoid showing form twice

I have a java script form in a website, that outputs some results -a silly simple mathematical operation or subtraction of dates.
I need these results to "remember" the visit so the div and the results
show when the user re-loads the page.
How can I achieve this?? It's my first time with facing a situation like this...
Note: its not a logged user!! but a non-logged visit..
http://goo.gl/OHQmpb
You can use localStorage.
Store the values in it by specifiying a key:
localStorage.setItem('key','value');
And, you can get the value by:
var value = localStorage.getItem('key');
HTML5 Web storage is the best option in your case.
Exact definition:
So what is HTML5 Storage? Simply put, it’s a way for web pages to
store named key/value pairs locally, within the client web browser.
Like cookies, this data persists even after you navigate away from the
web site, close your browser tab, exit your browser, or what have you.
Unlike cookies, this data is never transmitted to the remote web
server (unless you go out of your way to send it manually).
With HTML5, web pages can store data locally within the user's browser.
// Store it in object
localStorage.setItem("form attributes", "form values");
// Retrieve from object
localStorage.getItem("form attributes");
HTML5 Local Storage aka Web Storage can store values without maintaining a server side session. See this example:
function calculate(){
return 'some value';
}
window.onload = function(){
// submit handler for the form, store in local storage
document.getElementById("myform").onsubmit = function(){
localStorage.setItem('calcResult', calculate());
return false;
};
// load the value if present
var result = localStorage.getItem('calcResult');
if(result != null){
// show in div
document.getElementById("mydiv").innerHTML = result;
}
}

Jquery / Javascript - get list of request URLs for that session like in browser console

I need to be able to retrieve the list of request URLs that are displayed in the browser console, i.e: GET http://mydomain.com/index.php?p=1&curr=GBP&cat=Food. 200. Users can click around my app and apply different filters and scrolls through pages and I need some way of tracking this so that I always know what data has already been loaded for that users session.
I had thought about using PHPs $_SERVER['REQUEST_URI'] and saving them in a session but then I don't know how I would access this session from my JQuery as its JQuery that constructs the URLs.
Has anyone any idea how I can access this data from the console? Is this possible? If not can anyone suggest a workaround?
The PHP / JQuery mess I have so far:
<?php
session_start();
//keep track of requests.
if (!isset($_SESSION['requests'])) {
$_SESSION['requests'] = array();
} else {
if (!in_array( $_SERVER['REQUEST_URI'], $_SESSION['requests'])) {
$_SESSION['requests'][] = $_SERVER['REQUEST_URI'];
}
}
$requests = json_encode($_SESSION['requests']);
print_r($_SESSION['requests']);
print_r($requests); //these both have values
?>
//further down the page is the javascript
$('.filter a').click(function(e) {
var $this = $(this);
var $optionSet = $this.parents('.option-set');
var group = $optionSet.attr('data-filter-group');
filters[ group ] = $this.attr('data-filter-value');
//***more code for filtering etc******/
var paginate_url = $('.paginate a').attr('href');
//THIS IS PART I CANNOT GET WORKING
var visited_urls= <?=$requests?>;
//console.log($.parseJSON(visited_urls));
console.log(visited_urls); //is always empty
var pageno = ''; //somehow check to see if the URL that has been clicked exists int he requests array, if so get the page number and increment.
var next_url = UpdateQueryString(paginate_url, pageno, group, encodeURIComponent(filter_qry));
I'm not completely sure what you're trying to do but I think you can skip the PHP and just use JavaScript and sessionStorage: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#sessionStorage or localStorage: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#localStorage (depending on how persistent you want the data to be)
For example if I want to listen for all clicks on 'a' tags and track whether those hrefs have been visited (and how many times)
$(document).ready(function() {
// store an empty object in session storage when the page loads
sessionStorage.visited = JSON.stringify({});
});
$('a').on('click', function() {
var storage = JSON.parse(sessionStorage.visited),
href = $(this).attr('href');
// when we get a click check to see if this has been clicked before
if (!storage[href]) {
// if not save it and set the count to 1
storage[href] = 1;
} else {
// otherwise increment the count
storage[href]++;
}
sessionStorage.visited = JSON.stringify(storage);
});
If you want to save the urls from your ajax calls the same principle applies but listen for the ajaxSuccess event and store the url from the request in the callback: http://api.jquery.com/ajaxSuccess/
This is my suggestion:
PHP + Javascript Implementation:
In PHP, use $_GET['curr'] and $_GET['cat'] to retrieve the arguements from the URL.
Use $_SESSION['curr'] = $_GET['curr']; to save them per the session.
On your Javascript/jQuery use var curr = "<?php echo $_SESSION['curr']; ?>" to make the PHP session variables available to your Javascript.
Basically the key to have a good PHP/Javascript persistent memory is that you can set PHP content into a Javascript variable by using:
var x = <?php echo '123';?>;
console.log(x); //output '123' to Javascript console
If you need to have a list of all visited urls, you can save them in a PHP array and transfer it to Javascript as well.
On PHP side:
if (!isset($_SESSION['visited'])) $_SESSION['visited'] = array();//initialize the array if doesn't exist
if (!inarray( $_SERVER['REQUEST_URI'], $_SESSION['visited']) { //check if current URL is not in array
$_SESSION['visited'][] = $_SERVER['REQUEST_URI'];//push it to the array
}
On Client side:
//this will convert the PHP array to a Javascript array using json_encode
var visited_urls= <?php echo json_encode($_SESSION['visited']); ?>;
Don't forget to use session_start() on every page you need the session variables.
Javascript Only Implementation:
Use localStorage and keep everything on the client side.
EDIT: Note that localStorage is only supported in IE8 and up, so if versions prior to IE8 must be supported, you will need to use Cookies instead of localStorage.
$(document).ready(function() {
var urls = JSON.parse(localStorage["visited"]) || [];//get the visited urls from local storage or initialize the array
if (urls.indexOf(document.URL) == -1) {//if current url does not exist in the array
urls.push(document.URL);//add it to the array
localStorage["visited"] = JSON.stringify(urls);//save a stringifyed version of the array to local storage
}
});
Hope this helps!
It's unclear what you want to achieve with this feature. You state:
Users can click around my app and apply different filters and scrolls through pages and I need some way of tracking this so that I always know what data has already been loaded for that users session.
What do you want to achieve with this, why isn't the browser's cache enough for you?
My idea for a solution would be to sync server session array with an object inside the Browser via some sort of WebSocket (http://en.wikipedia.org/wiki/WebSocket).
UPDATE2:
It is possible to use localStorage as cache storage as Abel Melquiades Callejo suggests and then read from it bypassing HTTP requests. I would choose what content to save to that cache differently, no server involved:
add a custom attribute data-* to every HTML element you want cached (http://html5doctor.com/html5-custom-data-attributes/);
make a querySelectorAll (https://developer.mozilla.org/en-US/docs/Web/API/Document.querySelectorAll) for all HTML elements with that attribute;
storing and retrieving documents from localStorage should be easy now, you need a convention for naming files for easy finding;
storing images implies doing a base64 transformation which increases the size of the data by 34% (image with 64kb will take 86kb in localStorage).
you need a way to find when data in localStorage is obsolete and you need to make requests to the server (perhaps another data-age attribute to specify when should it expire).
However, this localStorage solution is limited to a small amount of data, see this issue https://github.com/RemoteStorage/remoteStorage.js/issues/144. So, although I now see that what you are asking is possible, because of this size limitation to localStorage, I strongly recommend the solutions in my UPDATE1, below.
UPDATE1: The point is that caching mechanisms are incredibly complex. A better alternative would be to use the default browser caching mechanisms:
1. HTML5 cache manifest
Go offline with application cache
http://html5doctor.com/go-offline-with-application-cache/
LET’S TAKE THIS OFFLINE http://diveintohtml5.info/offline.html
Using the application cache
https://developer.mozilla.org/en/docs/HTML/Using_the_application_cache
A Beginner's Guide to Using the Application Cache http://www.html5rocks.com/en/tutorials/appcache/beginner/
2. Server's response headers to HTTP requests
Optimize caching - Leverage browser caching
https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching
HTTP Caching FAQ https://developer.mozilla.org/en/docs/HTTP_Caching_FAQ

how to save a filter in Dojo

I have an EnhancedGrid that users regularly use complex filters on. Is there a way to allow users to save or bookmark a filter so they can easily re-apply it in future? I know I can programmatically set a filter, but I can't predict what filters my users will want.
Thank you!
edit: made some progress myself... using grid.getFilter() to return a JSON representation of the filter, then json.stringify(jsonRepresentation) to convert it into a string. Now I'm considering my options for how to store, load and convert that string. Would loading a string into a json object then applying it as my filter open me up to XSS vulnerabilities? If I want to have filters specified as arguments in the url, can I compress the string to reduce the character count?
Right off the bat, here are the two three approaches I see:
Store the filter in a URL (Okay)
Simply get the window.location and parse out the query string using dojo/io-query::queryToObject():
require(['dojo/io-query'], function (ioQuery) {
var uri = window.location.href;
var query = uri.substring(uri.indexOf("?") + 1, uri.length);
query = ioQuery.queryToObject(query);
});
(Documentation for dojo/io-query)
Store the filter in a cookie (Better)
The dojo/cookie module makes this very, very easy:
require(['dojo/cookie', 'dojo/json'], function (cookie, json) {
var filter = { ... };
cookie("myFilter", json.stringify(filter)); //store the cookie
// json.parse(cookie("myFilter"));
// ^-- returns the cookie as a JS object
});
(Documentation for dojo/cookie)
Obviously, the user must have cookies enabled for this to work, but it's much cleaner than storing a bunch of variables in a URL for them to bookmark.
Use HTML5 Local Storage as suggested by Dimitri M: (Even better)
Check to see if the user's agent supports Local Storage, and if so, use that global variable to hold on to the filter:
require(['dojo/json'], function(json) {
function supportsLocalStorage() {
return ('localStorage' in window) && window['localStorage'] !== null;
}
var filter = { ... };
if(supportsLocalStorage()) {
localStorage.setItem("myFilter", json.stringify(filter));
}
// json.parse(localStorage.getItem("myFilter"))
// ^-- returns the filter as a JS object
});
An advantage in using web storage is that you can store much more data than cookies can.
You could conceivably use cookies as a fallback for browsers that don't support Local Storage, (i.e. when supportsLocalStorage() returns false) at the cost of adding a touch more overhead to your design, so ultimately it's your call, depending on what browsers you want to support.
Browser Compatibility for Web Storage
How about cookies?
The grid widget has a cookie plugin(link), but id doesn't save the filter. Maybe extending the plugin or the grid could be an option.
Passing the filter properties as string also sounds like an option. Knowing the conditions, and the values that can be used, or their type, you can easily validate the filter before applying it to the grid.

Using an object property as a function and as an object simultaneously

I was wondering if there is a way to declare an object property as a function, but also as an object, at the same time.
I have a JavaScript program that provides a simple API that sends AJAX requests to a server. My goal is trying to make this API as simple and human-readable as possible.
Basically, I'd like to make it possible to do this:
var app = new App();
app.get.client(123) // Get client ID 123
app.get.client.list() // Get an array of all clients
app.login('username', 'password') // Send credentials to log as username/password
app.login.as('John') // Login using credentials stored in a server-side constant
I doubt that's even possible as I've never anything like it, but I can't think of a more clear and human-readable way to lay out methods. Sure would be nice!
A function’s an object too!
app.get.client = function(id) {
// Get client by ID
};
app.get.client.list = function() {
// List them
};
works as you’d expect.
Personally, though, I’d find:
app.clients.byId(123)
app.clients
app.login('username', 'password')
app.loginAs('John')
more readable.

Categories

Resources