serialize form to json and store in the cookie - javascript

i want to store form on clientside, in json in cookie, after that deserialize it back to form.
what i'm doing:
serialization to JSON:
function formToJSON(selector) {
var form = {};
$(selector).find(':input[name]:enabled').each(function () {
var self = $(this);
var name = self.attr('name');
if (name.indexOf('TextBox', 0) == 0) {
if (form[name]) {
form[name] = form[name] + ',' + self.val();
}
else {
form[name] = self.val();
}
}
});
return form;
}
then on form change, i'm trying to save form to cookie:
$('#form1 :input').change(function () {
var eba = formToJSON($('#form1'));
$.cookie.set('fo', eba, {json:true});
var a = $.cookie.get('fo',true);
alert(a);
//$.cookie.set('form123', { "ksf": "saf", "tt": "" }, { json: true });
//var b = $.cookie.get('form123', true);
//alert(JSON.stringify(b));
});
in debugger - eba is json object, but alert(a) gives null.
commented code works, this json serialized, and i'm gettin it from cookies.
but why code doesnt work for form???
cookie plugin taken from jquery.com

Use this library to stringify/parse JSON http://json.org/js.html
remember that there is an approx 4KB size limit on cookies , http://support.microsoft.com/kb/306070

AFAIK browser cookies cannot be read using javascript(except for your own domain), to prevent Cross Site Reeuqest Forgery
But you can still set them.

Related

ServiceNow UI Page GlideAjax

I created a form using UI Page and am trying to have some fields autopopulated onChange. I have a client script that works for the most part, but the issue arises when certain fields need to be dot-walked in order to be autopopulated. I've read that dot-walking will not work in client scripts for scoped applications and that a GlideAjax code will need to be used instead. I'm not familiar with GlideAjax and Script Includes, can someone help me with transitioning my code?
My current client script looks like this:
function beneficiary_1(){
var usr = g_user.userID;
var related = $('family_member_1').value;
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee',usr);
rec.addQuery('sys_id',related);
rec.query(dataReturned);
}
function dataReturned(rec){
//autopopulate the beneficiary fields pending on the user selection
if(rec.next()) {
$('fm1_ssn').value = rec.ssn;
$('fm1_address').value = rec.beneficiary_contact.address;
$('fm1_email').value = rec.beneficiary_contact.email;
$('fm1_phone').value = rec.beneficiary_contact.mobile_phone;
var dob = rec.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0] ;
$('fm1_date_of_birth').value = date;
}
}
fm1_address, fm1_email, and fm1_phone do not auto populate because the value is dot walking from the HR_Beneficiary table to the HR_Emergency_Contact table.
How can I transform the above code to GlideAjax format?
I haven't tested this code so you may need to debug it, but hopefully gets you on the right track. However there are a couple of steps for this.
Create a script include that pull the data and send a response to an ajax call.
Call this script include from a client script using GlideAjax.
Handle the AJAX response and populate the form.
This is part of the client script in #2
A couple of good websites to look at for this
GlideAjax documentation for reference
Returning multiple values with GlideAjax
1. Script Include - Here you will create your method to pull the data and respond to an ajax call.
This script include object has the following details
Name: BeneficiaryContact
Parateters:
sysparm_my_userid - user ID of the employee
sysparm_my_relativeid - relative sys_id
Make certain to check "Client callable" in the script include options.
var BeneficiaryContact = Class.create();
BeneficiaryContact.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getContact : function() {
// parameters
var userID = this.getParameter('sysparm_my_userid');
var relativeID = this.getParameter('sysparm_my_relativeid');
// query
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee', userID);
rec.addQuery('sys_id', relativeID);
rec.query();
// build object
var obj = {};
obj.has_value = rec.hasNext(); // set if a record was found
// populate object
if(rec.next()) {
obj.ssn = rec.ssn;
obj.date_of_birth = rec.date_of_birth.toString();
obj.address = rec.beneficiary_contact.address.toString();
obj.email = rec.beneficiary_contact.email.toString();
obj.mobile_phone = rec.beneficiary_contact.mobile_phone.toString();
}
// encode to json
var json = new JSON();
var data = json.encode(obj);
return data;
},
type : "BeneficiaryContact"
});
2. Client Script - Here you will call BeneficiaryContact from #1 with a client script
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var usr = g_user.userID;
var related = $('family_member_1').value;
var ga = new GlideAjax('BeneficiaryContact'); // call the object
ga.addParam('sysparm_name', 'getContact'); // call the function
ga.addParam('sysparm_my_userid', usr); // pass in userID
ga.addParam('sysparm_my_relativeid', related); // pass in relative sys_id
ga.getXML(populateBeneficiary);
}
3. Handle AJAX response - Deal with the response from #2
This is part of your client script
Here I put in the answer.has_value check as an example, but you may want to remove that until this works and you're done debugging.
function populateBeneficiary(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
answer = answer.evalJSON(); // convert json in to an object
// check if a value was found
if (answer.has_value) {
var dob = answer.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0];
$('fm1_ssn').value = answer.ssn;
$('fm1_address').value = answer.address;
$('fm1_email').value = answer.email;
$('fm1_phone').value = answer.mobile_phone;
$('fm1_date_of_birth').value = date;
}
else {
g_form.addErrorMessage('A beneficiary was not found.');
}
}

