inline javascript function call - missing ] after element list - javascript

I have a code:
var data = $('<span onclick="someFunction(' + element + ');">Element information</span>');
where element is a object.
Also, I have a function defined:
someFunction: function(element) {
console.log(element);
.... // some code
}
But when span element tries to call that function, I get error:
SyntaxError: missing ] after element list
someFunction([object Object]);
When I debug it in Firebug, I see
<span onclick="someFunction([object Object]);">
Element information
</span>
How can I normally call that function with concrete element as an argument?

You will not be able to pass the element as it is converted to string in your concatenation. When an object is converted to string it outputs: [Object object]. This is what you are seeing in your debug.
My suggestion:
You may add the element as data to the span like:
$('span).data('element', element);
And in someFunction retrieve it like:
var element = $(this).data('element');
Another option is to bind to click in Javascript at the place where your element is initialized. Like this
function anotherFunction() {
var element = {};
// Initialize element
...
// I have already got the element initialized, now I can bind the click
$('span').click(function() {
// For your debug and validation
console.log(JSON.stringify(element));
});
}

If you try to build some DOM elements with jQuery, you should do this:
// Wrong: $('<span onclick="someFunction(' + element + ');">Element information</span>');
// Right: build up the element step by step
var data = $('<span/>')
.append(
// build up the child <a> element here
$('<a href="#"/>')
.text("Element information")
//.attr('href',"#") Don't really need this
)
.click(
// Here is a real inline function
function(){
someFunction(element);
}
);
Note: .click in jQuery can be used to assign an event handler for the Click event.
In your original code, you are trying to concatenate a string with an object, which will result in applying toString to that object, converting it to a string:
console.log((new Object()).toString()); // [object Object]
console.log("blah" + (new Object())); // blah[object Object]
In your code, it seems that your object is in fact a jQuery object, but it won't make any differences.
So the resulting "code" used to form onclick is invalid:
someFunction([object Object]);
[ and ] is used to construct an Array in JavaScript, like [1, 2] is an Array with two elements. However [object Object] is an invalid JavaScript syntax so you get the error.
Anyway, this is not a correct way to build up DOM element with events, even with jQuery. The above shown the correct way.

You could also try:
var data = $('<span onclick="someFunction(' + JSON.stringify(element) + ');">Element information</span>');
The function:
someFunction: function(element) {
console.log(element);
.... // some code
}
Should return a JSON Object when called.

Related

How to make Jquery's .html() function in Vanilla JavaScript

I've been looking all over the web for how to do this. I am trying to make Jquerys .html() function in vanilla JavaScript. I want to recreate so I can understand it better. I've tried the following but nothing seems to work, I just don't understand what I am doing wrong.
let $ = function(ele) {
if (ele.charAt(0) == '.' || ele.charAt(0) == '#') {
let newEle = cut(ele,0);
if (ele.charAt(0) == '#')
get(newEle);
else
return document.getElementsByClassName(newEle);
} else
return document.getElementById(ele);
}
$.prototype.html = function(html) {
this.innerHTML = html;
}
$('test').html('hey');
$('.hey')[0].html('hey');
function cut(string,num) {
let a = string.slice(0,num);
let b = string.slice(num + 1,string.length);
return a + b;
}
It doesn't work, the console log reports this error:
Uncaught TypeError: $(...).html is not a function
Please help and thanks in advance.
The problem here is what you are returning from the $ function.
Think about this: document.getElementsByClassName and document.getElementById return dom elements and dom elements don't have a .html function. That is why you are getting the error.
What you need is to return is an object, a wrapper, with a .html function, and a closure over the dom elements that you want to modify.
Because you're returning an object from $, you're overriding the default behavior of new $; instead of resulting in the newly-created object, it results in the object you returned out of $.
Instead, you'd want to remember the results of those getElementsByClassName/getElementById calls in an array or Set you store on this (the newly-created object), and then use that array or Set within html (since you want to loop over all matching elements in the case where you're setting the new HTML).
Side note: Since you're using ES2015+ features anyway (let), you might want to use the simpler class syntax instead of a separate function declaration and assigning to $.prototype:
class $ {
constructor(ele) {
// ...
}
html(html) {
// ..
}
}

JavaScript - returning [object Object]

I'm working on a dynamic form that appends groups of input fields to the page based on user input. Because of some additional functionality that needs to be attached to some of these elements, I need to create them as JSON objects. When I test this method with only one input element, the element is appended to the page, no problem. However, when I try to incorporate a second element into the process, I get [object Object] [object Object] appended to the page instead.
Here's the gist...
//THIS IS THE PROBLEM FUNCTION, WHICH IS TRIGGERED BY THE CHANGE FUNCTION BELOW
function generateInput(siteNumber, x){
select = $("<select/>", {
id: 'select'+siteNumber+''+x+'',
name: 'select'+siteNumber+'['+x+']'
}).append(list);
notes = $("<input/>", {
type: 'text',
id: 'notes'+siteNumber+''+x+'',
name: 'notes'+siteNumber+'['+x+']'
});
//IF I RETURN ONE OR THE OTHER, NO PROBLEM
return select + notes;
};
$(document).on("change", ".number_select", function(){
siteNumber = $(this).parent().attr('data-site_number');
numberFound = $(this).val();
for(x = 1; x <= numberFound; x++){
this['inputArray' + siteNumber].push(generateInput(siteNumber, x));
};
$(this).parent().append(this['inputArray' + siteNumber]);
});
I imagine that the problem is with the way that I am returning the elements at the end of generateInput, but I'm not sure of the proper way to handle this. Basically, what I am aiming to get is the select element with the text element sitting next to it.
Thanks very much!
The + operator will call the toString() method of one of the terms if the other is a string.
This is not what you want, what you want instead is to merge the jQuery objects into one
Thus
return select + notes;
Could become (see jquery doc for add):
return select.add(notes);
If you have two objects and add them, they are cast to string using .toString() method, which returns string "[object Object]". It means this is an object, which is instance of Object. If you want to return both object, you can return them for example as array:
return [species, notes];
Then you can pass the result to the .push() method using spread operator:
this['inputArray' + siteNumber].push(...generateInput(siteNumber, x));
However, since the .push() method accepts many arguments, you don't even need to modify this part of code.

