Save and load full html select in cookie/localStorage - javascript

There have been previous questions surrounding this, however I want to know if its possible to save the whole configuration of the html select in a cookie/localStorage. By the whole configuration I mean all of the options that are currently in the select, and which option is selected.
And then load this configuration back from the cookie.
From previous questions, I currently save the select element using an onChange listener, which saves the element like:
$('#chosen-url').on("change", function () {
saveToBrowserCookies("settings_select", this);
});
function saveToBrowserCookies(key, value) {
document.cookie = key + "=" + value + "; path=/";
}
And then load the select like so (on initialization):
var savedSelect = getFromBrowserCookies("settings_select");
if (savedSelect) {
var select = document.getElementById("chosen-url");
select.value = savedSelect;
}
function getFromBrowserCookies(key) {
var cookies = {}
var all = document.cookie;
var value = null;
if (all === "") { return cookies }
else {
var list = all.split("; ");
for (var i = 0; i < list.length; i++) {
var cookie = list[i];
var p = cookie.indexOf("=");
var name = cookie.substring(0, p);
if (name == key) {
value = cookie.substring(p + 1);
break;
}
}
}
return value;
}
However this doesn't work.

You can save anything in storage or in cookie, as long as it is a string. So in your case I'd recommend:
Get all your select options and currently selected value and create
an object with structure that would be easy to understand.
Stringify this object to JSON form with JSON.stringify.
Save json string in cookie or in LS.
After reload, get saved json, read it with JSON.parse and take all needed information from the object.
Recreate select element and set its chosen value.
I think that controlling select input per se is outside of the scope of this question, especially because we don't know if you are programming in pure js or in some kind of framework. But there are many informations on how to control select inputs on the web, e.g. here you can find decent answers on "how to set select value programatically".
Edit: you edited your question, so I will also add something to my response. You are trying to save whole "this" as cookie. I am not a big fan of jquery, but I guess that "this" is not necessarily the selected value. It may be a whole DOM object or change event maybe. Try logging out "this" and see what it is. You need to save string in a cookie.
Also, check in developer tools if the cookie was saved.
Last but not least, using break in a for loop is questionable. You can try using list.find instead.

Related

Issue getting value from dynamic option set (picklist) using Javascript in CRM 2011

I am upgrading a CRM 4 solution to CRM 2011 and I am having an issue with a dynamic Option Set.
I am populating the option set by calling an API from the Javascript. This returns a list of text and value options, which I then iterate through.
Firstly, I retrieve the object itself and add a static Default option to the list:
var varPicklist = Xrm.Page.getControl("list_name");
//Add a System Default option to the picklist
var opt1 = new Option();
opt1.text = "System Default";
opt1.value = 100000;
varPicklist.addOption(opt1);
I then iterate through the collection, create an object and add each one to the list:
//Populate the rest of the list
var ObjectList = xmlDoc.getElementsByTagName("LookupItem");
for (var i = 0 ; i < ObjectList.length ; i++)
{
var optValue
var optText
var ObjectListItems = ObjectList[i].childNodes;
for (var j = 0 ; j < ObjectListItems.length ; j++)
{
var value = ObjectListItems[j].childNodes[0];
if (ObjectListItems[j].nodeName == "Key")
{
optValue = value.nodeValue;
}
else if (ObjectListItems[j].nodeName == "Value")
{
optText = value.nodeValue;
}
}
var opt = new Option();
opt.text = optText;
opt.value = optValue;
varPicklist.addOption(opt);
};
As stated, this all seems to work. The Picklist gets populated with the values and doesn't error. If I stick an alert in there during this process, the correct values or labels are displayed.
However, somehow the items seem to get lost along the way. If I try to reference them in any way from elsewhere in the form, I get null back. I tried this;
Xrm.Page.getAttribute("list_name").getSelectedOption().value
...and this;
Xrm.Page.getAttribute("list_name").getValue();
Neither of which worked. I tried accessing the text as opposed to the values (just as a test) and couldn't get those either.
But when I tried the same methods with option sets which contained static options, I could access them no problem.
Any help with where I'm going wrong would be appreciated...
CRM picklist is a weird control. Though getAttribute and getControl are CRM supported DOM manipulator, not 100% compatible like you expect in dynamic options.
Until unless you have physical static options added in CRM picklist control customizations, you cannot use that by getAttribute.
Using getControl, only you are displaying your options, but its not original CRM picklist options to store in DB.
Add all the options as static, hide/show based on your need.
Update:
To add a new optionset value on the fly, use InsertOptionValueRequest to target the metadata service & execute the request. Read MSDN

Need to get an array of the names of all applicationScope variables