Passing data between controllers in MVC Javascript

I am using Express and Node to build an app.
I have a route called '/new-poll' and '/poll-create'
//The poll-create route will give the user the option of creating a poll
app.route('/poll-create')
.get(function(req, res) {
res.sendFile(path + '/public/pollcreation.html');
});
//This is the route for creating a new poll by authenticated users. Authentication still needs to be added.
app.route('/poll-create')
.post(function(req, res) {
console.log('inside poll-create post request');
console.log(req.body);
serverHandler.newPoll(req, res, db, function(id) {
console.log('It worked');
req.session.poll_id = id;
res.json(id);
});
});
//The above response will redirect to this route, and here is where the poll data will be served up
app.route('/new-poll')
.get(function(req, res) {
console.log('Inside get request for new poll');
console.log(req.session.poll_id);
res.sendFile(path + '/public/pollvisualization.html');
});
//This is the route for making a post request to the same URL. Specifically to obtain the document inserted previously through creating a new poll
app.route('/new-poll')
.post(function(req, res) {
console.log('Inside new poll post');
serverHandler.check(db, req.session.poll_id, function(err, doc) {
if (err) {
console.log('There is an error');
throw err;
}
if (doc) {
res.json(doc); //send the json document generated by the poll creation by mongoDb to pollvisualizationClient.js through ajax-functions.js
}
});
});
Now, I have 2 controllers, controllerData and controllerNonData.
controllerData passes in data to the above POST request using an AJAX call. controllerNonData needs to access the data passed to the POST request by controllerData.
How can I do this in the simplest possible manner? Essentially, my question boils down to what is the easiest way to pass data between view controllers in Express and Node?
The way I'm doing it right now is, I make a POST request with data from controllerData and then make a POST request without data from controllerNonData and then try to differentiate between the two calls in the POST request. But, it seems like a giant pain!
NOTE: I am not using AngularJS in my app. Mentioning this because all the answers I have seen on StackOverflow mention ways to do this in AngularJS.
EDIT:
Code for controllerData
(function() {
$(document).ready(function() {
if (typeof FB !== 'undefined' && FB !== null) { //this if statement is to ensure FB object loads before doing anything else
FB.Event.subscribe('auth.authResponseChange', function() {
FB.getLoginStatus(function(response) {
var data = {}; //setting up the data object to fill with objects
$('.submit-butt').on('click', function() {
data.formData = $('form').serializeArray(); //this is the form data from the form
data.facebookData = response.authResponse; //facebook object data
console.log(data);
data = JSON.stringify(data); //this is done to pass the data and parse it through body parser. Not sure why it works this way.
ajaxFunctions.ready(ajaxFunctions.ajaxRequest('POST', appUrl + '/poll-create', data, function() {
window.open('https://fcc-votingapp-redixhumayun.c9users.io/new-poll', '_self');
}));
return false; //setting this statement to false ensures that the form data does not automatically submit independent of the AJAX call
});
});
});
}
else {
location.reload(); //reloads the page in case the if statement is not satisfied.
}
});
})();
Code for controllerNonData
(function() {
var value; //variable to store the value of the radio option selected
var custom_flag = false; //flag variable to check whether Custom radio button was selected
//This is where the AJAX request is initialized
ajaxFunctions.ready(ajaxFunctions.ajaxRequest('POST', appUrl + '/new-poll', null, function(data) {
//Parsing the data into JSON format below
$(document).ready(function() {
//this is the form data that has been provided via the AJAX request
data = JSON.parse(data);
console.log(data);
var options_count = data[0].options_counter; //this variable stores the options_counter, that is the number of options
var options_array = getSeperatedOptions(data[0].options);
var options_length = Object.keys(options_count).length; //finding out the length of the options_counter object in this line
//updating the header element
$('h1').html(data[0].title);
//Invoking the function that will create all of the options required by the user
createOptions(options_length, options_array);
//This method here checks to see if the user has selected Custom as their option
$('.radio-options').on('click', function() {
var entered_value = getEnteredOption(options_length); //calling this function to check if Custom has been chosen.
if (entered_value == options_length) { //parseInt of entered_value will return a NaN. Use this to check against the number that is returned for parseInt of the other radio buttons
$('.custom-div').show();
custom_flag = true; //set the custom flag to true here because Custom radio button was selected
}
});
$('.btn-danger').on('click', function() {
ajaxFunctions.ready(ajaxFunctions.ajaxRequest('POST', appUrl + '/new-poll/delete-poll', data[0]._id, function(data) {
console.log('This is data: '+data); //data contains the number of documents deleted
}));
});
//Submit button event click handler
$('.submit-butt').on('click', function() {
//if statement decides whether the radio button selected was the Custom radio button
if (custom_flag == true) {
var entered_value = $('.custom-text').val();
value = entered_value; //assigning the local entered_value to a global value variable to use in the next AJAX function
}
//else if statement decides whether a radio option button is checked or not! Fires only if Custom not selected
else if ($('.radio-options').is(':checked')) {
var entered_value = getEnteredOption(options_length); //Function call to get option entered by user. Returns the value of the radio button
value = entered_value; //assigning the local entered_value to a global value variable to use in the next AJAX function
}
//Fire this else statement if no option is selected but Submit button is clicked
else {
window.alert('You need to choose an option before trying to submit');
}
if (value.length > 0) {
var dataToPass = {}; //defining this object to pass data as JSON
dataToPass.value = value;
dataToPass = JSON.stringify(dataToPass); //stringify data to pass it through without error
ajaxFunctions.ready(ajaxFunctions.ajaxRequest('POST', appUrl + '/new-poll/option-entered', dataToPass, function(data) {
//This object contains the returned value from the above AJAX call
data = JSON.parse(data);
var optionsArray = getSeperatedOptions(data.value.options); //Keep the difference between optionsArray and options_array in mind AT ALL TIMES!
//This function is used to convert the options_counter object to an array so that it can be used to render the chart using ChartJS
var options_counterArray = convertOptionsCounterToArray(data.value.options_counter);
//call to function to create chart here
createChart(optionsArray, options_counterArray);
}));
}
else {
window.alert('Hi!');
}
});
});
}));
})();
EDIT: I have also updated my routes to use sessions.
So I am assuming that your Controllers are on the client side. http is a stateless protocol. So in order to pass data between states, you need to implement some kind of caching mechanism. There are a few ways to do this:
Use HTML5 localStorage or sessionStorage API directly, based on the length of time you want to save the data. Make sure you clear the storage once you're done with the data, to prevent hitting the 5MB limit. Using localStorage will allow you to use the data till it is manually cleared. sessionStorage will live as long as the tab is open.
Use some other kind of client side storage like Web SQL
If you want to store data within a page reload cycle (i.e. you will lose data once you reload the page), you can create a Javscript singleton function and inject it into both of your AJAX calls as a dependency, and store your response in that object. This is similar to what happens in AngularJS's Service providers. This is cleaner than the other two approaches, but is of course, shorter lived (unless used on conjunction with one of the above Storage APIs)
Creating singletons in Javascript
var UserStore = (function(){
var _data = [];
function add(item){
_data.push(item);
}
function get(id){
return _data.find((d) => {
return d.id === id;
});
}
return {
add: add,
get: get
};
}());

