How do I use a constructor in javascript - javascript

Here is my problem.
I am using Backbone js and every collection I have defined requires the same check on save or destroy. Except that the destroy success functions need to be passed an element to remove from the page when the destroy succeeds.
I didn't want to copy and paste the same code into every save or destroy method so I created this:
window.SAVE_TYPE_DESTROY = 'destroy';
window.SaveResponseHandler = function(el,type){
if (!type){
this.success = function() {
this._success();
};
}else if (type == window.SAVE_TYPE_DESTROY){
this.success = function() {
this._success();
$(el).remove();
};
}
};
SaveResponseHandler.prototype._success = function(model, response, options) {
if ((response.success * 1) === 0) {
persistError(model, {
responseText: response.message
}, {});
}
};
SaveResponseHandler.prototype.error = persistError;
var saveResponseHandler = new SaveResponseHandler();
And I use it like this:
destroy: function() {
var el = this.el;
var model = this.model;
this.model.destroy(new SaveResponseHandler(el,'destroy'));
},
change: function() {
this.model.set({
job_category_name: $($(this.el).find('input')[0]).val()
});
var viewView = this.viewView;
this.model.save(null, saveResponseHandler);
}
The problem is when success is called I get the following error:
Uncaught TypeError: Object [object Window] has no method '_success'
Any help will be much appreciated. I'm also open to any suggestions on better ways to handle this.

this inside of SaveResponseHandler.success isn't SaveResponseHandler, it's window.
window.SaveResponseHandler = function(el, type) {
var self = this;
if (!type) {
this.success = function() {
self._success();
};
} else if (type == window.SAVE_TYPE_DESTROY) {
this.success = function() {
self._success();
$(el).remove();
};
}
};
http://jsfiddle.net/ethagnawl/VmM5z/

Related

Create a function / event for user in Javascript prototype

I have a Protoype in my project as follows:
(function($) {
$.fn.observerPages = function(pageNo) {
return new ObserverPage($(this), pageNo);
};
function ObserverPage(Parent, pageNo) {
try {
this.parent = Parent;
this.isInitialized = false;
this.timer = -1;
this.highChart = [];
} catch (e) {
}
}
ObserverPage.prototype = {
initialize: function(url) {
isInitialized = true;
},
update: function(controllerurl) {
if (isInitialized == true) {
//Update
}
},
startTimer: function(url, interval) {},
stopTimer: function() {}
};
})(jQuery);
This initiates a page that is hooked with an observer and gets data from an ajax service at a defined interval.
What I require is to put an event in this where the user can put a function when this.isInitialized becomes true.
Currently I am using it like this.
var page = $("liveDiv").observerPages(2);
page.initialize("http://localhost:5549/GetLatestNews");
page.update("http://localhost:5549/GetLatestNewsData");
I want an event that the user can handle when isInitialized gets true and can be used like this
page.onInitialize(function(){
//User writes his function
});
How can I do that?
Solution might be similar to this:
var event = new Event('pageinit');
ObserverPage.prototype = {
initialize: function(url) {
isInitialized = true;
},
update: function(controllerurl) {
if (isInitialized == true) {
document.dispatchEvent(event);
}
},
startTimer: function(url, interval) {},
stopTimer: function() {},
onInitialize: function(callback)
{
document.addEventListener('pageinit', callback, false);
}
};
EDIT: this->document

Geting undefined when passing in a parameter to a Module pattern function

