Binary Search Tree Syntax - javascript

For this portion of an implementation of a binary search tree in JS, what is the significance of referring to "this._root"? (why can't they say "this.root")? The link for this is available at http://www.nczonline.net/blog/2009/06/16/computer-science-in-javascript-binary-search-tree-part-2/
BinarySearchTree.prototype = {
//more code here
remove: function(value){
var found = false,
parent = null,
current = this._root,
childCount,
replacement,
replacementParent;
//make sure there's a node to search
while(!found && current){
//if the value is less than the current node's, go left
if (value < current.value){
parent = current;
current = current.left;
//if the value is greater than the current node's, go right
} else if (value > current.value){
parent = current;
current = current.right;
//values are equal, found it!
} else {
found = true;
}
}
//only proceed if the node was found
if (found){
//continue
}
},
//more code here
};

They may be trying to indicate that this variable should not be accessed outside of the object (private in other languages).
Python has a strong convention of using names starting with underscore character to indicate that this field or method is private. The author may be trying to apply the same convention to javascript.

I suppose that more complete example is located here: https://github.com/nzakas/computer-science-in-javascript/blob/master/data-structures/binary-search-tree/binary-search-tree.js
Regarding this._root - I think it's author's decision only, without any special meaning.

Related

How to compare if an HTML element exists in the node array?

selectedContentWrap: HTML nodes.
htmlVarTag: is an string.
How do I check if the HTML element exists in the nodes?
The htmlVarTag is a string and don't understand how to convert it so it check again if there is a tag like that so that if there is I can remove it?
here is output of my nodes that is stored in selectedContentWrap
var checkingElement = $scope.checkIfHTMLinside(selectedContentWrap,htmlVarTag );
$scope.checkIfHTMLinside = function(selectedContentWrap,htmlVarTag){
var node = htmlVarTag.parentNode;
while (node != null) {
if (node == selectedContentWrap) {
return true;
}
node = node.parentNode;
}
return false;
}
Well if you could paste the content of selectedContentWrap I would be able to test this code, but I think this would work
// Code goes here
var checkIfHTMLinside = function(selectedContentWrap,htmlVarTag){
for (item of selectedContentWrap) {
if (item.nodeName.toLowerCase() == htmlVarTag.toLowerCase()){
return true;
}
}
return false;
}
Simplest is use angular.element which is a subset of jQuery compatible methods
$scope.checkIfHTMLinside = function(selectedContentWrap,htmlVarTag){
// use filter() on array and return filtered array length as boolean
return selectedContentWrap.filter(function(str){
// return length of tag collection found as boolean
return angular.element('<div>').append(str).find(htmlVarTag).length
}).length;
});
Still not 100% clear if objective is only to look for a specific tag or any tags (ie differentiate from text only)
Or as casually mentioned to actually remove the tag
If you want to remove the tag it's not clear if you simply want to unwrap it or remove it's content also ... both easily achieved using angular.element
Try using: node.innerHTML and checking against that
is it me or post a question on stackoverflow and 20min after test testing I figure it.,...
the answer is that in the selectedContentWrap I already got list of nodes, all I need to do i compare , so a simple if for loop will fit.
To compare the names I just need to use .nodeName as that works cross browser ( correct me if I am wrong)
Some dev say that "dictionary of tag names and anonymous closures instead" - but couldn't find anything. If anyone has this library could you please post it to the question?
here is my code.
var node = selectedContentWrap;
console.log('node that is selectedwrapper', selectedContentWrap)
for (var i = 0; i < selectedContentWrap.length; i++) {
console.log('tag name is ',selectedContentWrap[i].nodeName);
var temptagname = selectedContentWrap[i].nodeName; // for debugging
if(selectedContentWrap[i].nodeName == 'B' ){
console.log('contains element B');
}
}

InDesign script: footnotes loosing their style

