Why function name as variable? - javascript

While studying Element.scrollHeight i failed to understand 2 things. The code example is as described below:
function checkReading () {
if (checkReading.read) {
return;
}
checkReading.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight;
document.registration.accept.disabled = document.getElementById("nextstep").disabled = !checkReading.read;
checkReading.noticeBox.textContent = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}
onload = () => {
const oToBeRead = document.getElementById("rules");
checkReading.noticeBox = document.createElement("span");
document.registration.accept.checked = false;
checkReading.noticeBox.id = "notice";
oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead);
oToBeRead.parentNode.insertBefore(document.createElement("br"), oToBeRead);
oToBeRead.onscroll = checkReading;
checkReading.call(oToBeRead);
}
Why they have used checkReading(which is a function name) as object/variable?
I tried to remove checkReading and used oToBeRead object as this, so when i used this.reading = this.scrollHeight - Match.round(this.scrollTop)===this.clientHeight
the function checkReading is converted to constructor function,
why so?
here's my updated code where the function is converting to constructor function:
function checkReading () {
if (checkReading.read) {
return;
}
this.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight;
document.registration.accept.disabled = document.getElementById("nextstep").disabled = !this.read;
this.noticeBox.textContent = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}
onload = () => {
const oToBeRead = document.getElementById("rules");
oToBeRead.noticeBox = document.createElement("span");
document.registration.accept.checked = false;
oToBeRead.noticeBox.id = "notice";
oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead);
oToBeRead.parentNode.insertBefore(document.createElement("br"), oToBeRead);
oToBeRead.onscroll = checkReading;
checkReading.call(oToBeRead);
}
This picture is showing how the function is converted to constructor function and then quokka is giving tip to change it to class declaration

Related

JSlint warning "Move variable declaration to top of function or script."

I don't know why there is a warning of "Move variable declaration to top of function or script."
Although I move the variable "myName" to other places, the variable below will be the new one having the same warning. I have input "window, document" in the "Options" section in JSlint.
window.onload = function() {
"use strict";
var myLogin = document.forms.submitForm;
myLogin.onsubmit = processForm;
var myName = document.getElementById("result__username");
var myPassword = document.getElementById("result__password");
var myMessage = document.getElementById("output");
myMessage.classList.add("displaynone");
function processForm() {
var in_username = myLogin.username;
var in_password = myLogin.password;
if (in_username.value === "") {
in_username.classList.add("changered");
in_username.focus();
return false;
}
in_username.classList.add("changewhite");
if (in_password.value === "") {
in_password.classList.add("changered");
in_password.focus();
return false;
}
in_password.classList.add("changewhite");
myName.innerHTML = in_username.value;
myPassword.innerHTML = in_password.value;
myMessage.classList.add("displayblock");
return false;
}
};
If you are going to use a linter, you need to follow what ever rules you have applied. You need to move the vars before you touch the variables. You need to indent right. Set up your IDE with plug ins that will format your code for you.
window.onload = function () {
"use strict";
var myLogin = document.forms.submitForm;
var myName = document.getElementById("result__username");
var myPassword = document.getElementById("result__password");
var myMessage = document.getElementById("output");
myMessage.classList.add("displaynone");
myLogin.onsubmit = processForm;
function processForm() {
var in_username = myLogin.username;
var in_password = myLogin.password;
if (in_username.value === "") {
in_username.classList.add("changered");
in_username.focus();
return false;
}
in_username.classList.add("changewhite");
if (in_password.value === "") {
in_password.classList.add("changered");
in_password.focus();
return false;
}
in_password.classList.add("changewhite");
myName.innerHTML = in_username.value;
myPassword.innerHTML = in_password.value;
myMessage.classList.add("displayblock");
return false;
}
};

Using a JavaScript function to add data to a string that comes from the HTML document, and preserving that data after that function is called again

