Let's say i have some textboxes/textareas of which the values have to be stored. The values have to be stored on key press, so that no data is lost when the user closes the page too early. Here's my current code (using cookies):
function createCookie(name, value, days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = '; expires=' + date.toGMTString();
} else var expires = '';
document.cookie = name + '=' + value + expires + '; path=/';
}
$('input').keyup(function () {
var $this = $(this);
createCookie($this.attr('name'), $this.val(), 1);
});
jsFiddle
This works great.
With just 4 textboxes i see no problems but imagine having 50+ textboxes or textareas (not accounting usability/user experience). Will this cause any problems?
I'm open to any suggestions/alternatives
I'd opt for using local storage (see http://www.w3schools.com/html/html5_webstorage.asp), seems more scalable than setting a cookie for each text input.
Also, you mention that the values must be set with each keystroke, why not instead keep the value of the current input in memory, and bind a function which commits the value both to the blur event of the input, and also use setTimeout to impose, say, a 1 second delay on saving the value, queuing these timeouts in an array, and clearing outstanding ones on each keyup event, that way you're only writing to the local storage when the user pauses typing, not with every keystroke.
As Jamie suggested local storage is a really good approach, cookies could be used as a fallback if Local Storage is not supported.
On the snippet you have provided you have binded the cookie rewrite process in the keyup event, in order to avoid any data loss.
I have implemented a more neat solution , when the user unloads the window I have tried to serialise the form data and store it.
//save data generic function
function saveData() {
var dataObj = JSON.stringify($("input,textarea").serializeObject());
if (!Modernizr.localstorage) {
saveToLocalStorage(dataObj);
} else {
createCookie("jsonobj", dataObj, 1);
}
}
Modernizr is used to detect when local storage is available. Furthermore , I have found that using separate cookies for each field is an overkill, I have used a single JSON string instead.
Full jsFiddele example: http://jsfiddle.net/ARUM9/5/
Further reading:
Local storage :Storing Objects in HTML5 localStorage
Local storage browser support: http://caniuse.com/#search=localstorage
Using JSON serialisation : Serializing to JSON in jQuery
Modernizr documentation: http://modernizr.com/docs/
Use jquery-storage for saving the values https://github.com/julien-maurel/jQuery-Storage-API/blob/master/README.md
Its really simple
$.localstorage.set(inputfield, value)
For setting
$.localstorage.get(inputfield)
For retrieving.
Cookies are often abused for this purpose but cookies get sent to the server on every request. So storing a ton of data in cookies is not a good idea.
Localstorage however was designed for this purpose and is a simpe key value storw in the browser.
Please note that it is a html5 feature and will not work in some older browsers
To circumvent this you can use the cookiestorage provided by jquery storage. But then you also need to include the extra dependencies mentionend in the readme.md
Then use it like this:
var store = $.localstoreage || $.cookiestorage:
store.set(...........
Related
I'd like to perform a redirect, but I also wish to send additional information along with it.
I've tried to change the value of window.location.href but that doesn't seem to pass along the extra information.
I also get how I can do
$.get(
new_url,
{data : "mydata"},
function(data) {
alert('page content: ' + data);
}
);
and that will display the html content of the new page, but that doesn't help with actually getting there.
How can I achieve this?
Edit: I feel as if I must be phrasing this terribly because I'm pretty sure this is an easy/common task. This shouldn't be something that would require cookies - it should basically be like a post request (I think).
You have a few different options for this:
URI Variables - You can append extra data to the URL by appending a question mark (?) followed by a set of key-value separated by an ampersand (=) with each variable being separated by an ampersand (&). For instance, http://www.google.com/search?q=javascript+url+variables&ie=UTF-8 gives you a link to a Google search for "javascript url variables" using UTF-8 encoding. Your PHP code or JavaScript would need to handle passing along and processing these variables. If using JavaScript a nice library for processing URLs is URI.js or using PHP you can use the parse_url and http_build_query functions. You can use this with window.location.href; for instance: window.location.href = "http://www.google.com/search?q=javascript+url+variables&ie=UTF-8" (replace the Google URL with the one you created or set in a variable).
Storage API - You can use the localStorage or sessionStorage properties to store and retrieve information using JavaScript (information is stored in the user's browser - supported by IE 8 and newer and all other major browsers). Note that this is JavaScript only unless you grab the data with JavaScript and pass it to your PHP server through URL variables, form, AJAX request, etc.
Cookie - You can store additional information inside a cookie - however this is more difficult since you have to setup your variables as a parsable string (possibly JSON) and remember to encode/decode the string when setting/getting the cookie. I don't recommend this method.
IndexedDB API - This is a more advanced client-side/browser storage mechanism and currently only supported in IE 10 and newer (and nearly all other browsers). There are also still changes being made to the standard which means newer versions of browsers could break current implementations or be buggy. If all you need is simple key-value storage (not an SQL-like database) then you should stick with one of the above options.
You can use the window open method to redirect your user,and remember to use "_self"
window.open('url','_self');
Preferably you'd store the data in localStorage and fall back to a cookie (I really like js-cookie).
Here are the two helper functions you need to store and retrieve data:
function setMultiPageData(itemName, data) {
var dataStr = JSON.stringify(data);
var hasLocalStorage = typeof localStorage !== 'undefined';
if (hasLocalStorage) {
localStorage.setItem(itemName, dataStr);
}
else {
Cookies.set(itemName, dataStr, { path: '/' }); // path set to root to make cookie available on any page
}
}
function getMultiPageData(itemName) {
var data = null;
var hasLocalStorage = typeof localStorage !== 'undefined';
if (hasLocalStorage) {
data = localStorage.getItem(itemName);
}
if (!hasLocalStorage || data === null) {
data = Cookies.get(itemName);
}
var parsedObject = null;
try {
parsedObject = JSON.parse(data);
}
catch (ex) {
console.log(ex); // remove in production
}
return parsedObject;
}
usage:
var data = { first: 'this is the first thing', second: 'this is the second thing' };
setMultiPageData('stackoverflow-test', data);
// go to a new page
var retrievedData = getMultiPageData('stackoverflow-test');
if (retrievedData === null) {
console.log('something went wrong')
}
else {
console.log(retrievedData); // { first: 'this is the first thing', second: 'this is the second thing' }
}
According to the W3 Web Storage specs, values in localStorage are of type string.
Thus, an entry can't be granularly updated like a subproperty of a JS object and it's only possible to replace the entire key:
Updating/editing localStorage - JSONObject
Assume I want to "secure" user input frequently on the client side in the localStorage, and also update it on model changes on the server (only transmitting changes from server to client). How often can I JSON.stringify() my local data (=ViewModel state) and save it to the localStorage without causing trouble for the user? Is serializing and saving (not transmitting!) e.g. 30KB of data every 5 seconds to the localStorage going to cause lags?
Bonus question: Does any major browser vendor plan on storing JS objects directly in localStorage?
This may not be entirely true; there is a method for updating a single key to an object housed in local storage, and the code is below.
var updateLocalStorageKey = function(obj, key, val) {
var localObj = JSON.parse(localStorage[obj] )
localObj[key] = val;
//reset storage
localStorage[obj] = JSON.stringify(localObj)
}
The working jsbin is here: http://jsbin.com/jesapifa/4/edit?html,js,output
Hope this solves your problem!
I have a webapp that sets timezone
post_controller.rb
before_filter :set_time_zone
def set_time_zone
Time.zone = user.time_zone
end
Now, instead of getting the time_zone from the user at registration, I was wondering how I'd set the timezone dynamically from the client side and set it in the before_filter.
I was trying to use detect_timezone_rails gem. The gem provides an easy way to access clientside timezone, simply by calling the function like this from js file.
$(document).ready(function(){
$('#your_input_id').set_timezone();
});
Now, the above code automatically sets your hiddenfield input or select input, but I was wondering if you could simply use the function call to save to session and retrieve it from Rails server. I guess when the user first visits the site, the timezone can be set and the session value can be used to set timezone for the rest of the visit. I'd think it'd be possible to use the session value to set timezone in the before filter. Being pretty new to javascript, I'm not sure how to access Rail's encrypted cookie store to set the value. Is this possible? if so, how can I do this?
thanks in advance,
#javascript
function readCookieValue(cookieName)
{
return (result = new RegExp('(?:^|; )' + encodeURIComponent(cookieName) + '=([^;]*)').exec(document.cookie)) ? decodeURIComponent(result[1]) : null;
}
$(document).ready(function(){
if(readCookieValue("time_zone") === null) {
$.post('/set_time_zone',
{ 'offset_minutes':(-1 * (new Date()).getTimezoneOffset())});
}
#controller:
def set_time_zone
offset_seconds = params[:offset_minutes].to_i * 60
#time_zone = ActiveSupport::TimeZone[offset_seconds]
#time_zone = ActiveSupport::TimeZone["UTC"] unless #time_zone
if #time_zone
cookies[:time_zone] = #time_zone.name if #time_zone
render :text => "success"
else
render :text => "error"
end
end
We did this somewhat differently. We use the gon gem to set a variable on the Rails side if we want to collect the timezone from JS. Then we have JS code on the client that examines that variable, and if set, does an XHR post to an endpoint (like the OP did) with the timezone string as returned by the jstimezonedetect script, which returns an IANA timezone key. Finally, to convert this to a Rails 3.2.19 timezone name, we did ActiveSupport::TimeZone::MAPPING.invert[iana_key]. It took a few steps to figure this out, hope it helps someone.
I have this javascript code that changes the style of the website. but this code changes the style only when you click on it. and after you refresh the page it returns to default. I want it to save the users prefrences. I really like the code and I do not want to change it with another one. can you please help.
<script type="text/javascript">
$(document).ready(function() {
$("#fullswitch").click(function() {
$("#chpheader").removeClass("compact");
$("#imgg").removeClass("compact");
$("#chpheader").removeClass("original");
$("#imgg").removeClass("original");
$("#chpheader").addClass("normal");
$("#imgg").addClass("normal");
});
$("#compactswitch").click(function() {
$("#chpheader").addClass("compact");
$("#imgg").addClass("compact");
$("#chpheader").removeClass("original");
$("#imgg").removeClass("original");
$("#chpheader").removeClass("normal");
$("#imgg").removeClass("normal");
});
$("#originalswitch").click(function() {
$("#chpheader").addClass("original");
$("#imgg").addClass("original");
$("#chpheader").removeClass("compact");
$("#imgg").removeClass("compact");
$("#chpheader").removeClass("normal");
$("#imgg").removeClass("normal");
});
});
</script>
<html>
<body>
<span id="t1">0</span>
<span id="t2">0</span>
<span id="t3">0</span>
<span id="t4">0</span>
<span id="t5">0</span>
<span id="t6">0</span>
<div id="result"></div>
<script>
// Check browser support
if (typeof(Storage) !== "undefined") {
// Store
localStorage.setItem("lastname", "Smith");
localStorage.setItem("first", "Smi");
// Retrieve
var c = document.getElementById("result").innerHTML = localStorage.getItem("lastname");
var b = document.getElementById("result").innerHTML = localStorage.getItem("first");
document.getElementById("t1").innerHTML = c;
document.getElementById("t2").innerHTML = b;
//localStorage.removeItem("lastname");
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Storage....";
}
</script>
</body>
</html>
There is a jQuery cookie plugin there are examples on that page as well so you can see how you can set and read a value from the cookie.
Once the value is read it's just a simple matter of loading the right theme.
var theme = $.cookie('name_of_selected_theme');
setTheme(theme);
function setTheme(themeName){
if(themeName == "One"){
...
}else...
}
However cookies only allow for 4KB of data and are passed in every HTTP call. A better idea many be localStorage. You can use YUI Storage Lite library which is < 3KB in size and you can easily use it to save data in browser localStorage and load from it. You can save at least 5MB of data using localStorage.
Example code from the link above:
YUI({
//Last Gallery Build of this module
gallery: 'gallery-2010.12.01-21-32'
}).use('gallery-storage-lite', function (Y) {
// For full compatibility with IE 6-7 and Safari 3.x, you should listen for
// the storage-lite:ready event before making storage calls. If you're not
// targeting those browsers, you can safely ignore this step.
Y.StorageLite.on('storage-lite:ready', function () {
// To store an item, pass a key and a value (both strings) to setItem().
Y.StorageLite.setItem('kittens', 'fluffy and cute');
// If you set the optional third parameter to true, you can use any
// serializable object as the value and it will automatically be stored
// as a JSON string.
Y.StorageLite.setItem('pies', ['apple', 'pumpkin', 'pecan'], true);
// To retrieve an item, pass the key to getItem().
Y.StorageLite.getItem('kittens'); // => 'fluffy and cute'
// To retrieve and automatically parse a JSON value, set the optional
// second parameter to true.
Y.StorageLite.getItem('pies', true); // => ['apple', 'pumpkin', 'pecan']
// The length() method returns a count of how many items are currently
// stored.
Y.StorageLite.length(); // => 2
// To remove a single item, pass its key to removeItem().
Y.StorageLite.removeItem('kittens');
// To remove all items in storage, call clear().
Y.StorageLite.clear();
});
});
I suppose you have two options, store the info client side, or store the info server side.
If you actually have a "user" server side (the person has to log in, yada yada yada), you can store this setting for the user (add some data to where ever the user info is stored).
If you don't want it that persistent, you can store it in local storage (not very browser friendly) or cookies. You really have no guarantee that these settings will stay around, as they are controlled by the browser, users can have their browsers set to never save this info.
Either way (client or server) you can read the setting and set the classes server-side and skip the javascript for changing the classes. Always better to do it on the server.
You may use HTML5 window.localStorage to store user preferences and trigger the corresponding layout changes.
Or use cookies as previously suggested.
Take a look at this article: http://diveintohtml5.ep.io/storage.html
Use cookies to store the users options.
http://www.quirksmode.org/js/cookies.html
Use localStorage to store the user preferences, and on reload load the preferences back in.
Here's a good tutorial.
How to write:
localStorage['someKey'] = 5;
How to read: var lastKeyValue = localStorage['someKey'];
use session storage
//set in session storage
$("#block-menu-menu-organisation > ul > li > a" ).bind( "click", function(evt) {
//in that case one expanded at the time
sessionStorage.clear();
var par = $(evt.target).parent();
sessionStorage.setItem(par.attr('id'),par.attr('class'));
console.log(par.attr('class'));
});
// //retrieve class from session
if(typeof sessionStorage!='undefined') {
$('#block-menu-menu-organisation > ul > li' ).each(function(i) {
if( $(this).attr('id') in sessionStorage) {
$(this).attr('class', sessionStorage.getItem($(this).attr('id')));
}
});
}
There is a cool Firefox extension which lets you export all cookies to a Netscape HTTP Cookies File, cookies.txt, which you can then use with wget (et.al.)
Here is an example cookies.txt file for the happycog.com site:
# Netscape HTTP Cookie File
# http://www.netscape.com/newsref/std/cookie_spec.html
# This is a generated file! Do not edit.
cognition.happycog.com FALSE / FALSE 1345696044 exp_last_visit 998800044
cognition.happycog.com FALSE / FALSE 1345696044 exp_last_activity 1314160044
How can I build the same style "cookies export" with Javascript? Granted it would only be able to read cookies for the current domain. That would be just fine.
Additional Details:
I realize that cookies can't be exported to the file system with pure javascript. I'd be happy with them being exported to a textarea, or with document.write. I just want to know how I can get them in the same format where I can basically copy and paste them to a cookies.txt file. The challenge here is to do it with javascript, though, and not to use an addon.
var cookieData = document.cookie.split(';').map(function(c) {
var i = c.indexOf('=');
return [c.substring(0, i), c.substring(i + 1)];
});
copy(JSON.stringify(JSON.stringify(cookieData)));
This will export your cookies into an array of key/value pairs (eg. [ [key1, val1], [key2, val2], ...]), and then copy it to your clipboard. It will not retain any expiration date info because that's impossible to extract via Javascript.
To import the cookies back, you'd run the following code:
var cookieData = JSON.parse(/*Paste cookie data string from clipboard*/);
cookieData.forEach(function (arr) {
document.cookie = arr[0] + '=' + arr[1];
});
Sorry about the delayed response - had to sleep. I have just been playing with this and concluded that the answer is NO.
The reason for this is that Javascript does not have access to any more information than the cookie's name and value, you can't retrieve the path, expiry time, etc etc. What do you actually want to do? Is this for one specific site you are developing or just for general use when browsing?
All cookies for the page is stored in document.cookie