Module pattern jQuery - javascript

I'm having a problem using the module pattern in a very dummy javascript code.
This code is working perfectly:
;
var test = (function () {
var config = {
replacement: 'a'
};
var init = function () {
$(config.replacement).click(function(){
alert("hello world");
});
}
return {
init: init
}
})();
$(document).ready(test.init());
Instead, this code is not working when I click on any link of my website:
;
var test = (function () {
var config = {
replacement: $('a')
};
var init = function () {
config.replacement.click(function(){
alert("hello");
});
}
return {
init: init
}
})();
$(document).ready(test.init());
Anyone could tell me why I can not use a jQuery object as "default" initialization of config variable.

The $(a) is executed before DOM ready, probably when no a elements are accessible.
In your first example, the set was constructed after DOM ready.
You could turn it into a function instead...
var config = {
replacement: function() { return document.links; }
};

Then, Why in this example located in official jQuery website using a jQuery selector is working for the default config vars?
var feature = (function () {
var $items = $("#myFeature li");
var $container = $("<div class='container'></div>");
var $currentItem = null;
var urlBase = "/foo.php?item=";
var createContainer = function () {
var $i = $(this);
var $c = $container.clone().appendTo($i);
$i.data("container", $c);
},
buildUrl = function () {
return urlBase + $currentItem.attr("id");
},
showItem = function () {
$currentItem = $(this);
getContent(showContent);
},
showItemByIndex = function (idx) {
$.proxy(showItem, $items.get(idx));
},
getContent = function (callback) {
$currentItem.data("container").load(buildUrl(), callback);
},
showContent = function () {
$currentItem.data("container").show();
hideContent();
},
hideContent = function () {
$currentItem.siblings().each(function () {
$(this).data("container").hide();
});
};
$items.each(createContainer).click(showItem);
return {
showItemByIndex: showItemByIndex
};
})();
$(document).ready(function () {
feature.showItemByIndex(0);
});
Official jQuery website

Related

When creating js widgets, how do I get an instance of my widget?

I'm trying to implement widgits the way DevExtreme does it.
When they create a textbox widgit, this is the code:
$("#someContainer").dxTextBox({ options... });
When they get an instance of the widgit, they do this...
$("#someContainer").dxTextBox("instance");
This is my widget code so far ...
(function ($) {
'use strict';
$.myWidget = function (element, options) {
var plugin = this;
var $base = $(element);
var defaultOptions = {
id: null,
};
var opts = $.extend({}, defaultOptions, options);
var me = new function () {
var self = this;
var init = {
widgets: function () {
// Do some stuff
},
};
return {
init: init,
};
};
me.init.widgets();
};
$.fn.myWidget = function (options) {
return this.each(function () {
if (undefined === $(this).data('myWidget')) {
var plugin = new $.myWidget(this, options);
$(this).data('myWidget', plugin);
}
});
};
})(jQuery)
With this I can create a widget like this...
$("#someContainer").myWidget({ id: 1 });
But I would like to be able to get an instance of the widget, so I could do something like this:
$("#someContainer").myWidget("instance").showPopup();
And also:
var w = $("#someContainer").myWidget({ options... }).myWidget("instance");
w.showPopup();
How can I get an instance?
You have to detect the "special call" for when the instance is requested. Here a small example:
(function ($) {
'use strict';
$.myWidget = function (element, options) {
var plugin = this;
var $base = $(element);
var defaultOptions = {
id: null,
};
var opts = $.extend({}, defaultOptions, options);
var me = new function () {
var self = this;
var init = {
widgets: function () {
return {
hello: function(){
alert("it's me!");
}
}
},
};
return {
init: init,
};
};
return me.init.widgets();
};
$.fn.myWidget = function (options) {
if(options === "instance"){
return $(this).data('myWidget');
}
return this.each(function () {
if (undefined === $(this).data('myWidget')) {
var plugin = new $.myWidget(this, options);
$(this).data('myWidget', plugin);
}
});
};
})(jQuery)
$("#someContainer").myWidget({ id: 1 });
$("#someContainer").myWidget("instance").hello()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="someContainer"></div>

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/

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();

jQuery boilerplate call functions

i use jQuery Boilerplate: http://jqueryboilerplate.com/
and now i have a problem to call a function in a function..
i can't call "openOverlay" in "clickEvents", but i can call "openOverlay" in "init".
here is a snippet:
Plugin.prototype = {
init: function() {
var $me = $(this.element);
this.clickEvents($me);
},
clickEvents: function($el, func) {
$el.on('click', function() {
var $me = $(this);
var overlayName = $me.data('overlay');
this.openOverlay(overlayName);
});
},
openOverlay: function(overlayName) {
var $overlayContainer = $(defaults.$overlayContainer);
var $overlay = $overlayContainer.find('[data-overlay="' + overlayName + '"]');
$overlayContainer.fadeIn(500);
$overlay.delay(500).fadeIn(500);
}
};
the problem is that the on click function overrides "this"
try:
var self=this;
$el.on('click', function() {
var $me = $(this);
var overlayName = $me.data('overlay');
self.openOverlay(overlayName);
});

Categories

Resources