I wrote an object called TypeWriter2 and then I want to add it a function called type2().
I then call the TypeWriter2 object using a function called init2(), which queries some data from the html document and passes it to the TypeWriter2 object.
The data that init2() is querying from the html document is:
txtElement2 = a div element, that the type2() function will use to display some data.
words2 = the words that are to be displayed in txtElement2, which is "Hello, there... Yoo"
wait2 = an int that will be passed to setTimeout() later on.
The type2() function is meant is meant of add "iiiiii" to "txt2" (an empty string at the beginning), whenever "txt2" ends with 3 consecutive dots.
The problem being that after "iiiiii" is added to "txt2" and "setTimeout(() => this.type2(), this.wait2);" is called again, "iiiiii" is being deleted from "txt2".
document.addEventListener('DOMContentLoaded', init2);
const TypeWriter2 = function (txtElement2, words2, wait2 = 3000) {
this.txtElement2 = txtElement2;
this.words2 = words2;
this.wait2 = parseInt(wait2, 10);
this.txt2 = '';
this.type2();
}
TypeWriter2.prototype.type2 = function () {
this.txt2 = this.words2.substring(0, this.txt2.length + 1)
if (this.txt2.substr(this.txt2.length - 3) === "...") {
this.txt2 = this.txt2 + "iiiii"
this.txtElement2.innerHTML = `<span class="intro-text">${this.txt2}</span>`;
} else {
this.txtElement2.innerHTML = `<span class="intro-text">${this.txt2}</span>`;
}
setTimeout(() => this.type2(), this.wait2);
}
function init2() {
const txtElement2 = document.querySelector('.intro-text');
const words2 = txtElement2.getAttribute('hello-txt');
const wait2 = txtElement2.getAttribute("data2-wait");
new TypeWriter2(txtElement2, words2, wait2);
}
Thanks in advance!
I was unable to reproduce the bug as described using the posted code, but in all likelihood you can resolve the problem by changing your else statement to an else if such that the type2 method stops being called as soon as all of the text in the "hello-txt" attribute has been added to txtElement2.innerHTML
Attempted repro case: https://jsbin.com/wovatit/1/edit?html,js,output
document.addEventListener('DOMContentLoaded', init2);
const TypeWriter2 = function (txtElement2, words2, wait2 = 3000) {
this.txtElement2 = txtElement2;
this.words2 = words2;
this.wait2 = parseInt(wait2, 10);
this.txt2 = '';
this.type2();
}
TypeWriter2.prototype.type2 = function () {
console.log('called');
this.txt2 = this.words2.substring(0, this.txt2.length + 1)
if (this.txt2.substr(this.txt2.length - 3) === "...") {
this.txt2 = this.txt2 + "iiiii"
this.txtElement2.innerHTML = `<span class="intro-text">${this.txt2}</span>`;
console.log("finished")
} else if(this.txt2.length <= this.words2.length){
this.txtElement2.innerHTML = `<span class="intro-text">${this.txt2}</span>`;
setTimeout(() => this.type2(), this.wait2);
} else{
console.log("finsished")
}
}
function init2() {
const txtElement2 = document.querySelector('.intro-text');
const words2 = txtElement2.getAttribute('hello-txt');
const wait2 = txtElement2.getAttribute("data2-wait");
new TypeWriter2(txtElement2, words2, wait2);
}

My Closure Won't Work

I'm trying to prevent polluting the global space with a bunch of variables, and since I can't use let yet, I have to make closures. So I have this basic webpage with a bootstrap accordion, each card hiding different examples. In one I have a form that asks in a <select> what your position is. OnChange it will grab the eventData object, call spillObject() (the closure method), and populate another accordion card with its contents. It works, but problem is, I can't seem to make it work as a simple closure. Nothing seems to happen, and since you can't debug a closure, other than making it spit out console.logs() everywhere, I can't find out what's wrong with it.
Here's the code:
$(function() {
$("#position").change( /*(*/ function(eventData) {
var div = $('#explodedObject');
div.html('');
var result = spillObject('#explodedObject', eventData, '');
/*};*/
div.append(result);
} /*)()*/ );
var spillObject = (function(dataParent, obj, heirarchy) {
var heirArr = heirarchy == '' ? [] : heirarchy.split('_');
heirArr.push(1);
var teir = heirArr.length - 1;
var id = "#collapse" + heirArr.join('');
var headerID = 'header' + heirArr.join('');
var card = document.createElement('div');
card.classList.add('card');
var cardHeader = document.createElement('div');
cardHeader.classList.add('card-header');
cardHeader.id = headerID;
var h5 = document.createElement('h5');
h5.classList.add('mb-0');
var button = document.createElement('button');
button.classList.add('btn', 'btn-link');
button.setAttribute('data-toggle', 'collapse');
button.setAttribute('data-target', id);
var cardBody = document.createElement('div');
cardBody.classList.add('card-body');
var collapse = document.createElement('div');
collapse.id = id.substr(1, id.length - 1);
collapse.classList.add('collapse');
collapse.setAttribute('data-parent', dataParent);
var dl = document.createElement('dl');
dl.id = '#' + heirArr.join('');
var dt;
var dd;
var x;
return function() {
for (x in obj) {
dt = document.createElement('dt');
dd = document.createElement('dd');
dt.innerHTML = x;
if (typeof obj[x] == 'object' && heirArr.length < 3) {
heirArr[teir]++;
innerObj = spillObject(dl.id, obj[x], heirArr.join('_'));
dd.appendChild(innerObj);
} else {
dd.innerHTML = obj[x];
}
dl.append(dt);
dl.append(dd);
}
heirArr.pop();
heirArr[heirArr.length - 1] = parseInt(heirArr[heirArr.length - 1]);
heirArr[heirArr.length - 1]--;
collapse.appendChild(cardBody);
button.innerHTML = 'card ' + heirArr.join('.');
h5.appendChild(button);
cardHeader.appendChild(h5);
card.appendChild(cardHeader);
card.appendChild(collapse);
cardBody.appendChild(dl);
return card;
};
});
})();
More basically, I'm following this template:
var method = (function(param){
var var1 = 'default value';
return function(){
var1 = 'something else';
};
})();
Should I have used this one instead, and if so would it hide the variables?
var method2 = function(param) {
return function() {
var var1 = 'default value';
};
};
It's because the result of spillObject is a function, you must then also call that function. Here's a simplified version of what you are doing.
var spillObject = (function(dataParent, obj, heirarchy) {
console.log('first function')
return function() {
console.log('second function')
};
});
var result = spillObject()
console.log(result)
result()

