Iterating through array and not all items are showing - javascript

See the example here - http://jsfiddle.net/jayblanchard/b2y1tagk/
With the following code I would think that I would get all three elements appended to result, but I don't. I get:
primary - bar
secondary - glorp
var elements = [{
type: 'secondary',
name: 'foo'
}, {
type: 'primary',
name: "bar"
}, {
type: 'secondary',
name: "glorp"
}];
var elementItem;
$(elements).each(function () {
if (this.type == 'primary') {
elementItem = this.type + ' - ' + this.name + '<br />';
} else {
elementItem += this.type + ' - ' + this.name + '<br />';
}
});
$('#results').append(elementItem);
So I'm thinking that I should add the += operator to the first portion of the if condition, but when I do I get this:
undefinedsecondary - foo
primary - bar
secondary - glorp
It doesn't matter what order these are in when they are generated, they just all have to be there when complete. I feel sure that I am missing something obvious, can someone tell me what that is?

elementItem = this.type + ' - ' + this.name + '<br />';
needs to be:
elementItem = this.type + ' - ' + this.name + '<br />' + elementItem;
Otherwise, you overwrite it if primary is not the first item.
Initialize it with var elementItem = ""; so it doesn't typecast elementItem to the string "undefined"
http://jsfiddle.net/b2y1tagk/3/

You are resetting your elementItem variable with = when you reach the primary type. Try appending every item in your list. Initialize the elementItem by var elementItem=''.
var elements = [{
type: 'secondary',
name: 'foo'
}, {
type: 'primary',
name: "bar"
}, {
type: 'secondary',
name: "glorp"
}];
var elementItem = '';
$(elements).each(function () {
if (this.type == 'primary') {
elementItem += this.type + ' - ' + this.name + '<br />';
} else {
elementItem += this.type + ' - ' + this.name + '<br />';
}
});
$('#results').append(elementItem);

Related

Error unexpected token }, Unexpected identifier

When i click click_profile_list i get error
or Uncaught SyntaxError: Unexpected identifier
function click_profile_list(choice, profileid, i_array) {
if(choice==0) {
alert("Profile", i_array.firstname);
}
else {
alert("Profile 2" , i_array.firstname);
}
}
for(var key in msg.db) {
var bypass = {
firstname: msg.db[key].firstname,
lastname: msg.db[key].lastname,
email: msg.db[key].user_email,
};
//html = '<div class="rows" onclick=click_profile_list(' + input + ',' + msg.db[key].id + ',' + bypass + ');>' ;
html = '<div class="rows" onclick="click_profile_list(' + input + ',' + msg.db[key].id + ',' + bypass + ');">' ;
html += msg.db[key].id + ' - ';
html += msg.db[key].firstname + ' - ';
html += msg.db[key].lastname + ' - ';
html += msg.db[key].fallback;
html += '</div>' ;
$('#show_list_window_body').append(html);
}
EDIT: , is removed, onclick="function();" added
$('#show_list_window_body').html(html);
for(var key in msg.db) {
var bypass = {
firstname: msg.db[key].firstname,
lastname: msg.db[key].lastname,
email: msg.db[key].user_email
};
var tmp_id = 'iDontKnow' + msg.db[key].id;
html = '<div class="rows" id="' + tmp_id + '">' ;
html += msg.db[key].id + ' - ';
html += msg.db[key].firstname + ' - ';
html += msg.db[key].lastname;
html += '</div>' ;
$('#show_list_window_body').append(html);
let $elem = $("<div class='rows' id='" + tmp_id + "'>");
$elem.click( () => click_profile_list(input, msg.db[key].id, bypass) );
}
Remove the extra comma at the end of your object :
var bypass = {
firstname: msg.db[key].firstname,
lastname: msg.db[key].lastname,
email: msg.db[key].user_email, // <-- Remove this comma
};
Then, add double quotes around your onclick function :
html = '<div class="rows" onclick="click_profile_list(' + input + ',' + msg.db[key].id + ',' + bypass + ');">'
Or (much) better, attach a click handler instead of inline javascript :
let $elem = $("<div class='rows'>")
$elem.click( () => click_profile_list(input, msg.db[key].id, bypass) )
let $clickme = $("<div>Click me!</div>")
$clickme.click(() => alert("it works!"))
$("#main").append($clickme)
#main * {
font-size: x-large;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main"></div>
Here's a proper jQuery solution:
const msg = {};
msg.db = {
alice: {
firstname: "Alice",
lastname: "Bob",
user_email: "alice#bob.com",
id: 1,
fallback: "fallback"
},
charlie: {
firstname: "Charlie",
lastname: "Delta",
user_email: "charlie#delta.com",
id: 2,
fallback: "fallback2"
}
};
function click_profile_list(e) {
$el = $(e.target);
var choice = 0; // get from whatever sets this
var user = msg.db[$el.data("key")];
if (choice == 0) {
alert(user.firstname);
}
}
var input = 0;
for (var key in msg.db) {
var user = msg.db[key];
$user = $("<div>").addClass("rows").data("key", key);
$user.text([user.id, user.firstname, user.lastname, user.fallback].join(" - "));
$('#show_list_window_body').append($user);
}
$('#show_list_window_body').on("click", ".rows", click_profile_list);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="show_list_window_body"></div>
The list doesn't get awkward inline onclick code that tries to pass an object; instead each list item gets a data-key attribute referencing the database key. When clicked, the key is read back; this is used to grab the relevant data from the db.
You have two syntactical mistakes. One in your JavaScript and one in the HTML markup you produce.
JS
var bypass = {
firstname: msg.db[key].firstname,
lastname: msg.db[key].lastname,
email: msg.db[key].user_email, // <--- here is your issue, you should not use a comma after the last object element
};
HTML
html = '<div class="rows" onclick=click_profile_list(' + input + ',' + msg.db[key].id + ',' + bypass + ');>' ;
You must wrap the value of the attribute onclick with single or double quotes. In your code, just wrap it with double quotes onclick="...;"
Look #Jeremy Thille's answer for a better way to do this.

