Skip to content

Instantly share code, notes, and snippets.

@DorkForce
Last active March 6, 2024 18:33
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save DorkForce/34eb9a1ebf14cc5b0ba7 to your computer and use it in GitHub Desktop.
Save DorkForce/34eb9a1ebf14cc5b0ba7 to your computer and use it in GitHub Desktop.
Console script - Search breakpoint model for value. SYNTAX: scanScope($scope.model, 'Fred');
console.log("Usage Syntax: scanScope(objectToScan, 'scanFor', ['whatToIgnore']); %c(whatToIgnore is optional and can be a string, or an array of strings) (scanScope can be shortened to ss)", 'color: red');
var abortAtLevel = 20,
callStack = 0,
errArray = [],
funArray = [],
scanLoop = function (whatToScan, scanValue, whatToIgnore, parentTree) {
scanValue = scanValue.toLowerCase();
if (Array.isArray(whatToIgnore)) {
whatToIgnore.forEach(function (ignoreVal) {
ignoreVal = lowerCase(ignoreVal);
});
} else {
whatToIgnore = lowerCase(whatToIgnore);
}
var yesCheck = false,
insertString = '';
if (parentTree === undefined) {
callStack = 0;
}
callStack ++;
if (callStack > 1500) {
return;
}
for (var key in whatToScan) {
try {
yesCheck = (exists(whatToScan[key]) && (whatToScan[key].toString().indexOf !== undefined) && whatToScan[key].toString().toLowerCase !== undefined)
if ((yesCheck && whatToScan[key].toString().toLowerCase().indexOf(scanValue) > -1) || key.toLowerCase().indexOf(scanValue) >= 0) { // if we DO find a match...
if (dontIgnoreThis(whatToScan[key].toString().toLowerCase(), key.toLowerCase(), whatToIgnore)) { // check to see if we should ignore this match
if (exists(parentTree)) {
insertString = parentTree + '.';
} else {
insertString = '';
}
if (!isAutoVar(key) && !isAutoVar(insertString)) { // by default just ignore anything starting with typical auto-values
if (exists(whatToScan[key]) && whatToScan[key].toString().indexOf('function') > -1) {
funArray.push(insertString + key + ' = ' + whatToScan[key]); // we found a function so add it to the funArray
} else {
console.log(insertString + key + ' = ' + whatToScan[key]); // we found an actual variable match
}
}
}
} else { // no match found, so...
if( (typeof whatToScan[key] === 'object') && (key !== null) ) { // ... if this is an object, jump into it and continue scanning
if (exists(whatToScan[key]) && exists(whatToScan[key].toString()) && whatToScan[key].toString().indexOf('$$') < 0) {
if (exists(parentTree)) {
insertString = parentTree + '.' + key;
} else {
insertString = '' + key;
}
if (dontIgnoreThis(whatToScan[key].toString().toLowerCase(), insertString.toLowerCase(), whatToIgnore) && !tooManyLevelsDeep(insertString) ) {
scanLoop(whatToScan[key], scanValue, whatToIgnore, insertString);
}
}
}
}
} catch (err) {
errArray.push('>> ' + err + ' while scanning ' + key);
}
}
},
ss=scanScope = function (whatToScan, scanValue, whatToIgnore, parentTree) {
console.log('%c------------------------- Beginning scan', 'color: gold');
scanLoop(whatToScan, scanValue, whatToIgnore, parentTree);
if (funArray.length > 0 || errArray.length > 0) {
console.log('-------------------------');
}
if (funArray.length > 0) {
console.groupCollapsed('Functions found while scanning');
funArray.forEach(function(entry) {
console.log(entry);
});
console.groupEnd();
}
if (errArray.length > 0) {
console.groupCollapsed('Errors found while scanning');
errArray.forEach(function(entry) {
console.log(entry);
});
console.groupEnd();
}
console.log('%c------------------------- Scan complete', 'color: gold');
},
exists = function (whatToCheck) {
if (whatToCheck !== null & whatToCheck !== undefined) {
return true;
}
return false;
},
lowerCase = function (whatToLower) {
whatToLower = whatToLower !== undefined ? whatToLower.toLowerCase() : undefined;
return whatToLower
},
dontIgnoreThis = function (valToCheck1, valToCheck2, valToIgnore) {
if (!exists(valToIgnore)) {
return true;
}
var foundIgnoreInArrayCount = 0;
if (Array.isArray(valToIgnore)) {
valToIgnore.forEach(function (thisIgnoreVal) {
if (valToCheck1.indexOf(thisIgnoreVal) > -1 || valToCheck2.indexOf(thisIgnoreVal) > -1) {
foundIgnoreInArrayCount++;
}
});
if (foundIgnoreInArrayCount > 0) {
return false;
}
} else {
if (valToCheck1.indexOf(valToIgnore) > -1 || valToCheck2.indexOf(valToIgnore) > -1) {
return false;
}
}
return true;
},
tooManyLevelsDeep = function(valToCheck) {
if (valToCheck.length - valToCheck.replace(/\./g, '').length > abortAtLevel) {
return true;
}
return false;
},
isAutoVar = function(varToCheck) {
var prefixList = ['__', '$$'];
for (let prefix of prefixList) {
if (varToCheck.indexOf('.'+prefix) >= 0) return true;
if (varToCheck.substr(0,prefix.length) === prefix) return true;
}
return false;
};
@DorkForce
Copy link
Author