Difficulties with using function expression

Hopefully you will answer it !
var myform = document.getElementById("myform"),
saveBtn = document.getElementById("submit");
saveBtn.addEventListener("click", saveInfo);
var saveInfo = function (e){
e.preventDefault();
var dateValue = document.getElementById("inputdeadline").value;
var todoValue = document.getElementById("textarea").value;
todoValue = todoValue.replace(/\n/g," ");
if ( dateValue > 24 || dateValue <= 0) {
myform.reset();
return false;
};
if (!(todoValue)) {
myform.reset();
return false;
};
var todoObj = {
todoValue,
dateValue
};
if (localStorage.getItem("localTodoItem") === null) {
var todoArray = [];
todoArray.push(todoObj);
todoArray.sort(function (a, b) {
return a.dateValue - b.dateValue;
});
localStorage.setItem("localTodoItem", JSON.stringify(todoArray));
} else {
var todoArray = JSON.parse(localStorage.getItem("localTodoItem"));
todoArray.push(todoObj);
todoArray.sort(function (a, b) {
return a.dateValue - b.dateValue;
});
localStorage.setItem("localTodoItem", JSON.stringify(todoArray));
};
showTodoItems();
myform.reset();
};
Here when I am using function declaration for this saveInfo function it is correctly doing all functionalities but when I am using function expression it just reload the page that's it nothing happening.
Please help me.
If you need more clarification about code please visit github.
This is because function declarations are hoisted, whereas function expressions are not. You're using saveInfo before the expression is executed, which would work for a declaration but not an expression.
Function declaration hoisting on MDN

JavaScript object inheritance issue

I'm a beginner with JavaScript Objects and Prototypes and trying to develop my first " multi-level inherited" JS Objects, an unexpected issue came up.
This is my code:
var Utils = function () {};
Utils.prototype = {
sayHelloGeneral: function(){
console.log('hello');
}
};
var FormTools = function () {
Utils.call(this);
this.fields = [];
};
FormTools.prototype = Object.create(Utils.prototype);
FormTools.prototype.constructor = FormTools;
FormTools.prototype.sayHelloForm= function (fields) {
console.log('hello form');
};
function GroupManager(value) {
FormTools.call(this);
this.val = typeof values === 'undefined' ? 1 : value;
};
GroupManager.prototype = Object.create(FormTools.prototype);
GroupManager.prototype.constructor = GroupManager;
GroupManager.prototype.helloGroupManager= function (givenValue) {
console.log('Hello group manager');
};
Why when I try to call the group manager, it prints only the sayHelloGeneral function?
var GM = new GroupManager;
GM.sayHelloGeneral(); //->ok
GM.helloGroupManager(); //--> ok
GM.sayHelloForm(); //->sayHelloForm is not a function
It seems to be working fine. See the snippet below
var Utils = function () {};
Utils.prototype = {
sayHelloGeneral: function(){
console.log('hello');
}
};
var FormTools = function () {
Utils.call(this);
this.fields = [];
};
FormTools.prototype = Object.create(Utils.prototype);
FormTools.prototype.constructor = FormTools;
FormTools.prototype.sayHelloForm= function (fields) {
console.log('hello form');
};
function GroupManager(value) {
FormTools.call(this);
this.val = typeof values === 'undefined' ? 1 : value;
};
GroupManager.prototype = Object.create(FormTools.prototype);
GroupManager.prototype.constructor = GroupManager;
GroupManager.prototype.helloGroupManager= function (givenValue) {
console.log('Hello group manager');
};
var GM = new GroupManager;
//GM.sayhello(); //->ok---> should be sayHelloGeneral()
GM.sayHelloGeneral();
GM.helloGroupManager(); //--> ok
GM.sayHelloForm(); //->Works fine too

Categories

Resources