Convert XQuery Search API bucket generation to JSearch in MarkLogic - javascript

I wanted to "convert" one of my old XQuery examples that uses buckets (bucketed search) to JSearch:
import module namespace search =
"http://marklogic.com/appservices/search"
at "/MarkLogic/appservices/search/search.xqy";
declare variable $options := <options xmlns="http://marklogic.com/appservices/search">
<constraint name="height">
<range type="xs:double" facet="true">
<bucket ge="1.9" name="supertall">1.90m + </bucket>
<bucket lt="1.9" ge="1.7" name="tall">1.70m - 1.90m</bucket>
<bucket lt="1.7" ge="1.2" name="normalish">1.20m - 1.70m</bucket>
<bucket lt="1.2" name="short">0m - 1.20m</bucket>
<facet-option>limit=20</facet-option>
<json-property>height</json-property>
</range>
</constraint>
</options>;
let $results := search:search("height:short", $options)
for $facet in $results/search:facet
return $results;
The above allows the definition of buckets as well as allows the usage of 'height' as part of the search grammar, meaning that a search such as search:search('height:short') works just as fine.
Unfortunately I couldn't get the JSearch version working, this is what I have tried:
var jsearch = require('/MarkLogic/jsearch');
jsearch.documents(
jsearch.facet('Height', 'height').groupInto([
jsearch.bucketName('short'), 1.60,
jsearch.bucketName('normal'), 1.90,
jsearch.bucketName('tall'), 4.00
]))
.where(cts.parse('height:short'))
.result();
The above code returns:
{
"results": null,
"estimate": 0
}
I have also tried to add a reference to the JSON property 'height' but that didn't work either:
var jsearch = require('/MarkLogic/jsearch');
var reference = { height: cts.jsonPropertyReference('height') };
jsearch.documents(
jsearch.facet('Height', 'height').groupInto([
jsearch.bucketName('short'), 1.60,
jsearch.bucketName('normal'), 1.90,
jsearch.bucketName('tall'), 4.00
]))
.where(cts.parse('height:short', reference))
.result();
However when I remove the .where() constraint I get my buckets generated just fine. Any suggestions?

I believe I have found a solution to this. The values of height are numbers and in my JSearch query I am trying to match the string 'short' against those numbers. In order to overcome this I had to use a callback function which was documented on this page http://docs.marklogic.com/cts.parse
Essentially the solution was to create my own query using a set of cts query constructors (cts.andQuery and cts.jsonPropertyRangeQuery). The solution now looks like this:
var jsearch = require('/MarkLogic/jsearch');
var short = 1.60;
var normal = 1.80;
var tall = 1.90;
var refCallback = function(operator, values, options) {
if (values === 'short') {
return cts.jsonPropertyRangeQuery('height', '<=', short)
} else if (values === 'normal') {
return cts.andQuery([
cts.jsonPropertyRangeQuery('height', '>=', normal),
cts.jsonPropertyRangeQuery('height', '<', tall)
])
} else {
return cts.jsonPropertyRangeQuery('height', '>=', tall)
}
};
var reference = { height: refCallback };
jsearch.documents(
jsearch.facet('height').groupInto([
jsearch.bucketName('short'), short,
jsearch.bucketName('normal'), normal,
jsearch.bucketName('tall'), tall
]))
.where(cts.parse('height:tall', reference))
.result();
Note that I also had to externalise the variable declarations as now I can reuse those within the bucket definitions as well as the callback function.

Related

Is there a way to improved method for separating a substring from search position text via indexOf?

