Javascript 'while' loop causing browser to crash - javascript

I have a 'search and highlight' function that looks through each node in an element and highlights each instance of the keyword. Within this function I have used a while(true) that seems to be causing the browsers to either crash or lag! Are there any alternatives to this while loop?
Any help would be so greatly appreciated.
console.log(keyword);
if (keyword != "") {
SearchResultCount = 0;
currSelected = -1;
if (element) {
if (element.nodeType == 3) {
while (true) {
var value = element.nodeValue; // Search for keyword in text node
var idxSensitive = value.indexOf(keyword);
var idxInsensitive = value.toLowerCase()
.indexOf(keyword);
if ((idxInsensitive < 0)
&& (idxSensitive < 0))
break; // not found, abort
else if ((idxInsensitive >= 0)
&& (idxSensitive < 0))
var idx = idxInsensitive;
else if ((idxSensitive >= 0)
&& (idxInsensitive < 0))
var idx = idxSensitive;
var span = document.createElement("span");
var text = document.createTextNode(value
.substr(idx, keyword.length));
span.appendChild(text);
span.setAttribute("class",
"highlightedText");
span.style.backgroundColor = "lightblue";
span.style.color = "black";
text = document.createTextNode(value
.substr(idx + keyword.length));
element.deleteData(idx, value.length - idx);
var next = element.nextSibling;
element.parentNode.insertBefore(span, next);
element.parentNode.insertBefore(text, next);
element = text;
SearchResultCount++; // update the counter
}
}

While loops need a false condition or a break to end. All I see is a while (true) which will never evaluate to false. Since you have a never ending loop, it causes your browser to crash. Though it should break if idxSensitive and idxInsensitive are negative numbers, any other value will keep the loop running forever.

To loop something forever(instead of while(true)), you can use:
setTimeout(function, 1);
//Or
for (var i = 0; i < Infinity; i++) {
//Code goes here
}

Related

Compression String does not work for all strings

The idea is to complete the function and produce a compressed form of the string given. An example would be if the given string was aabbcc then you would get a2b2c2
The issue with the code I created is for some reason it does not work with anything right away that is consecutive or consecutive letters at the end. wwww turns into w4 but aa does not turn into a2 and wuenuneubgnjfniwfibwiebfaaa will not turn into wuenuneubgnjfniwfibwiebfa3
function compressedString(message) {
let out = '';
let count = 1;
for (let i = 0; i < message.length; i++) {
let current = message[i];
let next = message[i + 1];
if (current == next) {
count++;
} else {
out += current + String(count);
count = 1;
}
}
}
I test your algorithm, using given example of your question wuenuneubgnjfniwfibwiebfaaa, the output was w1u1e1n1u1n1e1u1b1g1n1j1f1n1i1w1f1i1b1w1i1e1b1f1a3, what sounds strange for the string compression requirement. When I add a nested condition inner first else in for loop, I acquired the correct result, please view the code bellow and let what do you think about:
function compressedString(message) {
let out = '';
let count = 1;
for (let i = 0; i < message.length; i++) {
let current = message[i];
let next = message[i + 1];
if (current == next) {
count++;
} else {
if(count == 1){
out += current;
}else{
out += current + String(count);
}
count = 1;
}
}
return out;
}
Your issue is the way you are handling it in the end. What happens to the variable next when the loop is on the last iteration? You need to add an extra check on your if.
Try this:
function compressedString(message) {
let out = '';
let count = 1;
for (var i = 0; i < message.length; i++){
let current = message[i];
let next = message[i + 1];
if ( i < message.length-1 && message[i] == next) {
count += 1;
} else {
out += current + String(count);
count = 1;
}
}
return out;
}

Parameter returns undefined

I am trying to write a function that identifies if a word is an isogram or not. This is what I have done so far:
function isIsogram(word) {
var result;
var counter = 0;
var dubs = 0;
if (word.length === 0) {
result = false;
} else {
var lower = word.toLowerCase();
var array = Array.from(lower);
for (i = 0; i < array.length; i++) {
counter++;
for (j = i + 1; j < array.length; j++) {
if (array[i] === array[j]) {
dubs++;
}
}
}
if ((counter > 0) && (dubs === 0)) {
result = true;
} else if ((counter > 0) && (dubs > 0)) {
result = false;
}
}
console.log(result);
return result;
}
isIsogram("word");
When I run the above code in my browser's javascript console, it works pretty well. But when I post it onto the environment where I am being tested, it gives an error that "word" (the parameter) is undefined.
I even tried hard coding a parameter by declaring a string value for word outside the function, it still said undefined. What am i not doing right?
Seems to work as far as I can see.
Can you provide information about how you call your function isIsogramm('teststring');?
https://jsfiddle.net/TobiObeck/z15eos81/

Multiple collision in canvas

I am trying to make unblock me game. I have array of objects and I made boundaries collision. But now I am stuck with collision between objects. I made cycle over objects in array but it stops on the last one. How can I make collision check on each object everytime I move with my selected object?
Full code here: http://foxfcb.sweb.cz/ I am newbie in programming so please be patient.
canvas.addEventListener('mousemove', function (e) {
...
var shapes = myState.shapes;
var l = shapes.length;
for (var i = 0; i < l; i++) {
var shape = myState.shapes[i];
var selection = myState.selection;
// collision between objects
if (selection.x < (shape.x + shape.w) && (selection.x + selection.w) > shape.x &&
selection.y < (shape.y + shape.h) && (selection.y + selection.h) > shape.y) {
myState.valid = true; //stop
}
// boundaries collision
else if (myState.selection.x < 0 || myState.selection.y < 0 || myState.selection.x + myState.selection.w > 600 || myState.selection.y + myState.selection.h > 600) {
myState.valid = true; //stop
}
else {
myState.valid = false; //moving
}
}
}
You are resetting the valid flag when you check other objects.
So here is your collision detection as a function. Notice I set state = false once before the loop and if there is a collision I break out of the loop as there is no point detecting other collisions as the flag is either true or false. You were setting the flag back to false on all but the last object if you detected a collision.
var textCollision = function(){
var shapes, l, shape, selection, i;
shapes = myState.shapes;
l = shapes.length;
myState.valid = false; // assume no collision
for (i = 0; i < l; i++) {
shape = myState.shapes[i];
selection = myState.selection;
if (selection.x < (shape.x + shape.w) && (selection.x + selection.w) > shape.x &&
selection.y < (shape.y + shape.h) && (selection.y + selection.h) > shape.y) {
myState.valid = true; //stop
// there is no point testing any others as it will make no dif
break; // step out of the for loop.
}
// boundaries collision
else if (myState.selection.x < 0 || myState.selection.y < 0 || myState.selection.x + myState.selection.w > 600 || myState.selection.y + myState.selection.h > 600) {
myState.valid = true; //stop
// there is no point testing any others as it will make no dif
break; // step out of the for loop.
}
}
}
Break.
Break is a javascript reserved token and is used to break out of loops and switches.
For loop
for(i = 0; i < 10; i++){
if(i === 2){
break; // exit the loop at 2
}
}
While loop
while(i < 10){
if(i === 2){
break; // exit out of the while loop
}
}
Also does the same on do{ }While() loops.
Break only exits the current loop;
for(j = 0; j < 10; j++){ // j loop
for(i = 0; i < 10; i++){ // i loop
if(i === 2){
break; // exit the i loop at 2
}
}
// the break moves execution to the first line after the loop it is in
// the j loop continues as normal
}
Break is also used in switch statements
function num(i){
switch(i){
case 1:
console.log("one");
// no break token so execution continues inside the switch
case 2:
console.log("two");
}
}
num(1); // outputs "one" "two"
To prevent this use break
function num(i){
switch(i){
case 1:
console.log("one");
break; // break out of the switch
case 2:
console.log("two");
// no point having a break here as it is at the end anyways
}
// break moves execution to here
}
num(1); // outputs "one"

Why is `appendChild()` giving me issues?

H~ I have a script that I've been working on which will, ultimately, display Pascal's Triangle. I developed this from scratch with JavaScript, and I want to display it in the DOM.
For the life of me, I can't figure out why this script produces a different effect in the DOM than it does in a console. Any help would be much appreciated!
Copyright (c) 2015 Peter Gray Ward
function randomScripts(){
var arr1 = ['_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'];
var arr2 = ['_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'];
var n = 0;
var len = 35;
var mid = Math.floor(len/2)
var destination = document.getElementById("destination");
var home = document.getElementById("home");
function first(){
for(var j = 1; j<=10; j++){
var o = j%2 !== 0;
var e = j%2 === 0
if(o){
for(var i = 0; i<len; i++){
odd = i%2 !== 0;
if(j === 1){
arr1.splice(i,1,"_")
}
if(odd && (i === mid + n || i === mid - n)){
arr1.splice(i,1,1);
}
var node = document.createTextNode(arr1.join(''));
}
console.log(arr1.join(''));
destination.appendChild(node);
home.appendChild(node);
//destination.appendChild("Please see Console for full version b/c of hackers");
}
else if(e){
for(var h = 0; h<len; h++){
even = h%2 === 0;
if(even && (h === mid + n || h === mid - n)){
arr2.splice(h,1,n);
}
}
console.log(arr2.join(''));
}
n++;
}
}
<p id="destination"></p>
You created functions, but you never call them. Try actually calling them to see what they do:
function randomScripts(){
var arr1 = ['_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'];
var arr2 = ['_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'];
var n = 0;
var len = 35;
var mid = Math.floor(len/2)
var destination = document.getElementById("destination");
var home = document.getElementById("home");
first();
function first(){
for(var j = 1; j<=10; j++){
var o = j%2 !== 0;
var e = j%2 === 0
if(o){
for(var i = 0; i<len; i++){
odd = i%2 !== 0;
if(j === 1){
arr1.splice(i,1,"_")
}
if(odd && (i === mid + n || i === mid - n)){
arr1.splice(i,1,1);
}
var node = document.createElement('p');
node.textContent = arr1.join('');
}
console.log(arr1.join(''));
destination.appendChild(node);
home.appendChild(node);
destination.innerHTML = "Please see Console for full version b/c of hackers";
}
else if(e){
for(var h = 0; h<len; h++){
even = h%2 === 0;
if(even && (h === mid + n || h === mid - n)){
arr2.splice(h,1,n);
}
}
console.log(arr2.join(''));
}
n++;
}
}
}
window.addEventListener('load', randomScripts, false);
<p id="destination"></p>
<div id="home"></div>
There may be other problems in the script, but here are a couple I noticed. First:
destination.appendChild(node);
home.appendChild(node);
You can't append the same node in two different places in the DOM. It will remove the first one when you append it the second time. You could either create a second text node the same way you created the first, or clone the node.
Also, these two lines of code come after the if(o) statement body, but the node variable is created inside that if body. In the general case, you wouldn't expect this to work always, because node would be undefined if the if body were not executed. In your specific code, that won't happen because o is true the first time through the loop. But node only gets updated on every second pass through the loop. Is that what you want?
One last thing, the indentation is not consistent, making it hard to see what is nested inside what. It's important to use correct and consistent indentation. (And I would suggest 4 spaces instead of 2 to make it easier for people to read.)

How do I count letters in JavaScript?

I have written this function (which is not working) which is supposed to count the letters in a global variable (paraText), and then insert it to count. How do I solve this?
This is a school project so I have to follow sertain rules. I have tried almost all answers but I can't get it to work :( maybe if you look at all the code you can see what I'm doing wrong.
"use strict";
var paraText = "";
var antalParagrafer = 0;
function addLetter(c) {
if(!paraText) {
addParagraph();
}
else { //add c to saved textnode
var tNod = document.createTextNode(c);
paraText.appendChild(tNod);
}
}
//function is called when enter is pressed
function addParagraph() {
/*create a new paragraph with related textnode
textnode is saved to the global textnodevariable
add paragraph to the div with id "output"
you also need to mark the paragraph with the class even/odd
depending on the class of the previous paragraph*/
var div = document.getElementById("output");
var nyParagraf = document.createElement("p");
div.appendChild(nyParagraf);
antalParagrafer += 1;
nyParagraf.className = (antalParagrafer % 2 === 0 ? 'even' : 'odd');
paraText = nyParagraf;
}
//function is called when count letters is pressed
function countLetters() {
var count=0;
for(var i = 0; i < paraText.length; i++) {
var c = paraText.charAt(i);
if (c >= 'a' && c <= 'z') count++;
}
return count;
}
I'd just strip out the non-letters and then use the length of what's left:
var count = paraText.replace(/[^a-zA-Z]/g, '').length;
Your function works otherwise fine (although it's perhaps not as elegant as it could be), but count = count ++ is wrong; either use
count++;
or
count = count + 1;
The statement count = count++ doesn't increase the counter, because the value of count++ is what's in the variable before it is increased, so you increse the variable, then assign back the value that was before.
Using a simple comparison gives better performance than using a regular expression for each character in the string:
function countLetters() {
var count=0;
for(var i = 0; i < paraText.length; i++) {
var c = paraText.charAt(i);
if (c >= 'a' && c <= 'z') count++;
}
return count;
}

Categories