Keep JQuery Vars for another function (Global vars?) - javascript

I'm trying to make a password check system.
I've decided I also want to check if it is a commonly used password.
For this, I'm loading an external txt file into an array. However, my password check function does not seem to be able to read this array.
jQuery(document).ready(function() {
var commonPass = new Array;
jQuery.get('/static/commonPass.txt', function(data){
commonPass = data.split('\n');
console.log(commonPass);
});
console.log(commonPass);
//you have to use keyup, because keydown will not catch the currently entered value
jQuery('input[type=password]').keyup(function() {
// set password variable
var pswd = jQuery(this).val();
//check if common password
console.log(pswd);
if ( jQuery.inArray(str.toLowerCase(pswd), commonPass)!= -1) {
console.log('InArray');
jQuery('#known').removeClass('valid').addClass('invalid');
} else {
console.log('NotInArray');
jQuery('#known').removeClass('invalid').addClass('valid');
}
});
Is it possible to make global jQuery/Javascript variables and would that be the solution to this issue?

Move commonPass outside of the scope of all functions
jQuery(document).ready(function() {
var commonPass = new Array;
...Should be...
var commonPass = new Array;
jQuery(document).ready(function() {
Or else you can use window.commonPass. window is javascript's "global" variable when working in the browser. Javascript's variables live inside the scope of the functions they were declared in (or window if outside of a function).

Related

Swapping hardcoded arguments for variables

I've got a functional script on my site that allows me to open a link in a new window when a specific class is added to the link. I need a lot of those on my site though so I figured I'd make the script a bit easier to edit by working with variables.
In the process of changing out hardcoded strings for variables my script stopped working though. The only one that works is the var where I set the url.
I'm learning that ${} doesn't work everywhere. Hope that someone can point out where my thinking is wrong. Also hope that I got the terminology right, trying to learn though! :-)
var function1Name = "test_function";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class";
function ${function1Name}() {
window.open(function1Url, "_blank", "height=200");
}
jQuery("${function1Class}").click(function(){
${function1Name}()
});
None of your uses of ${} are valid JavaScript syntax.
Your function declaration van be replaced with:
window[function1Name] = function () {
window.open(function1Url, "_blank", "height=200");
}
Please note that the function will no longer be hoisted when declared this way, so order of operation matters.
The click handler can be written as follows:
jQuery(function1Class).click(function() { // Note that I just used the variable there.
window[function1Name]();
});
There is a ${} concept in JavaScript, but that is only in template literals:
const myVariable = "Foo";
const message = `myVariable contains: "${myVariable}"!`;
console.log(message);
There's several syntax issues here.
Firstly, function ${function1Name}() is not valid syntax. Function names must be defined before runtime. If you want to dynamically access a function, place it in an object and set the key with the variable reference.
Secondly, ${function1Name}() is again not valid syntax. You cannot invoke a function like that dynamically. Referring to the suggestion above, you can access an object dynamically so the first point fixes this problem.
Thirdly, string interpolation only works within template literals, so you need to delimit the string with backticks: ``. However it's completely redundant here as you can just use $(function1Class)
With those issues in mind, here's an updated example:
var function1Name = "test_function";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class";
var funcObj = {
[function1Name]: function() {
console.log(`function called, window would open here containing ${function1Url}...`);
// window.open(function1Url, "_blank", "height=200");
}
}
$(function1Class).click(function() {
funcObj[function1Name]()
});
/*
alternative using a template literal, although note that it's redundant here
$(`${function1Class}`).click(function() {
funcObj[function1Name]()
});
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click me
One last thing to note is that no version of IE supports template literals, so be sure of your browser support requirements before using them.
So cool, I got it to work!
var function1Name = "test_function_1";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class1";
var function2Name = "test_function_2";
var function2Url = "https://www.cnn.com";
var function2Class = ".test_function_class2";
// Function 1
window[function1Name] = function () {
window.open(function1Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function1Class).click(function() {
window[function1Name]();
});
// Function 2
window[function2Name] = function () {
window.open(function2Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function2Class).click(function() {
window[function2Name]();
});
I can now add a bunch of url's and corresponding classes as was my intention. Super happy about that.
A follow up question though, as I'll have to experiment with what the ideal window parameters will be I'm trying to make those arguments variables as well. I've tried the examples of how to insert a variables output from the functional code but those methods don't work there. Here's that code:
var windowWidth = 250
var function1Name = "test_function_1";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class1";
var function2Name = "test_function_2";
var function2Url = "https://www.cnn.com";
var function2Class = ".test_function_class2";
// Function 1
window[function1Name] = function () {
window.open(function1Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=[windowWidth],height=745");
}
jQuery(function1Class).click(function() {
window[function1Name]();
});
// Function 2
window[function2Name] = function () {
window.open(function2Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function2Class).click(function() {
window[function2Name]();
});
How would I insert the variables value (2nd line of Function1) there ?

Is it bad practice to instantiate variables inside of $(document).ready as opposed to globally declaring them?

I'm trying to avoid the use of global variables in my code, so I'm trying to use a work around by declaring them inside of $(document).ready and passing them as parameters to functions outside of $(document).ready, updating them, and then returning the updated value from those functions to manipulate the variables inside of $(document).ready.
Another way around this is to use hidden input fields to store variables but I also heard that was bad practice.
I'm wondering if I should just use global variables, do it the way I'm currently doing it, or use hidden input fields?
Below is a brief example of what I'm trying to accomplish. The variable validations is the variable I want to be able to use and update.
$(document).ready(function(){
var validations = [];
$('#inp').keypress(function(e){
if(e.which == 13){
e.preventDefault();
scanValidation(validations, function(valid){
validations = valid;
});
}
});
}):
function scanValidation(valid, cb){
var scanval = $('#inp').val();
if(valid.includes(scanval)){
//display error
}
else{
var validarr = valid.slice();
validarr.push(scanval);
var myData=JSON.stringify({ "name":"user1", "validations":validarr});
//Makes an ajax call to see if the sent array validarr is a valid request
apiCall(myData,'scanValidation',function(decoded) {
if (decoded.Status!="ERROR") {
valid = validarr;
}
else {
//display error
}
return(cb(valid));
});
}
}
Any variables declared within the immediately executed function below will NOT be in the global scope.
(function () {
var someVar = 'someValue';
$(document).ready(function() {
});
})();
Is it bad practice to instantiate variables inside of $(document).ready as opposed to globally declaring them?
No, not at all! Variables should always be declared in the scope they're needed in, nowhere else.
Another way around this is to use hidden input fields to store variables but I also heard that was bad practice.
I've never heard of that, but yes it definitely sounds like a bad practise. That's just the same as a global variable, but a global variable stored in the DOM for some odd reason.
I'm trying to avoid the use of global variables in my code, so I'm trying to use a work around by declaring them inside of $(document).ready and passing them as parameters to functions outside of $(document).ready, updating them, and then returning the updated value from those functions to manipulate the variables inside of $(document).ready.
That, admittedly, is a bit weird.
The easiest way to improve this is to move the function declaration inside the ready handler as well, and just access the variable there directly - with the additional bonus of not having a scanValidation global variable:
$(document).ready(function() {
var validations = [];
function scanValidation() {
var scanval = $('#inp').val();
if (validations.includes(scanval)) {
//display error
} else {
var validarr = validations.slice();
validarr.push(scanval);
var myData = JSON.stringify({"name": "user1", "validations": validarr});
// Makes an ajax call to see if the sent array validarr is a valid request
apiCall(myData, 'scanValidation', function(decoded) {
if (decoded.Status!="ERROR") {
validations = validarr;
} else {
//display error
}
});
}
}
$('#inp').keypress(function(e){
if(e.which == 13){
e.preventDefault();
scanValidation();
}
});
});
If you want to make scanValidation reusable, so that it could be called from other places as well with its own array, I would suggest to create a factory function that creates validators, each of which is a closure over its own array. That way, the array is declared where it belongs, so that the user of the function does not have to store the state for them:
function makeScanValidator(display) { // any other configuration
var validations = [];
// returns closure
return function scanValidation(scanval) { // take it as an argument
if (validations.includes(scanval)) {
display(/* error */);
} else {
var validarr = validations.concat([scanval]);
var myData = JSON.stringify({"name": "user1", "validations": validarr});
apiCall(myData, 'scanValidation', function(decoded) {
if (decoded.Status!="ERROR") {
validations = validarr;
} else {
display(/* error */);
}
});
}
}
$(document).ready(function() {
var validate = makeScanValidator(function display() { … });
$('#inp').keypress(function(e){
if(e.which == 13){
e.preventDefault();
validate(this.value);
}
});
});

Storing Jquery reference

Is it possible to store the reference to an element in an array or object without having a unique ID on the element?
I am having trouble with storing a subtable in another table so I can reference it later. I get the table by class with this code:
$(this).parent('tr').parent().find('.tableSomeTable');
Is the only solution to have unique id's on each element and use the .selector method?
More of my code. Abit simplified.
var rows = [];
var historyLoad;
$(document).on("click", '.details-control', function (e) {
var t = $(this);
var tr = t.closest('tr');
var row = t.parent().parent().parent().DataTable().row(tr);
var id = t.closest('tr').attr('id');
var object = {
id: id,
btnHistory: t.parent('tr').next().find('#btnHistory'),
tblHistory: t.parent('tr').parent().find('.tableHistory'),
historyLoad: historyLoad
};
if ($.inArray(id, rows) > -1) {
loadData = false;
}
else {
loadData = true;
loadHistory(object);
rows.push(object);
}
};
Here is where I am having trouble retrieving the correct elements. And I also want to save the ajaxHistory element to my object (which is working fine).
This code is not working, but if I change it to $(result.btnHistory.btnHistory.selector) I get the object. But this doesn't seem to work very good with multiple rows.
function loadHistory(result) {
result.ajaxHistory = $.ajax({
...
beforeSend: function () {
$(result.btnHistory).html(<loading txt>);
$(result.tblHistory).find('tbody').html(<loading txt>);
},
....
success: function (data) {
if (data.TotalRecordCount > 0) {
$(result.tblHistory).find('tbody').html('');
$.each(data.Records, function (e, o) {
$(result.tblHistory).find('tbody').append(<data>)
});
}
else {
$(result.tblHistory).find('tbody').html(<txt no records>);
}
$(result.btnHistory).html(<txt loading done>));
},
First off, if you are trying to find the parent table, try
var $myObj = $(this).closest('table.tableSomeTable');
instead of navigating parents.
As far as storing the jQuery reference, define a variable and then store it. The above will store the object in $myObj but that is locally scoped. If you need a global variable then define it globally and just assign it here. If you want to define it as a property within an object then define it that way. It really comes down to a scope question at this point.
EDIT: Just saw your added content.
First off, don't name it 'object'. This may run into key word issues. Use var myObj or similar instead. Next, object.btnHistory is a reference to a jQuery object. So, when you pass it to loadHistory, you do not need to apply the $(...) again. Just use the reference directly: result.btnHistory.html(...). A good habit to get into is prepending you jQuery variables with $ so you remember it is already a jQuery variable.
The .find() method returns a jQuery object. So the answer is, yes, you can store this return object in a variable:
var $yourObject = $(this).parent('tr').parent().find('.tableSomeTable');

Store jquery function on variable

I have this code in .js file:
$.getJSON('http://api.wipmania.com/jsonp?callback=?', function (data) {
if (data.address.country='spain') {
var a="http://www.link1.com";
} else {
var a="http://www.link2.com";
}
return a;
});
var fan_page_url = data();
How can I store var a in var fan_page_url ?
Thank you very much.
Try getting rid of a and assigning the links directly.
var fan_page_url;
$.getJSON('http://api.wipmania.com/jsonp?callback=?', function(data) {
if (data.address.country = 'spain') {
fan_page_url = "http://www.link1.com";
} else {
fan_page_url = "http://www.link2.com";
}
});
You have two options: assigning the external variable directly, as depot suggested, or treating the $.getJSON return value as a Deferred:
$.when($.getJSON(...)).done(function(returnValue) {
fan_page_url = returnValue;
});
The latter is useful in case you don't want to hardcode the variable you'll store the results (though in general it's not a problem, and the former option is easier/cleaner).
It's an old question on which I just stumbled (looking for something slightly different) but as answers did not seem to hit the nail on the head, I thought I'd add 2 cents: if you (op) had success with a variable that was hardcoded and set manually in config.js, that you were able to grab from start.js, why not simply:
keep the variable declared like you did in the global scope
assign it a default or null or empty value:
var fan_page_url = null; // or
var fan_page_url = ''; // or
var fan_page_url = 'http://url_default'; // etc...
then update the global variable inside the json function:
$.getJSON('http://api.wipmania.com/jsonp?callback=?', function(data) {
if (data.address.country='spain') {
fan_page_url = "http://url1";
} else {
fan_page_url = "http://url2";
}
});
in your start.js page, you can always perform a check to see if the variable is set or not, or still carries it's default value or not and act accordingly...
It is likely that if it used to work with your normally, manually declared variable, it would work the same here as you would have changed nothing structurally, only would be updating the variable after the json response.
Answer posted for the posterity, it may help someone in the future.

Functional object basics. How to go beyond simple containers?

On the upside I'm kinda bright, on the downside I'm wracked with ADD. If I have a simple example, that fits with what I already understand, I get it. I hope someone here can help me get it.
I've got a page that, on an interval, polls a server, processes the data, stores it in an object, and displays it in a div. It is using global variables, and outputing to a div defined in my html. I have to get it into an object so I can create multiple instances, pointed at different servers, and managing their data seperately.
My code is basically structured like this...
HTML...
<div id="server_output" class="data_div"></div>
JavaScript...
// globals
var server_url = "http://some.net/address?client=Some+Client";
var data = new Object();
var since_record_id;
var interval_id;
// window onload
window.onload(){
getRecent();
interval_id = setInterval(function(){
pollForNew();
}, 300000);
}
function getRecent(){
var url = server_url + '&recent=20';
// do stuff that relies on globals
// and literal reference to "server_output" div.
}
function pollForNew(){
var url = server_url + '&since_record_id=' + since_record_id;
// again dealing with globals and "server_output".
}
How would I go about formatting that into an object with the globals defined as attributes, and member functions(?) Preferably one that builds its own output div on creation, and returns a reference to it. So I could do something like...
dataOne = new MyDataDiv('http://address/?client');
dataOne.style.left = "30px";
dataTwo = new MyDataDiv('http://different/?client');
dataTwo.style.left = "500px";
My code is actually much more convoluted than this, but I think if I could understand this, I could apply it to what I've already got. If there is anything I've asked for that just isn't possible please tell me. I intend to figure this out, and will. Just typing out the question has helped my ADD addled mind get a better handle on what I'm actually trying to do.
As always... Any help is help.
Thanks
Skip
UPDATE:
I've already got this...
$("body").prepend("<div>text</div>");
this.test = document.body.firstChild;
this.test.style.backgroundColor = "blue";
That's a div created in code, and a reference that can be returned. Stick it in a function, it works.
UPDATE AGAIN:
I've got draggable popups created and manipulated as objects with one prototype function. Here's the fiddle. That's my first fiddle! The popups are key to my project, and from what I've learned the data functionality will come easy.
This is pretty close:
// globals
var pairs = {
{ div : 'div1', url : 'http://some.net/address?client=Some+Client' } ,
{ div : 'div2', url : 'http://some.net/otheraddress?client=Some+Client' } ,
};
var since_record_id; //?? not sure what this is
var intervals = [];
// window onload
window.onload(){ // I don't think this is gonna work
for(var i; i<pairs.length; i++) {
getRecent(pairs[i]);
intervals.push(setInterval(function(){
pollForNew(map[i]);
}, 300000));
}
}
function getRecent(map){
var url = map.url + '&recent=20';
// do stuff here to retrieve the resource
var content = loadResoucrce(url); // must define this
var elt = document.getElementById(map.div);
elt.innerHTML = content;
}
function pollForNew(map){
var url = map.url + '&since_record_id=' + since_record_id;
var content = loadResoucrce(url); // returns an html fragment
var elt = document.getElementById(map.div);
elt.innerHTML = content;
}
and the html obviously needs two divs:
<div id='div1' class='data_div'></div>
<div id='div2' class='data_div'></div>
Your 'window.onload` - I don't think that's gonna work, but maybe you have it set up correctly and didn't want to bother putting in all the code.
About my suggested code - it defines an array in the global scope, an array of objects. Each object is a map, a dictionary if you like. These are the params for each div. It supplies the div id, and the url stub. If you have other params that vary according to div, put them in the map.
Then, call getRecent() once for each map object. Inside the function you can unwrap the map object and get at its parameters.
You also want to set up that interval within the loop, using the same parameterization. I myself would prefer to use setTimeout(), but that's just me.
You need to supply the loadResource() function that accepts a URL (string) and returns the HTML available at that URL.
This solves the problem of modularity, but it is not "an object" or class-based approach to the problem. I'm not sure why you'd want one with such a simple task. Here's a crack an an object that does what you want:
(function() {
var getRecent = function(url, div){
url = url + '&recent=20';
// do stuff here to retrieve the resource
var content = loadResoucrce(url); // must define this
var elt = document.getElementById(div);
elt.innerHTML = content;
}
var pollForNew = function(url, div){
url = url + '&since_record_id=' + since_record_id;
var content = loadResoucrce(url); // returns an html fragment
var elt = document.getElementById(div);
elt.innerHTML = content;
}
UpdatingDataDiv = function(map) {
if (! (this instanceof arguments.callee) ) {
var error = new Error("you must use new to instantiate this class");
error.source = "UpdatingDataDiv";
throw error;
}
this.url = map.url;
this.div = map.div;
this.interval = map.interval || 30000; // default 30s
var self = this;
getRecent(this.url, this.div);
this.intervalId = setInterval(function(){
pollForNew(self.url, self.div);
}, this.interval);
};
UpdatingDataDiv.prototype.cancel = function() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
})();
var d1= new UpdatingDataDiv('div1','http://some.net/address?client=Some+Client');
var d2= new UpdatingDataDiv('div2','http://some.net/otheraddress?client=Some+Client');
...
d1.cancel();
But there's not a lot you can do with d1 and d2. You can invoke cancel() to stop the updating. I guess you could add more functions to extend its capability.
OK, figured out what I needed. It's pretty straight forward.
First off disregard window.onload, the object is defined as a function and when you instantiate a new object it runs the function. Do your setup in the function.
Second, for global variables that you wish to make local to your object, simply define them as this.variable_name; within the object. Those variables are visible throughout the object, and its member functions.
Third, define your member functions as object.prototype.function = function(){};
Fourth, for my case, the object function should return this; This allows regular program flow to examine the variables of the object using dot notation.
This is the answer I was looking for. It takes my non-functional example code, and repackages it as an object...
function ServerObject(url){
// global to the object
this.server_url = url;
this.data = new Object();
this.since_record_id;
this.interval_id;
// do the onload functions
this.getRecent();
this.interval_id = setInterval(function(){
this.pollForNew();
}, 300000);
// do other stuff to setup the object
return this;
}
// define the getRecent function
ServerObject.prototype.getRecent = function(){
// do getRecent(); stuff
// reference object variables as this.variable;
}
// same for pollForNew();
ServerObject.prototype.pollForNew = function(){
// do pollForNew(); stuff here.
// reference object variables as this.variable;
}
Then in your program flow you do something like...
var server = new ServerObject("http://some.net/address");
server.variable = newValue; // access object variables
I mentioned the ADD in the first post. I'm smart enough to know how complex objects can be, and when I look for examples and explanations they expose certain layers of those complexities that cause my mind to just swim. It is difficult to drill down to the simple rules that get you started on the ground floor. What's the scope of 'this'? Sure I'll figure that out someday, but the simple truth is, you gotta reference 'this'.
Thanks
I wish I had more to offer.
Skip

Categories

Resources