breaking main loop - jstree - javascript

I am using jstree library to display a tree.
In the code below, I am looping through the selected nodes in the tree and based on some conditions, I am assigning a variable 'allow_edit' a boolean value.
I would like to break the main loop if 'allow_edit = false'.
I tried using label and breaking the loop but this does not seem to work. I am getting undefined label.
loop1:
$j.each($j("#demo2").jstree("get_selected"), function(index, element) {
var selected_node_depth = parseInt($j(element).attr('node_depth'));
var allow_edit = false;
var array_first_filter = $j.grep(array_first, function(v) { return v[1] != "not detected";})
var array_second_filter = $j.grep(array_first_filter, function(v) { return v[3] > selected_node_depth;})
if (array_second_filter.length === 0 || array_second_filter.length == null)
{
allow_edit = true;
}
else{
alert("Confliction exists in your selected terms.");
allow_edit = false;
//break loop1; /** not working, getting undefined label **/
}
}
Any suggestions on how to break the main loop if 'allow_edit = false'? Thanks a lot

If the function you pass to .each() returns false, the iteration will stop.
else {
allow_edit = false; // pointless since you're about to return ...
return false;
}
Also, as a programming style note, any construction of the form:
if (something) {
flag = true;
}
else {
flag = false;
}
can be better written as simply:
flag = something;
In JavaScript, to force flag to be boolean (true or false), you can do this:
flag = !!(something);
The two ! (logical "not") operators force the expression ("something") to be evaluated as a boolean by the same rules as are used when that expression is the test clause of an if statement.

Related

How to find an array of strings in a string?

I'd like to search a string for multiple strings, and return true if it finds any of them in there, false otherwise, something like this:
var s = "thing1 thing2"
s.contains(["thing1","thing44444"]) // true
s.contains("1") // true
s.contains("x") // false
Here's what I have so far, but it's getting messier and doesn't really work:
String.prototype.contains = function(xv) {
var t = this
if(xv.isString()){ // isString/isArray are functions I made elsewhere in my code, they work.
if(t.indexOf(xv) > -1)
return true;
} else if(xv.isArray()) {
if(xv.contains(t)){
return true
}
for(v in xv){
if(t.indexOf(xv[v]) > -1){
return true
}
}
} else {
return false
}
}
As of now, it will return undefined if it makes it through the for loop without finding anything. I had return false after the for loop, but it would run before the for finished.
I feel like there's gotta be an easier way to do this.
I've already tried How do you search multiple strings with the .search() Method? but I couldn't send an array to .search().
Frameworks I'm using: angular 1.5.8, jquery 1.11.1
You can use Array.some and String.indexOf or String.includes
var s1 = "thing1 thing2";
var s2 = "Hello Kitty";
var r1 = ["thing1","thing44444"].some( x => s1.includes(x));
var r2 = ["Travis","Heeeeeeter"].some( x => s2.includes(x));
console.log(r1, r2); // true, false

HTML 5 toggling the contenteditable attribute with javascript

enter code hereI am trying to make something editable online with a function like this
function toggle_editable (div, cssclass) {
var classToEdit = document.getElementsByClassName(cssclass)
for (i = 0;classToEdit.length; i++) {
if (classToEdit[i].contentEditable == false) {
classToEdit[i].contentEditable = true ;
}
if (classToEdit[i].contentEditable == true) {
classToEdit[i].contentEditable = false ;
}
}
}
classToEdit is a collection of HTML elements with the same class name or whatever document.getElementsByClassName(cssclass) returns
when going through the debugger it jumps over the line
classToEdit[i].contentEditable == true
as well as over the line
classToEdit[i].contentEditable == true
and does not execute the code in the braces following the if statements
this works however - meaning it sets the contenteditable property without hesitation
classToEdit.contenteditable = true;
as well as this
classToEdit.contenteditable = false;
(well obviously)
also this seemed to have no effect
classToEdit.contenteditable = !classToEdit.contenteditable
ideas anyone?
ps why is the loop
You've created an infinite loop here:
for (i = 0;classToEdit.length; i++) {
Should be:
for (var i = 0; i < classToEdit.length; i++) {
But, if you say classToEdit.contenteditable = true "works", you've to define "not working/is working" since the snippet doesn't definitely do what you expect it to do, if classToEdit is a HTMLCollection.
It looks like you'd want to toggle contentEditable values, you can do it like this:
for (var i = 0; i < classToEdit.length; i++) {
if (classToEdit[i].contentEditable == false) {
classToEdit[i].contentEditable = true ;
} else { // Notice else here, no need for another check
classToEdit[i].contentEditable = false;
}
}
Or simply without ifs in the loop:
classToEdit[i].contentEditable = !classToEdit[i].contentEditable;
Your current code will switch the value back to it's original in a case the value was false.
HTMLElement.contentEditable returns a string and not a boolean.
Hence, what you want to identify the state of your editable field is:
// Incorrect
classToEdit[i].contentEditable == true
// Coorect
classToEdit[i].contentEditable === 'true'
What's even better if you want to know the state of your fields is to use HTMLElement.isContentEditable
which returns a boolean:
classToEdit[i].contentEditable = !element.isContentEditable
Another way to refactor the above:
function toggleContentEdit() {
var editableFields = document.getElementsByClassName('editable');
[].forEach.call(editableFields, function(field){
var isEditable = field.isContentEditable;
field.setAttribute('contenteditable', !isEditable);
});
};
JSFiddle: http://jsfiddle.net/6qz3aotv/

JavaScript Throws Undefined Error

What it is supposed to do -
Example
url1(pages,"ALT") returns "www.xyz.ac.uk"
url1(pages,"xyz") returns ""
The error - TypeError: Cannot call method 'toUpperCase' of undefined
This is just for some coursework, Im stuck with these errors. Any help would be much appreciated
function index(string,pattern,caseSensitive) {
if(caseSensitive == false) {
var v = string.toUpperCase();
} else {
var v = string;
}
return indexNumber = v.indexOf(pattern);
}
var pages = [ "|www.lboro.ac.uk|Loughborough University offers degree programmes and world class research.", "!www.xyz.ac.uk!An alternative University" , "%www%Yet another University"];
alert(url1(pages, "ALT"));
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
if(pages[i].indexOf(seperator)>0){
siteContent = pages[i].split(pages[i].indexOf(seperator));
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
}
}
if(pages[i].indexOf(seperator)>0){
siteContent = pages[i].split(pages[i].indexOf(seperator));
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
If pages[i].indexOf(seperator)<=0, siteContent is still whatever it was from the last iteration. If that happens on the first iteration, siteContent is still [], and siteContent[2] is undefined.
Another problem: the expression pages[i].indexOf(seperator) returns a number, and pages[i].split expects a delimiting string as an argument. Since the number doesn't appear in your input, you'll always get a single-element array, and siteContent[2] will always be undefined. Get rid of .indexOf(seperator), change it to siteContent = pages[i].split(seperator).
One more: get rid of the else { return ""; }. Add a return ""; after the for loop.
Finally, in the first if statement condition, change .indexOf(seperator) > 0 to .indexOf(seperator, 1) !== -1. Since you're getting seperator from the first character of the string, it will be found at 0. You want the second occurrence, so start the search at 1. In addition, .indexOf returns -1 if it doesn't find the substring. You'll need to account for this in both if conditions.
Side note, as this is not causing your problem: never use == false. JS will coerce stuff like 0 and "" to == false. If that's what you want, just use the ! operator, because the expression has nothing to do with the value false.
My final answer is http://jsfiddle.net/QF237/
Right here:
alert(url1(pages, ALT)); // ALT ISN'T DEFINED
I believe you forgot to quote it:
alert(url1(pages, "ALT"));
You should split the string passing the separator character itself. Your function then will look like:
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
console.log(seperator);
if(pages[i].indexOf(seperator)>=0){
siteContent = pages[i].split(seperator); //fixed here
}
console.log(siteContent);
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
}
}
Tell us if it worked, please.
EDIT: It seeems your index() also has a little problem. Please try the function below.
function index(string,pattern,caseSensitive) {
var v;
if(caseSensitive == false) {
v = string.toUpperCase();
pattern = pattern.toUpperCase(); //to clarify: pattern should be uppercased also if caseSensitiveness is false
} else {
v = string;
}
return v.indexOf(pattern);
}
EDIT 2:
And url1() is finally like this:
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
if(pages[i].indexOf(seperator)>=0){
siteContent = pages[i].split(seperator);
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}
}
return "";
}
In this case, the first occurrence of pattern in all pages will be returned.

