Modify javascript code to iterate through all variables in the form - javascript

I have the following code that worked fine till now as I decided to add more variables to the form. How can I make this function smart and itterate and pass all the variables in the form?
function getquerystring(strFormName) {
var form = document.forms[strFormName];
var word = form.clock_code.value;
qstr = 'clock_code=' + escape(word); // NOTE: no '?' before querystring
return qstr;
}
complete JS code # pastie

It looks like you're serializing a form to a querystring? If that's the case, then this is one place where a JavaScript library is really nice.
Each of these will serialize the first form on the page to a querystring.
// ExtJS
var str = Ext.lib.Ajax.serializeForm(Ext.select('form').elements[0]);
// jQuery
var str = $("form").serialize();
// MooTools
var str = $$('form').toQueryString();
// PrototypeJS
var str = $$('form')[0].serialize();
You can see some other methods and how they compare at http://jquery.malsup.com/form/comp/

Try this
function formToQueryString(form) {
var elements = form.elements;
var cgi = [];
for (var i = 0, n = elements.length; i < n; ++i) {
var el = elements[i];
if (!el.name) { continue; }
if (el.tagName === 'INPUT' && (el.type === 'checkbox' || el.type === 'radio')
&& !el.checked) {
continue;
}
cgi.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value));
}
return cgi.length ? '?' + cgi.join('&') : '';
}

The issue with your code is that you're only grabbing the clock_code element value, and ignoring the rest. Here's a replacement I wrote up:
function getquerystring(strFormName) {
var qstr = '', word = '';
var key = 0;
var form = document.forms[strFormName];
var fields = ['clock_code', 'message', 'type'];
for (var i = 0; i<fields.length; i++) {
key = fields[i];
word = form[key].value;
if (qstr && qstr.length > 0) {
qstr += '&';
}
qstr += encodeURIComponent(key) + '=' + encodeURIComponent(word);
}
return qstr;
}
Benjamin's approach is a bit more flexible; mine only queries those fields specifically named in the fields array

Assuming they are all simple fields, the following should work just fine (didn't test it, though - sorry if it doesn't "compile"):
function getquerystring(strFormName) {
var qstr = '';
var form = document.forms[strFormName];
var elements = form.elements;
var first = true;
for (elem in elements) {
var word = elem.value;
var name = elem.name;
if (first) {
first = false;
} else {
qstr = qstr + '&';
}
qstr = qstr + name + '=' + escape(word);
}
return qstr;
}
Adding info on supporting multiple Element types:
The question only mentioned text fields so I assumed the easier answer would suffice. Wrong!
Glad you're able to use JQuery (which rocks), but for completeness I'll just flesh this out with a bit of info on how to build your own "dynamic form handler".
First, you have to add checking on the class of elem, like so:
function isCheckbox(o){ return (o && o.constructor == Checkbox) }
and you have to then do something a little different depending on the type of object you are looking at.
For example:
for (var elem in elements) {
var value = '';
var name = elem.name;
if (isCheckbox(elem)) {
value = elem.checked ? 'true' : 'false';
} else if (isSingleSelect(elem)) {
var index = elem.selectedIndex;
if(selected_index > 0) {
value = elem.options[selected_index].value;
}
}
}
There may be situations where you have to turn values into something that is meaningful to your app, like in a multiple-select combo box. You could send one name=value pair for each value or roll them into a comma-seperated list or the like - it all depends on your app. But with this approach one can certainly build the "dynamic form handler" that fits their specific needs.
Check out this article for helpful stuff about how to process each form field type: http://www.javascript-coder.com/javascript-form/javascript-get-form.htm

Related

Have a lot of variables that are in order. I need to convert them using JavaScript to contain something else but don't want to do it one by one

