I've have a CF page who's inventory search form, frm_inv post's back to itself. frm_inv's main table of records, tbl_inv, uses a tablesorter. A hidden input (sort_list) is used in conjunction with a cfparam to keep track of tbl_inv's sortList:
main.cfm
<cfparam name="form.sort_list" type="string" default="1,0">
<form id="frm_inv" action="main.cfm" method="post">
<input name="sort_list" type="hidden" value="#form.sort_list#"/>
<table id="tbl_inv" class="tablesorter">
...
</table>
</form>
When frm_inv is submitted, CF uses sort_list in $(document).ready() to restore tbl_inv's sort order:
$(document).ready(function(){
var sort_list_str = <cfoutput>"#form.sort_list#"</cfoutput>;
var sort_list = sort_list_str.split(",");
$("#tbl_inv").tablesorter({
textExtraction: ['complex'],
sortList:[[sort_list[0],sort_list[1]]]
}).bind("sortEnd", function(sorter) {
var sl = sorter.target.config.sortList;
$("input[name='sort_list']").val(sl.toString());
});
});
I would rather use arrays than convert a comma separated string into an array like I'm currently doing
<cfparam name="form.sort_list" type="string" default="1,0">
to
<cfparam name="form.sort_list" type="array" default="ArrayNew(2)">
however I need to know the proper javascript and coldfusion syntax in order pose everything that's relevant in arrays exclusively.
Copying a ColdFusion ... array into a JavaScript array
Why? For the most part, HTTP only transmits strings, so there is no translation between client and server complex types. Unless you are doing something more than just passing the sort value back and forth, converting between client and server side arrays is just an unnecessary complication. It is simpler to leave the value as a string and do any splitting or parsing on the client side.
You did not really explain what problem you are trying to solve, but .. there is nothing inherently wrong with the current approach. However, it could be simplified a bit. There is no need to cfoutput the variable again here:
(A) var sort_list_str = <cfoutput>"#form.sort_list#"</cfoutput>;
Since you already stored the current form.sort_list value in a hidden form field, the above is redundant. Instead, just read the field's value with javascript ie
(B) var sort_list_str = $("input[name='sort_list']").val();
Having said that, if you really prefer to work with arrays, you could store a JSON string representation of the arrays instead. Then use parse() and stringify() to convert the arrays back and forth. Same net effect as your current method, but a bit simpler in terms of code.
Form:
<cfparam name="form.sort_list" default="[[1,0]]">
...
<input id="sort_list" name="sort_list"
type="hidden" value="#encodeForHTML(form.sort_list)#" />
...
JQuery:
$(document).ready(function(){
$("#tbl_inv").tablesorter({
textExtraction: ['complex'],
sortList: JSON.parse($("#sort_list").val())
}).bind("sortEnd", function(sorter) {
var sort_arr = sorter.target.config.sortList;
$("#sort_list").val(JSON.stringify(sort_arr));
});
});
For creating a JavaScript variable from a ColdFusion variable, you can use toScript() function.
var #toScript(ListToArray(form.sort_list), "sort_list")#;
This can be used for wide range of variable types such as strings, arrays, structures etc.
Needs specific syntax to use an array in cfparam: ColdFusion CFParam Can Use Struct And Array Notation
<cfparam name="form.sort_list" type="array" default="#ArrayNew( 2 )#">
Related
I understand that if I use a checkbox value of name[], then I will receive a data array on the server (when using PHP), named 'name[]'. This has worked fine for me, but I'm running into some URL sizes that could cause issues with less robust IE browsers and all the encoded square braces are killing me in this area, easily causing the URL length to be at least 4-6 times longer than what it could possibly be, if another way were available. Is there a reliable method using javascript (jquery syntax even better) to intercept a checkbox forms values and convert them into something like this:
"&checkboxarray=1-23-45-13-67"
I figure that on the other end I can easily explode $_GET['checkboxarray'] into an actual array and go from there as I usually do with matching the selection array against the options array, etc... I just don't know if it's possible or how to create alter the submit process.
Side note, isn't passing "name[]" to a URL non-standards compliant anyways? Every browser I've used auto encodes it, but not Mozilla, however it seems to work fine.
EDIT: I need to create paginated links, which is why I'm using GET, instead of POST. This is also and industrial search, very comprehensive, lots of power user options.
UPDATE & Answer: I managed to come up with my own answer. For anyone else who wants to take advantage of $_GET's easy pagination workflow but you need to pass large data arrays and are worried about URL length, here's a simplistic way to compact it all down into one variable with dash separated values:
NOTE: I HIGHLY suggest you first make sure any dynamic arrays generated from queries start with 1 rather than 0 if your going to recheck values after submit, here's how, since 0 can be a real pain in the neck to work with in PHP conditional statements:
$your_array= array();
array_unshift($your_array,'');
unset($your_array[0]);
In your HTML code, set all checkbox input names to "something[]" and underneath this set of inputs, create a hidden input with the name "something", I suggest you make them match, but I suppose you could use another name, just make sure the hidden one is missing the square braces, also set the hidden input value to "":
<input type="text" name="something[]" value="1">
.....
<input type="text" name="something[]" value="20">
<input type="hidden" name="something" value="">
Javascript: NOTE, requires jquery... this grabs all the "something[]" input values and forms a dashed array while killing off "something[]" values from being submitted and only submitting "something".
$('#submitbutton').click(function(){
var searchIDs = $('input[name="something[]"]:checked').map(function(){
return $(this).val();
}).get();
var IDstring = searchIDs.toString();
var newvar = IDstring.replace(/,/g, '-');
$('input[name="something"]').val(newvar);
$('input[name="something[]"]:checkbox').prop("checked", false);
});
On the server side, simply explode the 'something' value from $_GET.
$somethingArray = explode('-',$_GET['something']);
There it is! Hope it helps someone in the future make their GET sent arrays more compact. Bonus: Avoids sending unsafe characters in the URL, Mozilla doesn't appear to auto encode square braces, at least not my version of it on Linux Mint ;)
Update:
I just implemented this code on a big country checkbox form with 284 possible selections. With my old code, even using 'c[]' as the name, my character count was around 3100 characters, with the new approach, my character count now rings in at just 1109. Worth the effort.
You can use POST instead of GET method.
GET has URL length limitations.
POST is useful in passing long data, e.g. an array in your case.
There is a default limit of POST method which is 2MB which is way higher than GET. If needed, it can easily be increased in php.ini file post_max_size 10MB.
Replace $_GET with $_POST in your script.
I created a few functions and some input boxes with a table to show the data when page is reloaded. The issue I am having is how do I get multiple inserts to local storage and be able to show all the data on the table with a loop statement. Also is there way to show the data right away instead of reload. I guess I am just confused with local Storage and I was trying to see how it works.
https://jsfiddle.net/zzLumrsd/
<!DOCTYPE>
<html>
<head>
<title> Local storage</title>
<style type="text/css">
table#table1{
width: 10%;
background-color: #gray;
}
</style>
<script>
function saveMy(){
var fieldValue = document.getElementById('textfield').value;
localStorage.setItem('text', fieldValue);
}
function load(){
var storedValue = localStorage.getItem('text');
if(storedValue){
document.getElementById('textfield2').value = storedValue;
}
}
function removeMy() {
document.getElementById('textfield').value = '';
localStorage.removeItem('text');
}
</script>
</head>
<body onload="load()">
<input type="text" id="textfield" />
<input type="button" value="save" onclick="saveMy()"/>
<input type="button" value="remove" onclick="removeMy()"/>
<hr/>
<table id="table1" border="1">
<tr>
<th>text</th>
</tr>
<tr>
<td>
<input type="text" id="textfield2" />
</td>
</tr>
</table>
</body>
</html>
As far as I understand, you want to store multiple strings into localStorage. You could achieve that using the following:
How
To achieve this, you would store all the Strings in an array. We can then put this into localStorage. In the examples, I will be using 'names' as the localStorage item name. An array can't be put into localStorage so we have to make it a String using JSON.stringify to do that.
Examples
Setting the Item
var vals = [];
vals.push('Bob');//Add the text 'item1' to vals
localStorage.setItem('names', JSON.stringify(vals));
Getting the Item
vals = JSON.parse(localStorage.getItem('name'));
In this, we will get the item from localStorage, and make the string into an array again using JSON.parse
Further Explanation
localStorage is an browser API that allows us to store data on a users computer. localStorage is somewhat like cookies but are less limited and don't expire.
We want to store in this case, names, in localStorage. You can store anything JavaScript in localStorage. Stack Overflow stores timestamps and a few other things in your localStorage.
Each item, or 'thing' in localStorage, has a name, and a value.
When using localStorage.setItem('name', 'Bob'), you create an item called name and it's value is Bob
This is all well and good until you want to add a second name. JavaScript has arrays which can store multiple values in one 'variable'. This means you can store multiple names, in one variable/item. The following is an example of an array
var myArray = ['Bob', 'Joe', 'Phil'];
That array has three values: Bob, Joe, and Phil. You can add an item into an array using Array.push(). I'm going to link an article on arrays here
Okay, so now you have your three values in an array and you want to store it. localStorage values can only be strings! JSON is is a special type of 'variable' similar to a JavaScript object, you can learn about it here. In simple terms, an array is 'JSON'.
Because localStorage only takes strings, we must turn our array (JSON) into a string which we can store. The way this is done is JSON.stringify(ARRAY_HERE). This will return a string like:
"["Bob","Joe","Phil"]"
Now that our array is a string, we can put it into localStorage using localStorage.setItem().
What do we do when we want to retrieve this?
To retrieve the array, we will use localStorage.getItem(). In localStorage.getItem() you put the name of the item you wish to access and it will return it. But the problem is it is still a string. That's where JSON.parse() comes in. This will convert our 'stringified' array into an actual array.
What does this all have to do
I want to store three names in localStorage
How would you do that? It's simple, what you add the names to the array using .push(), then you store it. When you want to display it, use the localStorage.getItem() I described before.
Further Reading
I wrote a lot but that might not be enough, check out the following:
MDN Arrays
localStorage Article
w3schools JSON
This has driven me "doo-lally" this afternoon!
A vendor (Zaxaa) uses a multi-dimentional form thus:
<form method="post" name="zaxaa" action="xxxx">
<input type="text" name="products[0][prod_name]" value="ABC">
<input type="text" name="products[0][prod_type]" id="pt" value="FRONTEND">
</form>
** This is my understanfing of how a multdimentional array is set up, and it seems to pass the variables to the server OK.
However, dependant on what other inputs are set to on the test form, the [prod_type] (and others) may need to change to "OTO" This is obviously going to be a javascript function, (but not the variant that starts with "$" on code lines ... whatever that type is!)
I have tried
document.zaxaa.products[0].prod_type.value
document.getElementById('products[0][prod_type]').value
document.getElementsByName('products[0][prod_type]').value
but in everycase, I get "products is not defined". (I have simplified the form as there are ten product[0] fields)
I've solved it... mainly a glaring error on my part. The getElementById worked fine ... except in my test script I'd used getElementById[xxx] and not getElementById(xxx)!! ie "[" rather than "(" Does help if you get the syntax right!
But I will take notice of those other methods, such as enclosing both array arguments in ["xxx"].
getElementById didn't work because the only one of those elements that has an id is the second input, with id="pt".
On any modern browser, you can use querySelector to get a list of the inputs using a CSS selector:
var nameInput = document.querySelector('input[name="products[0][prod_name]"]');
var typeInput = document.querySelector('input[name="products[0][prod_type]"]');
Then use their value property. So for instance, to set the name to "OTO":
document.querySelector('input[name="products[0][prod_name]"]').value = "OTO";
Use querySelectorAll if you need a list of relevant inputs, e.g.:
var nameInputs = document.querySelectorAll('input[name="products[0][prod_name]"]');
Then loop through them as needed (the list as a length, and you access elements via [n] where n is 0 to length - 1).
Re
* This is my understanfing of how a multdimentional array is set up...
All that HTML does is define input elements with a name property. That name property is sent to the server as-is, repeated as necessary if you have more than one field with that name. Anything turning them into an array for you is server-side, unrelated to JavaScript on the client. (The [0] is unusual, I'm used to seeing simply [], e.g name="products[][prod_name]".)
You can access it in this syntax:
document.zaxaa['products[0][prod_name]'].value
document.zaxaa.products[0].prod_type.value
The name is a single string, not making a nested structure to access the input. It would need to be
document.zaxaa["products[0][prod_type]"].value
// or better:
document.forms.zaxaa.elements["products[0][prod_type]"].value
The complicated name does only serve to parse the data into a (multidimensional) array on the server side, but all data will be sent "flattened".
document.getElementById('products[0][prod_type]').value
The id of your input is pt, so this should work as well:
document.getElementById("pt").value
document.getElementsByName('products[0][prod_type]').value
getElementsByName does return a collection of multiple elements - which does not have a .value property itself. Instead, access the first element in the collection (or iterate it completely):
document.getElementsByName('products[0][prod_type]')[0].value
I have a form with a hidden field:
<input type="hidden" name="newdesc[]" id="newdesc" />
I have an autolookup and a plus button so the plus button adds the field value of the autolookup to an array:
newdesc_a.push(document.getElementById('autocomplete1').value);
var x=document.getElementById("businesslist");
x.innerHTML=newdesc_a;
document.getElementById('newdesc').value = newdesc_a;
(newdesc_a is previously declared as an array)
It updates the div OK (businesslist) but does not assign the value to the newdesc.
I am sure it is simple but it is driving me mad!
Given the name="newdesc[]" attribute, I assume PHP on the server side. When you submit a key two or more times, only the last value is available in the script via $_REQUEST. In the case of a key ending with [] , instead, PHP builds an array and make it available to your script via $_REQUEST['key']. Note that this behavior is application-specific, there's nothing like an array at the HTTP level.
Now, you want to pass an array from the client side (Javascript) to the backend (PHP). You have two options:
Use a proprietary format, eg separate values by commas or colons, and split the string on the server side (or you can use an existing format like JSON, XML, ...)
Take advantage of the PHP syntax for passing arrays
It seems you want to adopt the 2nd way, so you will want to submit a form like the following
<input name="email[]" value="joel#example.com" />
<input name="email[]" value="mark#people.com" />
<input name="email[]" value="bill#hello.com" />
PHP will be able to access a plain array in $_REQUEST if you build your form like this. Now, you have the problem of building the form programmatically on demand. This is the best I can think of (jQuery):
var email = $("#autocomplete").value;
// if you really need to keep emails in an array, just
// emails.push(email);
$('<input type="hidden">').attr({
name: 'email[]',
value: email
}).appendTo('#myForm');
You want to assign a particular value of array to that element?
You can use like this.
document.getElementById('newdesc').value = newdesc_a.index;
where 'index' is the index of array. replace it.
I have an array I've created in JavaScript. The end result comes out to element1,element2,,,element5,element6,,,element9.... etc
Once passed to ColdFusion, it removes the null elements, I end up with element1,element2,element5,element6,element9
I need to maintain these spaces, any ideas? My problem may begin before this, to explain in more detail...
I have a form with 13 elements that are acting as a search/filter type function. I want to "post" with AJAX, in essence, i'm using a button to call a jQuery function and want to pass the fields to a ColdFusion page, then have the results passed back. The JavaScript array may not even be my best option.
Any ideas?
Are you deserializing the jS array into a list? CF ignores empty list fields using its built-in functions. This can be worked around by processing the text directly. Someone has already done this for you, fortunately. There are several functions at cflib.org, like:
ListFix
ListLenIncNulls
etc, etc, etc.
In exchanging data between javascript and coldfusion have a look at using JSON.
http://www.json.org
http://www.epiphantastic.com/cfjson/
Instead of using the CF ListToArray function, use the Java String methods to split the string into an array. This will maintain the empty list items.
<cfset jsList = "item1,item2,,item4,item5,,item6">
<cfset jsArray = jsList.split(",")>
<cfdump var="#jsArray#">
you are using array in JavaScript,Fine. instead of assigning by default empty value,assign some dummy value. whenever you use this array value ignore dummy value using condition.