Javascript function modular approach init variable issue - javascript

I have a modular libray javascript file where I am exposing two functions
init to initalise variables from my main.html file.
execValidation function to run based on those three variables collections initialised through main file.
For example:
var libraryModule = (function () {
var arVals = {};
var webFormData = {};
var rules = [];
function init(arVals, webFormData, rules) {
//init all variables to global variables to use in execute Validations
this.arVals = arVals;
this.webFormData = webFormData;
this.rules = rules;
}
//only passing RuleID, but it has dependencies of other variables, which I
//do not want to pass here
function execValidation(ruleID) {
//debugger;
//Load arVals, webFormData and Rules from init
var webFormData = this.webFormData;
var arVals = this.arVals;
var arVal = arVals[ruleID];
var rules = this.rules;
var rule = rules[ruleID]
console.log(arVal);
console.log(webFormData);
console.log(rules);
}
return {
execValidation: execValidation,
init : init
}
})(); // IIFE function
In My html file, I am calling like this
var arVals = {};
//calling json file using call back
ruleConfigModule.init(function (data) {
arVals = data;
});
//passing the arVals, webFormData and rules collection to init
libraryModule.init(arVals, webFormData, rules);
Only passing the ruleID
var result = libraryModule.execValidation("Rule1");
I only want to pass one variable which is RuleID from execValidation function, but the init function should setup those variables inside the js library itself. Please can anyone help, as it does not work or help to re-organise it.
JSON calling method to populate arVals
var ruleConfigModule = (function () {
function init(callback) {
loadJSON(function (json) {
callback(json);
});
}
// Let's hide this function
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'http://localhost/test/config.json', true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(JSON.parse(xobj.responseText));
}
};
xobj.send();
}
return {
//loadJSON: loadJSON,
init: init
}
})();
Updated:
Blockquote
How do I ensure that arVals populated before the init method gets called?

This should work
function LibraryModule() {
var arVals = {};
var webFormData = {};
var rules = [];
}
LibraryModule.prototype.init = function init(arVals, webFormData, rules) {
//init all variables to global variables to use in execute Validations
this.arVals = arVals;
this.webFormData = webFormData;
this.rules = rules;
}
LibraryModule.prototype.execValidation = function execValidation(ruleID) {
//debugger;
//Load arVals, webFormData and Rules from init
var webFormData = this.webFormData;
var arVals = this.arVals;
var arVal = arVals[ruleID];
var rules = this.rules;
var rule = rules[ruleID]
console.log(arVal);
console.log(webFormData);
console.log(rules);
return rules;
}
let libraryModule = new LibraryModule();
libraryModule.init({
rule: 'TEST'
}, {
rule: 'TEST'
}, {
rule: 'TEST'
})
var result = libraryModule.execValidation("rule");
console.log(result);

Related

Use the value of a variable in another file

Currently I am using protractor and using page object, so there is a file that I get the value of an element in a variable, but I need to call this value in another file.
vehiclePage.js
/*jshint esversion: 6 */
var basePage = require('./basePage.js');
var homePage = require('./homePage.js');
var VehiclePage = function() {
this.storeVehicleData = function() {
this.pessengersRuntValue = element(by.id('preview_ocupantes_runt')).getText();
};
};
VehiclePage.prototype = basePage; // extend basePage...
module.exports = new VehiclePage();
Now I need to use the value of the above variables in another file
checkoutPage.js
/*jshint esversion: 6 */
var basePage = require('./basePage.js');
var homePage = require('./homePage.js');
var CheckoutPage = function() {
this.getRuntValue = element(by.css('.mb10'));
this.compareValues = function() {
expect(this.getRuntValue.getText()).toContain(this.pessengersRuntValue);
};
};
CheckoutPage.prototype = basePage; // extend basePage...
module.exports = new CheckoutPage();
How can I make it work?
If you are following Page Object Design Pattern, I would say that the test should not be on the page object. I will write something like this.
VehiclePage.js
var VehiclePage = function(){
// if this is a browser testing something like this
browser.get('/vehicle');
};
VehiclePage.prototype = Object.create({}, {
runt: {
get: function(){
return element(by.id('preview_ocupantes_runt'));
}
}
});
module.export = VehiclePage;
CheckOutPage.js
var CheckOutPage = function(){
// if this is a browser testing something like this
browser.get('/checkout');
};
CheckOutPage.prototype = Object.create({}, {
runt: {
get: function(){
return element(by.css('.mb10'));
}
}
});
module.export = CheckOutPage;
TheTest.js
var VehiclePage = require('VehiclePage');
var CheckOutPage = require('CheckOutPage');
describe('testing something', () => {
var vehicle = new VehiclePage();
var checkout = new CheckOutPage();
it('should contain', () => {
expect(checkout.runt.getText()).toContains(vehicle.runt.getText());
});
});
One way to do this would be to pass a state object to both pages.
var VehiclePage = require('./vehiclePage.js');
var CheckoutPage = require('./checkoutPage.js');
class StateStorage {
constructor(){
this.savedVariable = null;
}
}
var state = new StateStorage();
var vehiclePage = new VehiclePage(state);
var checkoutPage = new CheckoutPage(state);
Then you can manipulate and access the state from both new pages.