Concatenation javascript error -probably simple to fix

I'm trying to do the next thing:
getChatListMessageString: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
var rowClass = this.DOMbufferRowClass,
userClass = this.getRoleClass(userRole),
colon = ': ';
if(messageText.indexOf('/action') === 0 || messageText.indexOf('/me') === 0 || messageText.indexOf('/privaction') === 0) {
userClass += ' action';
colon = ' ';
}
if (messageText.indexOf('/privmsg') === 0 || messageText.indexOf('/privmsgto') === 0 || messageText.indexOf('/privaction') === 0) {
rowClass += ' private';
}
var dateTime = this.settings['dateFormat'] ? '<span class="dateTime">'
+ this.formatDate(this.settings['dateFormat'], dateObject) + '</span> ' : '';
return '<div id="'
+ this.getMessageDocumentID(messageID)
+ '" class="'
+ rowClass
+ '">'
+ this.getDeletionLink(messageID, userID, userRole, channelID)
+ dateTime
//start of the code i added
+ '<a href="http://hostname.x/report_chat.php?usernameR='
+ userName
+ '/&useridR='
+ userID
+ '">'
+ '<img src="img/excl.png"></img></a>'
// end of the code i added
+ '<a href="http://www.hostname.x/'
+ userID
+ '" target="_blank"'
+ this.getChatListUserNameTitle(userID, userName, userRole, ip)
+ ' dir="'
+ this.baseDirection
+ '" onclick="ajaxChat.insertText(this.firstChild.nodeValue);">'
+ userName
+ '</a>'
+ colon
+ this.replaceText(messageText)
+ '</div>';
},
If I remove the portion that I added , the page works just fine. When I add it back , I get an Aw Snap error(cache reloaded -> incognito mode )
I'm pretty new with javascript so I can't really tell what I did wrong.
Thank you!
EDIT: THE AW SNAP ERROR comes from the <img> tag for whatever reason.
//Here a simple test
var Obj = (function(){
return{
DOMbufferRowClass : 'DOMbufferRowClass',
getRoleClass : function()
{
return 'roleClass';
},
settings : '',
getMessageDocumentID : function(){
return '123';
},
getDeletionLink : function(messageID, userID, userRole, channelID)
{
return 'DeletiongLink'
},
replaceText : function()
{
},
getChatListMessageString : function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
var rowClass = this.DOMbufferRowClass,
userClass = this.getRoleClass(userRole),
colon = ': ';
if(messageText.indexOf('/action') === 0 || messageText.indexOf('/me') === 0 || messageText.indexOf('/privaction') === 0) {
userClass += ' action';
colon = ' ';
}
if (messageText.indexOf('/privmsg') === 0 || messageText.indexOf('/privmsgto') === 0 || messageText.indexOf('/privaction') === 0) {
rowClass += ' private';
}
var dateTime = this.settings['dateFormat'] ? '<span class="dateTime">'
+ this.formatDate(this.settings['dateFormat'], dateObject) + '</span> ' : '';
return `<div id="${this.getMessageDocumentID(messageID)}" class="${rowClass}">
${this.getDeletionLink(messageID, userID, userRole, channelID)} ${dateTime}
<a href="http://hostname.x/report_chat.php?usernameR='${userName}/&useridR=${userID}">
<img src="img/excl.png"/></a><a href="http://www.hostname.x/${userID} target="_blank"
this.getChatListUserNameTitle(userID, userName, userRole, ip) dir="{this.baseDirection}
onclick="ajaxChat.insertText(this.firstChild.nodeValue);">${userName}</a>${colon}${this.replaceText(messageText)}</div>`;
}
};
})();
console.log(Obj.getChatListMessageString("05102017", '1234',"admin", '456', 'Test','11', '127.0.0.1'));
I would simplify your code with template literals and avoiding all the concatenation mess.
getChatListMessageString : function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
var rowClass = this.DOMbufferRowClass,
userClass = this.getRoleClass(userRole),
colon = ': ';
if(messageText.indexOf('/action') === 0 || messageText.indexOf('/me') === 0 || messageText.indexOf('/privaction') === 0) {
userClass += ' action';
colon = ' ';
}
if (messageText.indexOf('/privmsg') === 0 || messageText.indexOf('/privmsgto') === 0 || messageText.indexOf('/privaction') === 0) {
rowClass += ' private';
}
var dateTime = this.settings['dateFormat'] ? '<span class="dateTime">'
+ this.formatDate(this.settings['dateFormat'], dateObject) + '</span> ' : '';
return `<div id="${this.getMessageDocumentID(messageID)}" class="${rowClass}">
${this.getDeletionLink(messageID, userID, userRole, channelID)} ${dateTime}
<a href="http://hostname.x/report_chat.php?usernameR='${userName}/&useridR=${userID}">
<img src="img/excl.png"/></a><a href="http://www.hostname.x/${userID} target="_blank"
this.getChatListUserNameTitle(userID, userName, userRole, ip) dir="{this.baseDirection}
onclick="ajaxChat.insertText(this.firstChild.nodeValue);">${userName}</a>${colon}${this.replaceText(messageText)}</div>`;
}
Ouch! The best approach is not to build your HTML elements in this manner in the first place and use the DOM to construct and inject them into your document.
This makes the code MUCH easier to read and modify and removes the concatenation issue entirely.
Now, if you have errors, you can focus on the values your are assigning to the properties and not the syntax of the HTML.
// Create the div element in memeory
var div = document.createElement("div");
// Configure the attributes of that div
div.id = this.getMessageDocumentID(messageID);
div.classList.add(rowClass);
// Now, begin populating the div
div.innerHTML = this.getDeletionLink(messageID, userID, userRole, channelID) + dateTime;
// A new element belongs inside the div. Repeat the process:
var a1 = document.createElement(a);
a1.href = "http://hostname.x/report_chat.php?usernameR=" + userName + "/&useridR=" + userID;
var img = document.createElement("img");
img.src = "img/excl.png";
// Place the image into the anchor
a1.appendChild(img);
// Place the anchor into the div
div.appendChild(a1);
// Another anchor is now needed
var a2 = document.createElement(a);
a2.href = "http://www.hostname.x/" + userID;
a2.target = "_blank";
// It is unclear what the following line is based on the fact that whatever it returns, you have that
// being inserted where attributes go. It is commented here for that reason.
//this.getChatListUserNameTitle(userID, userName, userRole, ip) + " dir='" + this.baseDirection;
// Set up event handler for the anchor
a2.addEventListener("click", function(){
ajaxChat.insertText(this.firstChild.nodeValue);
});
// Populate the anchor
a2.innerHTML = userName;
// Insert this anchor into the div
div.appendChild(a2);
// Insert the final contents into the div
div.innerHTML += colon + this.replaceText(messageText);
// Return the final construct
return div;