In an application I am working on I need to get a list of the names of all applicationScope variable then I need to cycle through them and filter out the ones starting with a know string say $xyx. I thought that the applicationScope.keySet().
I'm using this code for starter:
var col = applicationScope.keySet();
var itr:java.util.Iterator = col.iterator();
if (itr.hasNext()){
var str:String = itr.next();
dBar.info(str,"Value = ");
}
if I put the variable col in a viewScope it shows a list of all the keys. but when I run the script the values displayed in the dBar info are not the keys but some other information that I'm not sure where it comes from.
I should just be able to iterat through the list of keys, am I missing something?
This code is in the before page loads event
After some poking around and experimenting I got this to work:
var col = applicationScope.keySet();
var itr:java.util.Iterator = col.iterator();
while (itr.hasNext()){
var str:Map.Entry = itr.next();
if (str.substring(0,9) == "$wfsLock_"){
//do stuff
}
}
so I'm now a happy camper.
Although your code works in SSJS, it is not correct (and that's why I don't like SSJS...).
The applicationScope is an implementation of the java.util.Map interface and the keySet() method returns a Set containing the keys in that Map. Every entry is (probably) a String (other data types like integers are actually also valid). The line
var str:Map.Entry = itr.next();
doesn't cast it to a Map.Entry: it doesn't really do anything: str remains a string.
The Map interface also has an entrySet() method that returns the entries (Map.Entry). You can use that to retrieve the key as well as the value:
var it = applicationScope.entrySet().iterator();
while (it.hasNext()) {
var entry = it.next();
print( entry.getKey() + " = " + entry.getValue() );
}
(in this code the print() line will use the toString() method of the key as well as the value to send information to the console)
I see from your code that you've installed my XPages Debug Toolbar. You can also use that to quickly check what's in the scopes and what the actual datatype is.

How would I dynamically convert form fields to multi-dimensional js object?

I'm struggling to dynamically convert a set of inputs into a multi-dimensional object for passing in an ajax call.
Assume I have a Person, with multiple Addresses.
My fields currently look like this:
<input name='Person[name]' value='Bradley'/>
<input name='Person[addresses][home]' value='123 Anywhere Drive.'/>
<input name='Person[addresses][work]' value='456 anywhere Road.'/>
How would one convert my fields into ab object that looks like this:
Person :
{
name: 'Bradley',
addresses:
{
home: '123 Anywhere Drive.',
work: '456 anywhere Road.'
}
}
I need to do this dynamically (function needs to work regardless of the inputs provided) and work at N-depth.
(Note: jQuery available).
http://jsfiddle.net/w4Wqh/1/
Honestly I think there's a way to do this in a regex.. but I couldn't figure it out. So, it's a bit of ugly string manipulation. Either way, this should get you on the right track I think:
function serialize () {
var serialized = {};
$("[name]").each(function () {
var name = $(this).attr('name');
var value = $(this).val();
var nameBits = name.split('[');
var previousRef = serialized;
for(var i = 0, l = nameBits.length; i < l; i++) {
var nameBit = nameBits[i].replace(']', '');
if(!previousRef[nameBit]) {
previousRef[nameBit] = {};
}
if(i != nameBits.length - 1) {
previousRef = previousRef[nameBit];
} else if(i == nameBits.length - 1) {
previousRef[nameBit] = value;
}
}
});
return serialized;
}
console.log(serialize());
Quick explanation. This just grabs anything with a 'name' attribute, and then iterates over them. For each iteration, it grabs the name and splits it on '['. This gets you basically how far into the object you need to put things. So, for Person[addresses][work], you would get Person, addresses], work].
Then, there's the tricky part. Since objects are always passed around by reference, we can see if the serialized variable has 'Person' in it. If not, it adds it, and sets the value to an empty object.. which is generic enough to be used for storing more things, or replaced if necessary. If there are no more levels that we need to go through, it just takes the value of the element and assigns it to the reference it has. Otherwise, the code grabs a reference to whatever it just made, and loops again, performing the same operation. So, for Person[addresses][work]..
Does serialized.Person exist? No. Setting serialized.Person to {}. This is not the end of the loop, store reference to serialized.Person as previousRef.
Does previousRef.addresses exist? (serialized.Person.addresses) No. Setting previousRef.addresses to {}. This is not the end of the loop, store reference to previousRef.addresses as previousRef.
Does previousRef.work exist? (serialized.Person.addresses.work) No. Setting previousRef.work to {}. Wait. This is the end of the loop. Setting previousRef.work to the value in the element.

Getting value of field with Javascript/jQuery