This is intended to be pasted into the console while investigating a breakpoint.

When run, it will search a complex model defined on the scope (submitted as 'whatToScan') for either a property that partially matches the desired search term ('scanValue'), or a property whose name partially matches the search term (also 'scanValue').

@DorkForce
Copy link
Author

Added maximum callStack of 1500 calls, filtering out angular variables starting with '$$'. This allows you to just scan your $scope for whatever you'd like. You could also increase this; I've gone 15000 calls, even, but you probably don't need that. Increasing the calls will allow it to crawl through all respecting $parent variables.

Added a try/catch in there that it shouldn't really need... hmph.

@DorkForce
Copy link
Author

Updated; apparently previously not searching for non-string values in the pairs

@DorkForce
Copy link
Author

Updated; better ongoing search indication to user. Any functions or errors found while search are now sorted into collapsed groups.

@DorkForce
Copy link
Author

Updated; surprisingly, it was logging null- or undefined- values as errors. Fixed!

@DorkForce
Copy link
Author

added spaces to the console.log line that outputs the sample syntax call. Makes it easier to select and copy after it's displayed in the console.

@DorkForce
Copy link
Author

Added optional ignore string. Later, planning on changing that to an array.

@DorkForce
Copy link
Author

Ignore value now accepts either a string OR an array of strings

@DorkForce
Copy link
Author

Redefined functions as variable declarations; certain circumstances in the developer console require this.

@DorkForce
Copy link
Author

Added "ss=scanScope" so that I can be even lazier in the console. :)

@DorkForce
Copy link
Author

Reworked the way "callStack" was implemented, renamed as abortAtLevel

@DorkForce
Copy link
Author

nope, keeping both "callStack" and "abortAtLevel" in there, because they do both matter.

@DorkForce
Copy link
Author

DorkForce commented Feb 23, 2018

Added "$$" to list of variables to exclude, and changed the way it searches for properties that begin with the "automatic" indicators __ and $$. Note that at this time, I see that if a certain-formatted object is a property on the object being searched, it's still possible that scanScope can decide to quit entirely before deciding to quit that object. Or something. Refinements, refinements.

@marvhen
Copy link

marvhen commented Sep 7, 2018

This is GREAT! thanks!

It errors in IE though because of the for...of.

I changed it to a foreach and that works.

@eioo
Copy link

eioo commented Feb 20, 2019

Thanks for this! Absolutely very nice

@mgutt
Copy link

mgutt commented Aug 28, 2021

I tried to use it with "window". Is it possible to avoid scanning nested window.window.window....?

@DorkForce
Copy link
Author

Ah crap, I realize I do not seem to get notifications about comments... my apologies for the lack of responses here... I hope/presume, @mgutt , that you were able to get around the nested window issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment