I have a html table to show images displayed on my site in a carousel. The images have a position in which they are displayed and this is shown in the table.
One of the features of this table is that it uses the jQuery .sortable() function. If an image is moved to the top of the table, the position of that image is changed to 0 and the subsequent positions are altered.
This is all working fine and I am able to capture the position in a variable.
However, what I now need to do is jQuery POST the data in the table, so I can update the fields in my database with the new positions any any other information that has been updated.
Ideally I need to be able to post an javascript associative array with the ID of the image as the key, and then the image information such as position and location in the sub array.
if it where php I imagine it would look something like this.
Array
(
[45] => Array
(
[name] => Image 45
[location] => img/Banner-45.jpg
[url] => http://www.exampleurl2.com
[position] => 0
)
[56] => Array
(
[name] => Image 56
[location] => img/Image-56.jpg
[url] => http://www.exampleurl2.com
[position] => 1
)
)
which I could loop through and update the values in the table.
All my attempts to create an array with this similar format in javascript/jquery have failed so far.
I have this loop which captures the details in jQuery
$("#banners tbody tr").each(function () {
var id = $('td:first', $(this)).text();
var name = $('td:nth(1)', $(this)).text();
var pos = $('td:nth(2)', $(this)).text();
var url = $('td:nth(3)', $(this)).text();
var loc = $('td:nth(5)', $(this)).text();
});
I understand that this is not the most efficient method of capturing the data from the tables but I am relatively new to jQuery.
Now I need to insert these into some form of associative array with the ID as the key within the loop.
Any pointers in the right direction or a more effective method would be greatly appreciated.
You can use jquery map function to traverse all <tr>'s from the table and create data for rows, then traverse all <td>'s inside the current <tr> for the column data :
var data = [];
var headers = [];
var tb = $('table.table');
var thead = tb.find('thead');
var tbody = tb.find('tbody');
thead.find('th').map(function(i,el){
var $el = $(el);
headers.push($el.attr('class'));
});
tbody.find('tr').map(function(i,el){
var $el = $(el);
var row = {};
$el.find('td').map(function(i,el){
var col = $(el).text();
row[headers[i]] = col;
});
data.push(row);
});
sample jsfiddle : http://jsfiddle.net/v6ZLj/1/
There are no associate arrays in JavaScript so to speak. In JavaScript arrays are one dimensional, you retrieve items based on their index within the array. You are talking about objects or object literals. I've coded an example and example structure for you below.
var saveObj = {}; //Setup a blank object for the data;
$("#banners tbody tr").each(function () {
var id = $('td:first', $(this)).text();
saveObj[id] = {
name : $('td:nth(1)', $(this)).text(),
pos : $('td:nth(2)', $(this)).text(),
url : $('td:nth(3)', $(this)).text(),
loc : $('td:nth(5)', $(this)).text()
};
});
This sets up a blank object literal first called saveObj. This is your blank canvas so to speak. Then within your loop you are grabbing the id as normal. This will be your key within the object and the value for the key will be another object literal which we create dynamically within the loop. using the same keys as your variables (name, pos, url, loc) with their data values in the same way you are grabbing them now. Your structure will be like this
var saveObj = {
"12" : {
name : "YourName",
pos : "YourPos",
url : "YourUrl",
loc : "YourLoc"
},
"16" : {
name : "YourName2",
pos : "YourPos2",
url : "YourUrl2",
loc : "YourLoc2"
}
};
Related
Json Array Object
Through Ajax I will get dynamic data which is not constant or similar data based on query data will change. But I want to display charts so I used chartjs where I need to pass array data. So I tried below code but whenever data changes that code will break.
I cannot paste complete JSON file so after parsing it looks like this
[{"brand":"DUNKIN' DONUTS KEURIG","volume":1.9,"value":571757},{"brand":"MC CAFE","volume":1.1,"value":265096}];
You can use Object.keys and specify the position number to get that value
var valueOne =[];
var valueTwo = [];
jsonData.forEach(function(e){
valueOne.push(e[Object.keys(e)[1]]);
valueTwo.push(e[Object.keys(e)[2]]);
})
It seems like what you're trying to do is conditionally populate an array based the data you are receiving. One solution might be for you to use a variable who's value is based on whether the value or price property exist on the object. For example, in your forEach loop:
const valueOne = [];
jsonData.forEach((e) => {
const val = typeof e.value !== undefined ? e.value : e.average;
valueOne.push(val);
})
In your jsonData.forEach loop you can test existence of element by using something like:
if (e['volume']===undefined) {
valueone.push(e.price);
} else {
valueone.push(e.volume);
}
And similar for valuetwo...
You could create an object with the keys of your first array element, and values corresponding to the arrays you are after:
var data = [{"brand":"DUNKIN' DONUTS KEURIG","volume":1.9,"value":571757},{"brand":"MC CAFE","volume":1.1,"value":265096}];
var splitArrays = Object.keys(data[0]).reduce((o, e) => {
o[e] = data.map(el => el[e]);
return o;
}, {});
// show the whole object
console.log(splitArrays);
// show the individual arrays
console.log("brand");
console.log(splitArrays.brand);
console.log("volume");
console.log(splitArrays.volume);
// etc
I have a Feed List for posting comments in my UI5 xml view
<layout:content>
<m:FeedInput post="onFeedPost" class="sapUiSmallMarginTopBottom"/>
<m:List id="feedList" showSeparators="Inner" items="{path: '/table', sorter: {path: 'DATE', descending: true}}">
<m:FeedListItem sender="{MEMBERID}" timestamp="{DATE}" text="{COMMENT}" convertLinksToAnchorTags="All"/>
</m:List>
</layout:content>
I want to not display duplicate comments that have the same text and date, but keep them in the database. My idea was to in the controller iterate over over the items to do this, but I am not sure what to do with the resulting array
var results = [];
var comments = feed.getItems();
for (var n = 0; n < comments.length - 1; n++) {
var contained = false;
for (var m = n + 1; m < comments.length; m++) {
if (comments[n].getText() === comments[m].getText() &&
comments[n].getDate() === comments[m].getDate()) {
comments.pop(m);
contained = true;
if (!results.includes(comments[n])) {
results.push(comments[n]);
}
}
}
if (!contained && !results.includes(comments[n])) {
results.push(comments[n]);
}
}
// replace list items with results array
I can't figure out how to replace the feed list's items with the new array as there is a getItems function but not a setItems function. It occurs to me there is probably a simpler more idiomatic UI5 way to do this but I haven't found it yet.
First off, the correct way to handle this situation is in the OData service. The service should remove the duplicates before sending the data to the client. If we assume, however, that you can't do this server side, then you have some options.
1.) Do not bind the list items to anything. Instead, use the ODataModel to read the data, then filter out duplicates, create a new list item and add it to the list
Read the data using the ODataModel, then pass the results to a method that will filter and add them items to the list
oModel.read("/EntitySet", {
success: function(oResponse) {
this._addCommentsToList(oResponse.results)
}.bind(this)
})
In your method to handle the results, you'll need to do three things -- create a new FeedListItem, set the binding context of the list item, and then add the list item to the list
var aDistinctComments = //use your logic to filter out duplicates
aDistinctComments.forEach(function(oComment) {
//to set the binding context, you'll need the entity key/path
var sCommentKey = oModel.createKey("/EntitySet", oComment)
//create a new binding context
var oContext = oModel.createBindingContext(sCommentKey)
//create a new FeedListItem
var oItem = new FeedListItem({
sender: "{MemberId}",
...
});
//set the context of the item and add it to the list
oItem.setBindingContext(oContext);
oList.addItem(oItem);
})
2.) Bind the list directly to the OData entity set and then when the list receives the data, iterate over the items and hide the duplicates
<List items="{/EntitySet}" updateFinished="onListUpdateFinished"....>
----- onListUpdateFinished ---
var aItems = oList.getItems();
for (var m = n + 1; m < aItems.length; m++) {
//set a boolean, true if duplicate
var bDuplicate = aItems[m].getText() ==== aItems[n].getText() &&
aItems[m].getDate() === aItems[n].getDate();
//set the visibility of the item to true if it is not a duplicate
aItems[m].setVisible(!bDuplicate)
}
3.) Read the data manually, remove duplicates, and stash it in a JSON model, and bind the table to your JSON model path
oModel.read("/EntitySet", {
success: function(oResponse) {
this._addCommentsToJSONModel(oResponse.results)
}.bind(this)
})
You can stash an array of objects in your JSON model, and then bind the table items to that path
var aDistinctComments = // your logic to get distinct comments
oJSONModel.setProperty("/comments", aDistinctComments)
oList.setModel(oJSONModel);
-----
<List items="{/comments"}....>
4.) Bind your list items to your entity set, iterate over the items, and then remove duplicates from the list. I don't recommend this approach. Removing items manually from lists bound to an entity set can lead to trouble with duplicate IDs.
var oItem = //use your logic to find a duplicate list item
oList.removeItem(oItem)
I recommend first handling this server side in the OData service, and if that's not an option, then use option 1 above. This will give you the desired results and maintain the binding context of your list items. Options 2 and 3 will get you the desired results, but depending on your applicaiton, may make working with the list more difficult.
Here is one approach :
Do not directly bind the list to your oData.
You can create a JSON model which will be the resulting model after removing duplicate items.
Bind the JSON model to the List as such:
var oList = this.getView().byId("feedList");
oList.bindAggregation("items", "pathToJsonArray", template);
(The template is feedlistitem in this case).
I have an extension which loads a docking panel with a text field and a button. The functionality of this button would be to display the DB-ID of the item name given in the text field.
Something like:
Rubber = 2130
where Rubber is the input and 2130(db-id) will be the output
How can I achieve this?
Thanks in advance.
Would suggest using .search() method, which is a supported way:
viewer.search('Rubber', function(dbIds){
// here the dbIds is a list of dbIds, you can handle it
callback(dbIds); // handle the results async
}, function(error){
// handle errors here...
}, ['name'] /* this array indicates the filter: search only on 'Name'*/
)
And look here on how to improve performance on search.
There is no such API available currently, but a workaround can be used in this case. It's shown as the following:
//-- For the element type or element category like "Floor [" or "Floor"
var it = viewer.model.getData().instanceTree;
var strIdx = it.nodeAccess.strings.indexOf( "Floor [" );
// var strIdx = it.nodeAccess.strings.indexOf( "Floor" );
var nameIdx = it.nodeAccess.names.indexOf( strIdx );
for( var key in it.nodeAccess.dbIdToIndex ) {
if( it.nodeAccess.dbIdToIndex[key] === nameIdx ) console.log( key )
}
//-- For element name like "Floor[766598]":
var it = viewer.model.getData().instanceTree;
var eidIndex = it.nodeAccess.nameSuffixes.indexOf( 766598 );
for( let key in it.nodeAccess.dbIdToIndex ) {
if( it.nodeAccess.dbIdToIndex[key] === eidIndex ) console.log( key )
}
P.S. Since this is just a workaround, not the formal solution. You would have to use it at your own risk.
If you want to avoid using the search() method, you could also create your own Object that maps the name to ID's. This is a temporary workaround until Autodesk implements its own method.
var instanceTree = viewer.model.getData().instanceTree; // Get model tree
var allDbIds = Object.keys(instanceTree.nodeAccess.names); //get array of all ID's
var forgeNameMap = {} //Empty array for mapping names
allDbIds.map(function(id) {
forgeNameMap[instanceTree.getNodeName(id)] = id
})
let rubberID = forgeNameMap["Rubber"]
A JSON encoded array is passed from PHP to an HTML document. It is not at all clear how to deconstruct that array into javascript-usable pieces. For example, consider the following HTML:
<div id="options">{"foo":[{"id":1},{"id":3}], "bar":[{"id":2},{"id":4}]}</div>
The only a priori known element of this array is that the key id exists. The indices, I know, can be found with
var data = JSON.parse($("#options").text());
$.each(data, function(index) {
// index will be foo & bar
});
The use case is to use the index and id to add an attribute to elements in a document. I have not yet stumbled upon the technique to return the ids associated with each index. How best can that be done?
Edit - a clarification of the use case - the long story
I want to re-enable some options on a form based on properties of an entity (in a Symfony application). Disabled options cannot be modified, but are also not not persisted - their values are set to null. I've built a service to determine the option elements that are disabled and send those elements to the form document as a JSON object. I'm assuming for now that the specific options are not known until the form is created. In the example above, foo & bar represent possible options, and the ids correspond to the option. For example, a Household entity might have Reason options selected but disabled of "Low wages" (id = 3). This would show up in as ...id="options">{"reasons":[{"id":3}]}<.... I would the use this information to remove the disabled="disabled" attribute from the set of checkboxes for the Reason, id=3 (i.e., id="household_reasons_3") field. I hope this makes sense.
Edit #2, by request - the PHP code creating the object.
The result of getMetatData() appears in the document at #options. From the above edit, the Household entity is $object.
public function getMetaData($object) {
$data = array();
$className = get_class($object);
$metaData = $this->em->getClassMetadata($className);
foreach ($metaData->associationMappings as $field => $mapping) {
if (8 === $mapping['type']) {
$data[$field] = $this->extractOptions($object, $field);
}
}
return json_encode($data);
}
private function extractOptions($object, $field) {
$data = [];
$method = 'get' . ucfirst($field);
$itemName = substr($field, 0, -1);
$getter = 'get' . ucfirst($itemName);
$entity = $object->$method();
foreach ($entity as $item) {
if (method_exists($item, 'getEnabled') && false === $item->getEnabled()) {
$data[] = ['id' => $item->getId()];
}
}
return $data;
}
Long before the infinite monkey limit was reached I stumbled on a method to create the results I was looking for. My thanks go out to all who pushed for clarifications. So, for the object
{"foo":[{"id":1},{"id":3}], "bar":[{"id":2},{"id":4}]}
the script
var data = JSON.parse($("#options").text());
var i = 0
var output = [];
$.each(data, function(index, item) {
$.each(item, function(k, v) {
output[i] = "household_" + index + "_" + v.id;
i++;
});
});
output;
produces this:
["household_foo_1", "household_foo_3", "household_bar_2", "household_bar_4"]
I get the strings I need; I can take it from here.
I need a help for How to get Individual values from HTML page.
i got response from some PAYU payment gateway team in HTML page but i need individual attributes values from tacking Transaction
Below is the response am getting from PAYU Team:
<h1>This is the success url</h1>
<p>Your transaction is completed successfully. Bank response is
mihpayid=403993715514374636&mode=&status=failure&unmappedstatus=userCancelled&key=gtKFFx&txnid=txn1r23fw&amount=100.00&discount=0.00&net_amount_debit=0.00&addedon=2016-04-25+10%3A48%3A29&productinfo=oxygenconcentrator&firstname=test&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test%40gmail.com&phone=8152709721&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=6a9d21bd423d61cd5a7d91098aa1140314e45eaddd8d4b9148399caba8ac61a9476aec130eb369f7d526e741b1b6c47b1ca71bec21fa69aa3deaa13740dbffbc&field1=&field2=&field3=&field4=&field5=&field6=&field7=&field8=&field9=Cancelled+by+user&payment_source=payu&PG_TYPE=&bank_ref_num=&bankcode=&error=&error_Message=
</p>
<script>
PayU.onSuccess("mihpayid=403993715514374636&mode=&status=failure&unmappedstatus=userCancelled&key=gtKFFx&txnid=txn1r23fw&amount=100.00&discount=0.00&net_amount_debit=0.00&addedon=2016-04-25+10%3A48%3A29&productinfo=oxygenconcentrator&firstname=test&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test%40gmail.com&phone=8152709721&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=6a9d21bd423d61cd5a7d91098aa1140314e45eaddd8d4b9148399caba8ac61a9476aec130eb369f7d526e741b1b6c47b1ca71bec21fa69aa3deaa13740dbffbc&field1=&field2=&field3=&field4=&field5=&field6=&field7=&field8=&field9=Cancelled+by+user&payment_source=payu&PG_TYPE=&bank_ref_num=&bankcode=&error=&error_Message=");
</script>
I got this response from below snippet
iabRef.executeScript(
{ code: "document.body.innerHTML" },
function( values ) {
alert(values[0]);
console.log(values[0]);
}
);
so i need individual attribute values like mihpayid ,mode,status and so on......
Assuming that values or values[0] will have :
"mihpayid=403993715514374636&mode=&status=failure&unmappedstat"
Then you could write a function as below:
function extractScript(source){
var pattern = /<script>(\w+)<\/script>/
var matches = source.match(pattern);
return matches[1];
}
function getValue(source, key){
var pattern = key+'=(\\w+)(&)?';
var expr = new RegExp(pattern);
var result = source.match(expr);
return result[1];
}
Then in executeScript:
iabRef.executeScript(
{ code: "document.body.innerHTML" },
function( values ) {
//incase values[0] contains result string
console.log(getValue(values[0], 'mihpayid'))
//or
//incase values[0] contains result string
console.log(getValue(values, 'mihpayid'))
}
);
You can just get the contents of the p tag then perform a split twice
Assuming that p is the only p tag in the page you can get the value by calling
var text= document.getElementByTagName('p').innerHtml;
First split the &
var theArray= text.split('&');//or just & depending on how your text comes out
this will return an array that'll contain something like [status=failure,phone=8152709721]
Then you can loop through this array and create an object
var obj = {} ;
//loop here then do this within the loop
var kv=theArray[i].split('=');
obj[kv[0]] = kv[1];
So you can get your attributes by calling obj.status