This is my page:
http://bryntum.com/examples/gantt-latest/examples/basic/basic.html
I want to get current value of Start and Finish date.
( I will later implement a button, that user can press and then it will get all dates and post them somewhere). At the moment I just need somehow to get the date values.
At first the values are loaded from XML, but you can change the values manually.
I tried looking into source code, but was not able to get the field IDs etc.
So how I can access those fields with JS?
In case you're still looking for JS solution:
I couln't use Jquery, does the server support it?
By using JS, since the cells do not have an ID, you can access your fields by class name:
document.getElementsByClassName("x-grid-cell-inner ");
And than iterating trough the returned array.
Complete code:
var data = document.getElementsByClassName("x-grid-cell-inner ");
var mark = 0;
var out = "";
var patt=/\d\/\d/;
for (i in data) {
var txt = new String(data[i].innerHTML);
if (patt.test(txt)) {
if (mark == 0) {
out += "start: "+txt+" ";
mark = 1;
} else {
mark = 0;
out += "end: "+txt+" ";
}
}
}
It would be totally wrong to do this with jquery - It's an Extjs component with really good documentation.
Gnt.panel.Gantt has a getStart method:
Method to get a the current start date of the scheduler view
and a getEnd method:
Method to get a the current end date of the scheduler view
http://bryntum.com/docs/#!/api/Gnt.panel.Gantt
Edit:
Try getTaskStore, then getById on the store witch will return a Task that has a StartDate and EndDate fields.
unfortunately, there's no unique id on the divs so you can't access them. but they seem to have unique class="" values:
class="x-grid-cell x-grid-cell-startdatecolumn-1011"
class="x-grid-cell x-grid-cell-enddatecolumn-1014"
create a javascript like this
document.getElementsByClassName("x-grid-cell x-grid-cell-enddatecolumn-1014")
to access them and then you can get their start and end dates

JSON how find another value at the same index from a value in Javascript Object

A simple question I'm sure, but I can't figure it out.
I have some JSON returned from the server
while ($Row = mysql_fetch_array($params))
{
$jsondata[]= array('adc'=>$Row["adc"],
'adSNU'=>$Row["adSNU"],
'adname'=>$Row["adname"],
'adcl'=>$Row["adcl"],
'adt'=>$Row["adt"]);
};
echo json_encode(array("Ships" => $jsondata));
...which I use on the client side in an ajax call. It should be noted that the JSON is parsed into a globally declared object so to be available later, and that I've assumed that you know that I formated the ajax call properly...
if (ajaxRequest.readyState==4 && ajaxRequest.status==200 || ajaxRequest.status==0)
{
WShipsObject = JSON.parse(ajaxRequest.responseText);
var eeWShips = document.getElementById("eeWShipsContainer");
for (i=0;i<WShipsObject.Ships.length;i++)
{
newElement = WShipsObject.Ships;
newWShip = document.createElement("div");
newWShip.id = newElement[i].adSNU;
newWShip.class = newElement[i].adc;
eeWShips.appendChild(newWShip);
} // end for
}// If
You can see for example here that I've created HTML DIV elements inside a parent div with each new div having an id and a class. You will note also that I haven't used all the data returned in the object...
I use JQuery to handle the click on the object, and here is my problem, what I want to use is the id from the element to return another value, say for example adt value from the JSON at the same index. The trouble is that at the click event I no longer know the index because it is way after the element was created. ie I'm no longer in the forloop.
So how do I do this?
Here's what I tried, but I think I'm up the wrong tree... the .inArray() returns minus 1 in both test cases. Remember the object is globally available...
$(".wShip").click(function(){
var test1 = $.inArray(this.id, newElement.test);
var test2 = $.inArray(this.id, WShipsObject);
//alert(test1+"\n"+test2+"\n"+this.id);
});
For one you can simply use the ID attribute of the DIV to store a unique string, in your case it could be the index.
We do similar things in Google Closure / Javascript and if you wire up the event in the loop that you are creating the DIV in you can pass in a reference to the "current" object.
The later is the better / cleaner solution.
$(".wShip").click(function(){
var id = $(this).id;
var result;
WShipsObject.Ships.each(function(data) {
if(data.adSNU == id) {
result = data;
}
});
console.log(result);
}
I could not find a way of finding the index as asked, but I created a variation on the answer by Devraj.
In the solution I created a custom attribute called key into which I stored the index.
newWShip.key = i;
Later when I need the index back again I can use this.key inside the JQuery .click()method:
var key = this.key;
var adt = WShipsObject.Ships[key].adt;
You could argue that in fact I could store all the data into custom attributes, but I would argue that that would be unnecessary duplication of memory.

Categories

Resources