How to properly structure class in Node.js

I have a class called TileStreamer that I am currently defining as follows:
function TileStreamer {
};
This class has constants, which I define as follows:
// Tiles are 256 x 256 pixels
TileStreamer.prototype.TILE_SIZE = 256;
// Header size in bytes
TileStreamer.prototype.HEADER_SIZE = 28;
// Various table entry sizes in bytes
TileStreamer.prototype.RESOLUTION_ENTRY_SIZE = 12;
TileStreamer.prototype.TILE_COUNT_SIZE = 4;
TileStreamer.prototype.TILE_ENTRY_SIZE = 12;
// Offsets within header
TileStreamer.prototype.WIDTH_OFFSET = 3;
TileStreamer.prototype.HEIGHT_OFFSET = 4;
TileStreamer.prototype.NUM_TABLES_OFFSET = 7;
TileStreamer.prototype.UNPOPULATED_OFFSET = 12092;
There also other variables. These variables are important because they need to be accessible from other classes. They get their values within the methods of this class. This is what I am unsure of as far as structure. What I'm currently trying is:
TileStreamer.prototype.header;
TileStreamer.prototype.resolutionEntry;
TileStreamer.prototype.resolutionTable;
TileStreamer.prototype.filepath;
TileStreamer.prototype.s3;
TileStreamer.prototype.level;
TileStreamer.prototype.ncols;
TileStreamer.prototype.nrows;
TileStreamer.prototype.nlevels;
TileStreamer.prototype.toffset;
TileStreamer.prototype.tsize;
TileStreamer.prototype.modifiedTime;
TileStreamer.prototype.tile;
TileStreamer.prototype.host;
TileStreamer.prototype.bucket;
This class also has methods such as:
TileStreamer.prototype.Init = function(filepath, index, s3config){
var retval = false;
AWS.config.update({accessKeyId: s3config.access_key, secretAccessKey: s3config.secret_key});
var blc = new BlockLibraryConfigs();
var awsConfig = blc.awsConfig;
AWS.config.update({region: awsConfig.region});
var aws = new AWS.S3();
var params = {
Bucket: s3config.bucket,
Key: s3config.tile_directory + filepath,
Range: 'bytes=0-' + (this.HEADER_SIZE - 1)
};
aws.getObject(params, function(err, data){
if(err == null){
TileStreamer.modifiedTime = data.LastModified;
var header = bufferpack.unpack('<7I', data.Body);
TileStreamer.header = header;
TileStreamer.nlevels = header[TileStreamer.NUM_TABLES_OFFSET];
if(TileStreamer.nlevels == 5){
TileStreamer.level = 0;
TileStreamer.ncols = Math.ceil((header[TileStreamer.WIDTH_OFFSET] * 1.0) / TileStreamer.TILE_SIZE);
TileStreamer.nrows = Math.ceil((header[TileStreamer.HEIGHT_OFFSET] * 1.0) / TileStreamer.TILE_SIZE);
}
}
});
};
The method above should set some of the values of the variables, such as modifiedTime so that I can access it in another class such as:
TileStreamer = require('tilestreamer.js');
var ts = new TileStreamer();
ts.Init(parPath, index, config);
var last_modified = ts.modifiedTime;
Just put any public properties you want to initialise when the object is created, directly in the init function. Here's a small example...
function TileStreamer() {
};
TileStreamer.prototype.Init = function() {
this.modifiedTime = new Date();
};
var ts = new TileStreamer();
ts.Init();
console.log(ts);
jsfiddle example
https://jsfiddle.net/v6muohyk/
To get around the issue you're having with setting the object properties in a callback from an asynchronous function, just create a locally accessible variable to reference the object that you are creating at that time...
TileStreamer.prototype.Init = function() {
var thisTileStreamer = this;
asynchFunction(function(err, data) {
thisTileStreamer.modifiedTime = data.lastModified;
});
};
To take it one step further, if you need to execute some code after the init function has completed, then that will require waiting for the asynchronous function to complete, as well. For that, pass a further parameter to init, that is a function to be executed after all the work is done...
TileStreamer.prototype.Init = function(callback) {
var thisTileStreamer = this;
asynchFunction(function(err, data) {
thisTileStreamer.modifiedTime = data.lastModified;
callback();
});
};
var ts = new TileStreamer();
ts.Init(function() {
// put code here that needs to be executed *after* the init function has completed
alert(ts.modifiedTime);
});