Why doesn't CasperJS' sendAJAX function send any content for PUT requests?

I want to update a JSON object though my app using the PUT method. I am attempting to partially simulate the operation of a form submission. This call is synchronous, as after the PUT, a 200 should be returned. However, when I try the code below, sendAJAX does not include the object's content, the PUT request has content-length: 0. A submission through the form has all of the correct settings - content-type, x-requested-with, etc. I'm not quite sure why the code below doesn't function as I'm expecting. I've also tried setting var 'data' as a string of json formatted parameters. That also results in a PUT request of content-length: 0.
What am I doing wrong here?
casper.then(function() {
this.evaluate(function() {
var element = document.querySelectorAll("h6");
for (var i = 0; i < element.length; i++) {
if (element[i].innerHTML == "Special Tag") {
var appid = element[i].parentNode.parentNode.getAttribute("app-id");
var wsurl = "https://appurl.net"+appid;
var data = new Object();
data.user_id = "xxxxx-xxxx-xxxx-xxxx-xxxx";
data.name = "Name";
data.description = "blahr blahr blahr";
data.amount = "-9000000";
data.start = 1409900400000;
data.finish = 1412492400000;
data.seq = 0;
data.locked = false;
data.paused = false;
data.contributed_amount = 0;
data.created = 1409920472782;
data.modified = 1426538857339;
data.color = "#E37368";
data.archived = false;
data.target_amount = null;
data.uuid = "xxxx-xxxxx-xxxxx-xxxxxx";
data.aprox_daily_contribution = 0;
return JSON.parse(__utils__.sendAJAX(wsurl, "PUT", data, false, { contentType: "application/json"}));
CasperJS' sendAJAX() function does not support PUT requests as seen in the code:
xhr.send(method === "POST" ? dataString : null);
Or more precisely, it only supports a payload for POST requests. You will have to build the XHR yourself or change the CasperJS code accordingly.
I don't think you need to simulate the form submission. If you're testing the web app, then it is better to actually submit the form and then check if it resulted in a correct page rather than parsing the response, because you will need to effectively implement the logic twice: in the page JavaScript and in your test script.

Strip out while(1) prepended to JSON object

I am making an ajax get request, but receive back a JSON object prepended with while(1) eg.
while(1);{"servers":[{"some_data": data, "etc":...}]}
We just started doing this to prevent malicious attacks, but I am not sure how to strip it out so that I can parse the JSON properly.
here is the function I am using for the $.get call
function myFunction() {
$.get('/v1/servers').success(function(data) {
data.servers.forEach(function(server){
presentServer(server);
});
});
}
Try this:
var text = ajaxResponse.responseText;
var jsonObject = JSON.parse(text.replace('while(1);', ''));
Another way without using replace:
var jsonObject = JSON.parse(text.substring(text.indexOf(';') + 1);
Updated with your function:
function myFunction() {
$.get('/v1/servers').success(function(response) {
var data = JSON.parse(response.responseText.substring(text.indexOf(';') + 1));
data.servers.forEach(function(server){
presentServer(server);
});
});
}
This is a standard XSS protection feature. Since you have tagged the question with jQuery, you should be able to do this:
$.get('/your/api.json', function (resp) {
var json = resp.substring(resp.indexOf(";")+1)),
data = $.parseJSON(json);
// do other things
});
with the code that you have posted above:
function myFunction() {
$.get('/v1/servers').success(function(resp) {
var json = resp.substring(resp.indexOf(";")+1)),
data = $.parseJSON(json);
data.servers.forEach(function(server){
presentServer(server);
});
});
}
You can use substring to strip your leading characters:
JSON.stringify(response);
response.substring(9,response.length);

Pure Javascript - store object in cookie

No jQuery.
I want to store an object or array in a cookie.
The object should be usable after page refresh.
How do I do that with pure JavaScript? I read many posts, but do not know how to serialize appropriately.
EDIT:
Code:
var instances = {};
...
instances[strInstanceId] = { container: oContainer };
...
instances[strInstanceId].plugin = oPlugin;
...
JSON.stringify(instances);
// throws error 'TypeError: Converting circular structure to JSON'
How do I serialize instances?
How do I maintain functionality, but change structure of instance to be able to serialize with stringify?
Try that one to write
function bake_cookie(name, value) {
var cookie = [name, '=', JSON.stringify(value), '; domain=.', window.location.host.toString(), '; path=/;'].join('');
document.cookie = cookie;
}
To read it take:
function read_cookie(name) {
var result = document.cookie.match(new RegExp(name + '=([^;]+)'));
result && (result = JSON.parse(result[1]));
return result;
}
To delete it take:
function delete_cookie(name) {
document.cookie = [name, '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.', window.location.host.toString()].join('');
}
To serialize complex objects / instances, why not write a data dump function in your instance:
function userConstructor(name, street, city) {
// ... your code
this.dumpData = function() {
return {
'userConstructorUser': {
name: this.name,
street: this.street,
city: this.city
}
}
}
Then you dump the data, stringify it, write it to the cookie, and next time you want to use it just go:
var mydata = JSON.parse(read_cookie('myinstances'));
new userConstructor(mydata.name, mydata.street, mydata.city);
Use either object's own .toString() method if it gives meaningful serialization or JSON.stringify(). Do note, however, that cookies are usually limited in length and won't be able to hold big amounts of data.
A cookie adaptation class from :
http://www.sitepoint.com/cookieless-javascript-session-variables/
All you need to do is to set and get variables you need to store in cookie.
Work with: int, string, array, list, Complex object
Exemple:
var toStore = Session.get('toStore');
if (toStore == undefined)
toStore = ['var','var','var','var'];
else
console.log('Restored from cookies'+toStore);
Session.set('toStore', toStore);
Class:
// Cross reload saving
if (JSON && JSON.stringify && JSON.parse) var Session = Session || (function() {
// session store
var store = load();
function load()
{
var name = "store";
var result = document.cookie.match(new RegExp(name + '=([^;]+)'));
if (result)
return JSON.parse(result[1]);
return {};
}
function Save() {
var date = new Date();
date.setHours(23,59,59,999);
var expires = "expires=" + date.toGMTString();
document.cookie = "store="+JSON.stringify(store)+"; "+expires;
};
// page unload event
if (window.addEventListener) window.addEventListener("unload", Save, false);
else if (window.attachEvent) window.attachEvent("onunload", Save);
else window.onunload = Save;
// public methods
return {
// set a session variable
set: function(name, value) {
store[name] = value;
},
// get a session value
get: function(name) {
return (store[name] ? store[name] : undefined);
},
// clear session
clear: function() { store = {}; }
};
})();
If you can serialize your object into its canonical string representation, and can unserialize it back into its object form from said string representation, then yes you can put it into a cookie.

Categories

Resources