Revealing module pattern with prototype - javascript

Te following code is fine:
var Pill = (function() {
var hideCheckPricesPill = function() {
$(HB.pillSearchBar.checkPrices).hide();
};
var hideAnyPill = function(pill) {
$(pill).hide();
};
var displaySearchBar = function() {
$("." + HB.pillSearchBar.hideSearchForm).removeClass(HB.pillSearchBar.hideSearchForm);
};
var isEditSearchPill = function(pill) {
if(pill === HB.pillSearchBar.editSearchText) {
hideCheckPricesPill();
}
else {
hideAnyPill(pill);
}
};
var isMobileSearch = function(pill) {
if(!$(pill).hasClass(HB.pillSearchBar.jsOpenMobileSearch)){
isEditSearchPill(pill);
displaySearchBar();
}
};
var addEventListenerOnPill = function(pill) {
$(pill).on('click', 'a', function() {
isMobileSearch(pill);
});
};
return {
addEventListenerOnPill: addEventListenerOnPill
}
})();
Is there a way to add a prototype functionality to one of the public functions so that it can be returned and initialized with the "new" key word?

Related

How to access object properties from prototype in javascript? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
I have class below when I call printData I get this.collection is undefined.
How do I access this.collection from the prototype inside printData()? Or do i need to change the class structure. Actually the object returns function which intern returns object in hierarchy.
Thanks in advance!
Sample Class:
var DbProvider = (function () {
function DbProvider(db) {
var that = this; // create a reference to "this" object
that.collection = db;
}
DbProvider.prototype.create = function () {
return {
action: function () {
var y = {
printData: function () {
alert('Hello ' + this.collection.Name);
}
};
return y;
}
};
};
return DbProvider;
})();
Usage:
var a = new DbProvider({ "Name": "John" });
a.create().action().printData();
You could save the this reference and bind it to the printData function
var DbProvider = (function () {
function DbProvider(db) {
var that = this; // create a reference to "this" object
that.collection = db;
}
DbProvider.prototype.create = function () {
var self = this;
return {
action: function () {
var y = {
printData: function () {
alert('Hello ' + this.collection.Name);
}.bind(self)
};
return y;
}
};
};
return DbProvider;
})();
var a = new DbProvider({ "Name": "John" });
a.create().action().printData();
Or you could refactor a bit and move that to the outer scope of DbProvider and use that in printData
var DbProvider = (function () {
var that;
function DbProvider(db) {
that = this; // create a reference to "this" object
that.collection = db;
}
DbProvider.prototype.create = function () {
return {
action: function () {
var y = {
printData: function () {
alert('Hello ' + that.collection.Name);
}
};
return y;
}
};
};
return DbProvider;
})();
var a = new DbProvider({ "Name": "John" });
a.create().action().printData();
just need to keep track of the this pointer correctly, like this
var DbProvider = (function() {
function DbProvider(db) {
this.collection = db;
}
DbProvider.prototype.create = function() {
var self = this;
return {
action: function() {
var y = {
printData: function() {
alert('Hello ' + self.collection.Name);
}
};
return y;
}
};
};
return DbProvider;
})();
let dbProvider = new DbProvider({
Name: "test"
});
dbProvider.create().action().printData();
Keeping ES5 syntax and the call structure a solution would be:
var DbProvider = (function () {
function DbProvider(db) {
var that = this; // create a reference to "this" object
that.collection = db;
}
DbProvider.prototype.create = function () {
var that = this;
return {
action: function() {
var y = {
printData: function () {
console.log('Hello ' + that.collection.Name);
}
};
return y;
}
};
};
return DbProvider;
})();
Definitely not elegant but it works :)
If you do not want to change your structure, you can achieve this behavior if you change you functions to arrow functions.
var DbProvider = (function () {
function DbProvider(db) {
var that = this; // create a reference to "this" object
that.collection = db;
}
DbProvider.prototype.create = function() {
return {
action: () => {
var y = {
printData: () => {
alert('Hello ' + this.collection.Name);
}
};
return y;
}
};
};
return DbProvider;
})();
The way you are creating this "class" is definitely non standard. Let me know if you want an example of how to better structure it.

Object.assign() a deep object