why my array is undefined in my savetime function but running properly in other functions?

i m calling my save function and st_bookmark and ed_bookmark array donot show any data in my JSON stringfy function the array is undefined or uncaught type error occur
<script>
var check = true;
var st_bookmark = new Array();
var str_print = new Array();
var end_print = new Array();
var ed_bookmark = new Array();
</script>
<script>
function save() {
var link = "M7lc1UVf-VE";
var bk_name = $('#bookmark_name').val();
var bk_tags = $('#bookmark_tags').val();
var bk_email = $('#bookmark_email').val();
var user = '#Session["email"]';
var t = st_bookmark.pop();
var ss = ed_bookmark.pop();
var data =
({ name: bk_name, tags: bk_tags, email: bk_email, link: link, start_bookmark: st_bookmark, end_bookmark: ed_bookmark });
$.ajax({
url: '#Url.Action("save_bookmark", "chopaal")',
type: "POST",
contentType: "application/json",
data: { data: data },
success: function () {
window.alert('success!!');
}
});
var check = true;
var st_bookmark = [];
var str_print = [];
var end_print = [];
var ed_bookmark = [];
}
function starttime() {
if (check == true) {
temp = player.getCurrentTime();
st_bookmark.push(temp);
str_print.push((temp / 60).toFixed(2));
document.getElementById("str_book").innerHTML = str_print;
check = false;
} else {
window.alert("Please End The Previous Bookmark");
}
}
function endtime() {
if (check == false) {
temp = player.getCurrentTime();
ed_bookmark.push(temp);
end_print.push((temp / 60).toFixed(2));
document.getElementById("end_book").innerHTML = end_print;
check = true;
} else {
window.alert("Please Add the Starting Bookmark");
}
}
</script>
Variable declarations are hoisted in JavaScript:
var data = {start_bookmark: st_bookmark};
var st_bookmark = [];
is equivalent to
var data;
var st_bookmark;
data = {start_bookmark: st_bookmark};
st_bookmark = [];
As you can see, st_bookmark is accessed before it got a value assignment, at which point its value is still undefined.
I guess what you really want is to access the variables with the same name that are declared globally. In that case, you should completely remove the declarations of these similarly named variables from save.
If you want to "reset" those variables after the Ajax call was successful, you need to move the assignment inside the success callback and remove the var keyword (so that the identifiers refer to the global variables):
success: function() {
window.alert('success!!');
check = true;
st_bookmark = [];
str_print = [];
end_print = [];
ed_bookmark = [];
}

Javascript Object communication and get parameter from other object