The method I use I need to put +13 and -1 inside the calculation when searching the position of each part of the text (const Before and const After), is there a more reliable and correct way?
const PositionBefore = TextScript.indexOf(Before)+13;
const PositionAfter = TextScript.indexOf(After)-1;
My fear is that for some reason the search text changes and I forget to change the numbers for the calculation and this causes an error in the retrieved text.
The part of text i'm return is date and hour:
2021-08-31 19:12:08
function Clock() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Clock');
var url = 'https://int.soccerway.com/';
const contentText = UrlFetchApp.fetch(url).getContentText();
const $ = Cheerio.load(contentText);
const Before = '"timestamp":"';
const After = '});\n block.registerForCallbacks();';
var ElementSelect = $('script:contains(' + Before + ')');
var TextScript = ElementSelect.html().replace("\n","");
const PositionBefore = TextScript.indexOf(Before)+13;
const PositionAfter = TextScript.indexOf(After)-1;
sheet.getRange(1, 1).setValue(TextScript.substring(PositionBefore, PositionAfter));
}
Example full text colected in var TextScript:
(function() {
var block = new HomeMatchesBlock('block_home_matches_31', 'block_home_matches', {"block_service_id":"home_index_block_homematches","date":"2021-08-31","display":"all","timestamp":"2021-08-31 19:12:08"});
block.registerForCallbacks();
$('block_home_matches_31_1_1').observe('click', function() { block.filterContent({"display":"all"}); }.bind(block));
$('block_home_matches_31_1_2').observe('click', function() { block.filterContent({"display":"now_playing"}); }.bind(block));
block.setAttribute('colspan_left', 2);
block.setAttribute('colspan_right', 2);
TimestampFormatter.format('block_home_matches_31');
})();
There is no way to eliminate the risk of structural changes to the source content.
You can take some steps to minimize the likelihood that you forget to change your code - for example, by removing the need for hard-coded +13 and -1. But there can be other reasons for your code to fail, beyond that.
It's probably more important to make it extremely obvious when your code does fail.
Consider the following sample (which does not use Cheerio, for simplicity):
function demoHandler() {
var url = 'https://int.soccerway.com/';
const contentText = UrlFetchApp.fetch(url).getContentText();
var matchedJsonString = contentText.match(/{.*?"timestamp".*?}/)[0];
if ( matchedJsonString ) {
try {
var json = JSON.parse(matchedJsonString);
} catch(err) {
console.log( err ); // "SyntaxError..."
}
console.log(json.timestamp)
} else {
consle.log( 'Something went terribly wrong...' )
}
}
When you run the above function it prints the following to the console:
2021-08-31 23:18:46
It does this by assuming the key value of "timestamp" is part of a JSON string, starting with { and ending with }.
You can therefore extract this JSON string and convert it to a JavaScript object and then access the timestamp value directly, without needing to handle substrings.
If the JSON is not valid you will get an explicit error similar to this:
[SyntaxError: Unexpected token c in JSON at position 0]
Scraping web page data almost always has these types of risk: Your code can be brittle and break easily if the source structure changes without warning. Just try to make suc changes as noticeable as possible. In your case, write the errors to your spreadsheet and make it really obvious (red, bold, etc.).
And make good use of try...catch statements. See: try...catch

Map.delete() not working on key in parent Map