I have a base object ProfileDialog which I am extending with Object.assign().
var ProfileDialog = function (containerObj) {
this.init = function () {
this.container = containerObj;
};
this.render = function () {
let content = document.createElement('div');
content.innerText = 'Dialog here';
this.container.appendChild(content);
};
this.init();
this.render();
};
Mixin:
var DialogMixin = function () {
return {
open: function () {
this.container.style.display = 'block';
},
close: function () {
this.container.style.display = 'none';
}
}
};
Now I do the assignment:
Object.assign(ProfileDialog.prototype, DialogMixin());
It works just fine, this context resolves fine in open and close methods.
But, when I put the mixin in a deeper structure, putting it inside actions property:
var DialogMixin = function () {
return {
actions: {
open: function () {
this.container.style.display = 'block';
},
close: function () {
this.container.style.display = 'none';
}
}
}
};
The context becomes actions object so the code breaks.
How do I properly extend the object with new methods when they are put in a deep structure?
The only thing i can think of is using bind to bind this.
So something like
var ProfileDialog = function (containerObj) {
this.containerObj = containerObj;
};
var DialogMixin = function (newThis) {
var obj = {
actions: {
open: function () {
console.log('open', this, this.containerObj.style);
}
}
}
obj.actions.open = obj.actions.open.bind(newThis);
return obj;
};
var container = {
style : 'some style'
};
var dialog = new ProfileDialog(container);
var mixinDialog = Object.assign(dialog, DialogMixin(dialog));
mixinDialog.actions.open();
See https://jsfiddle.net/zqt1me9d/4/

Is it possible to unit-test this javascript structure?

Given the following JavaScript structure:
addClickEvent: function() {
element.addEventListener('click', function() {
self.a();
self.b();
});
},
Is it possible to assert that a() and b() have been called without refactoring out the anonymous function or editing it's contents?
Assuming the self in your code is the window.self property.
You could do something like this:
function element_onclick_callsAandB() {
// Arrange
var aCalled = false;
var bCalled = false;
var element = ...;
var origA = self.a;
var origB = self.b;
self.a = function() {
aCalled = true;
origA();
};
self.b = function() {
bCalled = true;
origB();
};
try {
// Act
element.click();
// Assert
assertTrue(aCalled);
assertTrue(bCalled);
}
finally {
self.a = origA;
self.b = origB;
}
}

jquery object - function undefined error

In the following function, my objects inside floatShareBar function is undefined. Do I have to init or define a var before the functions? it throws me js error : .float - function undefined.
(function($) {
.
.
.
$("body").on("ab.snap", function(event) {
if (event.snapPoint >= 768) {
floatShareBar.float()
} else {
floatShareBar.unfloat();
}
});
var floatShareBar = function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log(
};
this.unfloat = function() {
console.log("unfloat");
};
};
.
.
.
})(jQuery);
You need to get an instance of that function with a self instantiating call:
var floatShareBar = (function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log('float');
};
this.unfloat = function() {
console.log("unfloat");
};
return this;
})();
UPDATE 1: I modified it to create an object within the function to attach those functions to, since in the previous example this refers to the window object
var floatShareBar = (function() {
var fShareBar = $('#article-share');
var instance = {};
instance.float = function() {
console.log('float');
};
instance.unfloat = function() {
console.log("unfloat");
};
return instance;
})();
UPDATE 2: You can actually just use the new keyword as well, look here for more info
var floatShareBar = new (function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log('float');
};
this.unfloat = function() {
console.log("unfloat");
};
})();
Change you function to this:
$("body").on("ab.snap", function(event) {
if (event.snapPoint >= 768) {
(new floatShareBar()).float()
} else {
(new floatShareBar()).unfloat();
}
});
function floatShareBar () {
var fShareBar = $('#article-share');
this.float = function() {
console.log(
};
this.unfloat = function() {
console.log("unfloat");
};
};
you should declare functions when using var before you call them.

Accessing a function within a function from outside in javascript

I have a nested function that I want to call from outside.
var _Config = "";
var tourvar;
function runtour() {
if (_Config.length != 0) {
tourvar = $(function () {
var config = _Config,
autoplay = false,
showtime,
step = 0,
total_steps = config.length;
showControls();
$('#activatetour').live('click', startTour);
function startTour() {
}
function showTooltip() {
}
});
}
}
function proceed() {
tourvar.showTooltip();
}
$(document).ready(function () {
runtour();
});
I was hoping to call it by tourvar.showTooltip(); but I seem to be wrong :) How can I make showTooltip() available from outside the function?
since my previous answer was really a hot headed one, I decided to delete it and provide you with another one:
var _Config = "";
var tourvar;
// Module pattern
(function() {
// private variables
var _config, autoplay, showtime, step, total_steps;
var startTour = function() { };
var showTooltip = function() { };
// Tour object constructor
function Tour(config) {
_config = config;
autoplay = false;
step = 0;
total_steps = _config.length;
// Provide the user with the object methods
this.startTour = startTour;
this.showTooltip = showTooltip;
}
// now you create your tour
if (_Config.length != 0) {
tourvar = new Tour(_Config);
}
})();
function proceed() {
tourvar.showTooltip();
}
$(document).ready(function () {
runtour();
});
function outerFunction() {
window.mynestedfunction = function() {
}
}
mynestedfunction();

Categories

Resources