Unable to assign an object with sessionStorage

I try to assign an object for further handling with jQuery but it doesn't work.
Here's my code:
$('.var').on('click', function () {
console.log($(this));
sessionStorage.setItem('object', JSON.stringify($(this)));
console.log(JSON.parse(sessionStorage.getItem('object')));
}
Both console logs don't have the same value. Why?
Second example:
$('.var').on('click', function () {
sessionStorage.setItem('object', JSON.stringify($(this)));
var item = JSON.parse(sessionStorage.getItem('object'));
item.addClass('not-work'); //does not work
$(this).addClass('work'); //works
e.preventDefault();
}
What am I doing wrong with sessionStorage().
JSON.stringify strips methods from the stringified object, because valid JSON does not include functions.
Example:
var obj = {
prop: 5,
method: function() {}
};
JSON.stringify(obj);
Result: "{"prop":5}"
#Ori Drori's answer explains the first example.
In the second example, you get the DOM element (jquery wrapped), convert it to a string! and save in the sessionStorage.
And then get this string out of sessionStorage, do JSON.parse in hope of getting the DOM element, but instead you'll get a javascript object which is certainly not an element in the DOM tree (as I believe you're expecting) & hence, calling .addClass on it doesn't work.

Are jQuery created nodes fakes?

I have been fighting with this for hours, and yet it evades my comprehension...
var newLabel = $('<div></div>');
newLabel.appendTo("#f0");
console.log($("#f0").html()); // <br><div></div>
console.log(newLabel); // [object Object]
var div = newLabel.first().get();
console.log(div); // [object HTMLDivElement]
if( div instanceof HTMLDivElement ) { console.log("VALID"); } //
else { console.log("INVALID"); } // INVALID
console.log(div.appendChild); // undefined
We create a div element using jQuery and append it to a DOM element. It goes in, check. Object prints as "HTMLDivElement", check.
HOWEVER. It fails the instanceof. Also, it should have the method appendChild, but its undefined. (Indeed, it throws an error if I try to call it.)
What on earth is happening here? Is the element jQuery created for us, a fake?
get() returns an array, so div is an array in your case (which obviously is not an HTMLDivElement nor does it have a method appendChild). See: http://api.jquery.com/get/#get2. If you use .get(0) (or just [0]) instead, you'll get the actual div element.

Javascript Object Passed Into Method Is A String

I'm building a phonegap project using jQuery mobile.
I have a javascript object that I'm iterating through.
Currently the problem is this:
Below is a method in my model object. It is self recursing, and once called, will recurse through itself to the next level every time a user clicks on a list item generated by the previous level of the object.
What I am battling with is passing the iterated segment, b, into the method itself as an object. For some reason this is returned as a string called [Object], and not the object itself.
This function does work as it's displaying the first level, but something about the "firstString" string I am creating for each child seems to be turning my object into a string named object. I have removed the quotes, placed the object in braces, to no avail.
Would anyone have any idea why this is happening, I'm obviously missing something important regarding passing objects into methods whose call is generated as a string...
My code is below, and line causing the issue is firstString+="model.recurseAppTree('"+b+"');";
recurseAppTree: function(AppTree)
{
$.each(AppTree, function(a,b)
{
var firstString='<li data-role="list-divider" role="heading" data-theme="b">'+b.DisplayValue+'</li>';
if(b.Children != null)
{
$.each(b.Children, function(c,d)
{
firstString+="<li data-theme='c'><a data-transition='slide' id='id-"+d.IdValue+"' href='javascript:void(0);'>"+d.DisplayValue+"</a></li>";
firstString+="<script>";
firstString+="$('#id-"+d.IdValue+"').click(function(){";
firstString+="model.recurseAppTree('"+b+"');";
firstString+="});";
firstString+="</script>";
});
}
$("#selectview").html(firstString);
$("#selectview").listview('refresh', true);
});
},
It's just normal.
You use an object in a string context by the concatenation with +. This tells JS to implicitely cast the object to a string.
b = {}
alert(typeof b) // object
alert(typeof (''+b)) // string
You should use event delegation for your gui
1- Add a (common) class to your '' tags, e.g. unrollLink :
var firstString='<li ...><a class="unrollLink" ...></a></li>"
2- Choose a node in your html, which is a parent of all your "tree" nodes, and will always be present in your html. Delegate the click handler to this node :
$('#selectview').on('click', '.unrollLink', function(){
//this === clicked link - write a function which returns the node you want based on the "id" you set
var myNode = getNode( this.id );
model.recurseAppTree( myNode );
});
3- change your function to produce the adequate html. You don't need to add code for the click events :
recurseAppTree: function(AppTree)
{
$.each(AppTree, function(a,b)
{
var firstString='<li data-role="list-divider" role="heading" data-theme="b">'+b.DisplayValue+'</li>';
if(b.Children != null)
{
$.each(b.Children, function(c,d)
{
// add the class you chose to the clickable items :
firstString+='<li data-theme="c"><a class="unrollLink" data-transition="slide" id="id-'+d.IdValue+'" href="javascript:void(0);">'+d.DisplayValue+'</a></li>';
});
}
$("#selectview").html(firstString);
$("#selectview").listview('refresh', true);
});
},

Categories