What I'm doing right now, is deleting any diff that doesn't contain the string, and if the diff's dictionary is empty, then i try to delete the map.
the issue here is that, i can't delete a map with data.delete(map) for some reasons (no errors in console) and any piece of code located after that deletion in the if statement won't run.
here is the code in question:
var data = new Map({"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {"difficulties": {"Titan": 86813}}, "859608 LiSA - ADAMAS (TV Size)": {"difficulties": {"Kibbleru's Blue Rose": 899}},"940746 CHiCO with HoneyWorks - Kimi ga Sora Koso Kanashikere": {"difficulties": {"Taeyang's Extra": 72321}}});
var string = "titan";
Array.from(data.keys()).forEach(function(map) {
if (!(map.toLowerCase().indexOf(string.toLowerCase()) >=0)) {
if (document.getElementById("diff_search_box").checked) {
Array.from(data.get(map).get("difficulties").keys()).forEach(function(diff) {
if (!(diff.toLowerCase().indexOf(string) >= 0)) {
data.get(map).get("difficulties").delete(diff)
}
})
if (Array.from(data.get(map).get("difficulties").keys()).length = 0) {
data.delete(map)
}
}
}
})
in this situation, I'm supposed to get a dictionary such as:
{
"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {
"difficulties": {"Titan": 86813}
}
}
Huge number of problems with this code. My recommendation is don't write so much code without running it to make sure it works first. Write small pieces at a time and run it as you go making sure everything works along the way.
Issue number one is you cannot initialize a map with an object like that. The Map must be initialized with an array of arrays that are each two elements long, each containing the key value pairs for the map. You can fix this by wrapping the object in Object.entries() as that will return the key vale pairs for the object.
Second problem is titan is a string so it should be "titan".
Number three, you're calling .get on an object in the line data.get(map).get("difficulties"). Objects do not have .get, you have to use brackets or dot syntax: data.get(map).difficulties or data.get(map).difficulties.
Fourth, I think you don't actually want to delete the data from the map. If you did, when the user changes the search text the old data would still be gone.
Why are you using map anyways? you can simply use a normal object.
Just do this if you must use maps:
var data = new Map(Object.entries({
"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {
"difficulties": {"Titan": 86813}
},
"859608 LiSA - ADAMAS (TV Size)": {
"difficulties": {"Kibbleru's Blue Rose": 899}
},
"940746 CHiCO with HoneyWorks - Kimi ga Sora Koso Kanashikere": {
"difficulties": {"Taeyang's Extra": 72321}
}
}));
var string = 'titan';
function search(s) {
var r = {};
for( const [key, value] of data ) {
for( const diffKey in value.difficulties ) {
if(diffKey.toLowerCase().indexOf(string) != -1)
r[key] = value;
}
}
return new Map(Object.entries(r));
}
With this function, you can do search(string) and it will return you the map that you were wanting originally.
Mainly you should writing a bunch of code without running anything.
Map needs an iterable like an array passed to it such as:
new Map([['Key 1', 'Value 1'], ['Key 1', 'Value 1']])
You can't pass an object literal to it but you can easily use Object.entries() to extract the needed array from your object.
Then you can use Map.prototype.forEach() to loop over all the Map entries
var data = {"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {"difficulties": {"Titan": 86813}}, "859608 LiSA - ADAMAS (TV Size)": {"difficulties": {"Kibbleru's Blue Rose": 899}},"940746 CHiCO with HoneyWorks - Kimi ga Sora Koso Kanashikere": {"difficulties": {"Taeyang's Extra": 72321}}};
const map = new Map(Object.entries(data));
map.forEach((value, key) =>{
const {difficulties} = value;
console.log('Map key:', key.toLowerCase());
// if(someCondition){
// map.delete(key)
// }
Object.entries(difficulties).forEach(([k,v])=>{
console.log('Diff key:', k, ' Diff value:', v)
// if(k.toLowerCase().includes('titan')){
// delete difficulties[key];
// }
})
console.log('*****************************')
})
surprising to see none of the previous answer saw that, another person on a discord server i do support for software stuff on pointed out the last if condition and the fact it's missing a = so it appear as
if (Array.from(data.get(map).get("difficulties").keys()).length == 0) {
// was = before, == now
data.delete(map)
}
so now i indeed obtain a data dictionary with only 1 element containing the map which also have the difficulty that's contained in the specified string.

node: managing SQL files with variable replacement

I have large SQL statements that I would like to store as separate files (with syntax highlighting etc). I like the accepted solution proposed here.
In my use case, I write SQL in Javascript Template Literal syntax for variable replacement. So my file looks like
-- some_file.sql
select col1, col2, col3
from my_table
where col1 = '${val1}'
and col2 between ${val2} and ${val3}
In fact this way of writing queries started from using template literals initially before the queries grew and demanded their own file.
The question is how to achieve template literals like evaluation for a query string read using fs.readFileSync without having to do the dreaded eval? I looked into es6-template-render, however that implementation is not suited for variables in the execution context; i.e. not specifying a separate context parameter, but implicitly using the variables (global/local) available in the environment during runtime.
Any pointers?
Apologies if my assumption is incorrect, but the quotes around '${val1}' suggest you're planning to use string substitution rather than parameterized queries. Don't do that. :-) Never use string substitution to put values into SQL queries. Let me introduce you to my friend Bobby:
Use parameterized queries instead.
For instance, you might use a format very much like you have, just without any quotes around ${val1}:
select col1, col2, col3
from my_table
where col1 = ${val1}
and col2 between ${val2} and ${val3}
Then your code could convert that into a query appropriate to your DB API. Many of them use ? placeholders, so for instance (here I'm using node-mysql2 as the DB API, but the specific API isn't the point):
const rexParam = /(?<!\$)\$\{([^}]+)\}/g;
function doQuery(sql, params) {
return new Promise((resolve, reject) => {
const values = [];
const preppedSql = sql.replace(rexParam, (_, paramName) => {
const value = params[paramName];
if (value === undefined) { // Or do an `in` check if you want to allow `undefined`
throw new Error(`Missing parameter ${paramName}`);
}
values.push(value);
return "?";
});
return connection.execute(
preppedSql,
values,
function(err, results, fields) {
if (err) {
reject(err);
} else {
resolve({results, fields});
}
}
);
});
}
That spins through the string, replacing the ${val1} and such tokens with ? and at the same time filling in an array of values to pass to the parameterized query function.
(Note the negative lookbehind so that $${...} isn't expanded, just like in template literals. The regex is a bit primitive, but should suffice for SQL I'd think...)
Live example just dumping out the string and values:
const sql =
"select col1, col2, col3\n" +
"from my_table\n" +
"where col1 = ${val1}\n" +
"and col2 between ${val2} and ${val3}";
const rexParam = /(?<!\$)\$\{([^}]+)\}/g;
function doQuery(sql, params) {
const values = [];
const preppedSql = sql.replace(rexParam, (_, paramName) => {
const value = params[paramName];
if (value === undefined) { // Or do an `in` check if you want to allow `undefined`
throw new Error(`Missing parameter '${paramName}'`);
}
values.push(value);
return "?";
});
console.log(preppedSql);
console.log(values);
}
doQuery(sql, {val1: "one", val2: 2, val3: 20});

