We need to see what methods/fields an object has in Javascript.
As the others said, you can use Firebug, and that will sort you out no worries on Firefox. Chrome & Safari both have a built-in developer console which has an almost identical interface to Firebug's console, so your code should be portable across those browsers. For other browsers, there's Firebug Lite.
If Firebug isn't an option for you, then try this simple script:
function dump(obj) {
var out = '';
for (var i in obj) {
out += i + ": " + obj[i] + "\n";
}
alert(out);
// or, if you wanted to avoid alerts...
var pre = document.createElement('pre');
pre.innerHTML = out;
document.body.appendChild(pre)
}
I'd recommend against alerting each individual property: some objects have a LOT of properties and you'll be there all day clicking "OK", "OK", "OK", "O... dammit that was the property I was looking for".
If you are using firefox then the firebug plug-in console is an excellent way of examining objects
console.debug(myObject);
Alternatively you can loop through the properties (including methods) like this:
for (property in object) {
// do what you want with property, object[property].value
}
A lot of modern browsers support the following syntax:
JSON.stringify(myVar);
It can't be stated enough that you can use console.debug(object) for this. This technique will save you literally hundreds of hours a year if you do this for a living :p
To answer the question from the context of the title of this question, here is a function that does something similar to a PHP var_dump. It only dumps one variable per call, but it indicates the data type as well as the value and it iterates through array's and objects [even if they are Arrays of Objects and vice versa]. I'm sure this can be improved on. I'm more of a PHP guy.
/**
* Does a PHP var_dump'ish behavior. It only dumps one variable per call. The
* first parameter is the variable, and the second parameter is an optional
* name. This can be the variable name [makes it easier to distinguish between
* numerious calls to this function], but any string value can be passed.
*
* #param mixed var_value - the variable to be dumped
* #param string var_name - ideally the name of the variable, which will be used
* to label the dump. If this argumment is omitted, then the dump will
* display without a label.
* #param boolean - annonymous third parameter.
* On TRUE publishes the result to the DOM document body.
* On FALSE a string is returned.
* Default is TRUE.
* #returns string|inserts Dom Object in the BODY element.
*/
function my_dump (var_value, var_name)
{
// Check for a third argument and if one exists, capture it's value, else
// default to TRUE. When the third argument is true, this function
// publishes the result to the document body, else, it outputs a string.
// The third argument is intend for use by recursive calls within this
// function, but there is no reason why it couldn't be used in other ways.
var is_publish_to_body = typeof arguments[2] === 'undefined' ? true:arguments[2];
// Check for a fourth argument and if one exists, add three to it and
// use it to indent the out block by that many characters. This argument is
// not intended to be used by any other than the recursive call.
var indent_by = typeof arguments[3] === 'undefined' ? 0:arguments[3]+3;
var do_boolean = function (v)
{
return 'Boolean(1) '+(v?'TRUE':'FALSE');
};
var do_number = function(v)
{
var num_digits = (''+v).length;
return 'Number('+num_digits+') '+v;
};
var do_string = function(v)
{
var num_chars = v.length;
return 'String('+num_chars+') "'+v+'"';
};
var do_object = function(v)
{
if (v === null)
{
return "NULL(0)";
}
var out = '';
var num_elem = 0;
var indent = '';
if (v instanceof Array)
{
num_elem = v.length;
for (var d=0; d<indent_by; ++d)
{
indent += ' ';
}
out = "Array("+num_elem+") \n"+(indent.length === 0?'':'|'+indent+'')+"(";
for (var i=0; i<num_elem; ++i)
{
out += "\n"+(indent.length === 0?'':'|'+indent)+"| ["+i+"] = "+my_dump(v[i],'',false,indent_by);
}
out += "\n"+(indent.length === 0?'':'|'+indent+'')+")";
return out;
}
else if (v instanceof Object)
{
for (var d=0; d<indent_by; ++d)
{
indent += ' ';
}
out = "Object \n"+(indent.length === 0?'':'|'+indent+'')+"(";
for (var p in v)
{
out += "\n"+(indent.length === 0?'':'|'+indent)+"| ["+p+"] = "+my_dump(v[p],'',false,indent_by);
}
out += "\n"+(indent.length === 0?'':'|'+indent+'')+")";
return out;
}
else
{
return 'Unknown Object Type!';
}
};
// Makes it easier, later on, to switch behaviors based on existance or
// absence of a var_name parameter. By converting 'undefined' to 'empty
// string', the length greater than zero test can be applied in all cases.
var_name = typeof var_name === 'undefined' ? '':var_name;
var out = '';
var v_name = '';
switch (typeof var_value)
{
case "boolean":
v_name = var_name.length > 0 ? var_name + ' = ':''; // Turns labeling on if var_name present, else no label
out += v_name + do_boolean(var_value);
break;
case "number":
v_name = var_name.length > 0 ? var_name + ' = ':'';
out += v_name + do_number(var_value);
break;
case "string":
v_name = var_name.length > 0 ? var_name + ' = ':'';
out += v_name + do_string(var_value);
break;
case "object":
v_name = var_name.length > 0 ? var_name + ' => ':'';
out += v_name + do_object(var_value);
break;
case "function":
v_name = var_name.length > 0 ? var_name + ' = ':'';
out += v_name + "Function";
break;
case "undefined":
v_name = var_name.length > 0 ? var_name + ' = ':'';
out += v_name + "Undefined";
break;
default:
out += v_name + ' is unknown type!';
}
// Using indent_by to filter out recursive calls, so this only happens on the
// primary call [i.e. at the end of the algorithm]
if (is_publish_to_body && indent_by === 0)
{
var div_dump = document.getElementById('div_dump');
if (!div_dump)
{
div_dump = document.createElement('div');
div_dump.id = 'div_dump';
var style_dump = document.getElementsByTagName("style")[0];
if (!style_dump)
{
var head = document.getElementsByTagName("head")[0];
style_dump = document.createElement("style");
head.appendChild(style_dump);
}
// Thank you Tim Down [http://stackoverflow.com/users/96100/tim-down]
// for the following addRule function
var addRule;
if (typeof document.styleSheets != "undefined" && document.styleSheets) {
addRule = function(selector, rule) {
var styleSheets = document.styleSheets, styleSheet;
if (styleSheets && styleSheets.length) {
styleSheet = styleSheets[styleSheets.length - 1];
if (styleSheet.addRule) {
styleSheet.addRule(selector, rule)
} else if (typeof styleSheet.cssText == "string") {
styleSheet.cssText = selector + " {" + rule + "}";
} else if (styleSheet.insertRule && styleSheet.cssRules) {
styleSheet.insertRule(selector + " {" + rule + "}", styleSheet.cssRules.length);
}
}
};
} else {
addRule = function(selector, rule, el, doc) {
el.appendChild(doc.createTextNode(selector + " {" + rule + "}"));
};
}
// Ensure the dump text will be visible under all conditions [i.e. always
// black text against a white background].
addRule('#div_dump', 'background-color:white', style_dump, document);
addRule('#div_dump', 'color:black', style_dump, document);
addRule('#div_dump', 'padding:15px', style_dump, document);
style_dump = null;
}
var pre_dump = document.getElementById('pre_dump');
if (!pre_dump)
{
pre_dump = document.createElement('pre');
pre_dump.id = 'pre_dump';
pre_dump.innerHTML = out+"\n";
div_dump.appendChild(pre_dump);
document.body.appendChild(div_dump);
}
else
{
pre_dump.innerHTML += out+"\n";
}
}
else
{
return out;
}
}
You want to see the entire object (all nested levels of objects and variables inside it) in JSON form. JSON stands for JavaScript Object Notation, and printing out a JSON string of your object is a good equivalent of var_dump (to get a string representation of a JavaScript object). Fortunately, JSON is very easy to use in code, and the JSON data format is also pretty human-readable.
Example:
var objectInStringFormat = JSON.stringify(someObject);
alert(objectInStringFormat);
console.dir (toward the bottom of the linked page) in either firebug or the google-chrome web-inspector will output an interactive listing of an object's properties.
See also this Stack-O answer
If you use Firebug, you can use console.log to output an object and get a hyperlinked, explorable item in the console.
A bit of improvement on nickf's function for those that don't know the type of the variable coming in:
function dump(v) {
switch (typeof v) {
case "object":
for (var i in v) {
console.log(i+":"+v[i]);
}
break;
default: //number, string, boolean, null, undefined
console.log(typeof v+":"+v);
break;
}
}
I improved nickf's answer, so it recursively loops through objects:
function var_dump(obj, element)
{
var logMsg = objToString(obj, 0);
if (element) // set innerHTML to logMsg
{
var pre = document.createElement('pre');
pre.innerHTML = logMsg;
element.innerHTML = '';
element.appendChild(pre);
}
else // write logMsg to the console
{
console.log(logMsg);
}
}
function objToString(obj, level)
{
var out = '';
for (var i in obj)
{
for (loop = level; loop > 0; loop--)
{
out += " ";
}
if (obj[i] instanceof Object)
{
out += i + " (Object):\n";
out += objToString(obj[i], level + 1);
}
else
{
out += i + ": " + obj[i] + "\n";
}
}
return out;
}
console.log(OBJECT|ARRAY|STRING|...);
console.info(OBJECT|ARRAY|STRING|...);
console.debug(OBJECT|ARRAY|STRING|...);
console.warn(OBJECT|ARRAY|STRING|...);
console.assert(Condition, 'Message if false');
These Should work correctly On Google Chrome and Mozilla Firefox (if you are running with old version of firefox, so you have to install Firebug plugin)
On Internet Explorer 8 or higher you must do as follow:
Launch "Developer Tools, by clicking on F12 Button
On the Tab List, click on "Script" Tab"
Click on "Console" Button in the right side
For more informations you can visit this URL: https://developer.chrome.com/devtools/docs/console-api
You can simply use the NPM package var_dump
npm install var_dump --save-dev
Usage:
const var_dump = require('var_dump')
var variable = {
'data': {
'users': {
'id': 12,
'friends': [{
'id': 1,
'name': 'John Doe'
}]
}
}
}
// print the variable using var_dump
var_dump(variable)
This will print:
object(1) {
["data"] => object(1) {
["users"] => object(2) {
["id"] => number(12)
["friends"] => array(1) {
[0] => object(2) {
["id"] => number(1)
["name"] => string(8) "John Doe"
}
}
}
}
}
Link: https://www.npmjs.com/package/#smartankur4u/vardump
Thank me later!
If you are looking for PHP function converted in JS, there is this little site: http://phpjs.org.
On there you can get most of the PHP function reliably written in JS. for var_dump try: http://phpjs.org/functions/var_dump/ (make sure to check the top comment, this depends on "echo", which can also be downloaded from the same site)
I used the first answer, but I felt was missing a recursion in it.
The result was this:
function dump(obj) {
var out = '';
for (var i in obj) {
if(typeof obj[i] === 'object'){
dump(obj[i]);
}else{
out += i + ": " + obj[i] + "\n";
}
}
var pre = document.createElement('pre');
pre.innerHTML = out;
document.body.appendChild(pre);
}
Based on previous functions found in this post.
Added recursive mode and indentation.
function dump(v, s) {
s = s || 1;
var t = '';
switch (typeof v) {
case "object":
t += "\n";
for (var i in v) {
t += Array(s).join(" ")+i+": ";
t += dump(v[i], s+3);
}
break;
default: //number, string, boolean, null, undefined
t += v+" ("+typeof v+")\n";
break;
}
return t;
}
Example
var a = {
b: 1,
c: {
d:1,
e:2,
d:3,
c: {
d:1,
e:2,
d:3
}
}
};
var d = dump(a);
console.log(d);
document.getElementById("#dump").innerHTML = "<pre>" + d + "</pre>";
Result
b: 1 (number)
c:
d: 3 (number)
e: 2 (number)
c:
d: 3 (number)
e: 2 (number)
Here is my solution. It replicates the behavior of var_dump well, and allows for nested objects/arrays. Note that it does not support multiple arguments.
function var_dump(variable) {
let out = "";
let type = typeof variable;
if(type == "object") {
var realType;
var length;
if(variable instanceof Array) {
realType = "array";
length = variable.length;
} else {
realType = "object";
length = Object.keys(variable).length;
}
out = `${realType}(${length}) {`;
for (const [key, value] of Object.entries(variable)) {
out += `\n [${key}]=>\n ${var_dump(value).replace(/\n/g, "\n ")}\n`;
}
out += "}";
} else if(type == "string") {
out = `${type}(${type.length}) "${variable}"`;
} else {
out = `${type}(${variable.toString()})`;
}
return out;
}
console.log(var_dump(1.5));
console.log(var_dump("Hello!"));
console.log(var_dump([]));
console.log(var_dump([1,2,3,[1,2]]));
console.log(var_dump({"a":"b"}));
Late to the game, but here's a really handy function that is super simple to use, allows you to pass as many arguments as you like, of any type, and will display the object contents in the browser console window as though you called console.log from JavaScript - but from PHP
Note, you can use tags as well by passing 'TAG-YourTag' and it will be applied until another tag is read, for example, 'TAG-YourNextTag'
/*
* Brief: Print to console.log() from PHP
* Description: Print as many strings,arrays, objects, and other data types to console.log from PHP.
* To use, just call consoleLog($data1, $data2, ... $dataN) and each dataI will be sent to console.log - note that
* you can pass as many data as you want an this will still work.
*
* This is very powerful as it shows the entire contents of objects and arrays that can be read inside of the browser console log.
*
* A tag can be set by passing a string that has the prefix TAG- as one of the arguments. Everytime a string with the TAG- prefix is
* detected, the tag is updated. This allows you to pass a tag that is applied to all data until it reaches another tag, which can then
* be applied to all data after it.
*
* Example:
* consoleLog('TAG-FirstTag',$data,$data2,'TAG-SecTag,$data3);
* Result:
* FirstTag '...data...'
* FirstTag '...data2...'
* SecTag '...data3...'
*/
function consoleLog(){
if(func_num_args() == 0){
return;
}
$tag = '';
for ($i = 0; $i < func_num_args(); $i++) {
$arg = func_get_arg($i);
if(!empty($arg)){
if(is_string($arg)&& strtolower(substr($arg,0,4)) === 'tag-'){
$tag = substr($arg,4);
}else{
$arg = json_encode($arg, JSON_HEX_TAG | JSON_HEX_AMP );
echo "<script>console.log('".$tag." ".$arg."');</script>";
}
}
}
}
NOTE: func_num_args() and func_num_args() are php functions for reading a dynamic number of input args, and allow this function to have infinitely many console.log requests from one function call
The following is my favorite var_dump/print_r equivalent in Javascript to PHPs var_dump.
function dump(arr,level) {
var dumped_text = "";
if(!level) level = 0;
//The padding given at the beginning of the line.
var level_padding = "";
for(var j=0;j<level+1;j++) level_padding += " ";
if(typeof(arr) == 'object') { //Array/Hashes/Objects
for(var item in arr) {
var value = arr[item];
if(typeof(value) == 'object') { //If it is an array,
dumped_text += level_padding + "'" + item + "' ...\n";
dumped_text += dump(value,level+1);
} else {
dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
}
}
} else { //Stings/Chars/Numbers etc.
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
}
return dumped_text;
}
I just want to add something relatively important about console.log
If you are debugging large variables (like large audio or video data buffers). When you print console.log(big_variable) the console will only display a small part of it. (it seems a bit obvious).
If however, the variable is in a loop and this variable is constantly changing, if you ever "copy it into your clipboard" , what the browser will do is to ask for the variable AGAIN (and that may have changed by the time you are copying).
I'll tell you my story. I am programming an app that deals with big chunks of audio data, with Float32arrays of size 8192. If the buffer had certain characteristics, I would print the variable using console.log() and then grab that variable to test and toy around and play with it (and even use it for mocks so I can do automated testing)
However, the results would never hold. The mic would capture the audio data, store it on a this.audioBuffer variable and the whole thing would work, but when I copied that exact variable from console.log so I could us it as a mock to run some automated tests, the behaviour would change dramatically.
It took me a while to figure this out, Apparently, whenever i "copied" or "set the variable as global" in the debugger, rather than copying the variables displayed in console.log, the jsvm would ask for the this.audioBuffer again. and since the variable was being used inside of a loop, the microphone would still record and I would get a completely different sound array than what I was listening to and thought the audio buffer was in the first place.
If you are dealing with large complex data structures like audio or video files, image files... and these are subject to change when you are reading the values in the chrome /firefox / edge console, make sure you don't console.log(variable), but rather console.log(JSON.stringify(variable)). it will save you a ton of time
you can use this for strings and objects/array
function print_r(obj){
return JSON.stringify(obj, null, "\t");
}
Related
So, I am making a trivia game. Here is my PHP code and my Ajax Code. The problem is, the variable $categoryName in my php code keeps returning null no matter what I do. As a result, in my JS code, when I try to fetch the url, I keep getting this error: "Uncaught (in promise) SyntaxError: Unexpected token . in JSON at position 0
at parse ()"
This code is not in a state of completion yet, but this issue is preventing me from moving forward. Any ideas? These are two different files on an AMPPS server
PHP File
/* Step 2: Write a trivia.php code to read the .txt files (from particular category specified by the fetch()) and output as JSON. You can use $_GET[“mode”], scandir and json_encode().
What you need to do is given the category query parameter from the trivia.js, create a random question (e.g. using array_rand()) send it back to the browser.
*/
//handles category names
$triviafiles = "trivia/"; //questions and answers themselves
$files = scandir("trivia/");
$categories = implode('<br>', $files);
echo $categories;
//gets questions
$categoryName = strtolower($_GET["name"]); //always is null. Don't know why
$trivia = glob($triviafiles.$categoryName."/*.txt");
//categoryName still shows up as Null. Hardcoding a name in works, but that obviously defeats the purpose.
foreach($trivia as $question){
$answer = file_get_contents($question);
}
echo(json_encode(array("question" => $question, "answer" => $answer)));
?>
JavaScript File
window.onload = function () {
"use strict";
let showCat = document.getElementById("view-all");
showCat.onclick = fetchCategories;
let show_answer = document.createElement("button");
show_answer.classList.add("controls");
show_answer.innerHTML += "Show Answer";
document.getElementById("question-view").append(show_answer);
// show_answer.onclick =
};
function displayCategories() {
document.getElementById("categories-heading").className = null;
document.getElementById("category-view").className = null;
}
function selectedText(category){
let categories = document.querySelectorAll("li");
for(let i = 0; i<categories.length; i++){
categories[i].classList.remove("selected-category");
}
category.classList.add("selected-category");
category.onclick = showTrivia;
}
function fetchCategories() {
let hrx = new XMLHttpRequest();
hrx.onload = displayCategories;
hrx.open("GET", "trivia.php?mode=category");
hrx.send();
hrx.onreadystatechange=function(){
if(hrx.readyState === 4 && hrx.status === 200) {
let list = hrx.responseText;
list=list.split("<br>");
for (let i = 0; i<list.length; i++){
let category = document.createElement("li");
category.innerHTML += list[i];
document.getElementById("categories").appendChild(category);
}
}
let categories = document.querySelectorAll("li");
for(let i = 0; i<categories.length; i++){
categories[i].classList.remove("selected-category");
categories[i].addEventListener("click",function(){selectedText(categories[i])}, false);
}
}
}
//include this code, based on: https://developers.google.com/web/updates/2015/03/introduction-to-fetch
function checkStatus(response){
if (response.status >= 200 && response.status < 300) {
return response.text();
}else{
return Promise.reject(new Error(response.status + ": " + response.statusText));
}
}
function displayQuestion() {
document.getElementById("question-view").className = null;
document.getElementById("card").className = null;
}
function showTrivia() {
let currentCategory = document.querySelector(".selected-category");
console.log(currentCategory);
let url = "trivia.php?mode=category";
url += "&name=" + currentCategory.innerHTML;
console.log(url);
fetch(url, {method: "GET"})
.then(checkStatus)
.then(JSON.parse) // main issue. Parsing error
.then(displayQuestion);
}
(i can't comment yet, but here's my take:)
as others have explained, you have 2 AJAX calls to trivia.php
in the first one (when user clicks on "view-all") you don't specify name in the GET
in the second one (when user clicks on a specific category) you specify name in the GET
during the first load of trivia.php it's logical that $categoryName is null, because you don't specify it
are you sure you are also checking the second load of trivia.php? because it seems that $categoryName should be filled in that time.
I have this code so far:
function print_r( obj ) {
if((typeof(obj)) == 'object' ) {
var output = [];
for(var x in obj) {
if((typeof(obj[x])) == 'object') {
output.push( print_r(obj[x]) );
} else {
output.push( x + ' => "' + obj[x].toString() + '"' );
}
}
return output.join("\n");
}
return obj;
}
It does some basic recursion, but it's not good at this point.
How can I make this JavaScript function behave as PHP's print_r function?
EDIT: With tab indents if the loop accours on a new object within the parent object.
Install Firebug for your browser do this:
console.log(myvar);
I have a php function which returns JSON in response to a ajax request for delivery charges. Here is the php function:
public function getDeliveryOptions($weight, $postcode)
{
if($weight == 0)
{
return array(array("name" => "Non-Deliverable", "value" => "0.00"));
}
$this->db->where('dmc_lower_boundary <=', $weight);
$this->db->where('dmc_upper_boundary >=', $weight);
if(preg_match("([aA][bB](3[1-8]|4[1-5]|5[1-6])\s?[1-9][a-zA-Z]{2}|[fF][kK](19|20|21)\s?[1-9][a-zA-Z]{2}|[hH][sS][1-9]\s?[1-9][a-zA-Z]{2}|[iI][vV][1-9]{1,2}\s?[1-9][a-zA-Z]{2}|[kK][aA](27|28)\s?[1-9][a-zA-Z]{2}|[kK][wW][1-9]{1,2}?\s?[1-9][a-zA-Z]{2}|[pP][aA][2-8][0-9]\s?[1-9][a-zA-Z]{2}|[pP][hH]([156789]|1[056789]|[2-5][0-9]){1,2}\s?[1-9][a-zA-Z]{2}|[zZ][eE][1-9]\s?[1-9][a-zA-Z]{2})", $postcode))
{
$this->db->where("dm_id = ", 1);
$this->db->or_where("dm_id =", 3);
}
elseif(preg_match("/([bB][tT][1-9]{1,2}\s?[1-9][a-zA-Z]{2}|[iI][mM][1-9]{1,2}\s?[1-9][a-zA-Z]{2}|[tT][rR](21|22|23|24|25)\s?[1-9][a-zA-Z]{2})/", $postcode))
{
$this->db->where("dm_id =", 1);
$this->db->or_where("dm_id =", 4);
}
elseif(preg_match("/([gG][yY][1-9]\s?[1-9][a-zA-Z]{2}|[jJ][eE][1-4]\s?[1-9][a-zA-Z]{2})/", $postcode))
{
$this->db->where("dm_id =", 1);
$this->db->or_where("dm_id =", 5);
}
else
{
$this->db->where("dm_id =", 1);
$this->db->or_where("dm_id =", 2);
}
$this->db->group_by("dm_id");
$query = $this->db->get("delivery_method_option_views");
//print_r($query->result());
//print_r(json_encode($query->result()));
return(json_encode($query->result()));
}
Here is my javascript (using prototype) to send the results to the server and use the response to create radio buttons:
function updateDelivery()
{
if($('deliveryUpdate') == null)
{
return false;
}
// This 'observes' our form submit - sort of like onsubmit
$('deliveryUpdate').observe('submit', function(evt) {
// Stop the actual event from happening
evt.stop();
// This is the url we submit to - change it as needed
var url = '/checkout/updateDelivery';
//This will be the form and div we update
var containerForm = $('deliveryUpdate');
var optionsDisplay = $('deliveryOptions');
// Grab all the info in the form
var form_data = containerForm.serialize();
var form = containerForm.innerHTML;
// Here we make the request
new Ajax.Request(url, {
method: 'post',
parameters: form_data,
onCreate: function() {
form = containerForm.innerHTML;
containerForm.update(form+'<img src="/images/loader.gif" alt="loading..." class="loader" />');
},
onSuccess: function(transport) {
containerForm.update(form);
NVPResponse = transport.responseText;
if(NVPResponse !== '[object Array]')
{
NVPResponse = new Array(NVPResponse);
}
alert(NVPResponse);
options = "";
for(i=0; i<NVPResponse.length; ++i)
{
options += '<label for="delivery">'+NVPResponse[i].dm_name+'</label><input type="radio" name="delivery" value="'+NVPResponse[i].dmc_price+'" />';
}
//optionsDisplay.update(NVPResponse);
optionsDisplay.update(options);
}
});
});
}
If I just update with the JSON results (for postcode ab31 2as), I get the following:
Calculate Delivery Costs[{"dm_id":"1","dm_name":"Royal Mail","dm_admin_name":"Royal Mail","dmc_lower_boundary":"101","dmc_upper_boundary":"250","dmc_price":"3.65"},{"dm_id":"3","dm_name":"Courier","dm_admin_name":"Fed Ex Zone 4","dmc_lower_boundary":"101","dmc_upper_boundary":"250","dmc_price":"4.50"}]
However, if I update with the options var, I get "undefined" where the label text and and radio button values go. This is built in the for loop in the onSuccess function. Any ideas?
Edit
I added the following code in before the for loop because I was trying to use JSON strings as objects instead of objects:
NVPResponse = JSON.parse(NVPResponse);
I am no big expert on prototype, but it seems to me that your NVPResponse is a string, not translated to a javascript object. (see prototype documentation for AJAX (specifically Evaluating a JavaScript response) and JSON).
Also there seem to be some other problems with your code.
In the PHP code:
if($weight == 0)
{
return array(array("name" => "Non-Deliverable", "value" => "0.00"));
}
you return an array without JSONing it, is that intentional?
In addition, there seems to be a logical error:
$this->db->or_where("dm_id =", 3);
Queries for dm_id = 3 regardless of any previous "where" that you set, so that
$this->db->where('dmc_lower_boundary <=', $weight);
$this->db->where('dmc_upper_boundary >=', $weight);
will be disregarded if dm_id = 3 (or any of the other or_where of course).
The solution can be something like this:
$this->db->where_in("dm_id", array(1,3));
edit:
In this case the query you wrote works perfectly well, but you should notice that Codeigniter does not put parentheses around OR arguments in its queries, therefore combining OR and AND in the same query can be buggy.
the way you wrote the code the query will look something like this (which works fine):
SELECT * FROM (`t_name`)
WHERE `dmc_lower_boundary` <= $weight AND `dm_id` = 1 OR `dm_id` = 3
writing the same query in a different order (or sometimes when writing complex queries) can give you a very different result:
SELECT * FROM (`t_name`)
WHERE `dm_id` = 1 OR `dm_id` = 3 AND `dmc_lower_boundary` <= $weight
after a few serious bugs I learned to be careful with "or_where" :)
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.
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