I am writing a chrome extension for practicing, which is basically remembers your password in a website the next time. However, I have a problem with running the code. window.onload, document.onload, none of them are fires my remember() function. Checked other answers, none of them could help. Checked if it gets overridden by actual code in the website, only body.onload is being overridden. Here is my code:
window.onload = remember;
var remember = function() {
var name = localStorage["name"];
var pw = localStorage["pw"];
if(pw != undefined && name != undefined)
{
document.sqrl.login_username.value = name;
document.sqrl.secretkey.value = pw;
};
document.sqrl.onsubmit = function() {
localStorage["name"] = document.sqrl.login_username.value;
localStorage["pw"] = document.sqrl.secretkey.value;
};
};
It executes the first two lines, but then does not enter inside the function, as I tested it with debugger in Chrome. What is missing in my code?
You are referencing to a variable before it is declared / visible in the scope. Do
var remember = function() {
...
...
};
window.onload = remember;
instead. Fiddle -> http://jsfiddle.net/9pcL3jz3/
You have several problems:
you use remember before defining it
your document.sqrl.login_username.value and document.sqrl.secretkey.value values depend on name and pw, name and pw depend on localStorage values, which in turn are set based on yourdocument.sqrlobjects. If you set document.sqrl.login_username.value and sqrl.secretkey.value somewhere else before the onsubmit is executed, then this is actually not a problem
you try to directly access "name" and "pw" from localStorage, I believe you cannot do that. Use the getItem and setItem functions instead
Suggested code:
var remember = function() {
var name = localStorage.getItem("name");
var pw = localStorage.getItem("pw");
if(pw != undefined && name != undefined)
{
document.sqrl.login_username.value = name;
document.sqrl.secretkey.value = pw;
};
document.sqrl.onsubmit = function() {
localStorage.setItem("name", document.sqrl.login_username.value);
localStorage.setItem("pw", document.sqrl.secretkey.value);
};
};
window.onload = remember;
EDIT:
I have read the comment of Xan and have tested the following code in my console:
localStorage["foo"] = "bar";
After reloading the page I have checked the value of localStorage["foo"] and it was "bar" indeed. Therefore, Xan was right and my third point is invalid indeed.
Try this?
window.onload = remember;
var remember = function() {
var name = localStorage.name;
var pw = localStorage.pw;
if(pw !== undefined && name !== undefined)
{
document.sqrl.login_username.value = name;
document.sqrl.secretkey.value = pw;
}
document.sqrl.onsubmit = function() {
localStorage.name = document.sqrl.login_username.value;
localStorage.pw = document.sqrl.secretkey.value;
};
};
Related
The variable cont is being lost in the following:
__factory.setupMenu = function(cont,input,multiSelect,exclusive,popMenu){
var __menu = {multiSelect:multiSelect};
spotter.events.setEventTrigger(input,'change');
__menu.exclusive = {inputs:[],values:exclusive||[],simpleValues:[]};
alert(cont);//<-- is defined here
window.popSelectComponent= cont;//<-- saved it globally to test reference
return function(ajaxResult){
var data = ajaxResult.template.response||[];
var info = {},l=data.length;
while(--l > -1){
info[String(data[l].value)] = data[l].abbr||data[l].name;
}
var textTarget;
alert(window.popSelectComponent);//<-- this is defined as expected
alert(cont);//<-- is now undefined
alert(input);//<-- this is defined as expected
if(!(textTarget = cont.querySelector('[data-pop-selected]'))){textTarget = cont;}
if(!input.popSelectTemplate){
spotter.data.bindElementToInput(textTarget,input,function(content){
content = content.split(',');
var l=content.length;
while(--l > -1){
content[l] = info[content[l]];
}
content = content.join(',');
return (content.length ? content : 'ignore');
});
}
else{
var cont = document.createElement('SPAN');//<-- PROBLEM IS CAUSED HERE. HOISTING IS CAUSING CONT TO BE UNDEFINED AT CLOSURE START
cont.className="multi-select";
cont.appendChild(cont);
//removal function
var remove = (function(input){
return function(e){
var evt = e ? e:window.event;
if (evt.stopPropagation) evt.stopPropagation();
if (evt.cancelBubble!=null) evt.cancelBubble = true;
if(input.value !== input.spotterPopSelectDefaultValue){
input.value = input.value.removeListValue(this.getAttribute('data-id'),',');
spotter.deleteElement(this);
if(input.value === '' && input.value !== input.spotterPopSelectDefaultValue){
input.value = input.spotterPopSelectDefaultValue;
input.eventTriggers['pop-select-change']();
}
}
};
}(input));
input.spotterPopMenuOptions = __menu;
input.addEventListener('pop-select-change',(function(cont, info, template){
return function(){
var HTML = '';
this.value.split(',').forEach(function(val){
HTML += template.replace('$[ID]', val).replace('$[NAME]', info[val]);
});
cont.innerHTML = HTML;
spotter.castToArray(cont.children).forEach(function(el){ console.log('option el',el); el.addEventListener('click',remove,false); });
console.log('input.spotterPopMenuOptions',input.spotterPopMenuOptions);
};
}(cont, info, input.popSelectTemplate.innerHTML)),false);
}
....
So running var func = __factory.setupMenu(...)({template:{}}) I am receiving an error message that cont is undefined while window.popSelectComponent is defined like expected. I tried changing the name of cont thinking I was overlooking something that was changing the value but that did not work either.
After running the function, I check cont in the context that initially created this closure and cont is still defined so it is not a matter of an object reference being lost as far as I can tell.
Perhaps a highly simplified example would make the problem more obvious:
var outer = function(theVariable) {
console.log("In the outer function, theVariable is", theVariable);
var inner = function() {
console.log("In the inner function, theVariable is", theVariable);
if (false) {
var theVariable = 2;
}
};
inner();
}
outer(1)
In the outer function, theVariable is 1
In the inner function, theVariable is undefined
As you have seen, the fact that a different variable with the same name has been declared (even though not initialized) in the inner function hides the properly initialized variable in the outer function that would have otherwise been visible.
You might think that because the variable is declared in a block, it would not affect other parts of the function. No, var is function scoped, not block scope.
This flaw has been addressed in modern versions of Javascript, and the var keyword has been superseded by let, which has the block scope you were expecting. var is kept for backwards compatibility, but you should not use it in new code.
Right now I'm having a major brain fart. I have this function:
function uplodeVirus(){
console.log('working')
console.log('uplodeVirus')
var form = document.getElementsByTagName('form')[1]
console.log(form)
var select = form.children[0]
console.log(select)
for (x in select) {
var lN = select[x].innerHTML // var linkName
if (lN == "vspam 0.3 [OpenRelay-backdoor.vspam ] (0.003 Gb)"){
value = select[x].value
select[x].setAttribute("selected", "selected");
form.submit()
break
}
}
}
Don't worry its not a real Virus!!! This is a bot for a game called slave hack - for learning purposes
Anyways, when I call the function:
var ip = '2.2.2.2'
var uplodeVirus = 'http://www.slavehack.com/index2.php?page=internet&var2=' + ip + '&var3=files&aktie=upload'
var currentUrl = window.location.href
console.log(currentUrl)
console.log(uplodeVirus)
if (currentUrl == uplodeVirus) { //Yes, I made sure that currentUrl = uplodeVirus
uplodeVirus()
}
Nothing happens... but if I take the code out of the function and do this:
if (currentUrl == uplodeVirus){
console.log('working')
console.log('uplodeVirus')
var form = document.getElementsByTagName('form')[1]
console.log(form)
var select = form.children[0]
console.log(select)
for (x in select) {
var lN = select[x].innerHTML // var linkName
if (lN == "vspam 0.3 [OpenRelay-backdoor.vspam ] (0.003 Gb)"){
value = select[x].value
select[x].setAttribute("selected", "selected");
form.submit()
break
}
}
}
It works!!! Now, I could go with option B, but I really want to figure out what i did wrong.
Thanks in advance!
You are naming both a URL variable and a function with the same name: uplodeVirus
Since the variable is initialized to hold a string before you try to call the function, calling uplodeVirus() is the same as calling ("")(). It doesn't make any sense, because a string is not a function.
Try changing the name of one or the other.
This is my code (it's a bookmarklet)
javascript:(function(){
a=document.createElement('script');
a.setAttribute('src','//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js');
document.body.appendChild(a);
data='[["#txtapplicantlname","agrawal","text"],["#txtapplicantfname","aayush","text"],["#txtfather","Ranjan","text"],["#txtmother","Neelam","text"],["#txtPincode","452010","text"],["#txtPhone","2147483647","text"],["#txtEmail","aayush#mail.com","text"]]';
for(a=$.parseJSON(data),b=a.length-1;0<=b;b--){
c=a[b];
if (c[2] == 'text') {
console.log(c);
$(c[0]).val(c[1]);
}
}
})();
It used to work fine until I inserted the if statement, then it broke. The console doesn't give me any errors and I have googled a lot for javascript string comparison errors and found nothing useful.
I tried to use equals and compareTo and ended up with console errors and nothing working.
Uncaught TypeError: Cannot call method 'equals' of undefined fillform.php:1
Uncaught TypeError: Cannot call method 'compareTo' of undefined
Help is highly appreciated.
Note: The variables are named like that for a reason, it being that it was initially compiled with Google closure compiler and the if statement is being edited in.
There are several things wrong with this code; string comparison is not one of them.
1) You aren't waiting for the asynchronously loaded script to complete. This code should pretty much always fail because $.parseJSON() isn't available. In fact, once I fixed that problem, this code works fine for me:
(function(){
a=document.createElement('script');
a.setAttribute('src','//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js');
var afterJqueryLoad = function() {
data='[["#txtapplicantlname","agrawal","text"],["#txtapplicantfname","aayush","text"],["#txtfather","Ranjan","text"],["#txtmother","Neelam","text"],["#txtPincode","452010","text"],["#txtPhone","2147483647","text"],["#txtEmail","aayush#mail.com","text"]]';
for(a=$.parseJSON(data),b=a.length-1;0<=b;b--){
c=a[b];
if (c[2] == 'text') {
console.log(c);
$(c[0]).val(c[1]);
}
}
};
var jqueryReady = false;
a.onreadystatechange= function () {
if((this.readyState == 'complete' || this.readyState == 'loaded') && !jqueryReady) {
jqueryReady = true;
afterJqueryLoad();
}
};
a.onload = function() {
if(!jqueryReady) {
jqueryReady = true;
afterJqueryLoad();
}
};
document.body.appendChild(a);
})();
2) Use better var names (a, b, and c are not good var names).
3) Use var to scope vars correctly. Right now your code is shadowing globals and stomping on vars even within the same scope; the a var, for example, would stomp on your script elem var. (You should still change the var names per (2) but using var is not optional; you must always do this to scope vars correctly.)
4) Use spaces to help readability; your for line is unnecessarily difficult to read having no spaces.
All together now:
(function(){
var jqueryScriptElem = document.createElement('script');
jqueryScriptElem.setAttribute('src', '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js');
var afterJqueryLoad = function() {
var data = '[["#txtapplicantlname","agrawal","text"],["#txtapplicantfname","aayush","text"],["#txtfather","Ranjan","text"],["#txtmother","Neelam","text"],["#txtPincode","452010","text"],["#txtPhone","2147483647","text"],["#txtEmail","aayush#mail.com","text"]]',
dataParsed = $.parseJSON(data);
for(var dataItemIndex = dataParsed.length - 1; 0 <= dataItemIndex; dataItemIndex--) {
var dataItem = dataParsed[dataItemIndex];
if (dataItem[2] == 'text') {
console.log(dataItem);
$(dataItem[0]).val(dataItem[1]);
}
}
};
var jqueryReady = false;
jqueryScriptElem.onreadystatechange = function () {
if((this.readyState == 'complete' || this.readyState == 'loaded') && !jqueryReady) {
jqueryReady = true;
afterJqueryLoad();
}
};
jqueryScriptElem.onload = function() {
if(!jqueryReady) {
jqueryReady = true;
afterJqueryLoad();
}
};
document.body.appendChild(jqueryScriptElem);
})();
This should be a simple if statement, but it's not working for me. Essentially, when you click an element, I want that element to be highlighted and the ID to be put into a the variable value. However, if in the situation the same element is clicked twice, I want to value = NULL.
(function($){
$(".list").click(function() {
$(this).toggleClass("hilite");
var temp = $(this).attr('id');
if (value != temp) {
var value = $(this).attr('id');
} else {
value = NULL;
}
});
})(jQuery);
Your primary problem is that you're "hoisting" the value variable by redefining it with the var keyword. This code can also be written more efficiently with a lot less code. This should work:
(function($) {
// somewhere outside click handler
var value = '';
// click handler
$(".list").click(function() {
var id = $(this).toggleClass('hilite').attr('id');
value = (value === id) ? null : id;
/* or if you prefer an actual if/else...
if (value === id) {
value = null;
else {
value = id;
}
*/
});
})(jQuery);
Edit: a couple general comments about the original snippet that might be useful:
NULL should be null
Try not to run the same selector multiple times, or recreate a jQuery object from the same DOM object multiple times - it's much more efficient and maintainable to simply cache the result to a variable (e.g., var $this = $(this);)
Your comparison there is probably "safe", but better to use !== than != to avoid unintentional type coercion.
Not sure how exactly you intended to use value in the original example, but always remember that variables are function-scoped in JavaScript, so your var value statement is hoisting the value identifier for that entire function, which means your assignments have no effect on anything outside that click handler.
You need to declare var value outside the scope of the function, so that its value is maintained across function calls. As it is, the value variable is lost right after it is set, because it goes out of scope.
var value = null;
(function($){
$(".list").click(function() {
$(this).toggleClass("hilite");
var temp = $(this).attr('id');
if (value != temp) {
value = temp;
} else {
value = null;
}
});
})(jQuery);
You could do:
(function($){
var tmp = {};
$(".list").click(function() {
$(this).toggleClass("hilite");
var id = $(this).attr('id');
if (!tmp[id]) {
var value = id;
tmp[id] = true;
} else {
value = NULL;
tmp[id] = false;
}
});
})(jQuery);
In this way you use a tmp object that stores the state for all the different id's
It might not be skipping that statement, you might just be getting a confusion over the implied global "value" and the local "value".
(function($){
$(".list").click(function() {
$(this).toggleClass("hilite");
var temp = $(this).attr('id');
if (value != temp) { // <-----------------Implied global var called "value"
var value = $(this).attr('id'); // <---Local variable valled "value"
} else {
value = NULL; // <---------------------Which one am I
}
});
})(jQuery);
Also, it ought to be value = null as NULL is just an undefined variable.
This should be a working example of both points:
var value = null;
(function($){
$(".list").click(function() {
$(this).toggleClass("hilite");
var temp = $(this).attr('id');
if (value != temp) {
value = $(this).attr('id');
} else {
value = null;
}
});
})(jQuery);
Do you not need to declare value before you use it in the conditional statement?
you aren't setting a value in this function.
var value = "NULL";
(function($){
$(".list").click(function() {
$(this).toggleClass("hilite");
var temp = $(this).attr('id');
if (value != temp) {
value = $(this).attr('id');
} else {
value = "NULL";
}
});
})(jQuery);
The variable value is not defined. And it either needs to be a global variable or you could use jQuery's $('.selector).data() method to attach it to the element:
http://api.jquery.com/data/
I also recommend using !== for the comparison, since that compares the type of the variable as well as the content.
How to write this JavaScript code without eval?
var typeOfString = eval("typeof " + that.modules[modName].varName);
if (typeOfString !== "undefined") {
doSomething();
}
The point is that the name of the var that I want to check for is in a string.
Maybe it is simple but I don't know how.
Edit: Thank you for the very interesting answers so far. I will follow your suggestions and integrate this into my code and do some testing and report. Could take a while.
Edit2: I had another look at the could and maybe itis better I show you a bigger picture. I am greatful for the experts to explain so beautiful, it is better with more code:
MYNAMESPACE.Loader = ( function() {
function C() {
this.modules = {};
this.required = {};
this.waitCount = 0;
this.appendUrl = '';
this.docHead = document.getElementsByTagName('head')[0];
}
function insert() {
var that = this;
//insert all script tags to the head now!
//loop over all modules:
for (var modName in this.required) {
if(this.required.hasOwnProperty(modName)){
if (this.required[modName] === 'required') {
this.required[modName] = 'loading';
this.waitCount = this.waitCount + 1;
this.insertModule(modName);
}
}
}
//now poll until everything is loaded or
//until timout
this.intervalId = 0;
var checkFunction = function() {
if (that.waitCount === 0) {
clearInterval(that.intervalId);
that.onSuccess();
return;
}
for (var modName in that.required) {
if(that.required.hasOwnProperty(modName)){
if (that.required[modName] === 'loading') {
var typeOfString = eval("typeof " + that.modules[modName].varName);
if (typeOfString !== "undefined") {
//module is loaded!
that.required[modName] = 'ok';
that.waitCount = that.waitCount - 1;
if (that.waitCount === 0) {
clearInterval(that.intervalId);
that.onSuccess();
return;
}
}
}
}
}
};
//execute the function twice a second to check if all is loaded:
this.intervalId = setInterval(checkFunction, 500);
//further execution will be in checkFunction,
//so nothing left to do here
}
C.prototype.insert = insert;
//there are more functions here...
return C;
}());
var myLoader = new MYNAMESPACE.Loader();
//some more lines here...
myLoader.insert();
Edit3:
I am planning to put this in the global namespace in variable MYNAMESPACE.loadCheck, for simplicity, so the result would be, combining from the different answers and comments:
if (MYNAMESPACE.loadCheck.modules[modName].varName in window) {
doSomething();
}
Of course I will have to update the Loader class where ever "varName" is mentioned.
in JS every variable is a property, if you have no idea whose property it is, it's a window property, so I suppose, in your case, this could work:
var typeOFString = typeof window[that.modules[modName].varName]
if (typeOFString !== "undefined") {
doSomething();
}
Since you are only testing for the existence of the item, you can use in rather than typeof.
So for global variables as per ZJR's answer, you can look for them on the window object:
if (that.modules[modName].varName in window) {
...
}
If you need to look for local variables there's no way to do that without eval. But this would be a sign of a serious misdesign further up the line.