Pass arbitrary Javascript data object to Node.js C++ addon

I have a Node.js addon written in C++ using Nan. Works fantastically. However, I've not been able to figure out how to have my Node Javascript code pass an arbitrary data object (ex. {attr1:42, attr2:'hi', attr3:[5,4,3,2,1]}) to the C++ addon.
Until now, I've got around this by calling JSON.stringify() on my data object and then parsing the stringified JSON on the C++ side.
Ideally, I'd like to avoid copying data and just get a reference to the data object that I can access, or at least to copy it natively and avoid stringifying/parsing...
Any help would be appreciated!
You can allow your Node.js c++ addons to take arbitrary typed arguments, but you must check and handle the types explicitly. He is a simple example function that shows how to do this:
void args(const Nan::FunctionCallbackInfo<v8::Value>& info) {
int i = 0;
while (i < info.Length()) {
if (info[i]->IsBoolean()) {
printf("boolean = %s", info[i]->BooleanValue() ? "true" : "false");
} else if (info[i]->IsInt32()) {
printf("int32 = %ld", info[i]->IntegerValue());
} else if (info[i]->IsNumber()) {
printf("number = %f", info[i]->NumberValue());
} else if (info[i]->IsString()) {
printf("string = %s", *v8::String::Utf8Value(info[i]->ToString()));
} else if (info[i]->IsObject()) {
printf("[object]");
v8::Local<v8::Object> obj = info[i]->ToObject();
v8::Local<v8::Array> props = obj->GetPropertyNames();
for (unsigned int j = 0; j < props->Length(); j++) {
printf("%s: %s",
*v8::String::Utf8Value(props->Get(j)->ToString()),
*v8::String::Utf8Value(obj->Get(props->Get(j))->ToString())
);
}
} else if (info[i]->IsUndefined()) {
printf("[undefined]");
} else if (info[i]->IsNull()) {
printf("[null]");
}
i += 1;
}
}
To actually solve the problem of handling arbitrary arguments that may contain objects with arbitrary data, I would recommend writing a function that parses an actual object similar to how I parsed function arguments in this example. Keep in mind that you may need to do this recursively if you want to be able to handle nested objects within the object.
You don't have to stringify your object to pass it to c++ addons. There are methods to accept those
arbitary objects. But it is not so arbitary. You have to write different codes to parse the object in c++ .
Think of it as a schema of a database. You can not save different format data in a single collection/table.
You will need another table/collection with the specific schema.
Let's see this example:
We will pass an object {x: 10 , y: 5} to addon, and c++ addon will return another object with sum and product of the
properties like this: {x1:15,y1: 50}
In cpp code :
NAN_METHOD(func1) {
if (info.Length() > 0) {
Local<Object> obj = info[0]->ToObject();
Local<String> x = Nan::New<String>("x").ToLocalChecked();
Local<String> y = Nan::New<String>("y").ToLocalChecked();
Local<String> sum = Nan::New<String>("sum").ToLocalChecked();
Local<String> prod = Nan::New<String>("prod").ToLocalChecked();
Local<Object> ret = Nan::New<Object>();
double x1 = Nan::Get(obj, x).ToLocalChecked()->NumberValue();
double y1 = Nan::Get(obj, y).ToLocalChecked()->NumberValue();
Nan::Set(ret, sum, Nan::New<Number>(x1 + y1));
Nan::Set(ret, prod, Nan::New<Number>(x1 * y1));
info.GetReturnValue().Set(ret);
}
}
In javascript::
const addon = require('./build/Release/addon.node');
var obj = addon.func1({ 'x': 5, 'y': 10 });
console.log(obj); // { sum: 15, prod: 50 }
Here you can only send {x: (Number), y: (number)} type object to addon only. Else it will not be able to parse or
retrieve data.
Like this for the array:
In cpp:
NAN_METHOD(func2) {
Local<Array> array = Local<Array>::Cast(info[0]);
Local<String> ss_prop = Nan::New<String>("sum_of_squares").ToLocalChecked();
Local<Array> squares = New<v8::Array>(array->Length());
double ss = 0;
for (unsigned int i = 0; i < array->Length(); i++ ) {
if (Nan::Has(array, i).FromJust()) {
// get data from a particular index
double value = Nan::Get(array, i).ToLocalChecked()->NumberValue();
// set a particular index - note the array parameter
// is mutable
Nan::Set(array, i, Nan::New<Number>(value + 1));
Nan::Set(squares, i, Nan::New<Number>(value * value));
ss += value*value;
}
}
// set a non index property on the returned array.
Nan::Set(squares, ss_prop, Nan::New<Number>(ss));
info.GetReturnValue().Set(squares);
}
In javascript:
const addon = require('./build/Release/addon.node');
var arr = [1, 2, 3];
console.log(addon.func2(arr)); //[ 1, 4, 9, sum_of_squares: 14 ]
Like this, you can handle data types. If you want complex objects or operations, you just
have to mix these methods in one function and parse the data.