Ok, I know this had been already discussed here but no clear answer had been provided. I often need to import XML files into InDesign, many footnotes included. Of course, InD is not able to use tags automatically in this case. This script works well except all footnotes loose their styles. I know it could be because of the contents on lines 27 and 35. It is needed to use move instead. Unfortunately, I am not good at JavaScript and can't figure out how to implement that properly.
Application.prototype.main = function(){
if ( this.documents.length <= 0 ) return;
var tg = this.selection[0] || this.activeDocument;
if( 'appliedFont' in tg ) tg = tg.parent;
if( tg.constructor == TextFrame ){ tg = tg.parentStory ; }
if(! ('findGrep' in tg) ) return;
var fnPatterns = ["#foot#([\\s\\S]*?)#foot#", "#footnotes_begin#([\\s\\S]*?)#footnotes_end#"];
var count = 0;
for(patterCounter = 0; patterCounter < fnPatterns.length; patterCounter++){
fnPattern = fnPatterns[patterCounter];
var fnFinds = (function(){
this.findGrepPreferences = this.changeGrepPreferences = null;
this.findGrepPreferences.findWhat = fnPattern;
var ret = tg.findGrep();
this.findGrepPreferences = this.changeGrepPreferences = null;
return ret;
}).call(this);
var fnFind, fnText, rg = new RegExp(fnPattern), ip, fnParent, fn, count;
while( fnFind=fnFinds.pop() ){
fnText = fnFind.contents.match(rg)[1];
fnParent = fnFind.parent.getElements()[0];
ip = fnFind.insertionPoints[0].index
try {
fnFind.remove();
fn = fnParent.footnotes.add(LocationOptions.BEFORE, fnParent.insertionPoints[ip]);
fn.texts[0].insertionPoints[-1].contents = fnText;
++count;
}
catch(_){}
}
}
alert((count)? (count+" footnote(s) successfully added."): "No footnote added. Make sure you use the relevant pattern.");
}
app.doScript('app.main();', ScriptLanguage.javascript,
undefined, UndoModes.entireScript, app.activeScript.displayName);
The problem is exactly the same as in the question you linked to: you are manipulating a plain string translation in Javascript, not the native InDesign text object itself. Use move and duplicate methods on the text property of the found list instead.
A basic solution is to use
fn = fnFind.footnotes.add(LocationOptions.AFTER, fnFind.insertionPoints[-1]);
fnFind.texts[0].move (LocationOptions.AT_END, fn.texts[0]);
but this will copy the start and end markers as well. It takes a bit more to remove them; I based the following adjustments in your original script on your GREP patterns, but it may be safer to build an explicit list of prefix/suffix pairs, as you also can use them to construct the GREP searches.
The next problem, then, is if you copy (duplicate, in InDesign's DOM) the found text, the original "found" text will now have the footnote attached to it! This is because one line earlier, you add the footnote to the "found" text. So you cannot use a simple remove to delete it; again, you need to manipulate the text object, but this time through its individual characters. My last adjusted line 'selects' the fnFind texts, minus its very last character (which is the newly added footnote), and deletes it.
var fnFind, fnPrefix,fnSuffix, rg = new RegExp(fnPattern), ip, fnParent, fn, count;
while( fnFind=fnFinds.pop() ){
fnPrefix = fnFind.contents.match(/^#[^#]+#/)[0];
fnSuffix = fnFind.contents.match(/#[^#]+#/)[0];
// add footnote
fn = fnFind.footnotes.add(LocationOptions.AFTER, fnFind.insertionPoints[-1]);
// duplicate the text
fnFind.texts[0].characters.itemByRange(fnPrefix.length,fnFind.texts[0].characters.length-fnSuffix.length-1).duplicate(LocationOptions.AT_END, fn.texts[0]);
// remove the original
fnFind.characters.itemByRange(0,fnFind.characters.length-2).remove();
++count;
}

String control in loops

I have a big question.
I have many Strings in my Programm and want to check these Strings on there values.
I wrote a Loop for it, but insted of the Definition of an String he is creating a new value. It's basicly really difficult to discribe, also because i am basicly German.
But i can give you my current code, so maybee you will see what I mean:
{
var Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
var Loch2G = $('#m1-Rundenanalyse-Turnier').val();
x=1
while (x <= 2) {
if ("Loch" + x + "G" == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1
}
}
How can I solve this?
I'd suggest using an array to store the values you want to check:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
for (var i = 0, len = lochs.length; i < len; i++){
if (lochs[i] == ''){
alert("Eingabe war leer");
}
}
JS Fiddle demos: passes (no alert), fails (alert)
This suggestion is based on my presumption that you're trying to create the names of the vars you want to check, which won't work, whereas this approach lets you store all values (however many) in the same array and then iterate over that array to find any values that are equal to an empty string.
If you really want to stick with your current approach, you could do the following:
{
window.Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
window.Loch2G = $('#m1-Rundenanalyse-Turnier').val();
var x=1;
while (x <= 2) {
if (window["Loch" + x + "G"] == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1;
}
}
But I can't think why you'd want to; plus the use of global variables is poor practice as it explicitly makes those variables available to every closure within the document, which allows them to be easily, and accidentally, overwritten.
In a reasonably up-to-date browser, that implements Array.prototype.every, you could dispense with the explicit iteration:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
if (!lochs.every(function(a){ return a !== ''; })) {
alert("Eingabe war leer");
}
JS Fiddle demos: passes (no alert), fails (alerts).

css to json parser freezes the browser-window

I found some days ago a really nice approach to parse css-strings (even nested) to json. However, it seems, that there's somewhere a big problem in it.
https://github.com/csvplot/cml-parse
If we try to parse a css-string, it will kill the browser window, don't know what's going on here... I already opend an issue but there's no one to answer the issue, since the maintainer David Ellis is lost.
Any ideas/suggestions?
function parse(data) {
var stateStack = [];
var scopeStack = [];
var outObj = {};
while(data) {
// Grab current number of indentation characters
/^(\s*)/.test(data);
// If we've entered any state, and that state is not an explicit block declaration ( {}'s ) and we have an indent level smaller than the most recent indent level,
// then remove the most recent scope level and recall the state back to the previous scope's state
if(stateStack.length &&
stateStack[stateStack.length-1] !== 'explicitBlock' &&
scopeStack.length &&
RegExp.$1.length < scopeStack[scopeStack.length-1].indent) {
scopeStack.pop();
while(stateStack.length && (stateStack[stateStack.length-1] !== 'block' || stateStack[stateStack.length-1] !== 'explicitBlock')) {
stateStack.pop();
}
}
// If current chunk is the key to an object
if(/^(\s*)([^:]*)\s*([{\n])/.test(data)) {
// Grab the indent size of the key and the current outObj position from the scope stack
var indentLength = RegExp.$1.length;
var currScope = (scopeStack.length ? scopeStack[scopeStack.length-1].ref : outObj);
// Split the identifier by spaces and construct/traverse down the defined path
// TODO: Figure out how to handle commas that define the same inner content along multiple paths
RegExp.$2.split(/\s*/).forEach(function(scope) {
if(scope !== '') {
currScope[scope] = currScope[scope] || {};
currScope = currScope[scope];
}
});
// Push the deepest scope and the current indent length onto the scope stack, and push the explicitBlock vs block state onto the state stack
// TODO: Work on a state diagram to truly handle all of the possible states involved properly
scopeStack.push({ref: currScope, indent: indentLength});
stateStack.push(RegExp.$3 === '{' ? 'explicitBlock' : 'block');
// Rip out the handled chunk of data from the string
data = data.replace(/^\s*[^:]*\s*[{\n]/, '');
}
}
return data;
}
http://fiddle.jshell.net/5pTBr/
Running the code, it looks like it just does not work.
It reaches an infinite loop since this regex is failing after the first run:
if(/^(\s*)([^:]*)\s*([{\n])/.test(data)) {
Hence why the browser is stuck. It also does not return the correct JSON.
I'd advise on writing something like this by yourself, or trying to debug and fix the existing code.

javascript - coldfusion - working with a list

This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.
Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}
Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function
Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/
I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;

Categories