How to set an element property from within a callback function

I have this "service" element where I would like to set the property "bookmarks" with the function getTree, which takes a callback function.
My problem is that I don't see how I could reach the property from within the callback function where "this" is undefined!!
<dom-module id="...">
<style>
:host {
display: none;
}
</style>
<script>
Polymer({
is: "bookmark-service",
properties: {
bookmarks: {
type: Array,
value: function() { return [{title:"init"}]; }
}
},
created: function() {
chrome.bookmarks.getTree(
function(bookmarkTreeNodes) {
this.bookmarks = bookmarkTreeNodes;
console.log(this.localName + '#' + this.id + ' in getTree.');
} );
console.log(this.localName + '#' + this.id + ' was created');
console.log("Bookmark: " + this.bookmarks[0].title + '.');
},
...
You could save a reference for this before calling getTree:
var that = this;
chrome.bookmarks.getTree(function(bookmarkTreeNodes) {
that.bookmarks = bookmarkTreeNodes;
console.log(that.localName + '#' + that.id + ' in getTree.');
});
You can use bind to set this in your callback function.
chrome.bookmarks.getTree(
function(bookmarkTreeNodes) {
this.bookmarks = bookmarkTreeNodes;
console.log(this.localName + '#' + this.id + ' in getTree.');
}.bind(this) );
That was a part of my problem and I prefer not to use "bind" which I fear may have side effects with this and looks more complicated.
But another problem, was the asynchronous nature of getTree. For this, I had to add an observer.
Also, the properties doesn't even exist in "created" phase, I had to use "ready"
So here is the almost final result:
properties: {
bookmarks: {
type: Array,
value: function() { return [{title:"init"}]; },
observer: 'bookready'
}
},
bookready: function(){
console.log("Bookmark ready: " + this.bookmarks[0].title + '.');
},
ready: function() {
var self = this;
chrome.bookmarks.getTree(
function(bookmarkTreeNodes) {
self.bookmarks = bookmarkTreeNodes[0].children;
}
);
console.log(this.localName + '#' + this.id + ' was readied');
console.log("Bookmark: " + this.bookmarks[0].title + '.');
},

How to use plotOptions in Highcharts?

The problem I have is that all the json we pass over come from python, and we can't send over javascript in such things. For instance', I need to include the tech from this question but obviously in the plotOptions. I'm just not sure how to do things like reference series, etc. So an example with the above series would be great. I tried the following but it didn't work since this is not what I expected it to be.
options.plotOptions = options.plotOptions || {};
options.plotOptions.series = options.plotOptions.series || {};
options.plotOptions.series.point =
options.plotOptions.series.point || {};
options.plotOptions.series.point.events =
options.plotOptions.series.point.events || {};
options.plotOptions.tooltip = {formatter: function() {
var text = '';
if(this.series.name == 'MSFT') {
text = this.x + ': ' + this.series.name +
'<br> $' + Highcharts.numberFormat(this.y, 0);
} else {
text = 'In ' + this.x + ' the median value was' + this.median +
'and the total $' + Highcharts.numberFormat(this.y, 0);
}
return text;
}
options.plotOptions.series.point.events.click = function() {
if (this.options.url){
window.open(this.options.url);
}
}

Traversing within javascript object in for loop

I want to refer to an object within the object itself. The following is not right, i know. But what is the right way?
And when googling for such problems, what would be the right keywords to search for?
for (var key in eName) {
var obj = eName[key];
eName[key] = {
type: 'id',
name: obj.substr(1),
html: this.type + '="' + this.name +'"' //<--- here
}
}
Try using the JS equivalent for class instead:
for (var key in eName) {
var obj = eName[key];
eName[key] = new CustomElement(obj);
}
...
function CustomElement(strData) {
this.type = "id";
this.name = strData.substr(1);
this.html = this.type + '="' + this.name +'"';
}
The this keyword for Javascript might help you understand what this really means. You might have to pass it in as an object to the function.
Try this:
for (var key in eName) {
var obj = eName[key];
eName[key] = {
type: 'id',
name: obj.substr(1),
html: '' //<--- here
}
eName[key].html = eName[key].type + '="' + eName[key].name +'"'
}
for (var key in eName) {
var obj = eName[key];
eName[key] = {
type: 'id',
name: obj.substr(1),
html: function() { return this.type + '="' + this.name +'"' }
}
}
Then you would use eName[key].html()

Categories