How to convert arrays to objects in javascript?

How could I rewrite this code to object javascript. Since Array usage is prohibed, I can only use objects here. Insted of pushing values to array, I would like to push this values into objects.
var container = [];
document.addEventListener("submit", function(e){
e.preventDefault();
});
window.addEventListener("load",function(){
var submit = document.getElementsByClassName("btn-primary");
submit[0].addEventListener("click",add,false);
document.getElementById("pobrisi").addEventListener("click",deleteAll,false);
var dateElement = document.getElementById('datum');
dateElement.valueAsDate = new Date();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1;
var yyyy = today.getFullYear();
if(dd<10){
dd='0'+dd
}
if(mm<10){
mm='0'+mm
}
today = yyyy+'-'+mm+'-'+dd;
dateElement.setAttribute("min",today);
});
function add() {
var title = document.getElementById("title").value;
var type = document.getElementById("type").value;
var datum = document.getElementById("datum").value.split("-");
datum = datum[2]+". "+datum[1]+". "+datum[0];
var data = new Book(title,type,datum);
container.push(data.add());
display();
}
function display(data) {
var destination = document.getElementById("list");
var html = "";
for(var i =0;i <container.length; i++) {
html +="<li>"+container[i]+"</li>";
}
destination.innerHTML = html;
}
function deleteAll(){
container=[];
document.getElementById("list").innerHTML="";
}
Wondering if is possible to write this code whitout any array usage.
initial remarks
The problem here, in my estimation, is that you haven't learned the fundamentals of data abstraction yet. If you don't know how to implement an array, you probably shouldn't be depending on one quite yet. Objects and Arrays are so widespread because they're so commonly useful. However, if you don't know what a specific data type is affording you (ie, what convenience does it provide?), then it's probable you will be misusing the type
If you take the code here but techniques like this weren't covered in your class, it will be obvious that you received help from an outside source. Assuming the teacher has a curriculum organized in a sane fashion, you should be able to solve problems based on the material you've already covered.
Based on your code, it's evident you really have tried much, but why do you think that people here will come up with an answer that your teacher will accept? How are we supposed to know what you can use?
a fun exercise nonetheless
OK, so (we think) we need an Array, but let's pretend Arrays don't exist. If we could get this code working below, we might not exactly have an Array, but we'd have something that works like an array.
Most importantly, if we could get this code working below, we'd know what it takes to make a data type that can hold a dynamic number of values. Only then can we begin to truly appreciate what Array is doing for us.
// make a list
let l = list(1) // (1)
// push an item on the end
l = push(l, 2) // (1 2)
// push another item on the end
l = push(l, 3) // (1 2 3)
// display each item of the list
listeach(l, function (x) {
console.log(x)
})
// should output
// 1
// 2
// 3
runnable demo
All we have to do is make that bit of code (above) work without using any arrays. I'll restrict myself even further and only use functions, if/else, and equality test ===. I see these things in your code, so I'm assuming it's OK for me to use them too.
But am I supposed to believe your teacher would let you write code like this? It works, of course, but I don't think it brings you any closer to your answer
var empty = function () {}
function isEmpty (x) {
return x === empty
}
function pair (x,y) {
return function (p) {
return p(x,y)
}
}
function head (p) {
return p(function (x,y) {
return x
})
}
function tail (p) {
return p(function (x,y) {
return y
})
}
function push (l, x) {
if (isEmpty(l))
return list(x)
else
return pair(head(l), push(tail(l), x))
}
function list (x) {
return pair(x, empty)
}
function listeach (l, f) {
if (isEmpty(l))
return null
else
(f(head(l)), listeach(tail(l), f))
}
// make a list
let l = list(1) // (1)
// push an item on the end
l = push(l, 2) // (1 2)
// push another item on the end
l = push(l, 3) // (1 2 3)
// display each item of the list
listeach(l, function (x) {
console.log(x)
})
closing remarks
It appears as tho you can use an Object in lieu of an Array. The accepted answer (at this time) shows a very narrow understanding of how an object could be used to solve your problem. After this contrived demonstration, are you confident that you are using Objects properly and effectively?
Do you know how to implement an object? Could you fulfill this contract (below)? What I mean by that, is could you write the functions object, set, and get such that the following expressions evaluated to their expected result?
In case it's not obvious, you're not allowed to use Object to make it happen. The whole point of the exercise is to make a new data type that you don't already have access to
m = object() // m
set(m, key, x) // m
get(m, key) // x
set(m, key2, y) // m
get(m, key2) // y
set(m, key3, set(object(), key4, z)) // m
get(get(m, key3), key4) // z
I'll leave this as an exercise for you and I strongly encourage you to do it. I think you will learn a lot in the process and develop a deep understanding and appreciation for what higher-level data types like Array or Object give to you
Since this is a homework I feel like I shouldn't solve it for you, but rather help you in the right direction.
Like Slasher mentioned you can use objects
With JavaScript object one book would look something like
const book = {
title: 'my awesome title',
type: 'novel'
};
book is the object
title is a property with a value 'my awesome title'
type is a property with a value 'novel'
But objects can also have other objects as values. Something like
const BookShelf= {
Book1: {
Title: 'my awesome title',
Type: 'novel'
},
Book2: {
Title: 'my horrible title',
Type: 'sci-fi'
}
};
You can reference the books in the bookshelf in two ways
const book1 = BookShelf.Book1 // Returns the book1 object
const title1 = Book1.Title; // Get the title
const sametitle = BookShelf.Book1.Title // Returns title for book1, same as above.
You can also use brackets:
const book1 = BookShelf['Book1'];
const title1 = BookShelf['Book1']['Title];
You can even make new properties on a object like this:
const Book3 = {
Title: 'running out of ideas'
Type: 'memoir'
};
BookShelf['Book3'] = Book3;
Now the BookShelf has a Book3 property. So your BookShelf object looks like
const BookShelf= {
Book1: {
Title: 'my awesome title',
Type: 'novel'
},
Book2: {
Title: 'my horrible title',
Type: 'sci-fi'
},
Book3 = {
Title: 'running out of ideas'
Type: 'memoir'
};
};
That should get you started :)
JavaScript Objects is a good way to go
1- define a new object:
var myVar = {};
or
var myVar = new Object();
2- usage
// insert a new value, it doesn't matter if the value is a string or int or even another object
// set a new value
myVar.myFirstValue="this is my first value";
// get existing value and do what ever you want with it
var value = myVar.myFirstValue

Categories

Resources