Add new rows to jqGrid Treegrid model - javascript
We've created a jqGrid TreeGrid that represents a filesystem, where branches are folders and leafs are files. We've implemented functionality within the TreeGrid to create new "files" by using addChildNode which works well enough. However, we also want to add functionality to create new folders. Our script works which creates new folders, but they are not immediately displayed on the TreeGrid unless it or the page is reloaded. However, reloading the TreeGrid will collapse all the folders, which is particularly annoying.
Is there a way to selectively refresh the nodes of the TreeGrid, or to add a new branch in that is functional? I've seen some partial documentation on addJSONData, but using this function completely purges the TreeGrid until refresh. I've also attempted to use addChildNode and change certain properties, and I've tried to add in the row manually using DOM manipulation; however, both of these methods break the node that was inserted.
Edit:
var grid = $("#grid");
grid.jqGrid({
treeGrid: true,
treeGridModel: "adjacency",
ExpandColumn: 'name',
ExpandColClick: true,
url:"",
datatype:"json",
colNames:['id','Name','Authorization','Views','Uri'],
colModel:[ {name:'id', index:'id', hidden:true, key:true},
{name:'name', index:'name', sorttype:"text", width:3, sortable:false},
{name:'auth',index:'auth', sorttype:"text", sortable:false, hidden:true},
{name:'views',index:'views', sorttype:"integer", width:1, sortable:false, align:"center"},
{name:'uri',index:'uri',sorttype:'text',sortable:false,hidden:true}],
jsonReader:{ root:"rows"
,page:"page"
,total:"total"
,records:"records"
,repeatitems:false
,cell:""
,id:"0"
,userdata:""
},
multiselect:false,
autowidth:true,
height:"auto",
sortable:false,
toppager:true,
hidegrid: false,
loadui: 'block',
pager:"#grid_pager",
caption: "Files",
});
A returned JSON request for the new folder looks something like this:
ret = {"error":"","total":1,"page":1,"records":1,"rows":[{"id":"1113","name":"test","uri":"accounting\/test\/","parent":1,"isLeaf":false,"expanded":true,"loaded":true}]}
Which I attempt to add in using:
grid[0].addJSONData(ret);
The initial data that is loaded is sent as JSON:
{"rows":[
{"id":"1","uri":"afolder\/","parent_id":"0","name":"afolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"4","uri":"bfolder\/","parent_id":"0","name":"bfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"7","uri":"cfolder\/","parent_id":"0","name":"cfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"20","uri":"dfolder\/","parent_id":"0","name":"dfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"48","uri":"efolder\/","parent_id":"0","name":"efolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"179","uri":"ffolder\/","parent_id":"0","name":"ffolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"182","uri":"gfolder\/","parent_id":"0","name":"gfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"186","uri":"hfolder\/","parent_id":"0","name":"hfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"201","uri":"ifolder\/","parent_id":"0","name":"ifolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"239","uri":"jfolder\/","parent_id":"0","name":"jfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"253","uri":"kfolder\/","parent_id":"0","name":"kfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"262","uri":"lfolder\/","parent_id":"0","name":"lfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"274","uri":"mfolder\/","parent_id":"0","name":"mfolder","level":0,"parent":"0","isLeaf":"false"}
]}
The demo shows how to use addChildNode method to add tree node. I added in the JSON data which you posted the "loaded":true part because I use in the test no server components and I want to load the treegrid at once.
To show that you should be very careful with ids of the new added row I added two buttons in the demo: "Insert tree node" and "Insert tree node with unique rowid". The first button use the id="1113" from the data which you posted. One click on the button work correct. the second click will insert rows having id duplicates which will be an error. The error you can see different in different web browsers. The second button use $.jgrid.randId() to generate unique rowid. It is probably not an option in your scenario, but it works perfect in case of local tree grid (like in my demo).
Another problem is that you use "parent":"0" in your demo for the root elements. Correct will be "parent":null or "parent":"null" (see the answer). Moreover the property with the name "parent_id" will be ignored. I removed from the demo some settings, so that local sorting can be used in the treegrid.
We solved this problem by extending the functionality of the jqGrid source. First we created a function that could delete all of the child nodes of a particular folder (both folders/branches and files/leaves), so that we could reload them and hence get the latest set of children. This function takes an integer rowid just like delTreeNode().
delChildren : function (rowid) {
return this.each(function () {
var $t = this, rid = $t.p.localReader.id,
left = $t.p.treeReader.left_field,
right = $t.p.treeReader.right_field, myright, width, res, key;
if(!$t.grid || !$t.p.treeGrid) {return;}
var rc = $t.p._index[rowid];
if (rc !== undefined) {
// nested
myright = parseInt($t.p.data[rc][right],10);
width = myright - parseInt($t.p.data[rc][left],10) + 1;
var dr = $($t).jqGrid("getFullTreeNode",$t.p.data[rc]);
if(dr.length>0){
for (var i=0;i<dr.length;i++){
if(dr[i][rid] != rowid)
$($t).jqGrid("delRowData",dr[i][rid]);
}
}
if( $t.p.treeGridModel === "nested") {
// ToDo - update grid data
res = $.jgrid.from($t.p.data)
.greater(left,myright,{stype:'integer'})
.select();
if(res.length) {
for( key in res) {
res[key][left] = parseInt(res[key][left],10) - width ;
}
}
res = $.jgrid.from($t.p.data)
.greater(right,myright,{stype:'integer'})
.select();
if(res.length) {
for( key in res) {
res[key][right] = parseInt(res[key][right],10) - width ;
}
}
}
}
});
},
Then, we created a function to force reloading of a certain node (folder).
reloadNode: function(rc) {
return this.each(function(){
if(!this.grid || !this.p.treeGrid) {return;}
var rid = this.p.localReader.id;
$(this).jqGrid("delChildren", rc[rid]);
var expanded = this.p.treeReader.expanded_field,
parent = this.p.treeReader.parent_id_field,
loaded = this.p.treeReader.loaded,
level = this.p.treeReader.level_field,
lft = this.p.treeReader.left_field,
rgt = this.p.treeReader.right_field;
var id = $.jgrid.getAccessor(rc,this.p.localReader.id);
var rc1 = $("#"+id,this.grid.bDiv)[0];
rc[expanded] = true;
$("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus");
this.p.treeANode = rc1.rowIndex;
this.p.datatype = this.p.treedatatype;
if(this.p.treeGridModel == 'nested') {
$(this).jqGrid("setGridParam",{postData:{nodeid:id,n_left:rc[lft],n_right:rc[rgt],n_level:rc[level]}});
} else {
$(this).jqGrid("setGridParam",{postData:{nodeid:id,parentid:rc[parent],n_level:rc[level]}} );
}
$(this).trigger("reloadGrid");
rc[loaded] = true;
if(this.p.treeGridModel == 'nested') {
$(this).jqGrid("setGridParam",{postData:{nodeid:'',n_left:'',n_right:'',n_level:''}});
} else {
$(this).jqGrid("setGridParam",{postData:{nodeid:'',parentid:'',n_level:''}});
}
});
},
This is the same as expandNode() save for that it does not check if the node was expanded to begin with, and forces it to send an AJAX request for the child elements of that node. This way, we always have the latest children.
Finally, we fixed a small bug in getRowData(), which prevented us from using it to supply the record argument to either expandNode() or our newly created reloadNode(). The issue was that the _id_ field in the JSON return was never created or filled. Adding that in fixed both expandNode() and reloadNode() The following is the changed source. Not ideal, but it works.
getRowData : function( rowid ) {
var res = {}, resall, getall=false, len, j=0;
this.each(function(){
var $t = this,nm,ind;
if(typeof(rowid) == 'undefined') {
getall = true;
resall = [];
len = $t.rows.length;
} else {
ind = $t.rows.namedItem(rowid);
if(!ind) { return res; }
len = 2;
}
while(j<len){
if(getall) { ind = $t.rows[j]; }
if( $(ind).hasClass('jqgrow') ) {
$('td',ind).each( function(i) {
nm = $t.p.colModel[i].name;
if ( nm !== 'cb' && nm !== 'subgrid' && nm !== 'rn') {
if($t.p.treeGrid===true && nm == $t.p.ExpandColumn) {
res[nm] = $.jgrid.htmlDecode($("span:first",this).html());
} else {
if($t.p.colModel[i].key != undefined && $t.p.colModel[i].key == true)
{
try {
res["_" + nm + "_"] = $.unformat(this,{rowId:ind.id, colModel:$t.p.colModel[i]},i);
} catch (e){
res["_" + nm + "_"] = $.jgrid.htmlDecode($(this).html());
}
}
try {
res[nm] = $.unformat(this,{rowId:ind.id, colModel:$t.p.colModel[i]},i);
} catch (e){
res[nm] = $.jgrid.htmlDecode($(this).html());
}
}
}
});
if(getall) { resall.push(res); res={}; }
}
j++;
}
});
return resall ? resall: res;
},
Finally, we pull this all together as follows, with a JSON return object from creating a folder such as
{{"id":"1267", "name":"test15", "uri":"sample1\/test15\/", "parent_id":1, "parent":1, "isLeaf":false}
We call the function like
var parentid = ret.rows[0].parent;
var parent = grid.jqGrid('getRowData', parentid);
grid.jqGrid('reloadNode', parent);
The functions will delete all the child nodes of parent, then send an AJAX request for the new, updated list from the database. I'm going to push this onto the jqGrid Github if possible, since a reload function maybe useful for many people. I've posted it in here in case it isn't approved.
Related
jquery-datatable: incorrect "Showing <range> of <total> entries" message is displayed
I am working on developing an ASP.NET web page where data will be displayed in a jquery Datatable. I am able to display the data but, the issue I am facing is, the information "Showing of entries" is displaying an incorrect value. Fiddler: https://jsfiddle.net/8f63kmeo/9/ HTML: <table id="CustomFilterOnTop" class="display nowrap" width="100%"></table> JS var Report4Component = (function () { function Report4Component() { //contorls this.customFilterOnTopControl = "CustomFilterOnTop"; //table id //data table object this.customFilterOnTopGrid = null; //variables this.result = null; } Report4Component.prototype.ShowGrid = function () { var instance = this; //add footer $('#' + instance.customFilterOnTopControl) .append('<tfoot><tr><th colspan="2" class="total-text">Total</th><th class="total-value"></th></tr></tfoot>'); //create the datatable object instance.customFilterOnTopGrid = $('#' + instance.customFilterOnTopControl).DataTable({ columns: [ { data: "Description", title: "Desc" }, { data: "Status", title: "Status" }, { data: "Count", title: "Count" } ], "paging": true, scrollCollapse: true, "scrollX": true, scrollY: "300px", deferRender: true, scroller: true, dom: '<"top"Bf<"clear">>rt <"bottom"<"Notes">i<"clear">>', buttons: [ { text: 'Load All', action: function (e, dt, node, config) { instance.ShowData(10000); } } ], initComplete: function (settings) { var api = this.api(settings); //now, add a second row in header which will hold controls for filtering. $(api.table().header()).append('<tr role="row" id="FilterRow">' + '<th>Desc</th>' + '<th>Status</th>' + '<th>Count</th>' + '</tr>'); //add input controls for filtering $('#FilterRow th', api.table().header()).each(function () { var title = $('#' + instance.customFilterOnTopControl + ' thead th').eq($(this).index()).text(); $(this).html('<input type="text" onclick="return false" placeholder="Search ' + title + '" class="form-control" />'); }); //todo: refactor this code. this is for displaying the scrollbar below the tfoot instead of tbody //when multiple tables are present, use tablename.find to get the specific class object //this code is not tested with other options $('.dataTables_scrollBody').css({ 'overflow-x': 'hidden', 'border': '0' }); $('.dataTables_scrollFoot').css('overflow', 'auto'); $('.dataTables_scrollFoot').on('scroll', function () { $('.dataTables_scrollBody').scrollLeft($(this).scrollLeft()); }); }, footerCallback: function (tfoot, data, start, end, display) { var api = this.api(); if (instance.result == null || instance.result.Total == undefined) { return; } $(api.column(2).footer()).html(instance.result.Total); } }); $("div.Notes").html('<div class="alert alert-warning">This is a notes section part of the table dom.</div>'); }; Report4Component.prototype.BindEvents = function () { var instance = this; $("#FilterRow th input").on('keyup change', function () { instance.customFilterOnTopGrid .column($(this).parent().index() + ':visible') .search("^" + $(this).val(), true, false, true) //uses regular expression and checks only for starts with .draw(); }); }; Report4Component.prototype.ShowData = function (limit) { if (limit === void 0) { limit = 100; } var instance = this; instance.customFilterOnTopGrid.clear(); //latest api function instance.result = instance.GetData(limit); instance.customFilterOnTopGrid.rows.add(instance.result.RecordList); instance.customFilterOnTopGrid.draw(); }; Report4Component.prototype.GetData = function (limit) { //structure of the response from controller method var resultObj = {}; resultObj.Total = 0; resultObj.RecordList = []; for (var i = 1; i <= limit; i++) { resultObj.Total += i; var record = {}; record.Description = "This is a test description of record " + i; record.Status = ["A", "B", "C", "D"][Math.floor(Math.random() * 4)] + 'name text ' + i; record.Count = i; resultObj.RecordList.push(record); } return resultObj; }; return Report4Component; }()); $(function () { var report4Component = new Report4Component(); report4Component.ShowGrid(); report4Component.BindEvents(); report4Component.ShowData(); }); function StopPropagation(evt) { if (evt.stopPropagation !== undefined) { evt.stopPropagation(); } else { evt.cancelBubble = true; } } Issue: In the snapshot below, you can see that there are 8 records displayed in the grid but, the count is showing as 1 to 1 of 100. It should be 1 to 8 of 100. Observation: If you resize the page, the counts seems to appear correctly. I don't want to trigger window resize event after every draw. Is there any api available to handle this issue? Expectation: How should I fix this issue? Any suggestion is appreciated.
With some fiddling (heh) with the JSFiddle, I think I've detected the reason for this issue. Summary of Issue: There's some issue whereby the scroller is unaware that the addition of all your rows (using rows.add() instead of initializing the table with the rows) has increased the physical dimensions of the table, and so believes that the initial 0 row table is the current size. This causes it to calculate the number of visible rows incorrectly. draw() won't help because it doesn't recreate the table, just the data, which is correct. The internal dimensions of the table are being given to scroller incorrectly. This may not be fixable with the way you've decided to load data without completely destroying and re-creating the table. Workaround Solution: Since you create and load your table/events before loading the data, somehow the scroller isn't aware that the Y dimension of the table has changed (the table is created with 0 rows, so it thinks there isn't room for more than 1). I'm not really exactly sure what you should do to update the scroller, but I found a workaround solution. If you don't like this workaround, you'll have to examine the possibility of loading your data during the construction of the table. See this fiddle where all I've done is change your HTML table by adding dummy rows: <table id="CustomFilterOnTop" class="display nowrap" width="100%"> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> <tr><td>asdf</td><td>asdf</td><td>asdf</td></tr> </table> This tricks the scroller into believing that there is room for 9 rows, which is how many you'll initially have. You're basically padding the initial table out to your 300px definition. And note that while the table appears to operate the exact same, it will now display the correct paging information. Note that these rows are destroyed when you initialize and load your table, so they're just a filler so that scroller knows to expect more rows. This is very 'hack-y', but hopefully it at least provides some insight into where you should look next, or a temporary workaround. A better solution would be to load the data into the table when it is initialized, which is the standard way of doing it anyways.
How to populate jqGrid filter toolbar and search when the page loads (ASP.net webforms)
Currently, I'm trying to populate the filterToolbar with values taken in from a cookie. If there is cookie data for the filters, I want it to fill the respective textboxes and filter the jqGrid for that data. I'm using ASP.net webforms, so most of my data is initialized already. How/where could I add javascript in order to get this going?
I actually figured out what I was doing. So what I ended up doing as a solution was adding a timeout function in the document.ready function $(document).ready(function () { // some code setTimeout(function () { $('#Jqgrid1')[0].triggerToolbar(); }, 500) //some code } My guess is that I couldn't use the $('#grid')[0].toggleToolbar() to force it because whenever I tried to use it, it was before the whole grid was finish setting up. In the ASP webform, I had several functions registered. <cc1:JQGrid ID="Jqgrid1" runat="server" Height="630" SearchDialogSettings-Draggable="true" EnableViewState="false" AutoWidth="True" > <ClientSideEvents LoadComplete="Jqgrid1_LoadComplete" GridInitialized="initGrid" /> <%-- grid code --%> </cc1:JQGrid> The LoadComplete is executed after the grid is loaded. I tried doing triggering my toolbar there, but didn't work. My guess is, again, it was too early in the grid execution to use the triggerToolbar() function. The same went for the GridInitialized events (even though both events would seem to imply to me that the grid is done doing its thing... but whatever...) The way that I read my cookies in was actually in the GridInitialized event handler. function initGrid() { var myJqGrid = $(this); var valueName = 'GridFilters'; var myCookie = document.cookie; var gridFilterString; var gridFilterArray; var currentFilter; var myCookie_arr; var myDic = {}; if (myCookie.indexOf(valueName) > -1) { // don't even bother if the cookie isn't there... myCookie_arr = myCookie.split("; "); // looking for the cookie I need // read cookies into an array for (var i = 0; i < myCookie_arr.length; i++) { parts = myCookie_arr[i].split("="); first = parts.shift(); // remove cookie name myDic[first.trim()] = parts.join("=").trim(); // handles multiple equality expressions in one cookie } if (myDic.hasOwnProperty("GridFilters")) gridFilterString = myDic["GridFilters"]; if (gridFilterString != "NONE") { myFiltersDic = {} myFiltersArr = gridFilterString.split("&") for (var i = 0; i < myFiltersArr.length; i++) { parts = myFiltersArr[i].split("="); myFiltersDic[parts[0].trim()] = parts[1].trim(); } myParams = $(this).jqGrid("getGridParam", "postData"); var filters = [] for (keys in myFiltersDic) { $('#gs_' + keys.trim()).val(myFiltersDic[keys].trim()); } $.cookie('m_blnSearchIsHidden', "0", "/"); if (!isLoaded) { $(this)[0].toggleToolbar(); } isLoaded = true; } } }
Extract field value present in javascript of a webpage
This is the script present in the html web-page. jQuery(function($) { new Shopify.OptionSelectors('productSelect', { product: { "id":626976579, "title":"changedMacbook Air", "handle":"macbook-air", "description":"\u003cp\u003elightweight \u003c\/p\u003e\n\u003cp\u003eawesome performance\u003c\/p\u003e\n\u003cp\u003ewow display\u003c\/p\u003e\nHello World626976579[\"78000.00\"] [\"78000.00\"]\\n[\"78000.00\"] [\"78000.00\"]\u003cbr\u003e[\"78000.00\"]\u003cbr\u003e626976579\u003cbr\u003e626976579\u003cbr\u003e626976579", "published_at":"2015-05-25T02:39:00-04:00", "created_at":"2015-05-25T02:40:44-04:00", "vendor":"Test_Store", "type":"Computers", "tags":[], "price":7800000, "price_min":7800000, "price_max":7800000, "available":true, "price_varies":false, "compare_at_price":null, "compare_at_price_min":0, "compare_at_price_max":0, "compare_at_price_varies":false, "variants":[{"id":1754837635,"title":"Default Title","options":["Default Title"],"option1":"Default Title","option2":null,"option3":null,"price":7800000,"weight":800,"compare_at_price":null,"inventory_quantity":-29,"inventory_management":null,"inventory_policy":"deny","available":true,"sku":"20","requires_shipping":true,"taxable":true,"barcode":"","featured_image":null}],"images":["\/\/cdn.shopify.com\/s\/files\/1\/0876\/1234\/products\/overview_wireless_hero_enhanced.png?v=1432536113"],"featured_image":"\/\/cdn.shopify.com\/s\/files\/1\/0876\/1234\/products\/overview_wireless_hero_enhanced.png?v=1432536113","options":["Title"],"content":"\u003cp\u003elightweight \u003c\/p\u003e\n\u003cp\u003eawesome performance\u003c\/p\u003e\n\u003cp\u003ewow display\u003c\/p\u003e\nHello World626976579[\"78000.00\"] [\"78000.00\"]\\n[\"78000.00\"] [\"78000.00\"]\u003cbr\u003e[\"78000.00\"]\u003cbr\u003e626976579\u003cbr\u003e626976579\u003cbr\u003e626976579"}, onVariantSelected: selectCallback, enableHistoryState: true }); How the value of "title" field be accessed, which here it is "changedMacbook Air" via my own JavaScript? Thanks in advance.
I don't know if it will work but try var myProduct = new Shopify.OptionSelectors('productSelect', { .... }) then try console.log(myProduct) or you can try this: $(document).ready(function(e){ console.log(document.title); })
I think you might have to pass it through the callback. $('#productSelect').on('change', function(e) { var t = e.target || e.srcElement, title = t.title.value; selectCallback(title); break; } } }); //If you want to trigger it right away for some reason, just use this... $("#productSelect").change(); Look for the code for option_selection.js in your products template or somewhere in your Snippets, Assets, or Templates. See this fiddle for an example of what the code looks like. option_selection.js You might also want to check this link, it's setting up an onchange event on the product variants. I'm not sure what your ultimate goal is but I see you are working with product options and variants so it might be helpful. You can modify option_selection.js if you need to, but more than likely you will just need some jquery in the document.ready. Here is an example from option_selection.js that builds the names of each selector. Though you probably don't need to modify this, see link above. Shopify.OptionSelectors.prototype.buildSelectors = function() { for (var t = 0; t < this.product.optionNames().length; t++) { var e = new Shopify.SingleOptionSelector(this, t, this.product.optionNames()[t], this.product.optionValues(t)); e.element.disabled = !1, this.selectors.push(e) } var o = this.selectorDivClass, i = this.product.optionNames(), r = Shopify.map(this.selectors, function(t) { var e = document.createElement("div"); if (e.setAttribute("class", o), i.length > 1) { var r = document.createElement("label"); r.htmlFor = t.element.id, r.innerHTML = t.name, e.appendChild(r) } return e.appendChild(t.element), e }); return r },
jQuery appending to a dynamically created div
Trying to add a save/load feature using JSON to a diagram that uses jsPlumb. The save feature works like a charm however the load feature is not able to replicate full initial saved state. That is, the problem occurs when jQuery is trying to append to a freshly/dynamically created div. The jsfiddle has the following functionality: I can add projects which are div containers. Inside these I can add tasks by clicking on the green projects. http://jsfiddle.net/9yej6/1/ My saving code plugins everything into an array which then becomes a string (using JSON). $('#saveall').click(function(e) { // Saving all of the projects' parameters var projects = [] $(".project").each(function (idx, elem) { var $elem = $(elem); projects.push({ blockId: $elem.attr('id'), positionX: parseInt($elem.css("left"), 10), positionY: parseInt($elem.css("top"), 10) }); }); // Saving all of the tasks' parameters var tasks = [] $(".task").each(function (idx, elem) { var $elem = $(elem); tasks.push({ blockId: $elem.attr('id'), parentId: $elem.parent().attr('id') }); }); // Convert into string and copy to textarea var flowChart = {}; flowChart.projects = projects; flowChart.tasks = tasks; var flowChartJson = JSON.stringify(flowChart); $('#jsonOutput').val(flowChartJson); }); The load code does the same in reverse. $('#loadall').click(function(e) { // Delete everything from the container $('#container').text(""); // Convert textarea string into JSON object var flowChartJson = $('#jsonOutput').val(); var flowChart = JSON.parse(flowChartJson); // Load all projects var projects = flowChart.projects; $.each(projects, function( index, elem ) { addProject(elem.blockId); repositionElement(elem.blockId, elem.positionX, elem.positionY) }); // Try to load all tasks var tasks = flowChart.tasks; $.each(tasks, function( index, elem ) { //Problem occurs here, I am unable to reference the created project $(elem.parentId).text('This is a test'); addTask(elem.parentId, 0); }); }); Basically, what's not working is the $(parentId).append(newState); line 75 in the jsFiddle, I can't seem to reference that div because it was just created using jquery ? edit: More specifically, I make use of these functions to create actual project and task divs function addProject(id) { var newProject = $('<div>').attr('id', id).addClass('project').text(id); $('#container').append(newProject); jsPlumb.draggable(newProject, { containment: 'parent' }); } function addTask(parentId, index) { var newState = $('<div>').attr('id', 'state' + index).addClass('task').text('task ' + index); $(parentId).append(newState); }
It should be: $('#' + parentId).append(newState); To search for an ID in a jQuery selector, you need the # prefix.
What event is triggered when a HTML5 Adobe Extension Panel is collapsed?
I am working on a HTML5 Adobe Extension that needs to load data from LocalStorage into some 's but for the life of me I can't figure out wether the panel is being collapsed or closed or what happens with it. The list items are generated dinamically. I would also need an ideea to save data upon exit so that the list elements inside the UL can be saved and retrieved when PS starts again. So far I noticed that the host i a chrome type browser that supports a lot of stuff, including localstorage. However, I've not seen a dead simple tutorial for saving ul items but only for variables and strings. right now I'm unable to save or retrieve the data from localstorage. here is my code so far. $(document).ready(function(){ var task = { "name" : "", "description" : "", "project" : "" }; $('#saveData').css("visibility", "hidden"); $('#btnMarkAsDone').css("visibility","hidden"); var toBeDone = Array(); var wasDone = Array(); $( window ).load(function() { for(var i = 0;i < toBeDone.length;i++){ $('#todo').append('<li class="todo-item">'+toBeDone[i]+'</li>'); } for(var i = 0; i < wasDone.length; i++){ $('#done').append('<li class="completed">'+wasDone[i]+'</li>'); } }); $( window ).width(function() { }); $("#btnAddTask").click(function(){ var oName = task.name; var oProject = task.project; var oDescription = task.description; var taskname = $("#txtTaskName").val(); var taskproject = $("#txtTaskProj").val(); var taskdescription = $("#txtTaskDesc").val(); oName = taskname; oProject = taskproject; oDescription = taskdescription; var input = "<b>Task: </b>"+oName+" | "+"<b>PSD: </b>"+oProject+" | "+"<b>Desc: </b>"+oDescription; $("#todo").append('<li class="todo-item">'+input+'</li>'); }); $("#todo").on('click','li',function(){ $(this).addClass('complete'); $("#done").append(this); }); $("#done").on('click','li',function(){ $(this).remove(); }); $("#saveData").click(function(){ if(localStorage['todo']){ toBeDone = JSON.parse(localStorage['todo']); }if(localStorage['done']){ wasDone = JSON.parse(localStorage['done']); } }); $(function() { $("button").button(); }); });
Fixed the localStorage part: $("#saveData").click(function(){ var toDo = $('#todo').html(); var finished = $('#done').html(); localStorage.setItem('todo',toDo); localStorage.setItem('done',finished); }); $(window).load(function() { $("#todo").html(localStorage.getItem('todo')); $("#done").html(localStorage.getItem('done')); }); Still need to find out what kind of event is fired when a window is collapsed though. I appreciate any help !