DynaTree Syntax Error in onLazyRead - javascript

I haven't touched Javascript in years. So I am reacquainting myself with it and am basically a newbie again.
I am using Dynatree in a Django application. I can load the first two levels of the tree with the initial call to Django. However, when I add the onLazyRead function I get a syntax error:
SyntaxError: missing ; before statement
The entire script:
<script type="text/javascript">
$(document).ready((function(){
// Initialize the tree in the onload event
$("#prjtree").dynatree({
title: "Projects",
initAjax: {url: "/get_prjtree/",
data: {key: "root", // Optional arguments to append to the url
mode: "all"
}
},
onLazyRead: function(node) {
node.appendAjax({url: "/get_pcttree/",
data: {key: node.data.key, // Optional arguments to append to the url
mode: "all"
}
});
},
onActivate: function(node) {
alert("You activated " + node);
},
}); // end DynaTree
}));
</script>
The error is on the line:
node.appendAjax: {url: "/get_pcttree/",
I even tried rearranging the order of the functions.
If I comment out the entire onLazyRead function, it works as expected.
I just can't see where the problem is. I have compared it to several examples and it seems to be exactly like them. What am I missing?

Maybe typo error in:
node.appendAjax: { , shouldnt it be node.appendAjax({ ?

Related

select2 : cannot read property query of null

I have create javascript like this
$(document).on("select2:open", ".provider_suggestion", function() {
$(this).select2({
minimumInputLength: 2,
ajax: {
url: "../include/suggestion/provider_name.php",
dataType: 'json',
delay: 250,
data: function(params){ return { q: params.term }; },
processResults: function (data, page) { return { results: data }; },
cache: true
}
});
});
and create select html input like this
<select id="c_providers" name="c_providers" class="provider_suggestion" style="width:100%"></select>
and when page loaded, I click the select input.
I open the browser console, its mentioned that
Uncaught TypeError: Cannot read property 'query' of null
I still dont understand about this issue.
You must have already initialized the select2 somewhere previous to your provided code snippet, or I expect the select2:open listener would never fire and cause your problem. When I replicated the situation in a fiddle and peeked at the select2 source, it seemed that select2 was complaining about a dataAdapter being null, which must be a side effect of this double select2() call, or that the .select2() call is inside the listener with an unexpected context... Or something, don't have the time or interest to explore down to the root cause.
Regardless, moving the .select2() call out of the listener (and removing the then empty listener) removed the problem. Based on the limited information available in your question, it does not seem like there is any need at all to use this listener, at least the way you are using it. A simplistic working example is in this JSfiddle, where the only real difference to your original code is the removal of the listener wrapping (and the mocking of AJAX calls). So, try something like
$('#c_providers').select2({
minimumInputLength: 2,
ajax: {
url: "../include/suggestion/provider_name.php",
dataType: 'json',
delay: 250,
data: function(params){ return { q: params.term }; },
processResults: function (data, page) { return { results: data }; },
cache: true
}
});
as the only select2 initialization for this #c_providers element.

Dynamically update syntax highlighting mode rules for the Ace Editor

Totally new to ace editor dev, to dynamically add additional rules to a mode file for syntax highlighting I'm doing an ajax call that sets a global variable that is available inside the mode file to process.
Here is the setup and initial ajax call:
var editor = ace.edit("editor");
$.ajax({
url: "json-mode-rules.php",
dataType: "json"
}).done(function(data) {
window.myModeRules=data; // ("foo","bar","etc")
editor.getSession().setMode("ace/mode/python");
});
The mode file is patched with the following:
// keywords has already been initialised as an array
// e.g. var keywords = ("and|as|assert...etc")
var extraRules=window.codebenderModeLibrary["myModeRules"].join("|");
keywords=(keywords[0]+"|"+ extraRules);
When the page is loaded initallly the ace editor gets all the keywords to syntax highlight. This works great.
The issue is that we have the rules changing when certain events occur and would like the ace editor to refresh its syntax rules.
Doing the ajax call again and calling setMode does nothing - this is due to require js not reloading the file.
I have posted an issue on GitHub without a resolution yet:
https://github.com/ajaxorg/ace/issues/1835
"If you really want to keep global variable, you can wrap everything
in a function, call that function to get updated Mode constructor, and
then call setMode(new Mode)."
I don't know how to do that and any help would be appreciated.
Anyone with techniques on how to dynamically update ace editor syntax highlighting rules?
See https://github.com/ajaxorg/ace/blob/9cbcfb35d3/lib/ace/edit_session.js#L888
setMode caches modes, unless they have options
so you can call
session.setMode({
path: "ace/mode/python",
v: Date.now()
})
to force it to create a new mode.
Another way is to do
var DynHighlightRules = function() {
// add function to change keywords
this.setKeywords = function(kwMap) {
this.keywordRule.onMatch = this.createKeywordMapper(kwMap, "identifier")
}
this.keywordRule = {
regex : "\\w+",
onMatch : function() {return "text"}
}
this.$rules = {
"start" : [
{
token: "string",
start: '"',
end: '"',
next: [{ token : "language.escape", regex : /\\[tn"\\]/}]
},
this.keywordRule
]
};
this.normalizeRules()
};
and then whenever highlight rules change do
// update keywords
editor.session.$mode.$highlightRules.setKeywords({"keyword": "foo|bar|baz"})
// force rehighlight whole document
editor.session.bgTokenizer.start(0)
see http://jsbin.com/ojijeb/445/edit

Calling rejectChanges on a entity with collection of complexTypes doubles the complexTypes in collection

This may be something I am doing wrong, but I am having an issue that I believe is repeatable. It may be by design, but right now I can't figure out how to get around it.
I have an entity with a few complexType arrays on them. If I push a new complexType into the array, I see the correct number of objects in the collection. If I call rejectChanges on the parent entity, it removes the new complexType but then copies all of the objects in that array.
Sample metadata -
metadataStore.addEntityType({
shortName: "Person",
namespace: "MyNameSpace",
dataProperties: {
id: { dataType: "String", isPartOfKey: true },
emails: { complexTypeName: "Email:#MyNameSpace", isScalar: false }
}
});
metadataStore.addEntityType({
shortName: "Email",
namespace: "MyNameSpace",
isComplexType: true,
dataProperties: {
id: { dataType: "String" },
text: { dataType: "String" },
preferred: { dataType: "Boolean" }
}
});
Steps to reproduce -
Create an entity
Add two complex types of email
Save all changes
Add another complex type of email
Call entityAspect.rejectChanges() on the parent entity
Look at the number of emails in the array now
I assume on steps 1-3 this will still reproduce the issue, right now I am getting the entity and the complex types from the server so I am only doing steps 4-6.
Notes
I tried calling rejectChanges on the complexAspect instead but it doesn't exist.
I have a ko.computed on the list of emails to return the 'preferred' one that sets the others to false, don't know if this is contributing
I am sorting the list of emails in the DOM
Edit
Just found that the same thing occurs when deleting one of the complex types and cancelling that change.
Sorry for taking so long on this one. It slipped... It is now in the current GitHub repo and will go out with the next release.
I don't know if you got a response for your problem but here is mine!
Reason:
There is a bug in breeze that causes this behavior. I am referring to breeze v1.4.11 (still present in 1.4.12)
Solution:
This is my fix for the issue:
complexArrayMixin._rejectChanges = function() {
if (!this._origValues) return;
var that = this;
this.forEach(function(co) {
clearAspect(co, that);
});
this.length = 0;
this._origValues.forEach(function(co) {
that.push(co);
});
// mathieug: previous call already fills array with origValues
//Array.prototype.push.apply(this, this._origValues);
};

Dirty Forms giving error when I try to set form to clean

I have a form that I am trying to monitor to see when it becomes "Dirty" (changed), so that I can then enable a Save Changes button. It's fairly simple. In the $(document).ready() section, I enable dirtyForms on my form.
$(".dirtyForm").dirtyForms();
Then, I load the form from an ajax call, and inside that same function, I set it to clean and then start calling a function to check when it's dirty.
$(".dirtyForm").dirtyForms("setClean");
constant = setInterval(function(){checkDirty()}, 500);
Here is my function to check for when this becomes Dirty. Btw, if anyone knows of a better way to do this part, please let me know.
function checkDirty(){
if ($.DirtyForms.isDirty()){
$(".saveDirtyForm").removeAttr("disabled");
$(".resetDirtyForm").removeAttr("disabled");
console.log("Dirty...");
clearTimeout(constant);
}
}
You will notice that in the checkDirty function, it has clearTimeout(constant) to stop the function from continually repeating after the form becomes dirty. This all up to this point works fine. The buttons stay disabled until I change something and then almost immediately become enabled. The problem comes when I recall the ajax function to load the form with more info. When it resets the form, it gives an error when it's set to clean. It says,
Uncaught TypeError: Object function ( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
} has no method 'facebox'
This error is in the jquery.dirtyForms.js file. It doesn't set the form to clean and start the monitoring function again. Does anyone have an idea what I'm doing wrong?
Here is the function that zeroflagL was asking about.
function getOrderDets(id){
$.ajax({
url: DONEP+"blueBlob/donors/"+donorID+"/orders/"+id,
type: "GET",
dataType: "json",
success: function(data){
console.log(data);
dataSec = data.main.aResultData[0];
//Clear Fields
$("#orderIdTag").text('');
$("#orderNum").val('');
$("#doPlaced").val('');
$("#doShip").val('');
$("#dTrack").val('');
$("#doNote").val('');
//Set Main fields
$("#orderIdTag").text(dataSec.OrderID);
$("#orderNum").val(dataSec.OrderNumber);
$("#doPlaced").val(dataSec.OrderDate);
$("#doShip").val(dataSec.ShipDate);
$("#dTrack").val(dataSec.TrackingNumber);
$("#doNote").val(dataSec.OrderNote);
//Clean Dirty Form
$(".dirtyForm").dirtyForms("setClean");
constant = setInterval(function(){checkDirty()}, 500);
//Set Table
$(".orderDetTable").dataTable({
aaData: data.array,
"bAutoWidth": false,
"bDestroy": true,
"aoColumnDefs" : [
{"sWidth" : "13%", "sTitle" : "Quantity", "mData" : "Quantity", aTargets : [0]},
{"sTitle" : "Code", "mData" : "Code", aTargets : [1]},
{"sTitle" : "Amount", "mData" : "Amount", aTargets : [2]},
{"sWidth" : "6%", "sTitle" : "", "mData" : "OrderDetailsID", aTargets : [3], "mRender" : function(data, type, full){
return "<a href='#'><i class='glyphicon glyphicon-pencil orderDetEdit' id='"+data+"'></i></a>";
}}
]
});
}
});
}
Here is the stack trace for the facebox call.
$.facebox#http://dev.mysite.info/details.php?id=63#:540
.DirtyForms.dialog.fire#http://dev.mysite.info/assets/js/jquery.dirtyforms.js:25
bindFn#http://dev.mysite.info/assets/js/jquery.dirtyforms.js:421
aBindFn#http://dev.mysite.info/assets/js/jquery.dirtyforms.js:311
jQuery.event.dispatch#http://dev.mysite.info/assets/js/jquery.js:5095
jQuery.event.add/elemData.handle#http://dev.mysite.info/assets/js/jquery.js:4766
The first step is to call setClean after changing anything in the form including data tables.
If it's just the error, then here's a hack. This will get you by if you're under a deadline, and will also help you debug:
if ( typeof $.facebox !== 'function' )
{
$.facebox = function(){
var console = window['console'];
if ( console && console.error ){
console.error( 'Warning: $.facebox() was called', arguments );
}
return $();
}
}
Another tip: If you include the same jQuery library more than once, your plugins may not work.
To solve that, do a search for all instances of jquery in your codebase using this magic:
grep -o 'jquery:[^"]*"1\....' -R *
This searches for the jQuery.fn.version string.
You also need to check that the plugin is working. Try checking the following:
Is the plugin added after jQuery? - JQuery plugin not working
Does the plugin support your version of jQuery? - Why is the lightbox jQuery plugin not working for me?
Is more than one copy of jQuery included on the page? That can cause things to go crazy.
Read: jQuery in widget
EDIT: To get a stacktrace to see what's calling the facebox function:
$.facebox = function(){
alert( new Error().stack );
};
The correct way to enable/disable the buttons when the form is dirty/clean is now posted in the official documentation. Do note that this only works with Dirty Forms 2.x.
// Enable/disable the reset and submit buttons when the state transitions
// between dirty and clean. You will need to first set the initial button
// state to disabled (either in JavaScript or by setting the attributes in HTML).
$('form').find('[type="reset"],[type="submit"]').attr('disabled', 'disabled');
$('form').on('dirty.dirtyforms clean.dirtyforms', function (ev) {
var $form = $(ev.target);
var $submitResetButtons = $form.find('[type="reset"],[type="submit"]');
if (ev.type === 'dirty') {
$submitResetButtons.removeAttr('disabled');
} else {
$submitResetButtons.attr('disabled', 'disabled');
}
});
Also, it is pretty clear from your error message that you are using the default Dirty Forms 1.x behavior, which uses FaceBox as the dialog, but you don't have a reference in your page to FaceBox. You could fix that by adding the reference:
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.facebox/1.4.1/jquery.facebox.min.js"></script>
Alternatively, you can use any dialog you want by setting the $.DirtyForms.dialog property, or you can set it to false to use the browser's default dialog.
$.DirtyForms.dialog = false;
In Dirty Forms 2.x, false is now the default setting, so there is no need to add a reference to FaceBox.

Trying to append a new node to an existing node doesn't work with custom schema

When working with Kendo UI Web v2012.3.1114 the issue that I have is I am trying to do a simple append to a TreeView with a node that I retrieve via an AJAX call to the server fails with the error below.
The node is the EXACT same format as the data returned from the normal read function.
I have successfully used data("kendoTreeView").insertBefore(...) for the same tree and call, but when I try to use data("kendoTreeView").append(...) it fails.
Error message:
Uncaught TypeError: Property 'data' of object # is not a
function kendo.web.min.js:25
Since I have to be able to create new child nodes for a node that was previously a leaf, I cannot use any other API to do this.
I've made a jsFiddle showing the definition of the tree and what I want to be able to do. I tried referencing the working sample on the Kendo site but it seems that as soon as I use a custom schema, things go south.
Here is the code from jsFiddle that I'm using:
function populateHierarchyTree(quotaSetID, columnID, treeDiv) {
var transport = {
read: {
url: '/Quota/QuotaHierarchy/GetQuotaHierarchyChildrenFromParent',
dataType: 'json',
data: { columnDefinitionID: columnID, quotaSetID: quotaSetID, batchSize:10 },
type: 'POST'
}
};
var schema = {
model: {
id: 'id',
hasChildren: 'hasChildren'
}
};
var dataSource = new kendo.data.HierarchicalDataSource({
transport: transport,
schema: schema
});
treeDiv.kendoTreeView({
loadOnDemand: true,
dataSource: dataSource,
dataTextField: "text",
});
}
// This function is called with a single node which contains the exact same structure returned from GetQuotaHierarchyChildrenFromParent used by the read. ParentElement could be anything.
function AddNode(node,parentElement,treeView){
treeView.append(node,parentElement);
}
How do you choose parentElement? Are you sure that it is a kendoTreeView node?
Try this:
treeView.append(node, parentElement.closest(".k-item"));
By adding .closest(".k-item"); what I try is finding the closest node ancestor of your parentNode.

Categories