I know I'm missing something basic. How do I invoke the checkValue method from inside the startup method (the commented line)? This is all contained within the view in an MVC framework and a custom API.
Essentially, when startup runs, I want the alert() to fire.
define(function(require) {
'use strict';
var Class = require('common/Class'),
ModuleView = require('common/platform/ModuleView');
var value = 0;
return Class.create(
ModuleView,
{
startup : function() {
value = 1;
//invoke checkValue(value) somehow... this.checkValue(value)?
},
checkValue: function(value) {
if (value >= 1) {
alert("Hello.");
}
}
}
);
});
How about writing the class like this:
return Class.create(ModelView, modelView());
function modelView() {
this.startup = function() {
value = 1;
this.checkValue(value);
}
this.checkValue = function(value) {
if (value >= 1)
alert("Hello.");
}
}
This way you can also use this class multiple times by declaring a new instance.
Related
A couple times now I have wanted to check element sizes as the page loads. I've been doing that using $(document).ready();, but find that often the properties are null. The same is true if I use $(window).load();.
To get around this I have been using a bit of a hack, where I recursively recall the function if the element is not set.
Question: Is there a better approach in terms of professionalism?
var makeMusic = {
init: function() {
if ($('#bloc-1').height() == null) {
setTimeout(function() {
makeMusic.init() ########## THIS IS THE HACK ##########
}, 10)
} else {
makeMusic.height = $('#bloc-1').height();
makeMusic.width = $('#bloc-1').width();
}
makeMusic.watchExperience();
},
watchExperience: function() {
//Some stuff
}
}
var Main = {
run: function() {
makeMusic.init();
}
}
$(document).ready(Main.run());
You do not need a hack at all. The issue here is that Main.run function is invoked before document.ready() is fired. You should:
$(document).ready(Main.run);
Instead of
$(document).ready(Main.run());
When you add () to the function name interpeter invokes it as soon as the line is reached.
When passing a callback, you should only pass a reference to the function.
In terms of proffessionalism i think its better to put your code in a namespace like this:
var app = window.app || {};
app.set = {};
app.set.makeMusic = (function(){
// private members
this.height = "";
this.width = "";
var init = function() {
height = $('#bloc-1').height();
width = $('#bloc-1').width();
alert(height + " " + width);
};
//public interface
return {
init: init
};
})(); // self invoked
$(function(){
app.set.makeMusic.init();
});
fiddle
I have a function that simply validates forms (for old browsers). The function works just fine except that I have to pass the parameters every time I call this function, where in fact I already specified the default parameters in 'config'.
So by logic, If I called the function as: validateMe(); it should run as validateMe({requiredClass: '.required', verifiedClass: 'invalid'});
but unfortunately calling the function without parameters doesn't work correctly ( in my case the form triggers the submission event) (it doesn't reach return false).
so what is missing in the code to run the function with the default settings??
function validateMe(vform, settings) {
var vform, //form name or id
config = {
'requiredClass': '.required',
'verifiedClass': 'invalid'
};
if (settings) {
$.extend(config, settings);
}
$(vform).on('submit', function(){
var inputs = $(this).find(config.requiredClass),
required = [];
for (i=0; i < inputs.length; i++) {
if (inputs[i] != null) {
if ($(inputs[i]).val().replace(/^\s+|\s+$/g, '') == '') {
required.push($(inputs[i]).index());
}
}
}
if (required.length > 0) {
$(this).find('input').removeClass(config.verifiedClass);
for(n=0;n<required.length;n++) {
$(inputs[n]).addClass(config.verifiedClass);
}
return false;
}
});
}
Any help?
Thanks.
function validateMe(vform, settings) {
this.vform = vform || 'default',
this.setting = 'whatever',
this.private = ''
}
var newInstance = new validateMe();
now you have an instance of it, so you can define it as you go.
I have a hash called options. The problem that I'm facing is that options['beforeOpen'] might already be a function, in which case I don't want to overwrite it. I'd like to instead call it then call another function that needs to be called every time
In this example the method that needs to be called every time is methodThatINeedToDo. I thought the code below would accomplish this but it's not working as I expected.
function methodThatINeedToDo(){alert('maintenance');}
var options = {beforeOpen: function(){alert('first');}}
if(typeof options['beforeOpen'] == "function"){
options['beforeOpen'] = function(){options['beforeOpen'].call(); methodThatINeedToAddToDo();}
} else {
options['beforeOpen'] = methodThatINeedToDo;
}
The problem is that within the function you're defining to override options['beforeOpen'], you're using options['beforeOpen'], which by that time has been overwritten!
You need to cache it and use the cached value within your new function:
var cachedBeforeOpen = options.beforeOpen;
if (typeof cachedBeforeOpen == "function") {
options.beforeOpen = function() {
cachedBeforeOpen.call();
methodThatINeedToDo();
};
} else {
options.beforeOpen = methodThatINeedToDo;
}
Simply always call methodThatINeedToDo, since you want to and in there check to see if you should call your options method:
function methodThatINeedToDo(){
options.beforeOpen && options.beforeOpen();
alert('maintenance');
}
That really smells like the wrong solution. Why not Publish/Subscribe pattern?
Here's a little example: http://jsfiddle.net/ajyQH/
$(function() {
var yourObj = { yourFct : [] };
$('#btn').click(function() {
yourObj.yourFct.push(function() {
$('#testibert').append($('<p>').text('hallo'));
});
});
$('#btn_exec').click(function() {
var len = yourObj.yourFct.length;
for(var i = 0; i < len; i++) {
yourObj.yourFct[i]();
}
});
});
var oldCall = options['beforeOpen'];
var newCall = function(){
oldCall();
methodThatINeedToAddToDo();
};
options['beforeOpen'] = newCall;
I've created a 'class' in javascript called QuoteProductService(), see below.
I've added two functions to the prototype and now, I'm trying to call one of the functions (getQuoteProductFromArray) from within a jquery $.each inside the other function (getFakeQuoteProducts). This doesn't work. I've tried adding 'this.', but this also does not work, because 'this' inside the .each refers to the current element in the loop.
How should I do this ?
function QuoteProductService() {
}
QuoteProductService.prototype.getQuoteProductFromArray = function(quoteproductarray, quoteproductid){
var founditem=null;
// do stuff
return founditem;
}
QuoteProductService.prototype.getFakeQuoteProducts = function(){
// do something to fill the mappedQuoteProducts array
$.each(mappedQuoteProducts, function (index, quoteproduct) {
if (quoteproduct!=-null) {
if (quoteproduct.parentid != "") {
// this is where it goes wrong :
var parent = getQuoteProductFromArray(mappedQuoteProducts, quoteproduct.parentid);
if (parent != null) {
parent.attachChild(quoteproduct);
}
}
}
});
}
Save a reference to your QuoteProductService instance before calling each
QuoteProductService.prototype.getFakeQuoteProducts = function(){
var _this = this;
// do something to fill the mappedQuoteProducts array
$.each(mappedQuoteProducts, function (index, quoteproduct) {
if (quoteproduct!=-null) {
if (quoteproduct.parentid != "") {
// this is where it goes wrong :
var parent = _this.getQuoteProductFromFlatArray(mappedQuoteProducts, quoteproduct.parentid);
if (parent != null) {
parent.attachChild(quoteproduct);
}
}
}
});
}
Add var self = this; to the beginning of the getFakeQuoteProducts function. Then call getQuoteProductFromFlatArray like this: self.getQuoteProductFromFlatArray.
First of all you provided wrong method name - getQuoteProductFromFlatArray instead of getQuoteProductFromArray. Secondly in JS you must provide scope for instance methods.
Easiest way to achieve this is to store this reference into some other, private variable. See the example below.
function QuoteProductService() {
}
QuoteProductService.prototype.getQuoteProductFromArray = function(quoteproductarray, quoteproductid){
var founditem=null;
// do stuff
return founditem;
}
QuoteProductService.prototype.getFakeQuoteProducts = function(){
var me = this; // store this into me
// do something to fill the mappedQuoteProducts array
$.each(mappedQuoteProducts, function (index, quoteproduct) {
// this === me will return false
if (quoteproduct!=-null) {
if (quoteproduct.parentid != "") {
// this is where it goes wrong :
var parent = me.getQuoteProductFromArray(mappedQuoteProducts, quoteproduct.parentid);
if (parent != null) {
parent.attachChild(quoteproduct);
}
}
}
});
}
I have a json object retrieved from server in my $(document).ready(...); that has an string that I would like to resolve to a function also defined within $(document).ready(...); so, for example:
$(document).ready(function{
$.getJSON(/*blah*/,function(data){/*more blah*/});
function doAdd(left,right) {
return left+right;
}
function doSub(left,right) {
return left-right;
}
});
with json string:
{"doAdd":{"left":10,"right":20}}
One way I thought about was creating an associative array of the function before loading the json:
var assocArray=...;
assocArray['doAdd'] = doAdd;
assocArray['doSub'] = doSub;
Using eval or window[](); are no good as the function may not be called for some time, basically I want to link/resolve but not execute yet.
Change your JSON to
{method: "doAdd", parameters : {"left":10,"right":20}}
Then do
var method = eval(json.method);
// This doesn't call it. Just gets the pointer
Or (haven't tried this)
var method = this[json.method]
How about something like this?
$(function(){
// Function to be called at later date
var ressolvedFunc = null;
// Ajax call
$.getJSON(/*blah*/,function(data){
// Generate one function from another
ressolvedFunc = (function(data) {
var innerFunc;
var left = data.left;
var right = data.right;
// Detect action
for (action in data) {
if (action == "doAdd")
innerFunc = function() {
return left + right;
};
else
innerFunc = function() {
return left - right;
};
}
return innerFunc;
})(data);
});
});
The anonymous function returns fresh function, with the new values stored within the enclosure. This should allow you to call the function at later date with the data previously retrieved from the GET request.
Rich
try this:
var doX = (function() {
var
data = [],
getDo = function(action) {
for(var d in data) {
if (data[d][action]) {
return data[d];
}
}
return null;
};
return {
set: function(sdata) {
data.push(sdata);
},
doAdd: function() {
var add = getDo("doAdd");
if (!add)
return 0;
return add.doAdd.left + add.doAdd.right;
},
doSub: function() {
var sub = getDo("doSub");
if (!sub)
return 0;
return sub.doAdd.left + sub.doAdd.right;
}
};
})();
$(document).ready(function{
$.getJSON(/*blah*/,function(data){ doX.set(data); });
});