First of all I'm not a programmer. I need to use some really basic HTML, CSS and XML for my work. The program I am using allows running javascripts, too.
I usually have a lot of variables from my XML files. They go by something like this:
VAL001
VAL002
VAL003
VAL004
You get it.
These variables are often checkboxes. The values can be either 'Checked' or 'Unchecked'.
Instead of embedding these variables in the HTML code, I tend to convert it to something else so it gets nicer. Like this:
if ( VAL001 == 'Checked' ) CHK001 = '✓';
else CHK001 = '';
When this is done, I insert CHK001 (instead of VAL001) in the HTML so I get a nice check mark if the box was checked and nothing when it was not checked. When there are a lot of these boxes it's not too effective to do it one by one.
What I tried in JavaScript is:
var i;
for ( i = 1, i <= 9, i++ ) {
if ( VAL00$i == 'Checked' ) CHK00$i = '✓'
else CHK00$i = '';
}
var j;
for ( j = 10, j <= 99, j++ ) {
if ( VAL0$j == 'Checked' ) CHK0$j = '✓'
else CHK0$j = '';
}
I thought that this would replace the last digits with i and j and I would get what I need. Unfortunately this just brings up a ReferenceError saying that VAL00$i can't be found.
If I replace the $i and $j with [i] and [j] I get the same ReferenceError but this time i and j are not told to be wrong so I get that VAL00 can't be found. A simple solution would really speed up things for me. Thank you in advance!
You could put your variables in an array and use map to check and change the variables to be a tick or not.
var array = [
VAL001,
VAL002,
VAL003,
VAL004
];
var newArray = array.map(val=>{
if (val === 'Checked') return '✓';
else return '';
});
Alteratively, if you need to know the names of the variables after checking everything you could use an object.
var obj = {
VAL001: VAL001,
VAL002: VAL002,
VAL003: VAL003,
VAL004: VAL004
};
var newObj;
for (var i of Object.keys(obj){
if (obj[i] === 'Checked') newObj[i] = '✓';
else newObj[i] = '';
}
If you are having VAL001 variables as property in obj then you can perform like below.
Here i.toString().padStart(3, 0), for i = 1 it will return 001 similarly for i=10 it will return 010; You can access property of object with obj[propertyName]. So these values will be accessible with obj[VAL${index}].
var obj = {
VAL001: 'Checked',
VAL002: '',
VAL003: 'Checked',
VAL004: '',
VAL010: '',
VAL099: 'Checked',
};
var result = {};
for (var i = 1; i <= 99; i++) {
let index = i.toString().padStart(3, 0);
if (obj.hasOwnProperty(`VAL${index}`)) {
if (obj[`VAL${index}`] == 'Checked') result[`CHK${index}`] = '✓'
else result[`CHK${index}`] = '';
}
}
console.log(result);
If you are having variables in global scope then you can use windows["VAL001"].
var VAL001 = 'Checked',
VAL002 = '',
VAL003 = 'Checked',
VAL004 = '',
VAL010 = '',
VAL099 = 'Checked';
for (var i = 1; i <= 99; i++) {
let index = i.toString().padStart(3, 0);
if (window.hasOwnProperty(`VAL${index}`)) {
if (window[`VAL${index}`] == 'Checked') window[`CHK${index}`] = '✓'
else window[`CHK${index}`] = '';
console.log(`CHK${index} = ` + window[`CHK${index}`]);
}
}
We are lacking some information about your environment, but assuming your framework gives you a set of global variables, this should get you started:
for (var i=1, i<=99, i++) {
var i_padded = i.toString().padStart(3, 0);
if (window["VAL" + i_padded] == 'Checked') {
window["CHK" + i_padded] = '✓';
} else {
window["CHK" + i_padded] = "";
}
}
In order to access your global variables I am using the window object here. This is assuming you are running this JS in a browser or browser-like environment.

Build object in JavaScript from PHP form input name

There are a couple of similar questions but none covers the case when a string looks like some-name[][some-key]. I have tried JSON.parse('some-name[][some-key]'); but it doesn't parse it.
Is there a way to convert such string to a JavaScript object that will look like { 'some-name': { 0: { 'some-key': '' } } }?
This is a name of a form field. It's normally parsed by PHP but I'd like to parse it with JavaScript the same way. I basically have <input name="some-name[][some-key]"> and I'd like to convert that to var something = { 'some-name': { 0: { 'some-key': VALUE-OF-THIS-FIELD } } }.
Try this:
JSON.parse('{ "some-name": [ { "some-key": "" } ] }');
I don't know exactly how you're doing this, but assuming they are all that format (name[][key]) and you need to do them one by one - this works for me:
var fieldObj = {};
function parseFieldName(nameStr)
{
var parts = nameStr.match(/[^[\]]+/g);
var name = parts[0];
var key = typeof parts[parts.length-1] != 'undefined' ? parts[parts.length-1] : false;
if(key===false) return false;
else
{
if(!fieldObj.hasOwnProperty(name)) fieldObj[name] = [];
var o = {};
o[key] = 'val';
fieldObj[name].push(o);
}
}
parseFieldName('some-name[][some-key]');
parseFieldName('some-name[][some-key2]');
parseFieldName('some-name2[][some-key]');
console.log(fieldObj); //Firebug shows: Object { some-name=[2], some-name2=[1]} -- stringified: {"some-name":[{"some-key":"val"},{"some-key2":"val"}],"some-name2":[{"some-key":"val"}]}
o[key] = 'val'; could of course be changed to o[key] = $("[name="+nameStr+"]").val() or however you want to deal with it.
Try this:
var input = …,
something = {};
var names = input.name.match(/^[^[\]]*|[^[\]]*(?=\])/g);
for (var o=something, i=0; i<names.length-1; i++) {
if (names[i])
o = o[names[i]] || (o[names[i]] = names[i+1] ? {} : []);
else
o.push(o = names[i+1] ? {} : []);
}
if (names[i])
o[names[i]] = input.value;
else
o.push(input.value);
Edit: according to your updated example, you can make something like this (view below). This will work - but only with the current example.
var convertor = function(element) {
var elementName = element.getAttribute('name');
var inpIndex = elementName.substring(0, elementName.indexOf('[')),
keyIndex = elementName.substring(elementName.lastIndexOf('[') + 1, elementName.lastIndexOf(']'));
var strToObj = "var x = {'" + inpIndex + "': [{'" + keyIndex + "': '" + element.value + "'}]}";
eval(strToObj);
return x;
};
var myObject = convertor(document.getElementById('yourInputID'));
Example here: http://paulrad.com/stackoverflow/string-to-array-object.html
(result is visible in the console.log)
old response
Use eval.. but your string must have a valid javascript syntax
So:
var str = "arr[][123] = 'toto'";
eval(str);
console.log(arr);
Will return a syntax error
Valid syntax will be:
var str = "var arr = []; arr[123] = 'toto'";
var x = eval(str);
console.log(arr);