Including a for loop in an if statement

I'm building an application in which I want to display some errors when a user enters invalid values in an input box. A correct value is appended as 'entry' to a div if no errors were found. In total there are 3 cases when to display errors:
The input value is empty
The input value is a number
The input value already exists
These errors are displayed with if else statements.
1.and 2. were easy, but the problem case (3.) only validates against the first element of class .cat_entry.
if(cat_input == '') { // generate errors
errorDisplay(error_input_empty);
} else if(!isNaN(cat_input)) {
errorDisplay(error_input_number);
} else if($('.cat_entry') == cat_input) { // THIS IS THE PROBLEMATIC LINE
// .cat_entry is the class of the entries that have been appended
errorDisplay(error_duplicate);
} else {
// stuff
};
So I believe I need a for loop/ .each() (no problem so far), but how do I include this as a condition in an if statement? Something like.. if( for(i=0;i<$('.cat_entry').length;i++) { ... }; ... How to return true (or something similar) when one of the entries matches the input value, then pass the return value to the if statement?
EDIT: here is a jsFiddle with the relevant code. I updated it with $.inArray() method. I'd like to try and use this instead of a for / .each() loop.
You can try this:
var a=$('.cat_entry'),o={};
for(i=0;i<a.length;i++) {
var s=a[i].val();
if(s in o){
errorDisplay(error_duplicate);
return;
}
o[s]=true;
}
or
var o={};
$('.cat_entry').each(function(){
var s=$(this).val();
if(s in o){
errorDisplay(error_duplicate);
return;
}
o[s]=true;
}
You can actually use the jQuery inArray function for this, such as:
else if($.inArray(cat_input, $('.cat_entry') != -1)
}
The solution was to add this to the function:
var isDuplicate = false;
$('.cat_entry').each(function() {
if(!$(this).text().indexOf(cat_input)) {
isDuplicate = true;
}
// And in the if else loop:
else if(isDuplicate == true)
//and just before the function ends
isDuplicate = false;
Thanks to all for the help you offered.

How do I call a function with in a function?

I need to add i3c to my and statements. I don't know the correct syntax. This code is broken. Would an anonymous function be better? So if c0() passes, c4() runs, if c4() passes I need i3c() to run or what is in i3c to run.
function o1(a,b)
{
document.getElementById(a).value=b;
}
function i3()
{
var a=document.forms['f3'].elements,b='f3e';
c0(a,'Please enter both a tile and a url',b)&&c4(a[2],'Please enter a valid url',b)&&d0()&&s0('pi3a.php',is('f3'),s2);
o1(f3aa,'');o1(f3bb,'');
}
function d0()
{
var a=document.getElementById('Bb1c'),
b=document.createElement('a'),
c=document.forms['f3'].elements;
b.href=c[2].value;
b.name="a1";
b.className ="b";
b.innerHTML = c[1].value;
a.appendChild(b);
return 1;
}
The && (logical AND operator) is processed left to right. If any expression returns false, that value is returned. If all but the last one return true, then the value of the last expression is returned (whether it is true or false).
So if i3c is not being called, it is because the return value of one of the preceding calls is falsey, i.e. it type converts to false, so it might be 0, '' (empty string), undefined, NaN, null, ... I've probably left one out.
Edit
As patrick w commented, the line:
c.setAttribute("class","b");
will fail in IE. Don't use setAttribute for standard attributes, use DOM properties instead:
c.href = d[2].value;
c.name = "a1";
c.className = "b";
Faster and less bugy.
function i3() {
var e = 'f3e';
if ( !(c0(a,'Please enter both a tile and a url',e)) ) { return flase; }
if ( !(c4(a[2],'Please enter a valid url',b)) ) { return flase; }
(function() {
var doc = document,
a = doc.forms.f3.elements,
b = doc.getElementById('Bb1c'),
c = doc.createElement('a'),
d = doc.forms.f3.elements;
c.href = d[2].value;
c.name = "a1";
c.className = "b";
c.innerHTML = d[1].value;
b.appendChild(c);
// which a you need here ???
//var a = is('f3');
var someOtherA = is('f3');
//------------------------
s0('pi3a.php', a, s2);
// if these are part of the form you use in this function
// use
// document.forms[<name>].elements[<name>].value
doc.getElementById('f3aa').value = '';
doc.getElementById('f3bb').value = '';
})();
}
This may work, I suppose c0 and c4 return true/false. This way they are easier to read. If they return true, continue with the next one and don`t return.
In the i3c function you declare a twice!
Look at the comments for more details.

Categories