I'm currently working on a ckeditor plugin, the selectbox gets its data from a DB and I can only get the first character to appear in the selectbox.
get_pages.php
$query = selectQuery('
SELECT title, pageID
FROM `page_info`
WHERE partnerID =?',array($partnerId));
$test = '';
foreach ($query as $key => $value) {
$test .= $value['title'].",";
}
Plugin.js
var pages = $.post(
"/action/ac_select_pages.php",
{ pid: "1" },
function(data) {
return (data);
}
);
pages = pages.responseText.split(',');
my variable:
pages: Array[31]
0: "Home"
1: "Control Panel"
2: "24/7 Support"
3: "Script / Databases"
4: "Last Announcment"
5: "E-mail: No Limit"
6: "Webmail & Push Mail"
and so on..
what I do to make my selectbox:
{
type : 'select',
id : 'moreinfo',
label : 'Meerinfo Link',
style : 'width:300px;',
items : pages ,
setup : function( element )
{
this.setValue( element.getAttribute( "moreinfo" ) );
},
commit : function( element )
{
var id = this.getValue();
// If the field is non-empty, use its value to set the element's id attribute.
if ( id )
element.setAttribute( 'moreinfo', id );
// If on editing the value was removed by the user, the id attribute needs to be removed.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dom.element.html#removeAttribute
else if ( !this.insertMode )
element.removeAttribute( 'moreinfo' );
}
}
As you can see I simply put the array in the items , but it shows only the first character
So what am I doing wrong?
So, to summarize...
split() Splits a String object into an array of strings by separating the string into substrings.
So, presumably your pages.responseText looks like this:
Home,Control Panel,24/7 Support,Script / Databases,Last Announcment,E-mail: No Limit,Webmail & Push Mail
Which means that after doing pages = pages.responseText.split(',');, pages looks like this (an array):
["Home", "Control Panel", "24/7 Support", "Script / Databases", "Last Announcment", "E-mail: No Limit", "Webmail & Push Mail"]
According to your previous comment, this works:
var pages = [{0: 'Home', 1: 'Control Panel', ...}];
As you can see (an array with multiple values):
["Home", "Control Panel", ...]
is not the same as (an array with one object with several properties):
[{0: 'Home', 1: 'Control Panel', ...}]
If all of this is still true, something like this should work:
var pagesObject = {};
for (var i=0, max=pages.length; i<max; i += 1) {
pagesObject[i] = pages[i];
}
var correctPages = [ pagesObject ];
Demo here: http://jsbin.com/ikazes/1/edit
Based on the for loop of Ayman Sadadi I got it finally right:)
// page1, 1,00,page2, 12,00,page3, 23 \\
pages = pages.responseText.split(',00,');
// ["page1, 1","page2, 12","page3, 23"] \\
var a = [];
a[0] = '';
for (var b = 0; b < pages.length; b++) {
var c = pages[b].split(', ');
var pageName = c[0];
var pageId = c[1];
a[b] = [ pageName, c ];
};
a is now:
a: Array[31]
0: Array[2]
0: "Home"
1: Array[2]
0: "Home"
1: "1"
length: 2
__proto__: Array[0]
1: Array[2]
0: "Control Panel"
1: Array[2]
0: "Control Panel"
1: "152"
length: 2
__proto__: Array[0]
this is the same as the required [['Home']['Control Panel']].
If I use that as my items it works correctly.
previous conversation:
try to put local data in the select. var pages = [{0: 'Home', 1: 'Control Panel', ...}];. ...
I tryed that :) and it works, but as the pages are constantly added and deleted i can't hard code the pages in the select
Ayman Safadi: According to your previous comment, this works...
Only if I hard code it like [['home']['Control Panel']] it works. [{0: 'Home', 1: 'Control Panel', ...}] did not work. I'm sorry to be a little unclear about what I meant.
Thank you for helping me with my problem.
Credits go to Ayman Safadi / pbaris :)
Related
I am working on a chrome plugin that fetches data. But now i have been running into a problem, I have been asked to put together a nested array with all the data I have retrieved but I have no clue on how to pull this off.
What i want to create:
var messagedata [{
time: messageTime,
Date: messageDate,
Text: messageText
{
time: messageTime,
Date: messageDate,
Text: messageText
}
}];
Note that I know how to create the above when I have the variables. That is not the problem. But in this case i do not know how to declare the variables for each message from the array that is generated.
What i need is a nested array for each message that is in the HTML. So the above example displays 2 arrays but it could be 54 for example.
Code i use to generate normal array:
adiv.innerHTML = cleanupDocString;
trs = adiv.querySelectorAll('tr[bgcolor="#FFFFFF"]');
trs.forEach(function(tr) {
var d = [];
tr.querySelectorAll("td")
.forEach(function(td) {
var img = td.querySelector("img"),
src = img && img.attributes.getNamedItem("src").value;
d.push(src || td.textContent);
});
msgs.push(d);
});
The code above puts this out in console (this example has 2 messages inside it, there are also arrays with 54 messages):
0:Array(6)
0:"2017-08-31T00:00:00"
1:"13:22"
2:"MessageType"
3:ā€¯ClientName"
4:"Subject "
5:"messageText"
length:6
proto:Array(0)
1:Array(6)
0:"2017-08-31T00:00:00"
1:"13:21"
2:" MessageType "
3: "ClientName"
4:" Subject "
5:" messageText "
lenth:6
proto:Array(0)
To make the question easier:
I need to know how i can put the data into a variable that i fetch from the array above. I just don't know how to do it so its dynamic.
What i tried:
var messageDate = msgs[0][0];
var messageTime = msgs[0][1];
var messageType = msgs[0][2];
var messageClient = msgs[0][3];
var messageSubject = msgs[0][4];
var messageText = msgs[0][5];
The above code works but only fetches the first message. I need all the messages that are on the page that is provided. I tried using a ID in the first [] but that also didn't give me the desired result.
Thanks for your help and patience in advance.
Output and code has been slightly edited so it hides personal information
i am assuming msgs is arrray of arrays and the order of properties is guaranteed
var mappedArray = msgs.map((msg)=> {
return {
messageDate : msg[0];
messageTime : msg[1];
messageType : msg[2];
messageClient : msg[3];
messageSubject : msg[4];
messageText :msg[5];
}
})
Edit1
you can use arrayconcat
var mergedArray = mappedArray.concat(otherArray);
To transform the multidimensional array to an array of objects with the help of Array.prototype.map and a simple helper dictionary which defines the index => property mapping.
var messages = [
[
"2017-08-31T00:00:00",
"13:22",
"MessageType",
"ClientName",
"Subject",
"messageText",
"unwanted value"
],
[
"2017-08-31T00:00:00",
"13:22",
"MessageType",
"ClientName",
"Subject",
"messageText",
"unwanted value"
],
[
"2017-08-31T00:00:00",
"13:22",
"MessageType",
"ClientName",
"Subject",
"messageText",
"unwanted value"
]
];
var mappingDef = {
0: 'messageDate',
1: 'messageTime',
2: 'messageType',
3: 'messageClient',
4: 'messageSubject',
5: 'messageText'
};
function transformMessages(messages, mappingDef) {
return messages.map(function(message) {
var obj = {};
for(var index in mappingDef) {
if(mappingDef.hasOwnProperty(index)) {
obj[mappingDef[index]] = message[index];
}
}
return obj;
});
}
console.log(transformMessages(messages, mappingDef));
I have this code:
tickets = new Object()
$(this).parents('.request-form').find('.Single').each ->
if $(this).find('.checkBoxParent input').prop('checked')
params = new Object()
params.sarId = $(this).parents('.request-form').find('.sarId').text()
params.comments = $(this).find('.commentBoxParent textarea').val()
params.serviceId = $(this).find('.serviceId').text()
tickets[$(this).parents('.categoryQuestions').find('.form-label').text()] = params
The idea is that tickets will stay empty, but as it looks through the html, it will add items and a list of sub items to it.
for example, it can find a label "classrooms" and the 3 parameters for that part of the form.
Thus I want the object to look like:
tickets[classrooms][{sarId: 1, serviceId: 3, comments: "hi"}]
Then it can find another "classroom" label and I want it to append, such that the object will now look like:
tickets[classrooms][{sarId: 1, serviceId: 3, comments: "hi"}, {sarId: 1, serviceId: 6, comments: "Another comment"}]
How can I make this happen?
switching it to a multidimensional array/object worked like this:
requestForm = $(this).parents('.request-form');
tickets = {}
requestForm.find('.Single').each ->
#alert("this should happen... 4 times")
focus = $(this)
if $(this).find('.checkBoxParent input').prop('checked')
label = $(this).parents('.categoryQuestions').find('.form-label').text()
if (!tickets.hasOwnProperty(label))
tickets[label] = []
tickets[label].push({
sarId: requestForm.find('.sarId').text(),
comments: $(this).find('.commentBoxParent textarea').val(),
serviceId: $(this).find('.serviceId').text()
})
I'm writing a 'personality type' quiz and want to assign values to choices that a user selects as they progress through the quiz. The idea is each response to a question will have a different numeric weight, which I'll tally as someone progresses through and ultimately completes the quiz. At the end, I'll use the tally to present one of a few different results.
At the moment, users are able to progress through the quiz but I can't get the numeric weight to work.
This is my approach in the code below:
- I am using countValue as my tally. It's set at 1 at the top of my JS.
- In each question within the quiz, there's a value titled addition that is assigned a number, like initial view of the quiz has addition: 0
- As the quiz progresses, there's a field for addition.
- At the bottom of the quiz is a function titled display_scenario in which I attempt to add the value of addition to countValue, but it's not working. I can see that it's not working because the console log gives me values of NaN for the values within the function.
So it seems like I'm not turning the addition value into an integer/number. I'm not sure how to do this. I've tried using parseInt() and Number() and had no luck.
The full code is on Codepen - http://codepen.io/msummers40/pen/EKJQmN - but the key JavaScript/jQuery is below. Thanks in advance for any help.
//establishing counter for weighted answer
var countValue = 1;
console.log(countValue);
// var additionInt = 1;
// console.log(additionInt);
// JSON for personality quiz
// Contains the story, paths and variable to weight answers
var story = {
intro: {
prompt: 'Welcome message. Let\'s get started.',
quizImage: '<img id="quizImage" src="https://media.giphy.com/media/vc6gDdl4rHusE/giphy.gif"><br />',
options: [{
name: 'get started',
path: 'get_started',
addition: 0,
}]
},
get_started: {
prompt: 'You need pancakes. What kind will you make: thin or fluffy?',
quizImage: '<img id="quizImage" src="http://www.allgifs.com/wp-content/uploads/2013/09/pancake.gif">',
options: [{
name: 'thin',
path: 'thin',
addition: '2'
}, {
name: 'fluffy (leading to thin temporarily)',
path: 'thin',
addition: '3'
}]
},
//THIN PANCAKE SECTION
thin: {
prompt: 'Yum. What do you do next?',
quizImage: '<img id="quizImage" src="//media.giphy.com/media/2Mp7y2FkcW80M/giphy.gif">',
options: [{
name: 'pop out to get store-bought pancakes',
path: 'result',
addition: '2'
}, {
name: 'use a recipe',
path: 'result',
addition: '1'
}]
},
result: {
prompt: 'That is all I have for this example!',
quizImage: '<img id="quizImage" src="http://www.technologytell.com/entertainment/files/2013/11/Leonardo-DiCaprio-Toast-Fireworks-Gif.gif">',
options: [{
name: 'Reset',
path: 'intro' //RESET
}]
}
};
/* Chosen option is an object with properties {name, path} */
function display_scenario(chosen_option) {
var option_name = chosen_option.name;
var option_path = chosen_option.path;
var additionInt = chosen_option.addition;
additionInt = Number(additionInt);
console.log(additionInt);
countValue = (additionInt + countValue);
console.log(countValue);
var scenario = story[option_path];
You should double check that your additionInt is not undefined before incrementing the countValue (which is what's causing the problem at the intro).
function display_scenario(chosen_option) {
var option_name = chosen_option.name;
var option_path = chosen_option.path;
var additionInt = chosen_option.addition;
// Make sure all is well
if(additionInt){
countValue += additionInt;
}
var scenario = story[option_path];
...
...
}
As a side note, your addition property is already a number so you can remove the line additionInt = Number(additionInt);
1) As the other answer states, your chosen option's addition property starts out undefined, so you can check for this and give it a default value in one line:
// with default value using ||
var additionInt = +chosen_option.addition || 0;
// or with ternary operator
var additionInt = !chosen_option.addition ? 0 : +chosen_option.addition;
Then augment countValue:
countValue += additionInt;
2) The + operator in the first couple of lines above will coerce the option.addition value to a number, but you should be consistent with your addition values one way or the other. You currently have the first as a number and the rest strings.
3) Below the section you duplicated here from the codepen, you have:
jQuery('<p>').html(countValue).appendTo('#countValueHere');
But you do not have an element with that id in your html. I assume you meant #runningTotalHere.
I am building a file management system for the web right now.
But I have some problems with javascript array's.
In the system there is an opportunity to add labels to file's.
In javascript I want to have the ID and the value's of the labels with the fileId in 1 array.(as below).
I also want the FileId and the LabelId not as the index of the array's. Because the FileId and labelId can be a realy high number. And then I have an array full of undefined items.
Here an example of how I would like to have it:
array[FileId][labelId,labelValue]
If you have an solution please help me.
Thanks.
You can form structure like this:
arr = [{FieldId:fid_value, Labels:[{labelId:lid_value, labelValue:label_text}]}]
Basically, an array with objects. Each object contains two fields: field id and labels.
Labels is an array with objects also. Each object has label id and label value property.
Code to create new items might be like this:
arr = array();
fieldObj = {FieldId:fid_value, Labels:[]};
fieldObj.Labels.push({labelId:lid_value, labelValue:label_text});
fieldObj.Labels.push({labelId:lid_value, labelValue:label_text});
fieldObj.Labels.push({labelId:lid_value, labelValue:label_text});
...
arr.push(fieldObj);
I'm not entirely sure what you're asking but array within array is possible...
a = []
a.push('a')
Result:
["a"]
a.push(['hello','world'])
Result:
["a",
Array[2]
0: "hello"
1: "world"
]
It sounds like you want objects instead of arrays:
var obj = {};
obj["fieldName"] = {label: "labelname", labelId: 1234};
Then you can access this data as:
obj["fieldName"].label
You could also use an object
var data = {};
data["item1"] = { "labelId" : "foo1", "labelValue" : "bar1" };
data["item2"] = { "labelId" : "foo2", "labelValue" : "bar2" };
console.log(data.item1.labelId);
There are plenty of ways you can strcture the object, it is normally better to use an object than to remember that index 0 is the id and that index 1 is a value.
Use should use objects as well as arrays:
var root = [{
id: '12345',
metadata: {
label: 'foo',
},
type: 'folder',
name: 'Folder Name',
children: [...]
}
];
Now, you can iterate through the folders and files in your root:
for (var i = 0; i < root.length; i++) {
var item = root[i];
console.log(item.type, item.name, item.id);
}
I have a JavaScript object like this:
[{
name : "soccer",
elems : [
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
},
{
name : "basketball",
elems : [
{name : "Dallas Mavericks"}
]
}]
Now I want to search on this JavaScript object in the browser. The search for "FC" should give me something like this:
[
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
How to do this fast? Are there any JavaScript libs for this?
You might like using jLinq (personal project)
http://hugoware.net:4000/Projects/jLinq
Works like LINQ but for JSON and it allows you to extend it and modify it however you want to. There is already a bunch of prebuilt methods to check values and ranges.
Seeing as though the only helpful answers have been referencing third party libraries - here's your native javascript solution. For anyone that only wants a few lines of code rather than a stack:
The function:
Array.prototype.findValue = function(name, value){
var array = map(this, function(v,i){
var haystack = v[name];
var needle = new RegExp(value);
// check for string in haystack
// return the matched item if true, or null otherwise
return needle.test(haystack) ? v : null;
});
return array;
}
A native .map() function:
map = function(array, mapFunction) {
var newArray = new Array(array.length);
for(var i = 0; i < array.length; i++) {
newArray[i] = mapFunction(array[i]);
}
return newArray;
}
Your object:
(skimmed from your posted abject):
myObject = {
name : "soccer",
elems : [
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
},
{
name : "basketball",
elems : [
{name : "Dallas Mavericks"}
]
}
For usage:
(This will search your myObject.elems array for a 'name' matching 'FC')
var matched = myObject.elems.findValue('name', 'FC');
console.log(matched);
The result - check your console:
[Object, Object, findValue: function]
0: Object
name: "FC Barcelona"
__proto__: Object
1: Object
name: "Liverpool FC"
__proto__: Object
length: 2
__proto__: Array[0]
Try jOrder. http://github.com/danstocker/jorder
It's optimized for fast O(logn) search and sorting on large (thousands of rows) tables in JS.
As opposed to array iteration, which most of the answers here are based on, jOrder uses indexes to filter data. Just to give you an idea, free-text search on a 1000-row table completes about 100 times faster than iteration. The bigger the table, the better ratio you get.
However jOrder can't process the format of your sample data. But if you re-format it like this:
var teams =
[
{ sport : "soccer", team: "FC Barcelona" },
{ sport : "soccer", team: "Liverpool FC" },
{ sport : "basketball", team : "Dallas Mavericks"}
]
You can get the desired results by first setting up a jOrder table:
var table = jOrder(teams)
.index('teams', ['team'], { grouped: true, ordered: true, type: jOrder.text });
And then running a search on it:
var hits = table.where([{ team: 'FC' }], { mode: jOrder.startof });
And you'll get exactly the two rows you needed. That's it.
The straightforward way to do this is simply to iterate over every property of the object and apply a test function to them (in this case, value.contains("FC")).
If you want it to go faster, you'd either need to implement some kind of caching (which could be eagerly populated in the background ahead of any queries), or perhaps precalculate the result of various popular test functions.
You could do this with regular expressions performed against a serialized JSON string:
var jsonString = "[{ name : \"soccer\", elems : [ {name : \"FC Barcelona\"}"
+", {name : \"Liverpool FC\"}]},{name : \"basketball\",elems : ["
+"{name : \"Dallas Mavericks\"} ]}]";
var pattern = /\s*([\w\d_]+)\s*:\s*((\"[^\"]*(your pattern here)[^\"]*\")|(\'[^\']*(your pattern here)[^\']*\'))\s*/g;
var foundItems = [];
var match;
while(match = pattern.exec(jsonString)){
foundItems.push(match[0]);
}
var foundJSON = "[{" + foundItems.join("}, {") + "}]";
var foundArray = eval(foundJSON);
I haven't tested the loop part of this, but the Regex seems to be working well for me with simple tests in firebug.
In regards to AngularJS, you can do this:
var item = "scope-ng-model";
(angular.element('form[name="myForm"]').scope())[item] = newVal;