Convert Indented Text List to HTML List (jQuery)

I am attempting to create a jQuery script which will convert an indented text list of arbitrary length and depth into a properly formatted HTML list. The lists on which I will be running this script are simple tree structures for directories. Within the tree structures, folders are denoted by a semicolon following the folder name (and files have no ending punctuation). Given this, I would like to attach a <span class="folder"></span> or <span class="file"></span> to the lines as appropriate.
I've found it to be fairly easy to generate most of the structure, but I cannot seem to get the recursion (which I suspect will be necessary) down to ensure that the tags are properly nested. The page on which this will be implemented will include the most recent (i.e., 3.0.3) version of Bootstrap, so feel free to use any of its functionality. I have about two dozen (generally abortive) fragments of code which I've tried or which I'm currently attempting to tweak to produce the desired result. Instead of posting a mass of (likely unhelpful) code, I've created a JSFiddle with the basic form which will be used for input/output, a bit of jQuery, and an example list and some external libraries loaded.
Any help or suggestions will be greatly appreciated.
Try this. I copied it to your fiddle and it seems to work.
var indentedToHtmlList = function indentedToHtmlList (text, indentChar, folderChar, listType, showIcons) {
indentChar = indentChar || '\t';
folderChar = folderChar || ':';
listType = listType || 'ul';
showIcons = !!showIcons;
var lastDepth,
lines = text.split(/\r?\n/),
output = '<' + listType + '>\n',
depthCounter = new RegExp('^(' + indentChar + '*)(.*)');
for (var i = 0; i < lines.length; i++) {
var splitted = lines[i].match(depthCounter),
indentStr = splitted[1],
fileName = splitted[2],
currentDepth = (indentStr === undefined) ? 0 : (indentStr.length / indentChar.length),
isFolder = (fileName.charAt(fileName.length - 1) === folderChar);
if (isFolder) {
fileName = fileName.substring(0, fileName.length -1);
}
if (lastDepth === currentDepth) {
output += '</li>\n';
} else if (lastDepth > currentDepth) {
while (lastDepth > currentDepth) {
output += '</li>\n</' + listType + '>\n</li>\n';
lastDepth--;
}
} else if (lastDepth < currentDepth) {
output += '\n<' + listType + '>\n';
}
output += '<li>';
if (showIcons) {
output += '<span class=" glyphicon glyphicon-' +
(isFolder ? 'folder-open' : 'file') +
'"></span> ';
}
output += fileName;
lastDepth = currentDepth;
}
while (lastDepth >= 0) {
output += '\n</li>\n</' + listType + '>';
lastDepth--;
}
return output;
};
You could use spans and classes to denote files and folders, but you should consider using ul and li elements, they were built for that.
The whole list should be enclosed within an ul element. Each entry on the top level list should create an li element inside of the main element. If the element is a folder, then it should also append another ul. This is where you'll need recursion to allow proper nesting.
However, if you intend to use indentation (no pun indented) the tab and or whitespace parsing is a problem by itself which I'm not solving in this answer. For the sake of this example, I'll just pretend you have a magic function that turns text into a parsed list called MyList, and that files that belong to a folder are whatever lies after the first semicolon of each list element.
var turnTextIntoList=function(AText) {
//magic stuff;
return SomeList;
};
var populateList=function(AList) {
var mainelement=jQuery('<ul></ul>');
for(element in AList) {
var the_li=jQuery('<li></li>');
if(element.indexOf(';')!=-1) {
the_li.append('<span class="file">'+element+'</span>');
} else {
var thefolder=element.split(';')
the_li.append('<span class="folder">'+thefolder[0]+'</span>');
the_li.append(populateList(turnTextIntoList(thefolder[1])));
}
mainelement.append(the_li);
}
return mainelement;
};
var MyList=turnTextIntoList(MyText);
jQuery('#targetdiv').append(populateList(MyList));
See, the recursion part is where you do
the_li.append(populateList(turnTextIntoList(thefolder[1])));
which will keep drilling into nesting levels until it reaches a file so it can start its way back.
It appears that someone already created a script which does this. Unfortunately, that script is in CoffeeScript, not JavaScript. However, there are a number online converters which will convert from CoffeeScript to JavaScript. Thanks to #charlietfl who provided a link to a working converter, supra.
Here is the converted, working code:
var bind, blank, convert, index, li, lineToMap, linesToMaps, parse, parseTuples, ptAccum, runConvert, tabCount, ul, ulEnd;
convert = function(text) {
return parse(text.split('\n'));
};
li = function(t) {
var html;
html = "<li>" + t['line'] + "</li>";
ptAccum.push(html);
return html;
};
ul = function(t) {
return ptAccum.push("<ul>" + (li(t)));
};
ulEnd = function() {
return ptAccum.push("</ul>");
};
ptAccum = [];
index = 0;
parse = function(lines) {
var ts;
ts = linesToMaps(lines);
ptAccum = ["<ul>"];
index = 0;
parseTuples(ts, 0);
ulEnd();
return ptAccum.join("\n");
};
parseTuples = function(tuples, level) {
var stop, _p, _results;
stop = false;
_p = function() {
var curLevel, t;
t = tuples[index];
curLevel = t['level'];
index++;
if (curLevel === level) {
return li(t);
} else if (curLevel < level) {
index--;
return stop = true;
} else {
ul(t);
parseTuples(tuples, level + 1);
return ulEnd();
}
};
_results = [];
while (!stop && index < tuples.length) {
_results.push(_p());
}
return _results;
};
tabCount = function(line) {
var c, count, i, inc, isTab, tc;
tc = 0;
c = '\t';
count = 0;
if (line) {
count = line.length;
}
i = 0;
isTab = function() {
return c === '\t';
};
inc = function() {
c = line.charAt(i);
if (isTab()) {
tc++;
}
return i++;
};
while (isTab() && i < count) {
inc();
}
return tc;
};
lineToMap = function(line) {
return {
line: line,
level: tabCount(line)
};
};
blank = function(line) {
return !line || line.length === 0 || line.match(/^ *$/);
};
linesToMaps = function(lines) {
var line, _i, _len, _results;
_results = [];
for (_i = 0, _len = lines.length; _i < _len; _i++) {
line = lines[_i];
if (!(blank(line))) {
_results.push(lineToMap(line));
}
}
return _results;
};
runConvert = function() {
var result;
result = convert($('#textarea-plain-text').val());
$('#textarea-converted-text').val(result);
return $('#div-converted-text').html(result);
};
bind = function() {
return $('#list-conversion-button').click(runConvert);
};
$(bind);
JSFiddle