$("#foo").on("click", function() {
amountItems.speek('heey')
})
var amountItems = (function(el) {
// var el = el;
return {
speek: function() {
alert(el)
}
}
}())
This is my first attempt to using a module pattern. basically when foo get's clicked i want the speek method inside the amountItems function to be called and I want to pass the string 'heey' to the method so it should alert 'heey' when foo is clicked. originally i wanted to pass something like $("#foo").text() but either way I get 'undefined'.
can you show me how to work with a jQuery object when it's passed into this type of function?
You just have the parameter for el in the wrong place. This works:
$("#foo").on("click", function() {
amountItems.speek('heey')
})
var amountItems = (function() {
return {
speek: function(el) {
alert(el);
}
}
}())
--edit--
Just in case you were wondering how the whole scope / private variables thing works:
$("#foo").on("click", function() {
amountItems.load('heey');
amountItems.speek();
})
var amountItems = (function() {
var el = ""
return {
load: function(str) {
el = str;
},
speek: function() {
alert(el);
}
}
}())
When you do this:
var amountItems = (function(el) {
// var el = el;
return {
speek: function() {
alert(el)
}
}
}())
You execute a wrapper function and assign amountItems with the inner object.
You don't pass a param(el) when you invoke this and therefore el is undefined.
amountItems is an object with a method called speek that doesn't except params.
The right way to do this is:
var amountItems = {
speek: function(txt) {
alert(txt);
}
};
$("#foo").on("click", function() {
amountItems.speek('heey')
})

Persisting values in the plugin object for a jQuery plugin

I'm trying to write a simple jQuery plugin that follows similar structure to the one below. The problem I'm having is that when I initialize the plugin the value plugin.myValue is set to 1 however when I try to access that value in the talk function it's undefined. Can anyone help me refine this plugin structure so when I set values on the plugin object they can be accessed in different methods.
Please keep in mind that the plugin below is not my actual use case it is just a simple example to illustrate the problem I'm having.
My actual use case would be very long because it is a jQuery carousel that I'm writing. If it will help I can provide that code however it's much longer and the below example follows the same flow. I would initialize this plugin with the following code:
$('#Div1').talk({ message: "test message" });
$('#Div1').talk('talk');
(function ($) {
$.fn.talk = function(method) {
var settings = {};
var $el = $(this);
var plugin = this;
var methods = {
init: function(options){
settings = $.extend(true, settings, this.talk.defaults, options);
return this.each(function() {
plugin.myValue = 1;
});
},
talk: function(){
helpers.talk(settings.message);
}
}
var helpers = {
talk: function(message){
if (plugin.myValue == 1)
{
alert(message);
}
}
}
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error( 'Method "' + method + '" does not exist in talk plugin!');
}
}
$.fn.talk.defaults = {
message: "default message"
}
})(jQuery);
When you define a plugin, this refers already to the jquery object (not the dom element), so I think your plugin var should go en each element, like this:
(function ($) {
$.fn.talk = function(method) {
var settings = {};
var $el = this; //Not need of $() here
var methods = {
init: function(options){
settings = $.extend(true, settings, this.talk.defaults, options);
return this.each(function(index, item) {
item.myValue = 1; //check this
});
},
talk: function(){
helpers.talk.call(this, settings.message); //talk needs scope
}
}
var helpers = {
talk: function(message){
var $elems = this;
if ($elems[0] && $elems[0].myValue == 1) //Something like this
{
alert(message);
}
}
}
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error( 'Method "' + method + '" does not exist in talk plugin!');
}
}
$.fn.talk.defaults = {
message: "default message"
}
})(jQuery);
I hope you get my idea. Don't forget that your selector might match to more than one element. You were stroring the data to the jquery object, and don't forget that it's a different one each time you call $("#yourDiv"), so your data was lost.
Note: It'd be cleaner to do $(item).data('myValue', 1); instead of item.myValue = 1; (and its proper retrieval), but it's a matter of choice
EDIT Option 2. This may look more similar to your code, but will work only when your selector only matched a single element
(function ($) {
$.fn.talk = function(method) {
var settings = {};
var $el = this; //Not need of $() here
var methods = {
init: function(options){
settings = $.extend(true, settings, this.talk.defaults, options);
$el.data("myValue", 1);
},
talk: function(){
helpers.talk(settings.message);
}
}
var helpers = {
talk: function(message){
if ($el.data("myValue") == 1)
{
alert(message);
}
}
}
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error( 'Method "' + method + '" does not exist in talk plugin!');
}
}
$.fn.talk.defaults = {
message: "default message"
}
})(jQuery);
Hope this helps. Cheers