I have a problem with share parameters from one object to other
I have one LatestVideos object with options my video galleries and other object with methods to Paginate, Render, Categories and LocalStorage, witch handup all functionality but I use this to many this I need this as separete object
(function (window, document, none) {
"use strict";
var LatestVideos = window.LatestVideos = function (option) {
/* object to init puglin data JSON FORMAT keys Jsondata or url , container,
actual page wrapper on paggination, number of item per page, categorywrapper*/
this.fragments = document.createDocumentFragment();
this.categories = ["Favorite"];
this.statusLoad = 0;
this.allid = [];
this.categoryid = [];
this.actual = [];
//this.categoryChecked=[];
this.page = 0;
loadJSON(option.url,this.initData.bind(this));
this.settings = { /// init data from options object from parameter constructor
JsonData :option.data || 0,
container : option.container,
actpage : option.actpage || 1,
buttonwrapper : option.paginationwrapper,
categorywrapper : option.categorywrapper,
itemperpage : option.itemperpage, // get value from prev Selection or default
};
};
LatestVideos.prototype.initData = function (data) { // assinchrounous call json with ajax
this.settings.JsonData = data;
this.settings.lengthData = data.length;
Render.setData(this);
Render.getCategories();
};
var Render = { // need this data from LASTESTVIDEOS data,conteiner,paginationwrapper,categorywrapper
/// object with method to render articles to my website
};
var Pagination = function(){
// from LASTESTVIDEOS I need JsonData, actPage overide page and paginatorwrapper
// object with method to calculate number of pages and paginate my articles
};
var Cateogry = function(){
// from LASTESTVIDEOS categoryid change actual and allid
// object with method to changeCategory and get category from data atribut
};
var LocalStoraget = function (){
// I JSON data from LASTESTVIDEOS
// object with method to getFavorite item form localstorage and add to localstorage
};
})(window, document);
function loadJSON(url, callback) {
/* function to load ajax from url input(url- form and callback function),
output function call and post (ARRAY JSON OBJECTS)*/
var xmlhttp =0;
if (typeof XMLHttpRequest !== 'undefined') {
xmlhttp = new XMLHttpRequest();
} else {
var versions = ["Microsoft.XmlHttp",
"MSXML2.XmlHttp",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.5.0"];
var len = versions.length;
for (var i = 0; i < len; i++) {
try {
xmlhttp = new ActiveXObject(versions[i]);
break;
}
catch(e){}
}
}
xmlhttp.onreadystatechange = ensureReadiness;
function ensureReadiness(){
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
{
JSONObject = JSON.parse(xmlhttp.responseText);
callback (JSONObject);
}else{
return;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
var options = {url:"someURL",container:"videox",paginationwrapper:"pages"};
var opp = new LatestVideos(options);
and this is a plugin witch I need create xtimes with differend options and sometimes I need separetly render or paginate object or localstorage
I would probably change it a bit:
var Render = function (options) {
this.options = $.extend({ //default options
data: [],
container: null
}, options);
// use internal logic here
var getCategories = function(){
...
};
// and return public methods
return {
getCategories: getCategories
};
};
and change the code in LatestVideos to the following:
LatestVideos.prototype.initData = function (data) { // assinchrounous call json with ajax
this.settings.JsonData = data;
this.settings.lengthData = data.length;
var renderer = new Render({
data: this.settings.JsonData,
container: this.settings.container
});
renderer.getCategories();
};

Initialize Object with different parameters

Hello I have code which replaces document.write, makes a buffer and than pushes buffer into the document:
var lazyLoad = (function () {
var counter = 0
var buffer = new Array()
function work(options){
window.d = document
var tmp_buffer
d.write = d.writeln = function(s){ tmp_buffer += s}
d.open = d.close = function(){}
s = d.createElement('script')
s.setAttribute('type','text/javascript')
s.setAttribute('src',options.url)
d.getElementById(options.block).appendChild(s)
s.onload = function () {
buffer[counter] = tmp_buffer
console.log(buffer[1])
window.setTimeout(function() {
d.getElementById(options.block).innerHTML += buffer[counter]
}, 0)
counter++
}
}
return {
init: function (options) {
var CONFIG = {
url: '',
block: ''
}
$.extend(CONFIG, options)
random = $('#'+CONFIG.block).attr('rel')
id = $('#'+CONFIG.block).attr('id').replace(random,'')
id = id.replace('DIV','')
size = id.split('X')
ele_width = size[0] || CONFIG.width
ele_height = size[1] || CONFIG.height
$('#'+CONFIG.block).css({
'width':ele_width+'px',
'height':ele_height+'px'
})
$(window).load(function(){
if(options.adfox) {
random = $('#'+CONFIG.block).attr('id')
AdFox_getCodeScript(1, random, CONFIG.url)
}else{
work(options)
}
})
}
}
})();
If I init it once:
lazyLoad.init({
'http://test.com/test.js',
div1
})
But if I call it again with other parameters:
lazyLoad.init({
'http://test2.com/test.js',
div2
})
First init wont work. buffer will be empty. Where is my mistake?
I think that
$(window).load(function(){
will overwrite the event handler. Try using:
$(function(){
});
instead. I think it'll add an array of event handlers. I could be wrong though. Please let me know how it turns out.
Also, it doesn't look like you're defining "s" in the local scope. If you don't put "var" in front of a variable when you define it, it'll get created in the global scope.

Categories