Way to save console.count() as an integer? - javascript

I am trying to divide 1 by the console.count() every time it is used. However, this code does not work.
var counter = console.count();
console.log(1/counter);
Any suggestions on how I could do this? I tried doing parseInt but no luck.

Way to save console.count() as an integer?
No. console.count() does not return anything, it directly prints to the console, just like console.log().
Simple implementation of console.count:
var count = (function() {
var counter = {};
return function(v) {
return (counter[v] = (counter[v] || 0) + 1);
}
}());
console.log('foo', count('foo'));
console.log('foo', count('foo'));
console.log('bar', count('bar'));

Here is a script that intercepts messages sent to the console.
var counter = 0;
function takeOverConsole(){
var console = window.console
if (!console) return
function intercept(method){
var original = console[method]
console[method] = function(){
var message = Array.prototype.slice.apply(arguments).join(' ')
// do sneaky stuff
if (original.call){
// Do this for normal browsers
original.call(console, message)
}else{
// Do this for IE
original(message)
}
counter++;
}
}
var methods = ['log', 'warn', 'error', 'count']
for (var i = 0; i < methods.length; i++)
intercept(methods[i])
}
To take Felix King's answer a bit further. Here is a more accurate way to intercept and count anything being sent to the console.
You can customize the function a bit and add any methods you want to track and count.
All console methods
I talk about it more here

Related

Accessing a variable in a function for a different function - Javascript