How to return a object method in a jquery event

I am trying to return an object method on the event jQuery.change() of a text field,
here is the code:
var Utente = function(indice){
this.Indice = indice;
this.Dati = new Array();
this.initialize = function() {
this.Dati['stato_civile'] = this.getField('stato_civile').val();
this.onChange('stato_civile',this.checkObbligatorieta);
}
this.getField = function(name) {
return $('#'+indice+name);
}
this.onChange = function(field, func) {
this.getField(field).live('change',function() {
return func.apply();
});
}
this.checkObbligatorieta = function() {
this.Dati['stato_civile'] = this.getField('stato_civile').val();
[...]
}
this.initialize();
}
Using this I get the field "#stato_civile" returns the function this.checkObbligatorieta correctly but it gives me an error:
** this.getField('stato_civile').val() is not a function
I think it's something strictly related with the scope, but I can't figure it out.
That's because you're not invoking func() in the same context as the caller, so this is not bound to the same object.
You can fix the problem by passing this to apply():
this.onChange = function(field, func) {
this.getField(field).live("change", function() {
return func.apply(this);
});
};

JavaScript refer to a method inside a method?

Ok, just solved one problem where this refered to the wrong scope. Now I have another problem.
So I want to call a method that is inside a method. But I do not know how, check this source:
function someObj() {
var self = this;
this.someMethod1 = function() {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function() {
self.someMethod2.methodMethod();
//I want this.someMethod2.methodMethod() to be called
//...but I get an big error instead. Is it even possible?
//this.someMethod2() works fine.
};
};
this.someMethod2 = function() {
this.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
alert('NO, NOT THIS!');
};
}
Error msg:
Uncaught TypeError: Object function () { ...
With your code, someMethod2 would need to execute first for the function expression to be assigned. Even then, it would be assigned to the parent instance.
Bearing in mind that all functions are objects in JavaScript, this is what you want instead:
this.someMethod2 = function() {
alert('NO, NOT THIS!');
};
this.someMethod2.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
You are trying to use an object accessor on a function. If you want it to work in this way, you need to return an object literal from your call to the "outer" function.
this.someMethod2 = function() {
return {
methodMethod: function() {
alert('THIS IS THE ONE I WANTED!');
}
}
};
You can then chain the call. self.someMethod2().methodMethod();
While this is not directly possible, you can pass a "command" to the outer function to tell it to execute the inner function. But, are you sure this is what you really need? Perhaps you should use objects instead of functions here. But here's the "command" way:
this.someMethod2 = function(cmd) {
var methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
if (cmd === "methodMethod") {
methodMethod();
return;
}
alert('NO, NOT THIS!');
};
function someObj() {
var self = this;
this.someMethod1 = function () {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function () {
self.someMethod2().methodMethod();
};
};
this.someMethod2 = function () {
this.methodMethod = function () {
alert('THIS IS THE ONE I WANTED!');
};
//return this for chain method.
return this;
};
}
trying
function someObj() {
var self = this;
this.someMethod1 = function() {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function() {
self.someMethod2().methodMethod();
};
this.someMethod2 = function() {
this.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
alert('NO, NOT THIS!');
return this;
};
}
Also if you use prototype then
function someObj() {
var self = this;
this.someMethod1 = function() {
var elementBtn = document.getElementById('myBtn');
elementBtn.onclick = function() {
self.someMethod2.methodMethod();//['methodMethod']();
};
};
this.someMethod2 = function() {
};
this.someMethod2.methodMethod = function() {
alert('THIS IS THE ONE I WANTED!');
};
};
But the method methodMethod is static

Categories