How to dynamically access nested Json object

I am trying to populate my input fields based on the retrieved JSON object. The field names in my form would be something like:
fullName
account.enabled
country.XXX.XXXX
The function should return something like below for the above fields
aData["fullName"]
aData["account"]["enabled"]
aData["country"]["XXX"]["XXXX"]
How should I write my a function that returns a matching JSON entry for a given HTML field's name ?
you could use the attached method that will recursively look for a given path in a JSON object and will fallback to default value (def) if there is no match.
var get = function (model, path, def) {
path = path || '';
model = model || {};
def = typeof def === 'undefined' ? '' : def;
var parts = path.split('.');
if (parts.length > 1 && typeof model[parts[0]] === 'object') {
return get(model[parts[0]], parts.splice(1).join('.'), def);
} else {
return model[parts[0]] || def;
}
}
and you can call it like that :
get(aData, 'country.XXX.XXXX', ''); //traverse the json object to get the given key
Iterate over the form elements, grab their names, split on '.', then access the JSON Object?
Something like:
var getDataValueForField = function (fieldName, data) {
var namespaces = fieldName.split('.');
var value = "";
var step = data;
for (var i = 0; i < namespaces.length; i++) {
if (data.hasOwnProperty(namespaces[i])) {
step = step[namespaces[i]];
value = step;
} else {
return (""); // safe value
}
}
return (value);
};
var populateFormFields = function (formId, data) {
var fields = document.querySelectorAll('#' + formId + ' input');
for (var i = 0; i < fields.length; i++) {
fields[i].value = getDataValueForField(fields[i].name, data);
}
};
populateFormFields('myForm', fetchedFromSomeWhere());

