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.
Related
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.
So i'm trying to make two functions that allow a user to move an item from their cart to the "saved cart" and vise versa. These functions depend on the "cart group item" module which also contains the events for the button clicks. My question is, i'm unsure how to correctly call these functions to allow the click event to take place in my current js file. Hopefully someone can help!
Event's in module:
cartGroupItem.prototype.createMoveEvent = function (elem) {
if (undefined !== elem && null !== elem) {
var button = elem.querySelector('.cartGroupItem__move');
if (button !== null) {
button.addEventListener('click', function (e) {
ajax('GET',
'/resources/ajax/cart.aspx?sub=3&Saved=0&Cart_Group_ID='+this.cartGroupId,
true, {}, function () {
this.moveToCartCallback();
}.bind(this), function () {
this.showErrorDiv();
}.bind(this));
}.bind(this));
}
}
};
cartGroupItem.prototype.createSaveEvent = function (elem) {
if (undefined !== elem && null !== elem) {
var button = elem.querySelector('.cartGroupItem__save');
if (button !== null) {
button.addEventListener('click', function (e) {
ajax('GET',
'/resources/ajax/cart.aspx?sub=3&Saved=1&Cart_Group_ID='+this.cartGroupId,
true, {}, this.saveForLaterCallback.bind(this), this.showErrorDiv.bind(this));
}.bind(this));
}
}
};
Move functions:
function moveToSaved(cartGroupId) {
for (var i = 0, l = activeCartList.length; i < l; i++) {
if (activeCartList[i].cartGroupId === cartGroupId) {
activeCartList.remove();
savedCartList.push(activeCartList[i]);
}
}
}
function moveToActive(cartGroupId) {
for (var i = 0, l = savedCartList.length; i < l; i++) {
if (savedCartList[i].cartGroupId === cartGroupId) {
savedCartList.remove();
activeCartList.push(savedCartList[i]);
}
}
}
Your Event module probably define the function cartGroupItem right?
What you need to do is pass this function from its file to your current file, and then "instanciate" a carteGroupItem:
// In your current JS file
var myCartGroupItem = new cartGroupItem();
myCartGroupItem.createMoveEvent();
myCartGroupItem.createSaveEvent();
We also would need to see this function "constructor" (where it is defined) as it probably takes a few callbacks as parameters. Otherwise you can add them manually:
myCartGroupItem.moveToCartCallback = function() {
// do what you want when the item is moved to cart
};
// Same for the other callbacks
myCartGroupItem.saveForLaterCallback = function() { ... };
myCartGroupItem.showErrorDiv = function() { ... };
Finally, the way to pass things with RequireJS is that for instance, your Event module returns cartGroupItem so in your file module:
define(['Event'], function(cartGroupItem) {
// Your code where you can use cartGroupItem
});
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;
JQuery can handle events implementing Observer Design Pattern, but it can handle only one event for one callback function
I was wondering, if it could handle many events: when all this events was triggered, or when all boolean premises became true then call a function
It would be much better to develop dynamic applications
Do you know if already exist something like that?
If not: do you think it would be nice if i develop?
EDIT:
i would like to do something like this:
when((a==b && c!=0), function(){
//do something when a==b and c!=0
alert("a==b && c!=0");
});
EDIT 2:
I've found a great API that allow listen for variable changes. You just have to do something like this:
obj.watch(function(){
alert("obj changes");
});
http://watch.k6.com.br/
Sounds like Promises to me. Most of the libraries developed with that concept (there are many for JavaScript, including jQuery.deferred) can simply build a new Promise for the event that some others got fulfilled.
You can easily do this manually:
var flag1 = false;
var flag2 = false;
var flag3 = false;
var checkAllFlags = function () {
if (!flag1 || !flag2 || !flag3) return;
checkAllFlags = function () { };
allFlagsSet();
}
var allFlagsSet = function () {
// Execute here when all flags are set
}
// When you set a flag do it like this:
flag2 = true;
checkAllFlags();
Or you could use this class:
window.flagger = function (count, callback, once) {
var curr = this;
curr.callback = callback;
if (once)
curr.called = false;
curr.flags = [];
curr.flagsLeft = count;
for (var i = 0; i < count; i++)
curr.flags[i] = false;
this.flag = function (index) {
if (!curr.flags[index]) {
curr.flags[index] = true;
if (--curr.flagsLeft <= 0 && (!once || !curr.called)) {
if (once) curr.called = true;
curr.callback();
}
}
};
this.unflag = function (index) {
if (curr.flags[index]) {
curr.flags[index] = false;
curr.flagsLeft++;
}
};
this.reset = function (force) {
for (var i = 0; i < count; i++)
curr.flags[i] = false;
curr.flagsLeft = count;
if (once && force)
curr.called = false;
};
this.isFlagged = function (index) {
return curr.flags[index];
};
}
And use it like this:
var myFlagger = new flagger(
/* The amount of flags that need to be set: */8,
/* The function that needs to be called when the flags are all set: */
function () { alert('Callback function called'); },
/* If the callback function should be called again when a flag is unflagged and reflagged.
Optional. Default: false */false);
// You can now use these functions:
myFlagger.flag(0); // Use this to set a flag, index ranges from 0 to count - 1.
myFlagger.unflag(0); // Unflags an index.
myFlagger.reset(); // Resets all flags to false.
myFlagger.reset(true); // Using this forces the reset, returning to full start
// state, causes callback function to be called again
// even if 'once' is specified.
alert('0 is flagged: ' + myFlagger.isFlagged(1)); // Returns if flag is flagged.
I hope this somewhat helps you.
I am trying to set a custom error handler for 3rd party plugins/modules in my core library, but somehow, myHandler does not alert the e.message.
Can somebody help me please? thank you
Function.prototype.setErrorHandler = function(f) {
if (!f) {
throw new Error('No function provided.');
}
var that = this;
var g = function() {
try {
var a = [];
for(var i=0; i<arguments.length; i++) {
a.push(arguments[i]);
}
that.apply(null,a);
}
catch(e) {
return f(e);
}
};
g.old = this;
return g;
};
function myHandler(e) {
alert(e.message)
};
// my Core library object
(function(){
if (typeof window.Core === 'undefined') {
var Core = window.Core = function() {
this.addPlugin = function(namespace, obj){
if (typeof this[namespace] === 'undefined') {
if (typeof obj === 'function') {
obj.setErrorHandler(myHandler);
} else if (!!obj && typeof obj === 'object') {
for (var o in obj) {
if (obj.hasOwnProperty(o) && typeof obj[o] === 'function') {
obj[o].setErrorHandler(myHandler);
}
}
}
this[namespace] = obj;
return true;
} else {
alert("The namespace '" + namespace + "' is already taken...");
//return false;
}
};
};
window.Core = new Core();
}
})();
// test plugin
(function(){
var myPlugin = {
init: function() {},
conf: function() {
return this.foo.x; // error here
}
};
Core.addPlugin("myPlugin", myPlugin);
})();
// test
Core.myPlugin.conf(); // supposed to alert(e.message) from myHandler()
setErrorHandler in the above code doesn't set an error handler on a Function, as such. JavaScript does not give you the ability to change the called code inside a Function object.
Instead it makes a wrapped version of the function it's called on, and returns it.
obj.setErrorHandler(myHandler);
Can't work as the returned wrapper function is thrown away, not assigned to anything.
You could say:
obj[o]= obj[o].setErrorHandler(myHandler);
though I'm a bit worried about the consequences of swapping out functions with different, wrapped versions. That won't necessarily work for all cases and could certainly confuse third-party code. At the least, you'd want to ensure you don't wrap functions twice, and also retain the call-time this value in the wrapper:
that.apply(this, a);
(Note: you don't need the manual conversion of arguments to an Array. It's valid to pass the arguments object directly to apply.)