This may seem like a duplicate question, and to some extent, it is, but I have already been through many similar questions, and sadly, none have suited my need. I would really appreciate problem-specific advice.
My main problem in the JavaScript code here is that I cannot access the values in the variables RememberText20 and RememberFullText, in function TextLimiter, from function ReadMoreLessText. The "Message" is an argument for the ReadMoreLessText function, which essentially matches the element clicked to the correct value in the aforementioned variables, which are themselves arrays.
*I know there is nothing wrong with the arrays themselves, as they retain their values as they are supposed to, because a simple alert() proves this. Similarly, there is nothing wrong with the Message argument, as the function ReadMoreLessText works fine with other values.
My simple problem is that I cannot access the values in the aforementioned variables, from the ReadMoreLessText function, although they are global variables, as they should be.
I would really appreciate a problem-specific answer here. Thank you in advance.
// JavaScript Document
//Start Text250
window.onload = function TextLimiter() {
for (y = 0; y < 6; y++) {
FullText = document.getElementsByClassName("Introduction")[y].innerHTML;
TextLength = FullText.length;
RememberFullText = [];
RememberFullText[y] = FullText;
var Text250 = FullText.substr(0, 250) + "...";
RememberText250 = [];
RememberText250[y] = Text250;
if (TextLength > 250) {
document.getElementsByClassName("Read_More")[y].innerHTML = "Read More→";
document.getElementsByClassName("Introduction")[y].innerHTML = Text250;
} else {
document.getElementsByClassName("Read_More")[y].innerHTML = "";
}
}
};
//End Text250
//Start ReadMoreLessText
var ReadMore = function(Message) {
var ScreenText = document.getElementsByClassName("Introduction")[Message].innerHTML;
if (ScreenText === RememberText250[Message]) {
document.getElementsByClassName("Introduction")[Message].innerHTML = RememberText250[Message];
} else {
document.getElementsByClassName("Introduction")[Message].innerHTML = RememberText250[Message];
}
};
//End ReadMoreLessText
Try defining RememberFullText and RememberText250 outside the enclosing for loop.
window.onload = function TextLimiter() {
RememberFullText = [];
RememberText250 = []
for (y = 0; y < 6; y++) {
...
As written they are set to an empty array in each iteration of the loop. Hence only the last entry of each array will be retained after the loop has finished.
I don't see your variables declared as globals. Do you have a var RememberText20, RememberFullText; outside any function?

Iterate a function until result from called function is equal, javascript

I need to iterate a function several times until it returns same thing twice.
This needs to go into a for-loop somehow but I can't get my head around how to this. Here's some code with 4 manual iterations. Any ideas how to put this in a for-loop?
Velocity.prototype.removeCombinedDistancesThatAreShorterThanTrainLength = function(wayPoints, lengthOfTrain){
var firstTry = this.removeWayPointsWhichAreShorterThenTrainLength(wayPoints, lengthOfTrain);
var secondTry = this.removeWayPointsWhichAreShorterThenTrainLength(firstTry, lengthOfTrain);
if(firstTry === secondTry){
return firstTry;
}else{
var thirdTry = this.removeWayPointsWhichAreShorterThenTrainLength(secondTry, lengthOfTrain);
if(thirdTry === secondTry){
return secondTry
}else{
var forthTry = this.removeWayPointsWhichAreShorterThenTrainLength(thirdTry, lengthOfTrain);
if(thirdTry === forthTry){
return forthTry
}
}
}
return forthTry;
};
Something like this (not tried, but should give you the general idea):
var lastTry = null;
var thisTry = wayPoints;
do
{
lastTry = thisTry;
thisTry = this.removeWayPointsWhichAreShorterThenTrainLength(lastTry, lengthOfTrain);
} while (lastTry !== thisTry);
If it's possible that the result will never become equal, consider implementing a safeguard for this, like a maximum number of iterations.

Accessing the value of an observable inside a plain JS array in Knockout JS?

Background
I have a plain JS array, initially empty. I later populate it with values. The values sent to it are numbers that are Knockout observables. Later, I want to compare those values to values in another, knockout observable array. My problem is that whenever I pass the index of the current item in my array loop, and pass that index value (a number!), the array returns a function. To get an idea, look at the JS that follows.
Note that my project and actual script is viewable on JSBin. Further, to view the problem in the console, you have to add assignments, then press 'sort'.
JSBin: http://jsbin.com/fehoq/177/edit]1
JS
//example script that follows actual script
var _this = this;
//initialize my array
this. lowest = [];
// I want to compare values in lowest to values in this array
this.scores = ko.observableArray();
// method that does comparison
this.myMethod = function(){
// initialize my helper, k
var k;
...
// loop through one array
ko.utils.arrayForEach(_this.scores(), function (score) {
// make sure my value is a number...
if (!isNaN(parseFloat(score()))) {
// this is important, I need to current index for comparison
k = _this.scores.indexOf(score);
console.log(k);
// this is where things break - it prints a function, not a value!
console.log(_this.lowest[k]);
// useless check, the value is a function, so they're always different
if (score()!=_this.lowest[k]){
// do stuff
}
}
}
}
Update
Putting the method I'm using, maybe someone will notice something I missed given that my syntax is correct(?).
this.mean = (function(scores,i) {
var m = 0;
var count = 0;
var k;
ko.utils.arrayForEach(_this.scores(), function(score) {
console.log([typeof score(), score()]);
if (!isNaN(parseFloat(score()))) {
console.log(i);
console.log(_this.lowest[i]);
if (score() != _this.lowest[i]) {
m += parseFloat(score());
count += 1;
}
}
});
if (count) {
m = m / count;
return m.toFixed(2);
} else {
return 'N/A';
}
});
}
Update 2
Just in case someone else wanders over here since my problem isn't solve still. The following code is how I set the value of lowest:
this.dropLowestScores = function() {
ko.utils.arrayForEach(_this.students(), function(student){
var comparator = function(a,b){
if(a()<b()){
return 1;
} else if(a() > b()){
return -1;
} else {
return 0;
}
};
var tmp = student.scores().slice(0);
tmp.sort(comparator);
student.lowest = ko.observableArray(tmp.splice((tmp.length-2),tmp.length-1));
});
};
Outstanding Questions, 5/9/2014
Jeremy's script runs but without the desired effects. For example, console.log(_this.lowest[k]) prints undefined, just as mine does. Further, the matched scores aren't skipped, which they should be.
Jeremy's script specifies lowest as a ko.observable. My script also now has lowest as a ko.observable, but why shouldn't a plain JS array work for this? I only need lowest to update when the button it's bound to is clicked, and those bindings are already taken care of.
That is how observables work in Knockout.
When you create one, you are creating a function.
var myObservable1 = ko.observable(); // Create it.
var myObservable2 = ko.observable("Hola!"); // Create it with a value.
console.log(typeof myObservable2); // It is indeed a function
console.log(typeof myObservable2()); // That returns a string
console.log(myObservable2()); // And get the value.
EDIT BASED ON QUESTION IN COMMENTS
var koTest = ko.observableArray();
koTest.push("Line0");
koTest.push("Line1");
koTest.push("Line2");
koTest.push("Line3");
koTest.push("Line4");
var jsTest = [];
jsTest.push("Line0");
jsTest.push("Line1");
jsTest.push("Line2");
jsTest.push("Line3");
jsTest.push("Line4");
alert(koTest()[2]);
alert(jsTest[2]);
alert(koTest()[2] === jsTest[2]);
Test Code
I went ahead and make a runnable test of your code and everything was working just fine for me. I had to make some assumptions about the contents of _this -- in particular the declaration of lowest, which I made an observableArray based on how you were accessing it.
Anyways, this code runs:
var _this = {
scores: ko.observableArray(),
lowest: ko.observableArray()
};
var mean = (function(scores) {
var m = 0;
var count = 0;
var k;
ko.utils.arrayForEach(_this.scores(), function(score) {
console.log([typeof score(), score()]);
if (!isNaN(parseFloat(score()))) {
k = _this.scores.indexOf(score);
console.log(k);
console.log(_this.lowest[k]);
if (score() != _this.lowest[k]) {
m += parseFloat(score());
count += 1;
}
}
});
if (count) {
m = m / count;
return m.toFixed(2);
} else {
return 'N/A';
}
});
for (var i = 0; i < 10; i++) {
_this.scores.push(ko.observable(i));
}
var m = mean();
alert(m);

Error calling function second time

I have a function which works just fine the first if I call it just once, but when I call it repeatedly within a for loop, I get the following error:
TypeError: getNamedRange is not a function, it is string.
Doing a search on this error gives me a clue that this is a javascript error, not a Google Apps Script error. I haven't worked much with javascript, but I suspect it may have something to do with how I return the value from the function.
This is the code which calls the function:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var baseSheet = ss.getSheetByName("Base");
var catCol = 9;
var riskAreaColumn = 10;
var numRows = baseSheet.getDataRange().getNumRows();
// I am not using this var, should I be?
var data = baseSheet.getDataRange().getValues();
var cell;
var rangeName;
var range;
var rule;
for(var i=2; i<numRows; i++){
cell = baseSheet.getRange(i, riskAreaColumn);
rangeName = getNamedRange("CategoryRiskRange",baseSheet.getRange(i, catCol).getValue());
range = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(rangeName);
rule = SpreadsheetApp.newDataValidation().requireValueInRange(range).build();
cell.setDataValidation(rule);
}
SpreadsheetApp.flush();
}
This is the function being called:
function getNamedRange(categoryRange, category) {
var categoryList = SpreadsheetApp.getActive().getRangeByName(categoryRange).getValues();
for (var i = 0; i < categoryList.length; i++) {
if (categoryList[i][0] == category) {
getNamedRange = categoryList[i][1];
return getNamedRange;
}
}
}
The first time through the for loop works, the second time gives me the aforementioned error. Thank you for reading this, I hope it's clear.
you are overwriting the function definition here:
getNamedRange = categoryList[i][1];
this will work:
if (categoryList[i][0] == category) {
return categoryList[i][1];
}
Javascript doesn't interpret things until it gets to them, and is very happy to redefine things when you tell it to.
The first time through, it sees
function getNamedRange(categoryRange, category)
and says "oh, a function! Cool!" But in that function, you have the line
getNamedRange = categoryList[i][1];
and it says "Oh, so getNamedRange is something else now. Okay, I'm fine with that."
Rename your variable, and you should be fine.

How to stop all timeouts and intervals using javascript? [duplicate]

This question already has answers here:
javascript: Clear all timeouts?
(13 answers)
Closed 6 years ago.
I'm working on an ajax web appliation which contains many running timeouts and intervals. And now I need to clear all running timeouts and intervals sometimes. Is there a simple way to stop everything without need to store every timeout and interval ID and iterate through them and clear them?
Sometimes it's possible to save the timer Id / Handle to clear it later which would be the best solution. So this is a second best. But I wanted to give a better understanding of what's going on. It basically grabs the highest timer id and clears everything less than that. But it's also possible to clear other timers that you do not want to clear!
It is a little hackish, so be warned!
// Set a fake timeout to get the highest timeout id
var highestTimeoutId = setTimeout(";");
for (var i = 0 ; i < highestTimeoutId ; i++) {
clearTimeout(i);
}
Updated answer after reading the duplicate I closed this question with -
It works and tested in Chrome on OSX
// run something
var id1 = setInterval(function() { console.log("interval", new Date())}, 1000);
var id2 = setTimeout(function() { console.log("timeout 1", new Date())}, 2000);
var id3 = setTimeout(function() { console.log("timeout 2", new Date())}, 5000); // not run
setTimeout(function() { console.log("timeout 3", new Date())}, 6000); // not run
// this will kill all intervals and timeouts too in 3 seconds.
// Change 3000 to anything larger than 10
var killId = setTimeout(function() {
for (var i = killId; i > 0; i--) clearInterval(i)
}, 3000);
console.log(id1, id2, id3, killId); // the IDs set by the function I used
NOTE: Looked at window objects that had a typeof number - funnily enough IE assigns an 8 digit number, FF a single digit starting with 2
Here is a workaround.
window.timeoutList = new Array();
window.intervalList = new Array();
window.oldSetTimeout = window.setTimeout;
window.oldSetInterval = window.setInterval;
window.oldClearTimeout = window.clearTimeout;
window.oldClearInterval = window.clearInterval;
window.setTimeout = function(code, delay) {
var retval = window.oldSetTimeout(code, delay);
window.timeoutList.push(retval);
return retval;
};
window.clearTimeout = function(id) {
var ind = window.timeoutList.indexOf(id);
if(ind >= 0) {
window.timeoutList.splice(ind, 1);
}
var retval = window.oldClearTimeout(id);
return retval;
};
window.setInterval = function(code, delay) {
var retval = window.oldSetInterval(code, delay);
window.intervalList.push(retval);
return retval;
};
window.clearInterval = function(id) {
var ind = window.intervalList.indexOf(id);
if(ind >= 0) {
window.intervalList.splice(ind, 1);
}
var retval = window.oldClearInterval(id);
return retval;
};
window.clearAllTimeouts = function() {
for(var i in window.timeoutList) {
window.oldClearTimeout(window.timeoutList[i]);
}
window.timeoutList = new Array();
};
window.clearAllIntervals = function() {
for(var i in window.intervalList) {
window.oldClearInterval(window.intervalList[i]);
}
window.intervalList = new Array();
};
It works for set/clear timeout/interval functions called after these lines are executed. Try and see it works:
setInterval('console.log(\'a\')', 1000);
setInterval('console.log(\'b\')', 500);
setInterval('console.log(\'c\')', 750);
setTimeout('clearAllIntervals()', 10000);
Proxying does the magic.
var noofTimeOuts = setTimeout('');
for (var i = 0 ; i < noofTimeOuts ; i++) clearTimeout(i);
var max = setTimeout(function(){ /* Empty function */ },1);
for (var i = 1; i <= max ; i++) {
window.clearInterval(i);
window.clearTimeout(i);
if(window.mozCancelAnimationFrame)window.mozCancelAnimationFrame(i); // Firefox
}
There's nothing built-in, but it's pretty easy to blast through all currently outstanding deferred execution functions by calling this clearAll() function:
function clearAll() {
for (var i = setTimeout(function() {}, 0); i > 0; i--) {
window.clearInterval(i);
window.clearTimeout(i);
if (window.cancelAnimationFrame) window.cancelAnimationFrame(i);
}
}
If you are in charge of the page you run, and can wrap the native deferred execution functions in wrappers that do the house keeping for of course equip each setter function with a corresponding .clearAll() too:
(function(deferFunctions) {
for (var setter in deferFunctions) (function(setter, clearer) {
var ids = [];
var startFn = window[setter];
var clearFn = window[clearer];
function clear(id) {
var index = ids.indexOf(id);
if (index !== -1) ids.splice(index, 1);
return clearFn.apply(window, arguments);
}
function set() {
var id = startFn.apply(window, arguments);
ids.push(id);
return id;
}
set.clearAll = function() { ids.slice(0).forEach(clear); };
if (startFn && clearFn) {
window[setter] = set;
window[clearer] = clear;
}
})(setter, deferFunctions[setter]);
})(
{ setTimeout: 'clearTimeout'
, setInterval: 'clearInterval'
, requestAnimationFrame: 'cancelAnimationFrame'
});
To try that it works, you could then try doing this, for instance, which will remain silent, as none of the callbacks end up firing before they're cancelled again:
// Some example timers of all types:
requestAnimationFrame(console.error);
setInterval(console.info, 1000, 'interval');
setTimeout(alert, 0, 'timeout');
// Now you can clear all deferred functions
// by execution type, whenever you want to:
window.setTimeout.clearAll();
window.setInterval.clearAll();
window.requestAnimationFrame.clearAll();
A little hack added to Gokhan Ozturk's answer
If you are using third party libraries which uses Timeouts and Intervals then they will also be cleared, so I added one parameter to notify function that this interval is to be push'ed or not to array.
window.setTimeout = function(code, delay, toBeAdded) {
var retval = window.oldSetTimeout(code, delay);
var toBeAdded = toBeAdded || false;
if(toBeAdded) {
window.timeoutList.push(retval);
}
return retval;
};
... // likewise for all functions.
You might be better off creating a scheduler. Take a look at this approach by Nader Zeid:
https://www.onsip.com/blog/avoiding-javascript-settimeout-and-setinterval-problems
It's an approach that help create some determinacy (because "the time interval argument of each of those functions really only establishes that the given function will execute after at least that amount of time. So a timed event can miss its target by literally any amount of time.").
Specifically, to the question you raise here, you can easily add and remove functions from the queue. While this response is long after the question was raised, hopefully it's helpful to any who find themselves struggling with Timeouts and Intervals.
You cannot clear any timeouts and intervals you don't know about.
You'd need something like getTimeoutList which isn't in the DOM3 spec, or even planned, AFAIK.
The previous proxying trick is nice, but if you have a lot of timeouts and intervals, I would not fill the arrays with consecutive numbers [1,2,3....], but with intervals. For example, instead of having [1,2,3,7,8,9], you would have maybe something like ['1-3','7-9'] or [[1,3],[7,9]], as a memory optimization. Of course this trick is only suited if you have a lot of timeouts and intervals and also if you would not stop arbitrary intervals that often.

Categories

Resources