I am trying to replace a value in a search.create function with a filter. the filter returns one or more objects, and i store them in an array. On accessing the array, i want to replace a certain value with 0, if a certain field 'lastinv' is empty. here is my code below;
// a is lastinv
if (a == null || a == '') {
todate = format.format({
value: todate,
type: format.Type.DATE
});
// creates a custom search on a record with specific filters
var reading = search.create({
type: 'customrecord_ew_meterreading_form',
columns: ['name', 'id', 'custrecord_ew_mr_metername', 'custrecordmeternumber', 'custrecord_ew_mr_site', 'custrecord1', 'custrecord_ew_meterreading_value'],
filters: [{
name: 'custrecord_ew_mr_site',
operator: search.Operator.IS,
values: site
}, {
name: 'custrecord1',
operator: search.Operator.ON,
values: todate
}] // end of filter*/
});
// gets a custom search for the readings of a site on the
// firstdate/lastdate of the month and stores in a array called ar_readings
reading.run().each(function(result) {
ar_reading.push(result);
return true;
});
return ar_reading;
}
And this next part is me trying to replace the value on a certain index;
for (var k = 0; k < firstReading.length; k++) {
ar_mtrdata[k] = new Array();
var l_meternumber = firstReading[k].getValue('custrecordmeternumber');
var mtrdtls = getMeterDetails(l_meternumber);
ar_mtrdata[k][0] = mtrdtls.getValue('itemid'); // Meternumber
if (lastinv == '' || lastinv == undefined || lastinv == null) {
ar_mtrdata[k][2] = 0;
} else {
ar_mtrdata[k][2] = firstReading[k].getValue('custrecord_ew_meterreading_value'); // previous reading
}
/* ... */
}
Why don't you extract the values within the first code block inside of the run().each loop?
The you could push a organized object into the array that already has the values the way you want them.
I have a array type in Javascript:
var type=[0,1,2,3,4,5];
The corresponding key value pair collection is actually like this;
[{0:'Pointer'},{1:'Line'},{2:'Oval'},{3:'Rectangle'},{4:'Ellipse'},{5,'Star'}]
My .dust file displays the {type} mark, how should I display their corresponding values?
You may use a custom filter. The approximate implementation would be:
var mapping = {
'0':'Pointer',
'1':'Line',
'2':'Oval',
'3':'Rectangle',
'4':'Ellipse',
'5':'Star'
};
dust.filters['typeFilter'] = function(value) {
return mapping[value] || '';
}
And in you template: {type|typeFilter}
It's a bit simpler to store the mapping in an object than array. For you array version it would be like:
var mapping = [{0:'Pointer'},{1:'Line'},{2:'Oval'},{3:'Rectangle'},{4:'Ellipse'},{5:'Star'}];
dust.filters['typeFilter'] = function(value) {
var typeId = parseInt(value);
for(var len = mapping.length - 1; len >=0; len--) {
if (mapping[len].hasOwnProperty(typeId)) {
return mapping[len][typeId];
}
}
return '';
}
A bit more information here
I have this 2D array as follows:
var data = [[1349245800000, 11407.273], [1349247600000, 12651.324],
[1349249400000, 11995.017], [1349251200000, 11567.533],
[1349253000000, 11126.858], [1349254800000, 9856.455],
[1349256600000, 8901.779], [1349258400000, 8270.123],
[1349260200000, 8081.841], [1349262000000, 7976.148],
[1349263800000, 7279.652], [1349265600000, 6983.956],
[1349267400000, 7823.309], [1349269200000, 6256.398],
[1349271000000, 5487.86], [1349272800000, 5094.47],
[1349274600000, 4872.403], [1349276400000, 4168.556],
[1349278200000, 4501.939], [1349280000000, 4150.769],
[1349281800000, 4061.599], [1349283600000, 3773.741],
[1349285400000, 3876.534], [1349287200000, 3221.753],
[1349289000000, 3330.14], [1349290800000, 3147.335],
[1349292600000, 2767.582], [1349294400000, 2638.549],
[1349296200000, 2477.312], [1349298000000, 2270.975],
[1349299800000, 2207.568], [1349301600000, 1972.667],
[1349303400000, 1788.853], [1349305200000, 1723.891],
[1349307000000, 1629.002], [1349308800000, 1660.084],
[1349310600000, 1710.227], [1349312400000, 1708.039],
[1349314200000, 1683.354], [1349316000000, 2236.317],
[1349317800000, 2228.405], [1349319600000, 2756.069],
[1349321400000, 4289.437], [1349323200000, 4548.436],
[1349325000000, 5225.245], [1349326800000, 6261.156],
[1349328600000, 8103.636], [1349330400000, 10713.788]]
How do I get the index of value 1349247600000 in the array? I have tried $.inArray(1349247600000, data) but as expected this fails. Is there any other way or do I have to iterate over each? I am reluctant to add another loop to my process
This is a typical performance versus memory issue. The only way (that I know of) to avoid looping through the array, would be to maintain a second data structure mapping the timestamps to the index of the array (or whatever data might needed).
So you would have
var data = [
[1349245800000, 11407.273],
[1349247600000, 12651.324],
// ...
[1349330400000, 10713.788]
];
// the timestamps pointing at their respective indices
var map = {
'1349245800000': 0, // 0
'1349247600000': 1, // 1
// ...
'1349330400000': 42, // n - 1 (the length of the data array minus one)
}
This way, you use more memory, but have a constant lookup time when needing the index of the item in the array that a given timestamp belongs to.
To get the index of a given timestamp do:
map['1349247600000']; // resulting in 1 (e.g.)
If the data structure is dynamically changed, you would of course need to maintain the map data structure, but depending on the context in which you need the lookup, the constant time lookup can potentially be a real time saver compared to a linear time lookup.
I think you need a different data structure.
Try using a standard javascript object ({ key: value } - sometimes called a map or dictionary) to express your data. Looking up keys in an object is highly optimized (using something called hash tables).
If the index in your array has any meaning, store it as a property (typically named _id).
Ideally you should be using an object for this:
var data = {
'1349247600000': 12651.324
}
which you can access like:
data['1349247600000'];
However, this might be a nice solution (IE9 and above) in the meantime:
var search = 1349247600000;
function findIndex(data, search) {
var filter = data.filter(function (el, i) {
el.unshift(i);
return el[1] === search;
});
return filter[0][0];
}
console.log(findIndex(data, search));
fiddle : http://jsfiddle.net/CLa56/
var searchElement = 1349251200000;
var strdata = data.toString();
var newdata = eval("[" + strdata + "]");
var indexsearch = newdata.indexOf(searchElement);
var index = indexsearch/2; // 2 because array.length = 2
var params = {id: 1349251200000, index: -1};
data.some(function (e, i) {
if (e[0] === this.id) {
this.index = i;
return true;
}
}, params);
console.log(params.index);
jsfiddle
MDN|some Array Method
Note that this solution stops iterating after found, not necessarily over the entire array, so could be much faster for large arrays.
What about a custom cross browser solution ?
function findIndexBy(a, fn) {
var i = 0, l = a.length;
for (; i < l; i++) {
if (fn(a[i], i)) {
return i;
}
}
return -1;
}
Usage :
var list = [[1],[2],[3]], idx;
// idx === 1
idx = findIndexBy(list, function (item, i) {
return item[0] === 2;
});
// idx === -1
idx = findIndexBy(list, function (item, i) {
return item[0] === 4;
});
I have a form
<form>
<input type="text" name="Name" />
<input type="checkbox" name="Feature.Translate" />
<input type="checkbox" name="Feature.Share" />
<input type="submit" value="Convert into an object" />
</form>
I want to convert it in an object
{
Name: "John Connor's Terminator",
Feature:
{
Translate: true // if checked
// Share wasn't checked
}
}
How can I map the form to an object that has this tree structure?
Add this method to help you build the tree
// add keys to an object as a tree
// ["a", "b", "c"] will generate
// a { b: { c: def } }
// def is the value of the leaf node
var AddToTree = function(obj, keys, def)
{
for (var i = 0, length = keys.length; i < length; ++i)
obj = obj[keys[i]] = i == length - 1 ? def : obj[keys[i]] || {};
};
Create a function for a jQuery selector that will convert the form in an object
$.fn.serializeObject = function()
{
var o = {}; // final object
var a = this.serializeArray(); // retrieves an array of all form values as
// objects { name: "", value: "" }
$.each(a, function() {
var ns = this.name.split("."); // split name to get namespace
AddToTree(o, ns, this.value); // creates a tree structure
// with values in the namespace
});
return o;
};
With these two functions define you can set an event on the submit button:
$(":submit").click(function(e){
// contains the object from the form
// respecting element namespaces
var obj = $("form").serializeObject();
});
Something like the following should work:
function serializeData() {
//this is where we'll store our serialized data
var serializedData = {};
//iterate over input, select, and textarea elements
jQuery("input, select, textarea").each(function(index) {
var $element = jQuery(this);
var name = $element.attr("name");
//we only want to serialize the element if it has a 'name' attribute
if(typeof name != "undefined") {
//split on the . to get an array
var parts = name.split(/\./);
//start building the serialized data
var currentPart = serializedData;
for(var i = 0; i < parts.length; i++) {
//if this particular element doesn't already exist in our hash, create it
//and initialize it to an empty hash
if(typeof serializedData[parts[i]] == "undefined") {
currentPart[parts[i]] = {};
}
//if we're currently looking at the very last element in the array then
//it means that we need to set its value to the value of the corresponding
//input element. Otherwise, it means that there are still keys within the
//array and so we set `currentPart` to the new hash that we just created
if(i == parts.length - 1) {
//if the element is a checkbox or a radio, we need to see if it's checked
//instead of looking at its value
if($element.attr("type").toLowerCase() == "checkbox" || $element.attr("type").toLowerCase() == "radio") {
currentPart[parts[i]] = $element.is(":checked");
}
else {
currentPart[parts[i]] = $element.val();
}
}
else {
currentPart = currentPart[parts[i]];
}
}
}
});
console.log(serializedData);
}
Check out the fiddle.
All you need to do now is to bind serializeData to the submit event on the form.
I have two Select lists, between which you can move selected options. You can also move options up and down in the right list.
When I move options back over to the left list, I would like them to retain their original position in the list order, even if the list is missing some original options. This is solely for the purpose of making the list more convenient for the user.
I am currently defining an array with the original Select list onload.
What would be the best way to implement this?
You can store the original order in an array, and when inserting back, determine what's the latest element in the array that precedes the one to be inserted AND matches what's currently in the select list. Then insert after that.
A better solution is to just store the old array whole and re-populate on every insertion with desired elements as follows (warning: code not tested)
function init(selectId) {
var s = document.getElementById(selectId);
select_defaults[selectId] = [];
select_on[selectId] = [];
for (var i = 0; i < s.options.length; i++) {
select_defaults[selectId][i] = s.options[i];
select_on[selectId][i] = 1;
var value = list.options[i].value;
select_map_values[selectId][value] = i if you wish to add/remove by value.
var id = list.options[i].id; // if ID is defined for all options
select_map_ids[selectId][id] = i if you wish to add/remove by id.
}
}
function switch(selectId, num, id, value, to_add) { // You can pass number, value or id
if (num == null) {
if (id != null) {
num = select_map_ids[selectId][id]; // check if empty?
} else {
num = select_map_values[selectId][value]; // check if empty?
}
}
var old = select_on[selectId][num];
var newOption = (to_add) : 1 : 0;
if (old != newOption) {
select_on[selectId][num] = newOption;
redraw(selectId);
}
}
function add(selectId, num, id, value) {
switch(selectId, num, id, value, 1);
}
function remove(selectId, num, id, value) {
switch(selectId, num, id, value, 0);
}
function redraw(selectId) {
var s = document.getElementById(selectId);
s.options.length = 0; // empty out
for (var i = 0; i < select_on[selectId].length; i++) {
// can use global "initial_length" stored in init() instead of select_on[selectId].length
if (select_on[selectId][i] == 1) {
s.options.push(select_defaults[selectId][i]);
}
}
}
I would assign ascending values to the items so that you can insert an item back in the right place. The assigned value stays with the item no matter which list it's in.