Simplified working demo code here.
Relevant JS code:
;(function(exports) {
//--------------------------------------------------------------------------
//
// Private properties:
//
//--------------------------------------------------------------------------
var _msg = '',
_ol = document.getElementById('debug');
//--------------------------------------------------------------------------
//
// Public methods:
//
//--------------------------------------------------------------------------
exports.init = function(arg) {
_msg = arg;
// Add a listener to the `window.resize` event, pass `exports`/`self` as the scope:
_addEvent(window, 'resize', _listenForChange, exports);
};
//--------------------------------------------------------------------------
//
// Private methods:
//
//--------------------------------------------------------------------------
function _addEvent(elem, type, handle, context) {
// Attache event:
if (elem) {
if (elem.addEventListener) {
// If the browser supports event listeners, use them:
elem.addEventListener(type, function() { handle.call(context); }, false);
} else if (elem.attachEvent) {
// IE & Opera:
elem.attachEvent('on' + type, function() { handle.call(context); });
} else {
// Otherwise, replace the current thing bound to `on[whatever]`!
elem['on' + type] = function() { handle.call(context); };
}
}
}
function _listenForChange() {
var li = document.createElement('li');
li.innerHTML = String(_msg);
_ol.appendChild(li);
if (typeof console !== 'undefined') console.log(_msg);
}
return exports; // Expose the API.
}(window.FOO = window.FOO || {}));
//--------------------------------------------------------------------
window.onload = function() {
FOO.init('world');
FOO.init('universe');
};
Problem with existing code:
When re-sizing the window, I only see "universe".
Goal:
When browser window re-sizes, I want to world "world" and "universe" output as a list item (and to the console).
I want to have the ability to instantiate FOO multiple times and have it work independently from any other running instances.
My questions:
Is there a pattern (or patterns), similar to the one(s) that I'm currently using, that will allow me to run multiple instances of FOO without having the last FOO called trump all previously called FOOs?
The code I posted is obviously not real world; my end goal is to allow/modify a plugin I wrote to be used without the end user having to worry if FOO is already being used by another script.
EDIT #1
Here's a JSBin version of my example code that incorporates Abuzittin's (and Joseph's) suggestions. Many thanks for the help folks!
Unfortunately, I was not able to get it to work out of the box. Though, based on those suggestions, I came up with this:
;(function(exports) {
var _ol = document.getElementById('debug');
exports.init = function(arg) {
this._msg = arg;
// Add a listener to the `window.resize` event, pass `exports`/`self` as the scope:
this.addEvent(window, 'resize', exports.listenForChange, exports);
exports.listenForChange(); // Fire off first time.
};
exports.listenForChange = function() {
var msg = this._msg;
var li = document.createElement('li');
li.innerHTML = String('Hello ' + msg);
_ol.appendChild(li);
if (typeof console !== 'undefined') {
console.log(msg, '...');
}
};
exports.addEvent = function(elem, type, handle, context) {
// Attache event:
if (elem) {
if (elem.addEventListener) {
// If the browser supports event listeners, use them:
elem.addEventListener(type, function() { handle.call(context); }, false);
} else if (elem.attachEvent) {
// IE & Opera:
elem.attachEvent('on' + type, function() { handle.call(context); });
} else {
// Otherwise, replace the current thing bound to `on[whatever]`!
elem['on' + type] = function() { handle.call(context); };
}
}
};
return exports; // Expose the API.
}(window.FOO = window.FOO || {}));
//--------------------------------------------------------------------
window.onload = function() {
FOO.init('world');
FOO.init('universe');
};
... which works (JSBin example), but only on init (like Abuzittin was saying).
Updated question:
Is it it even possible to have multiple copies of window.FOO? Is there some way to allow the end user to define what FOO is? Or, could I setup my pattern to allow for the user to say FOO.CUSTOMINSTANCENAME.init()?
NOTE:
I had originally asked my question on StackOverflow; I soon realized that I needed to move my question here, to CodeReview.
On Stack, user fab had recommended:
function initFoo(fooName) {
(function(foo) {
foo.init = function() {};
// other public/private methods here.
return foo;
}(window[fooName] = window[fooName] || {}));
}
initFoo('FOO');
initFoo('BILLY');
In your opinions, based on the code I have provided, would that be my best option? Are there alternatives?
Also, Oerd recommended I read:
Addy Osmani's Essential JS Namespacing Patterns
... Which is an awesome article! I'm just having troubles trying to figure out if any of those namespace patterns mentioned in the article would meet the needs of my code.