I found compact function very useful (in php). Here is what it does:
$some_var = 'value';
$ar = compact('some_var');
//now $ar is array('some_var' => 'value')
So it create array from variables which you specify, when key for elements is variable name.
Is there any kind of function in javascript ?
You can use ES6/ES2015 Object initializer
Example:
let bar = 'bar', foo = 'foo', baz = 'baz'; // declare variables
let obj = {bar, foo, baz}; // use object initializer
console.log(obj);
{bar: 'bar', foo: 'foo', baz: 'baz'} // output
Beware of browsers compatibilities, you always can use Babel
No there is no analogous function nor is there any way to get variable names/values for the current context -- only if they are "global" variables on window, which is not recommended. If they are, you could do this:
function compact() {
var obj = {};
Array.prototype.forEach.call(arguments, function (elem) {
obj[elem] = window[elem];
});
return obj;
}
You can also use phpjs library for using the same function in javascript same as in php
Example
var1 = 'Kevin'; var2 = 'van'; var3 = 'Zonneveld';
compact('var1', 'var2', 'var3');
Output
{'var1': 'Kevin', 'var2': 'van', 'var3': 'Zonneveld'}
If the variables are not in global scope it is still kinda possible but not practical.
function somefunc() {
var a = 'aaa',
b = 'bbb';
var compact = function() {
var obj = {};
for (var i = 0; i < arguments.length; i++) {
var key = arguments[i];
var value = eval(key);
obj[key] = value;
}
return obj;
}
console.log(compact('a', 'b')) // {a:'aaa',b:'bbb'}
}
The good news is ES6 has a new feature that will do just this.
var a=1,b=2;
console.log({a,b}) // {a:1,b:2}
Related
js
var a = 'sun';
var b = 'earth';
var fn = 'some_fn';
$.post('index-pro.php', {fn, a, b}, function(data){
console.log(data);
});
I have a lot of code parts like the above, using different variables, but always refering to index-pro.php as a target file.
index-pro.php
if(isset($_POST)){extract($_POST);}
if(isset($fn) && $fn == 'some_fn'){some_fn($a, $b);}
elseif(isset($fn) && $fn == 'another_fn'){another_fn($another_vars);}
elseif(isset($fn) && $fn == 'another_fn'){another_fn($another_vars);}
How can I say something like this:
whatever fn is set -> run this fn using its variables.
You can call function using not only it's name, but even by a variable, which stores function name:
$fn = 'doStuff';
$a = 2;
$fn($a);
function doStuff($arg) {
echo $arg;
}
If your arguments are different for different functions then I advise to post data as two items: funcName and funcArguments, for example:
$.post('index-pro.php', {funcName: fn, funcArguments: [a, b]}, function(data){
console.log(data);
});
On server side you can do something like (I skip checks and other stuff, just baseline):
$fn = $_POST['funcName'];
$arguments = $_POST['funcArguments'];
// with php5.6/php7 you have variadic `...` syntax
$fn(...$arguments);
// or use plain old `call_user_func_array`:
call_user_func_array($fn, $arguments);
That's what you need. Simple idea: provide an array with arguments to a function name: http://php.net/manual/de/function.call-user-func.php
I didn't tried it out, but this should work:
JS
var a = 'sun';
var b = 'earth';
var fn = 'some_fn';
$.post('index-pro.php', {function: fn, args: [a, b]}, function(data){
console.log(data);
});
PHP
$functionName = $_POST['function'];
$args = $_POST['args'];
call_user_func ($functionName,$args)
I've been involved in a large web application where I have a lot of functions that calls web services through JSON. For instance:
/*...*/
refreshClientBoxes: function(customerNr) {
var request = {};
request.method = "getClientBoxes";
request.params = {};
request.params.customerNr = customerNr;
request.id = Math.floor(Math.random() * 101);
postObject(jsonURL, JSON.stringify(request), successClientBoxes);
},
/*...*/
Where “postObject” it’s a function that receive an URL, the data and a callback.
As you can see I have to construct this piece of code in every single method:
var request = {};
request.method = "getClientBoxes";
request.params = {};
request.params.customerNr = customerNr;
request.id = Math.floor(Math.random() * 101);
What's change is the name of the method that we will call and the name and values of parameter that we want to pass.
So I was wondering if there is a way that we can avoid this effort through a method that receive the name of the method that we will call and array of parameters, and using some kind of reflection construct the request parameters and return the request stringifyed.
For the WS I used php + zend 1.12, the MVC framework in JS its ember 0.95 and jQuery.
Edit 1: So thanks all for your answers. What I want it's a way that can give me the name of the parameters that I'm passing to the function or the name of a variable that I passed. Something like this:
var contructRequest = function (methodName, paramList) {
var request = {};
request.method = methodName;
request.params = {};
for(var i = 0; i < paramlist; i++){
/*some how get the paramName through reflection...so if i give a variable called customerNr this "for" add this new parameter to list of parameters like request.params.customerNr = customerNr whatever the variable name is or its value*/
}
request.params[paramName] = paramValue;
request.id = Math.floor(Math.random() * 101);
return request;
}
How about a method like this:
var contructRequest = function (methodName, paramList, paramName, paramValue) {
var request = {};
request.method = methodName;
request.params = paramList;
request.params[paramName] = paramValue;
request.id = Math.floor(Math.random() * 101);
return request;
}
This exploits the fact that object.property can also be referred to using object["property"].
You can call the method like so:
var customerRequest = constructRequest("getClientBoxes", {}, "customerNr", customerNr);
postObject(jsonURL, JSON.stringify(customerRequest), successClientBoxes);
You could DRY this by encapsulating the common parts in a separate function which takes the non-common parts as arguments, and returns the JSON. For example, if we assume that the only parts that change across the different functions are the method and customerNr:
buildRequest(method, customerNr) {
var request = {
method: method,
params: {
customerNr: customerNr
},
id: Math.floor(Math.random() * 101)
};
return JSON.stringify(request);
}
and you'd use it like so:
refreshClientBoxes: function(customerNr) {
var json = buildRequest('getClientBoxes', customerNr);
postObject(jsonURL, json, successClientBoxes);
},
How do I submit an array from dojo to php.
I'm submitting these values:
["a", "b", "c"]
Here's what I got so far:
btn_send.onclick(function(){
var name_array = name_looper();
console.log(name_array);
dojo.xhrPost({
url: "dojo_phpform.php",
content: {names: name_array},
load: function(result) {
var x = dojo.byId('results');
x.innerHTML = result;
}
});
});
function name_looper(){
var names = dojo.query('input[type=text]');
var name_array = [];
names.forEach(function(element, index, array){
name_array[index] = dojo.attr(element, 'value');
});
return name_array;
}
I tried to echo $_POST['names'] from the php file(dojo_phpform.php) and it didn't return any errors. It seems like the array isn't actually submitted. The only thing that's returned is the last item in the array. What do I do?Please help, Thanks in advance!
I just tested this with grails and php. In grails I have no problem getting an array submitted through a dojo xhrPost : I retrieve the array properly parsed with all its values as expected.
If I post :
dojo.xhrPost({
content : {
names : ['foo', 'bar']
},
url : "mygrailscontroller"
});
I get an array param on the other side. Which proves the problem hasn't to be solved on the dojo side, but on the php side.
In php, if a form input has a variable of type array, its name parameter has to be set with square brackets, like : "names[]" rather than "names".
So... in your case the solution is not to flatten the array into a string (sorry), but to name your array argument with brackets. So it would be :
dojo.xhrPost({
content : {
"names[]" : ['foo', 'bar']
},
url : "myphpcontroller"
});
As far as I've been able to see, dojo's xhr functions don't support it. I'm using a helper function to "flatten" parameters myself.
_flattenXhrParams: function(params)
{
var newParams = {};
for(var key in params)
{
if(dojo.isObject(params[key]))
{
for(var innerKey in params[key])
{
newParams[key + "[" + innerKey + "]"] =
params[key][innerKey];
}
}
else if(dojo.isArray(params[key]))
{
for(var i = 0, l = params[key].length; i < l; i++)
{
newParams[key + "[]"] = params[key][i];
}
}
else
{
newParams[key] = params[key];
}
}
return newParams;
}
It's butt ugly, I know, and obviously only works on one dimensional arrays/objects. In your case, you'd do:
dojo.xhrPost({
url: "dojo_phpform.php",
content: _flattenXhrParams({names: name_array}),
load: function(result) {
var x = dojo.byId('results');
x.innerHTML = result;
}
});
.. and you'd get POST parameters like names[]=a&names[]=b&names[]=c. For objects, you'd get names[somekey]=a&names[otherKey]=b etc. PHP handles both nicely.
I'm pretty sure the values of the content object only take strings. If you want to submit an array, you'd have to turn it into JSON and then json_decode it on the server.
i have a php script that print with echo this:
'&string="tom,dick,harry"'
and i need to put the "tom,dick,harry" in an actionscript string, that i have to split in an array. I'm having problems reading the php output, i'm using the URLLoader and TheURLVariables Classes in this way
var myRequest:URLRequest = new URLRequest("ip/directory/script.php");
var myLoader:URLLoader = new URLLoader();
function onLoaded(event:Event):void {
var variables:URLVariables = new URLVariables( event.target.data );
modelli = variables.string.split(",");
caricaColori(modelli[0]);
}
myLoader.addEventListener(Event.COMPLETE, onLoaded);
myLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
myLoader.load(myRequest);
What am i doing wrong?
Thought that you got problem with URLVariables, I still not totally understand this yet
function onLoaded(event:Event):void {
var variables:URLVariables = new URLVariables( event.target.data );
modelli = variables.string.split(",");
caricaColori(modelli[0]);
}
why do you need to store it into a URLVariables instance? Why don't parse it directly. If you are afraid of the "&string=", you don't need to echo it on PHP side, or can slice it out on Actionscript side.
modelli = event.target.data.split(",");
Perhaps using a variable name that isn't reserved might help. string seems like a bad choice.
// in php change
echo '&string="tom,dick,harry"'
// to
echo "tom,dick,harry"
// in actionscript change
function onLoaded(event:Event):void {
var str:String = event.target.data;
modelli = str.split(",");
caricaColori(modelli[0]);
}
If you want to add more variables and whatever, I would suggest turning the php response into an xml file. URLVariables should be used to SEND data to the server not for parsing a server response.
LOOK HERE
function onLoaded(event:Event):void {
var variables:URLVariables = new URLVariables( event.target.data );
modelli = variables.string.split(",");
caricaColori(modelli[0]);
}
Your problem is that you're loading the variables into a URLVariables container, and then trying to call a string function on it. I would do it this way instead:
function onLoaded(event:Event):void {
//load data as a string
var variables:String = event.target.data;
//make a new array
var modelli:Array = new Array();
modelli = variables.split(",");
//possibly pop the array
modelli.pop(); //pop off the last empty element of array
caricaColori(modelli[0]);
}
There's also a good chance that when you load this PHP data, you'll need to pop() the last element off of the array because it will be an empty string.
Really like that function.
$matches = array('12', 'watt');
list($value, $unit) = $matches;
Is there a Javascript equivalent of that?
There is, in 'newer' versions of Javascript: Destructuring assignment - Javascript 1.7. It's probably only supported in Mozilla-based browsers, and maybe in Rhino.
var a = 1;
var b = 3;
[a, b] = [b, a];
EDIT: actually it wouldn't surprise me if the V8 Javascript library (and thus Chrome) supports this. But don't count on it either
Now supported in all modern browsers(except IE, of course).
try this:
matches = ['12', 'watt'];
[value, unit] = matches;
ES6 does support this directly now via array destructuring.
const matches = ['12', 'watt'];
const [value, unit] = matches;
This is my solution for using List/Explode on Javascript.
Fiddle Working Example
First the implementation :
var dateMonth = "04/15";
dateMonth.split("/").list("month","day", "year");
month == "04";
day == "15";
year == null;
It also allows for scoping the new generated variables :
var scoped = (function()
{
var dateMonth = "07/24/2013";
dateMonth.split("/").list("month","day", "year", this);
this.month == "07";
this.day == "24";
this.year == "2013";
})();
This was accomplished by modifying an the Array prototype.
Array.prototype.list = function()
{
var
limit = this.length,
orphans = arguments.length - limit,
scope = orphans > 0 && typeof(arguments[arguments.length-1]) != "string" ? arguments[arguments.length-1] : window
;
while(limit--) scope[arguments[limit]] = this[limit];
if(scope != window) orphans--;
if(orphans > 0)
{
orphans += this.length;
while(orphans-- > this.length) scope[arguments[orphans]] = null;
}
}
There is a experimental implementation of list() by PHPJS here:
https://github.com/kvz/phpjs/blob/master/_experimental/array/list.js
CoffeeScript offers destructuring assignment with the syntax:
[a, b] = someFunctionReturningAnArray()
This is pretty much identical to the feature offered in very new JavaScript versions. However, CoffeeScript produces compiled JS that is compatible even with IE6's JavaScript engine, and therefore it's a good option if compatibility is vital.
Since most JavaScript implementations don't yet support that feature, you could simply do it in a more JavaScript-like fashion:
function list(){
var args = arguments;
return function(array){
var obj = {};
for(i=0; i<args.length; i++){
obj[args[i]] = array[i];
}
return obj;
};
}
Example:
var array = ['GET', '/users', 'UserController'];
var obj = {};
obj = list('method', 'route', 'controller')(array);
console.log(obj.method); // "GET"
console.log(obj.route); // "/users"
console.log(obj.controller); // "UserController"
Check the fiddle
An alternative is to add a list-method to Array.prototype (even I wouldn't recommend it):
Array.prototype.list = function(){
var i, obj = {};
for(i=0; i<arguments.length; i++){
obj[arguments[i]] = this[i];
}
// if you do this, you pass to the dark side `,:,´
this.props = obj;
return obj;
};
Example:
/**
* Example 1: use Array.prototype.props
*/
var array = ['GET', '/users', 'UserController'];
array.list('method', 'route', 'controller');
console.log(array.props.method); // "GET"
console.log(array.props.route); // "/users"
console.log(array.props.controller); // "UserController"
/**
* Example 2: use the return value
*/
var array = ['GET', '/users', 'UserController'];
var props = array.list('method', 'route', 'controller');
console.log(props.method); // "GET"
console.log(props.route); // "/users"
console.log(props.controller); // "UserController"
Check the fiddle for that one
This is my hack at it; as short as I could get it without writing a function to do it. Gotta be careful of the scope of "this" though:
list = ["a","b","c"];
vals = [1,2,3];
for(var i in vals)this[list[i]]=vals[i];
console.log(a,b,c);
Good enough for a laugh. I still assign each variable one at a time:
a=vals[0];
b=vals[1];
c=vals[2];
It's much shorter this way. Besides, if you've got a bunch of variables they should probably be kept in the array, or even better they should be properties of a closure, instead of declaring them all separately.
function list(fn,array){
if(fn.length && array.length){
for(var i=0;i<array.length;i++){
var applyArray = [];
for(var j=0;j<array[i].length;j++){
fn[j] = array[i][j];
applyArray.push(fn[j]);
}
fn.apply(this,applyArray);
}
}
}
Example:
//array array mixture for composure
var arrayMixture = [ ["coffee","sugar","milk"], ["tea","sugar","honey"] ];
//call our function
list(function(treat,addin,addin2){
console.log("I like "+treat+" with " + addin + " and " + addin2);
},arrayMixture);
//output:
//I like coffee with sugar and milk
//I like tea with sugar and honey