javascript module pattern: initialise two objects on load - javascript

I have two objects defined, each one has an init function as follows
var TestSound = {
settings: {
testSoundFile : "static/main/persoonS",
postUrl : "dummy.com",
},
init : function(){
this.cacheDom();
this.bindEvents();
},
cacheDom: function(){
this.oneCertainButton = document.getElementById("buttonId");
this.soundElement = document.getElementById("sound");
},
bindEvents : function(){
that = this;
this.oneCertainButton.onclick = function(){ that.playSound(that.settings.testSoundFile); };
},
............
var CheckInput = {
settings: {
correctAnswer : "persoon",
},
init : function (){
this.cacheDom();
this.bindEvents();
},
cacheDom: function (){
this.submitButton = document.getElementById("submitButtonId");
this.answerInputBox = document.getElementById("answerId");
this.feedbackField = document.getElementById("feedbackId");
},
bindEvents: function(){
that = this;
this.submitButton.addEventListener("click", function(event){
..........
I wish to initialise them both (one after the other) with "window onload" like so:
window.onload = function() {
CheckInput.init.bind(CheckInput);
TestSound.init.bind(TestSound);
};
This doesn't work apparently as the init functions do not seem to be called.
However, it works if I initialise just one of the modules like so:
window.onload =
CheckInput.init.bind(CheckInput);
Any explanations on what is going wrong here much appreciated!

You want either
window.onload = function() {
CheckInput.init();
TestSound.init();
};
or
window.addEventListener("load", CheckInput.init.bind(CheckInput));
window.addEventListener("load", TestSound.init.bind(TestSound));
Any explanations on what is going wrong here much appreciated!
You have to create a function to be used as a handler that is called when the event fires. You can do that by using bind or with a function expression, but if you use both then only another function will be created when the event happens, and the init method is not called at all.

Related

Test Case to call function on Document.ready

My JS code is mentioned below:
if (typeof IPL === "undefined") {
IPL = {};
}
/// <summary>Declare Namespace IPL.Register</summary>
if (typeof IPL.Register === "undefined") {
IPL.Register = {};
}
$(document).ready(function () {
IPL.Register.Print.initialize();
});
/// <summary>Declare Namespace IPL.Register.Print</summary>
IPL.Register.Print =
{
/// <summary>Function to call on initialize page.</summary>
initialize: function () {
window.onload = function () {
window.print();
};
}
};
When I run Test case (Qunit.js and blanket.js) as mentioned below then Document.ready function is not getting called and Code coverage not cover that line.
Below test case works fine but it only include last lines of code and initialize function on window load.
test("initialize test", 1, function () {
var result = IPL.Register.Print.initialize();
equal(undefined, result, "passed");
});
Someone please assist how to write Test case to execute function on document load?
The best way to do this is by not testing the load event at all. Just put the event handler into a named function and then test the behaviour of that function.
/// <summary>Declare Namespace IPL.Register.Print</summary>
IPL.Register.Print = {
/// <summary>Function to call on initialize page.</summary>
initialize: function() {
window.onload = function() {
window.print();
};
},
print: function() {
window.print();
}
};
test("initialize test", 1, function() {
var result = IPL.Register.Print.print();
equal(undefined, result, "passed");
});
http://jsfiddle.net/Tintin37/vpqjsr8L/
The load event just runs your function, what do you want specifically achieve by testing the load event ?

Call function in prototype from other prototype

I have two prototypes in my jquery script :
script1.prototype.initScript = function() {
//first one
this.saveGrid = function () {
alert("here");
}
};
script1.prototype.otherFunction = function () {
//second
//script1.initScript.saveGrid ?
};
I'd like to call saveGrid in otherFunction. How can I do that?
Edit :
And there ?
script1.prototype.initScript = function() {
//first one
this.saveGrid = function () {
alert("here");
}
};
script1.prototype.otherFunction = function () {
//second
$('button').on("click", function(){
//call savegrid here
});
};
Thanks.
You can access the function over this, like you already did in you example while creating the function saveGrid.
You should instead ask yourself, if this is a good idea, to create a function in another function and re-use them elsewere. What will happen, if you call otherFunction before initScript?
function script1() {}
script1.prototype.initScript = function() {
this.saveGrid = function() {
alert("here");
}
};
script1.prototype.otherFunction = function() {
this.saveGrid();
};
var s = new script1();
s.initScript();
s.otherFunction();
For you second example you have to store this before creating your event listener.
function script1() {}
script1.prototype.initScript = function() {
this.saveGrid = function() {
alert("here");
}
};
script1.prototype.otherFunction = function() {
var that = this;
$('button').on("click", function(){
that.saveGrid();
});
};
var s = new script1();
s.initScript();
s.otherFunction();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>click me</button>
Prototype It depends on the type .
the correct way is defined as a prototype , so you can call them in different situations
script1.prototype.saveGrid=function () {
alert("here");
}
script1.prototype.initScript = function() {
//first one
this.saveGrid()
};
script1.prototype.otherFunction = function () {
//second
//this.saveGrid()
};`
or you can define an object which then associates the prototypes
var script1=(function () {
function initScript(){
this.saveGrid();
}
function otherFunction(){
this.saveGrid();
}
script1.prototype.saveGrid=function () {
alert("here");
}
});

$(this) in JavaScript Module Pattern

I'm trying to use the Javascript module pattern for the first time to organize my code. I understand the how "this" works here but cannot figure out how $(this) works. For example, the code below,
$(this).addClass('video-active'); in "chooseVideo" function, I want to apply addClass only for the clicked element. But it does not work. Could anybody give me some advice? Thank you!
;(function() {
'use strict';
if (typeof window.jQuery !== 'function') {
return;
}
var $ = jQuery;
var video = {
init: function() {
this.cacheDom();
this.bindEvents();
this.render();
},
cacheDom: function() {
this.$el = $('#videoWrap');
this.$button = this.$el.find('.video');
},
render: function() {
},
bindEvents: function() {
this.$button.bind('click', this.chooseVideo.bind(this));
},
chooseVideo: function(e) {
e.preventDefault ? e.preventDefault() : e.returnValue = false;
this.$button.removeClass('video-active');
$(this).addClass('video-active');
}
};
video.init();
})();
when you use bind, you are changing the context of this
So you will need to use the event object to get what was clicked.
chooseVideo: function(e) {
e.preventDefault ? e.preventDefault() : e.returnValue = false;
this.$button.removeClass('video-active');
$(e.target).addClass('video-active');

Cocos2d js touch events

I'm building an app in cocos2d-js, and I've got a problem with listening to keyboard events. I expect a method called setKeyboardEnabled to exists but when I call it i get an error that setKeyboardEnabled is not a function, Am I missing something?
var AnimationLayer = cc.Layer.extend({
ctor : function() {
this._super();
this.setKeyboardEnabled(true);
},
onKeyDown : function(key) {
cc.log("action");
}
...
...
)}
The same thing happens when I try to listen to touch events.
In Cocos2D v3 the way events are handled has changed. For a proper explanation of the whole system you should read New event manager in Cocos2d-Html5 v3.0.
In short, if you used to have:
var AnimationLayer = cc.Layer.extend({
ctor : function() {
this._super();
this.setKeyboardEnabled(true);
},
onKeyDown : function(key) {
cc.log("action");
}
...
...
)}
You have to turn it into something like:
var AnimationLayer = cc.Layer.extend({
ctor : function() {
this._super();
cc.eventManager.addListener({
event: cc.EventListener.KEYBOARD,
onKeyDown : function(key) {
cc.log("action");
}
}, this);
},
...
...
)}
This can sound a bit complicated at first, but this new mechanism allows you to attach these event listeners to any kind of cc node, not just layers. So for example you could do something like this to make a Sprite fade when the mouse is above it:
var hoverHandler = cc.EventListener.create({
event: cc.EventListener.MOUSE,
onMouseMove: function (event) {
var target = event.getCurrentTarget();
var locationInNode = target.convertToNodeSpace(event.getLocation());
var s = target.getContentSize();
var rect = cc.rect(0, 0, s.width, s.height);
if (cc.rectContainsPoint(rect, locationInNode)) {
cc.log("It's hovering! x = " + locationInNode.x + ", y = " + locationInNode.y);
target.opacity = 180;
return true;
} else {
target.opacity = 255;
return false;
}
}
});
var MyLayer = cc.Layer.extend({
init: function() {
this._super();
var mySpriteThatFadesWhenHovered = cc.Sprite.create(...);
this.addChild(mySpriteThatFadesWhenHovered);
cc.eventManager.addListener(hoverHandler.clone(), mySpriteThatFadesWhenHovered );
}
)}

Create a jQuery special event for content changed

I'm trying to create a jQuery special event that triggers when the content that is bound, changes. My method is checking the content with a setInterval and check if the content has changed from last time. If you have any better method of doing that, let me know. Another problem is that I can't seem to clear the interval. Anyway, what I need is the best way to check for content changes with the event.special.
(function(){
var interval;
jQuery.event.special.contentchange = {
setup: function(data, namespaces) {
var $this = $(this);
var $originalContent = $this.text();
interval = setInterval(function(){
if($originalContent != $this.text()) {
console.log('content changed');
$originalContent = $this.text();
jQuery.event.special.contentchange.handler();
}
},500);
},
teardown: function(namespaces){
clearInterval(interval);
},
handler: function(namespaces) {
jQuery.event.handle.apply(this, arguments)
}
};
})();
And bind it like this:
$('#container').bind('contentchange', function() {
console.log('contentchange triggered');
});
I get the console.log 'content changed', but not the console.log 'contentchange triggered'. So it's obvious that the callback is never triggered.
I just use Firebug to change the content and to trigger the event, to test it out.
Update
I don't think I made this clear enough, my code doesn't actually work. I'm looking for what I'm doing wrong.
Here is the finished code for anyone interested
(function(){
var interval;
jQuery.event.special.contentchange = {
setup: function(){
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function(){
if($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.handle.call(self, {type:'contentchange'});
}
},100);
},
teardown: function(){
clearInterval(interval);
}
};
})();
Thanks to Mushex for helping me out.
also take a look to James similar script (declaring as jquery object method and not as event)
jQuery.fn.watch = function( id, fn ) {
return this.each(function(){
var self = this;
var oldVal = self[id];
$(self).data(
'watch_timer',
setInterval(function(){
if (self[id] !== oldVal) {
fn.call(self, id, oldVal, self[id]);
oldVal = self[id];
}
}, 100)
);
});
return self;
};
jQuery.fn.unwatch = function( id ) {
return this.each(function(){
clearInterval( $(this).data('watch_timer') );
});
};
and creating special event
jQuery.fn.valuechange = function(fn) {
return this.bind('valuechange', fn);
};
jQuery.event.special.valuechange = {
setup: function() {
jQuery(this).watch('value', function(){
jQuery.event.handle.call(this, {type:'valuechange'});
});
},
teardown: function() {
jQuery(this).unwatch('value');
}
};
Anyway, if you need it only as event, you script is nice :)
I know this post/question is a little old, but these days I was behind a similar solution and I found this:
$('#selector').bind('DOMNodeInserted', function(e) {
console.log(e.target);
});
Source: http://naspinski.net/post/Monitoring-a-DOM-Element-for-Modification-with-jQuery.aspx
Hope this help someone!
The finished code in the original question worked for me, thank you! I would just like to note that I am using jquery 1.9.1 and $.event.handle seems to have been removed. I changed the following to get it to work.
jQuery.event.handle.call(self, {type:'contentchange'});
to
jQuery.event.dispatch.call(self, {type:'contentchange'});
maybe you could try Mutation Observer
Here are the code:
mainArea = document.querySelector("#main_area");
MutationObserver = window.MutationObserver;
DocumentObserver = new MutationObserver(function() {
//what you want to run
});
DocumentObserverConfig = {attributes: true, childList: true, characterData: true, subtree: true};
DocumentObserver.observe(mainArea, DocumentObserverConfig);

Categories

Resources