get regex pattern for current URL

I have a url like this:
http://mysite.aspx/results.aspx?s=bcs_locations&k="Hospital" OR "Office" OR...
The terms after k= are coming from checkboxes, when checked the checkboxes values are being passed. Now I need to get the current URL and get all the values after k, so if there are two 'Hospital' and Office then grab those values and make the checkboxes with those values checked.. Trying hard to persist the checked checkboxes coz on refresh, all the checked checkboxes loose their state..
Hospitals<input name="LocType" type="checkbox" value="Hospital"/>  
Offices<input name="LocType" type="checkbox" value="Office"/>  
Emergency Centers<input name="LocType" type="checkbox" value="Emergency"/>
What I have so far is:
I want the regular expression for such URl pattern..can someone help?
var value = window.location.href.match(/[?&]k=([^&#]+)/) || [];
if (value.length == 2) {
$('input[name="LocType"][value="' + value[1] + '"]').prop("checked", true);
}
This is what we use to grab info from the query string. It's from another S.O. answer that I can't find. But this will give you an object which represents all the options in the query string.
var qs = function(){
var query_string = {};
if(window.location.search){
(function () {
var e,
a = /\+/g, // Regex for replacing addition symbol with a space
r = /([^&=]+)=?([^&]*)/g,
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
q = window.location.search.substring(1);
while (e = r.exec(q)){
query_string[d(e[1])] = d(e[2]);
}
}());
}
return query_string;
};
You could do it like this:
var MyApp = {
urlArgs:{}
};
MyApp.processUrlArgs = function() {
this.urlArgs = {};
var str = window.location.search ? window.location.search.substring(1) : false;
if( ! str ) return;
var sp = str.split(/&+/);
var rx = /^([^=]+)(=(.+))?/;
var k, v, i, m;
for( i in sp ) {
m = rx.exec( sp[i] );
if( ! m ) continue;
this.urlArgs[decodeURIComponent(m[1])] = decodeURIComponent(m[3]);
}
};
But what I don't understand is why do it like this? If you work in asp why don't you use HttpUtility.ParseQueryString?
try this
function getParamsFromUrl(url){
var paramsStr = url.split('?')[1],
params = paramsStr.split('&'),
paramsObj = {};
for(var i=0;i < params.length; i++){
var param= params[i].split('='),
name = param[0],
value = param[1];
paramsObj[name] = value;
}
return paramsObj;
}
var testUrl = 'http://mysite.aspx/results.aspx?s=bcs_locations&k=Hospital';
getParamsFromUrl(testUrl);//return: Object { s="bcs_locations", k="Hospital"}

Categories

Resources