how to validate form(do not take null value) on sapui5 - sapui5

my form
var oSimpleForm = new sap.ui.layout.form.SimpleForm({
maxContainerCols: 2,
content:[
new sap.ui.core.Title({text:"Employee"}),
new sap.ui.commons.Label({text:"Emp No",required:true}),
new sap.ui.commons.TextField({value:"",}),
new sap.ui.commons.Label({text:"First Name"}),
new sap.ui.commons.TextField({value:"",required: true}),
new sap.ui.commons.Label({text:"Last Name"}),
new sap.ui.commons.TextField({value:"",required: true}),
new sap.ui.commons.Label({text:"Street"}),
new sap.ui.commons.TextField({value:"",required: true}),
new sap.ui.commons.Label({text:"Country"}),
new sap.ui.commons.TextField({value:"",required: true}),
new sap.ui.commons.Label({text:"City"}),
new sap.ui.commons.TextField({value:"",required: true})
]
});
oCreateDialog.addContent(oSimpleForm);
oCreateDialog.addButton(
new sap.ui.commons.Button({
text: "Submit",
press: function() {
//validate input data not null
}
})
);
This is simple form, to take some input data.My question is -- On click of submit button how can i validate input data or no data field should be empty at the time of submitting...
Thank you

function() {
// get the content (as array)
var content = oSimpleForm.getContent();
// check every single control
for (var i in content) {
var control = content[i];
// check control only if it has the function getValue
// a rather primitive way to filter the TextFields
if(control.getValue) {
// check the value on empty text
if(control.getValue() === "") {
// do whatever you want to show the user he has to provide more input
alert("empty value found");
}
}
}
}
to only alert once:
function() {
var content = oSimpleForm.getContent();
// assume all controls are valid, if one is invalid this flag is set to false
var allValid = true;
for (var i in content) {
var control = content[i];
// in case one control was invalid the variable allValid has been set to false
if(allValid && control.getValue && control.getValue() === "") {
allValid = false;
// stop the for-loop
break;
}
}
if(!allValid) {
alert("empty value found");
}
}

Related

How can I send and receive a signal when a file loads in my GJS app?

I have an app that needs to open a file and update UI elements accordingly. I can select and open the file (and log the file contents), but I can't tell the UI elements to update.
I have tried read that I can create and add signals to just about any object, but I need to emit a signal from a function in an imported library.
I'm trying to do something like this:
(in my function that has read a file from disk)
try {
Signals.addSignalMethods(this);
this.emit('update_ui', true);
} catch(e) {
print(e);
}
(and in the main app class)
Signals.addSignalMethods(this);
this.connect('update_ui',() => {
try {
print('>>> updating UI');
this.ui.updateUI();
} catch (e) {
print(e);
}
});
I don't get any errors when I run the app, but the update function is never called.
How can I get the signal to go through?
Here's the code from the main.js file that should catch the signal :
#!/usr/bin/gjs
Gio = imports.gi.Gio;
GLib = imports.gi.GLib;
Gtk = imports.gi.Gtk;
Lang = imports.lang;
Webkit = imports.gi.WebKit2;
Signals = imports.signals;
GObject = imports.gi.GObject;
Pango = imports.gi.Pango;
//
// add app folder to path
//
function getAppFileInfo() {
let stack = (new Error()).stack,
stackLine = stack.split('\n')[1],
coincidence, path, file;
if (!stackLine) throw new Error('Could not find current file (1)');
coincidence = new RegExp('#(.+):\\d+').exec(stackLine);
if (!coincidence) throw new Error('Could not find current file (2)');
path = coincidence[1];
file = Gio.File.new_for_path(path);
return [file.get_path(), file.get_parent().get_path(), file.get_basename()];
}
const path = getAppFileInfo()[1];
imports.searchPath.push(path);
const myApp = new Lang.Class({
Name: 'My Application',
// Create the application itself
_init: function() {
this.application = new Gtk.Application();
// Connect 'activate' and 'startup' signals to the callback functions
this.application.connect('activate', Lang.bind(this, this._onActivate));
this.application.connect('startup', Lang.bind(this, this._onStartup));
},
// Callback function for 'activate' signal presents windows when active
_onActivate: function() {
this._window.present();
},
// Callback function for 'startup' signal builds the UI
_onStartup: function() {
this._buildUI();
},
// Build the application's UI
_buildUI: function() {
// Create the application window
this._window = new Gtk.ApplicationWindow({
application: this.application,
title: "My App",
default_height: 200,
default_width: 400,
window_position: Gtk.WindowPosition.CENTER
});
//
// menu bar
//
const Menubar = imports.lib.menubar;
this._window.set_titlebar(Menubar.getHeader());
Signals.addSignalMethods(this);
this.connect('update_ui', () => {
try {
print('>>> updating UI');
//this.ui.updateUI();
} catch (e) {
print(e);
}
});
// Vbox to hold the switcher and stack.
this._Vbox = new Gtk.VBox({
spacing: 6
});
this._Hbox = new Gtk.HBox({
spacing: 6,
homogeneous: true
});
// const UI = imports.UI.UI;
// this.ui = new UI.UIstack();
// this.ui._buildStack();
// this._Hbox.pack_start(this.ui._stack_switcher, true, true, 0);
this._Vbox.pack_start(this._Hbox, false, false, 0);
// this._Vbox.pack_start(this.ui._Stack, true, true, 0);
// Show the vbox widget
this._window.add(this._Vbox);
// Show the window and all child widgets
this._window.show_all();
},
});
// Run the application
const app = new myApp();
app.application.run(ARGV);
and here's the header bar file that emits the signal:
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const File = imports.lib.file;
const PopWidget = function(properties) {
let label = new Gtk.Label({
label: properties.label
});
let image = new Gtk.Image({
icon_name: 'pan-down-symbolic',
icon_size: Gtk.IconSize.SMALL_TOOLBAR
});
let widget = new Gtk.Grid();
widget.attach(label, 0, 0, 1, 1);
widget.attach(image, 1, 0, 1, 1);
this.pop = new Gtk.Popover();
this.button = new Gtk.ToggleButton();
this.button.add(widget);
this.button.connect('clicked', () => {
if (this.button.get_active()) {
this.pop.show_all();
}
});
this.pop.connect('closed', () => {
if (this.button.get_active()) {
this.button.set_active(false);
}
});
this.pop.set_relative_to(this.button);
this.pop.set_size_request(-1, -1);
this.pop.set_border_width(8);
this.pop.add(properties.widget);
};
const getHeader = function() {
let headerBar, headerStart, imageNew, buttonNew, popMenu, imageMenu, buttonMenu;
headerBar = new Gtk.HeaderBar();
headerBar.set_title("My App");
headerBar.set_subtitle("Some subtitle text here");
headerBar.set_show_close_button(true);
headerStart = new Gtk.Grid({
column_spacing: headerBar.spacing
});
// this.widgetOpen = new PopWidget({ label: "Open", widget: this.getPopOpen() });
imageNew = new Gtk.Image({
icon_name: 'document-open-symbolic',
icon_size: Gtk.IconSize.SMALL_TOOLBAR
});
buttonNew = new Gtk.Button({
image: imageNew
});
buttonNew.connect('clicked', () => {
const opener = new Gtk.FileChooserDialog({
title: 'Select a file'
});
opener.set_action(Gtk.FileChooserAction.OPEN);
opener.add_button('open', Gtk.ResponseType.ACCEPT);
opener.add_button('cancel', Gtk.ResponseType.CANCEL);
const res = opener.run();
if (res == Gtk.ResponseType.ACCEPT) {
const filename = opener.get_filename();
print(filename);
const fileData = File.open(filename);
print(JSON.stringify(fileData, null, 2));
File.unRoll(fileData);
//
// SHOULD SEND A SIGNAL
//
try {
Signals.addSignalMethods(this);
this.emit('update_ui', true);
} catch (e) {
print(e);
}
// this._window.ui.updateUI();
}
opener.destroy();
});
// headerStart.attach(this.widgetOpen.button, 0, 0, 1, 1);
headerStart.attach(buttonNew, 1, 0, 1, 1);
headerBar.pack_start(headerStart);
popMenu = new Gtk.Popover();
imageMenu = new Gtk.Image({
icon_name: 'document-save-symbolic',
icon_size: Gtk.IconSize.SMALL_TOOLBAR
});
buttonMenu = new Gtk.MenuButton({
image: imageMenu
});
buttonMenu.set_popover(popMenu);
popMenu.set_size_request(-1, -1);
buttonMenu.set_menu_model(this.getMenu());
headerBar.pack_end(buttonMenu);
return headerBar;
};
const getPopOpen = function() {
/* Widget popover */
let widget = new Gtk.Grid(),
label = new Gtk.Label({
label: "Label 1"
}),
button = new Gtk.Button({
label: "Other Documents ..."
});
button.connect('clicked', () => {
this.widgetOpen.pop.hide();
this.printText('Open other documents');
});
button.set_size_request(200, -1);
widget.attach(label, 0, 0, 1, 1);
widget.attach(button, 0, 1, 1, 1);
widget.set_halign(Gtk.Align.CENTER);
return widget;
};
const getMenu = function() {
/* GMenu popover */
let menu, section, submenu;
menu = new Gio.Menu();
section = new Gio.Menu();
section.append("Save As...", 'app.saveAs');
section.append("Save All", 'app.saveAll');
menu.append_section(null, section);
section = new Gio.Menu();
submenu = new Gio.Menu();
section.append_submenu('View', submenu);
submenu.append("View something", 'app.toggle');
submenu = new Gio.Menu();
section.append_submenu('Select', submenu);
submenu.append("Selection 1", 'app.select::one');
submenu.append("Selection 2", 'app.select::two');
submenu.append("Selection 3", 'app.select::thr');
menu.append_section(null, section);
section = new Gio.Menu();
section.append("Close All", 'app.close1');
section.append("Close", 'app.close2');
menu.append_section(null, section);
// Set menu actions
let actionSaveAs = new Gio.SimpleAction({
name: 'saveAs'
});
actionSaveAs.connect('activate', () => {
const saver = new Gtk.FileChooserDialog({
title: 'Select a destination'
});
saver.set_action(Gtk.FileChooserAction.SAVE);
saver.add_button('save', Gtk.ResponseType.ACCEPT);
saver.add_button('cancel', Gtk.ResponseType.CANCEL);
const res = saver.run();
if (res == Gtk.ResponseType.ACCEPT) {
const filename = saver.get_filename();
print(filename);
const data = File.rollUp();
File.save(filename, data);
// let data = JSON.stringify(<FILE DATA>, null, '\t');
// GLib.file_set_contents(filename, data);
}
saver.destroy();
});
APP.add_action(actionSaveAs);
let actionSaveAll = new Gio.SimpleAction({
name: 'saveAll'
});
actionSaveAll.connect('activate', () => {
Gtk.FileChooserAction.OPEN
});
APP.add_action(actionSaveAll);
let actionClose1 = new Gio.SimpleAction({
name: 'close1'
});
actionClose1.connect('activate', () => {
this.printText('Action close all');
});
APP.add_action(actionClose1);
let actionClose2 = new Gio.SimpleAction({
name: 'close2'
});
actionClose2.connect('activate', () => {
this.printText('Action close');
});
APP.add_action(actionClose2);
let actionToggle = new Gio.SimpleAction({
name: 'toggle',
state: new GLib.Variant('b', true)
});
actionToggle.connect('activate', (action) => {
let state = action.get_state().get_boolean();
if (state) {
action.set_state(new GLib.Variant('b', false));
} else {
action.set_state(new GLib.Variant('b', true));
}
this.printText('View ' + state);
});
APP.add_action(actionToggle);
let variant = new GLib.Variant('s', 'one');
let actionSelect = new Gio.SimpleAction({
name: 'select',
state: variant,
parameter_type: variant.get_type()
});
actionSelect.connect('activate', (action, parameter) => {
let str = parameter.get_string()[0];
if (str === 'one') {
action.set_state(new GLib.Variant('s', 'one'));
}
if (str === 'two') {
action.set_state(new GLib.Variant('s', 'two'));
}
if (str === 'thr') {
action.set_state(new GLib.Variant('s', 'thr'));
}
this.printText('Selection ' + str);
});
APP.add_action(actionSelect);
return menu;
};
it's not a class, just a static library... it's imported by the main.js file, so I would think the scope would be the same, but maybe not...
I'm going to over-answer while I get to your question again, because I see some difficulties and some "best practices" you could be using. I think it's much preferrable to use a direct subclass of GtkApplication and use ES6 classes.
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
var MyApp = GObject.registerClass({
// This must be unique, although I don't believe you have to specify it
GTypeName: 'MyApp',
// GObject already have their own signal system, so invoking addSignalMethods()
// will override the existing methods and could cause you problems. Here's a
// simple example of how you'd add a GObject signal to a subclass; the resulting
// callback would look like:
//
// myapp.connect('update-ui', (application, bool) => { ... });
Signals: {
'update-ui': {
param_types: [GObject.TYPE_BOOLEAN]
},
}
}, class MyApp extends Gtk.Application {
_init(params) {
// You could pass the regular params straight through
//super._init(params);
// Or setup your class to be initted without having to pass any args in your
// constructor
super._init({
// This will also become your well-known name on DBus, with the matching
// object path of /org/github/username/MyApp.
//
// GApplication framework will also use these for other things like any
// GResource you bundle with your application.
application_id: 'com.github.username.MyApp',
// There are other flags you can set to allow your app to be a target for
// "Open with...", but that's not what you're asking about today :)
flags: Gio.ApplicationFlags.HANDLES_OPEN
});
// You can also do other setup , however it's important to note that
// GApplication's are generally "single-instance" processes, so you want most
// of that setup in ::startup which will only run if this is the primary
// instance.
//
// On the other hand if you pass HANDLES_OPEN, for example, that signal/vfunc
// will still be invoked.
GLib.set_prgname(this.application_id);
GLib.set_application_name('MyApp');
}
_buildUI() {
// ...
}
// defining a virtual function usually means overriding the default handler for a
// a signal. In this case, it's not much of an issue but for frequently emitted
// signals it avoids "marshalling" the C values into JS values and back again.
//
// In other words, defining this function means it will be called as if you
// connected to the ::activate signal.
vfunc_activate() {
this._window.present();
}
// ::activate is a special case, but for most vfunc's is necessary to "chain up",
// which really just means calling the super class's original function inside your
// override.
vfunc_startup() {
// In ::startup we need to chain up first since GApplication does important
// setup checks here
super.vfunc_startup();
// your stuff after
this._buildUI();
// In _buildUI() you correctly passed your GtkApplication as the application
// property, which will keep the application running so long as that window
// is open.
//
// If you wanted your application to stay open regardless, you call hold()
this.hold();
}
vfunc_shutdown() {
// ::shutdown on the other hand is the reverse; first we do our stuff, then
// chain up to super class. This is a good time to do any cleanup you need
// before the process exits.
this._destroyUI();
// chain up
super.vfunc_shutdown();
}
});
// For technical reasons, this is the proper way you should start your application
(new MyApp()).run([imports.system.programInvocationName].concat(ARGV));
The addSignalMethods() function only needs to be called once, but as mentioned it will override the existing signal methods and that could cause you problems if you call it on a GObject that already has signals defined. It basically does this:
addSignalMethods(obj) {
obj.emit = function() {
// custom signal code
}
...
It was really meant for pure JS classes that don't have a signal system already.
// SHOULD SEND A SIGNAL
//
try {
Signals.addSignalMethods(this);
this.emit('update_ui', true);
} catch (e) {
print(e);
}
The reason why this wasn't working for you is that getHeaderbar() is a top-level function in imports.lib.menubar so when you called addSignalMethods(this), this === imports.lib.menubar. Therefore to catch that signal you would had to call:
imports.lib.menubar.connect('update_ui', () => {});
When you called it in _buildUI():
Signals.addSignalMethods(this);
this.connect('update_ui', () => {
try {
print('>>> updating UI');
//this.ui.updateUI();
} catch (e) {
print(e);
}
});
this === MyApp, so you were first overriding MyApp's signal methods, then connecting to itself. The Signals import is fairly lax so it doesn't require a signal to be defined before use; you just connect to what you want and emit what you want. This is why you weren't getting any errors or warnings.
There are couple ways you can solve your problem:
// (1) Pick an object to emit and connect from and only add the signal methods once
Signals.addSignalMethods(headerBar);
// Since you're using an arrow function you can call this in the same place since it
// should still be in scope
headerBar.emit('update_ui', true);
// You can connect by grabbing the headerbar widget from your constructed window
this._window.get_titlebar().connect('update_ui', (headerBar, bool) => {});
// (2) Define a signal *on* your GtkApplication and use it as a relay
// Connect from a function in MyApp (so in `this.connect`, `this === MyApp`)
// To set `this` for the callback itself, use `Function.bind()`
this.connect('update-ui', this.ui.updateUI.bind(ui));
// You can always grab the primary instance of your GtkApplication (from anywhere)
// and emit the signal to invoke the MyApp.ui.updateUI() function
let myApp = Gio.Application.get_default();
myApp.emit('update-ui', true);
// (3) How I'd probably do it; just invoke the method directly
let myApp = Gio.Application.get_default();
myApp.ui.updateUI();

How to preserve `LokiJS` data in `localstorage`

my data base is not preserved in local storage. any one help me here? I guess that, lokijs will preserve the data in localstorage by default. But after refresh I am not getting the updated datas.
here is my code :
jQuery(document).ready(function($) {
var db = new loki("test", {
autosave: true, //setting to save
autosaveInterval: 1000
});
var children = db.addCollection('children')
//adding defualt datas
children.insert({name:'Sleipnir', legs: 8})
children.insert({name:'Jormungandr', legs: 0})
children.insert({name:'Hel', legs: 2});
$("#local").on("click", function(e){
e.preventDefault();
var callback = function( data ){
console.log("call back data", data );
}
$.mockjaxSettings.namespace = "";
myCaller( callback );
})
$("#remote").on("click", function(e){
e.preventDefault();
$.mockjaxSettings.namespace = "///";
myCaller();
});
$("#getData").on("click", function(e){
e.preventDefault();
var child = children.find();
console.log( "children", child );
});
$("#insertData").on("click", function(e){
e.preventDefault();
//inserting new data, but after refresh i am not getting it!!!
children.insert({name:'Mohamed Arif', legs: 2});
})
});
Your data are preserved in local storage, you just erase them every time you load a page with var children = db.addCollection('children')
Replace it by :
var children
db.loadDatabase({}, () => {
children = db.getCollection('children')
if(!children) {
children = db.addCollection('children')
}
})
So with this, if your collection doesn't exist you create it and you don't erase it if it already exists.
I quickly made a plunker that does what you asked : https://plnkr.co/edit/eOgc1ZoQioaI4JYpeggY

Angular 2 Cross Field Validation (model based) addErrors?

I am implementing a cross field validation for two fields in a form (reactive / model based approach) and do not know how should I add an error to existing Error List of a formcontrol
Form:
this.myForm = new FormGroup({
name: new FormControl('', Validators.minLength(3));
city: new FormGroup({
cityOne: new FormControl('', Validators.minLength(3)),
cityTwo: new FormControl('', Validators.minLength(3))
}, this.validateEqualCities)
});
Validator:
validateEqualCities(formGroup: FormGroup) {
return (control: AbstractControl): { [key: string]: any } => {
if (formGroup.controls['cityOne'].value && formGroup.controls['cityTwo'].value && formGroup.controls['cityOne'].value !== formGroup.controls['cityTwo'].value) {
formGroup.controls['cityOne'].setErrors({ 'equalCities': true }, { emitEvent: true });
formGroup.controls['cityTwo'].setErrors({ 'equalCities': true }, { emitEvent: true });
return { 'equalCities': false };
} else {
formGroup.controls['cityOne'].updateValueAndValidity({ onlySelf: true, emitEvent: false });
formGroup.controls['cityTwo'].updateValueAndValidity({ onlySelf: true, emitEvent: false });
}
return null;
};
}
My Problem:
If the validation fails "setErrors(..)" overrides all errors which are already there (Validators of formControls), so there is no correct state, because actually there should be 2 errors.
If I do not set errors to form controls directly and only return an error to the form, only the form is invalid and gets the error, but not its controls.
How can I achieve that both, form and controls has the real state of validation?
Thank you very much!
You can capture the errors object as it is before you assign the errors, modify it, and write the entire object back.
validateEqualCities(formGroup: FormGroup) {
return (control: AbstractControl): { [key: string]: any } => {
if (formGroup.controls['cityOne'].value && formGroup.controls['cityTwo'].value && formGroup.controls['cityOne'].value !== formGroup.controls['cityTwo'].value) {
let errors = formGroup.controls['cityOne'].errors ? formGroup.controls['cityOne'].errors : {};
errors['equalCities'] = false;
formGroup.controls['cityOne'].setErrors(errors, { emitEvent: true });
errors = formGroup.controls['cityTwo'].errors ? formGroup.controls['cityTwo'].errors : {};
errors['equalCities'] = false;
formGroup.controls['cityTwo'].setErrors(errors, { emitEvent: true });
return { 'equalCities': false };
<...>
Here's a Plunker with a working demo: http://plnkr.co/edit/XTeH1ifQTJSoMvBEvE0d?p=preview

Assertion Failed: ArrayProxy expects an Array or Ember.ArrayProxy, but you passed object

This is my code
/******************************************************/
import Ember from "ember";
var TodosController = Ember.ArrayController.extend({
actions: {
createTodo: function(){
// Get the todo title by the "New Todo" input
var title = this.get('newTitle');
if(!title.trim()){ return; }
// Create the new Todo model
var todo = this.store.createRecord('todo', {
title: title,
isCompleted: false
});
// Clear the 'New Todo' input field
this.set('newTitle', '');
// Save the new model
todo.save();
},
clearCompleted: function(){
var completed = this.filterBy('isCompleted', true);
completed.invoke('deleteRecord');
completed.invoke('save');
}
},
remaining: function() {
return this.filterBy('isCompleted', false).get('length');
}.property('#each.isCompleted'),
inflection: function() {
var remaining = this.get('remaining');
return remaining === 1 ? 'todo' : 'todos';
}.property('remaining'),
hasCompleted: function(){
return this.get('completed') > 0;
}.property('completed'),
completed: function(){
return this.filterBy('isCompleted', true).get('length');
}.property('#each.isCompleted'),
allAreDone: function(key, value) {
if(value === undefined){
return !!this.get('length') && this.everyProperty('isCompleted', true);
} else {
this.setEach('isCompleted', value);
this.invoke('save');
return value;
}
}.property('#each.isCompleted')
});
export default TodosController;
/*******************************************************/
In terminal not showing any error when i run this command
$ ember server
but in browser not showing any thing and console showing this error
Uncaught Error: Assertion Failed: ArrayProxy expects an Array or
Ember.ArrayProxy, but you passed object
Please suggest me what i m doing wrong, the code is also on github : https://github.com/narayand4/emberjs
thanks in advance.
The most likely reason for this is that you have a controller which extends from Ember.ArrayController while you only return a plain object in the corresponding model.
I had the same issue and changed my controller to extend Ember.Controller instead.
In the related route for this controller, your model method doesn't return an array, as you've indicated by extending an arrayController.

alert() message isn't being called in my form

Firebug is giving me no error messages, but it's not working. The idea is regardless of whether the user picks an option from dropdown or if they type in something in search box, I want the alert() message defined below to alert what the value of the variable result is (e.g. {filter: Germany}). And it doesn't. I think the javascript breaks down right when a new Form instance is instantiated because I tried putting an alert in the Form variable and it was never triggered. Note that everything that pertains to this issue occurs when form.calculation() is called.
markup:
<fieldset>
<select name="filter" alter-data="dropFilter">
<option>Germany</option>
<option>Ukraine</option>
<option>Estonia</option>
</select>
<input type="text" alter-data="searchFilter" />
</fieldset>
javascript (below the body tag)
<script>
(function($){
var listview = $('#listview');
var lists = (function(){
var criteria = {
dropFilter: {
insert: function(value){
if(value)
return handleFilter("filter", value);
},
msg: "Filtering..."
},
searchFilter: {
insert: function(value){
if(value)
return handleFilter("search", value);
},
msg: "Searching..."
}
}
var handleFilter = function(key,value){
return {key: value};
}
return {
create: function(component){
var component = component.href.substring(component.href.lastIndexOf('#') + 1);
return component;
},
setDefaults: function(component){
var parameter = {};
switch(component){
case "sites":
parameter = {
'order': 'site_num',
'per_page': '20',
'url': 'sites'
}
}
return parameter;
},
getCriteria: function(criterion){
return criteria[criterion];
},
addCriteria: function(criterion, method){
criteria[criterion] = method;
}
}
})();
var Form = function(form){
var fields = [];
$(form[0].elements).each(function(){
var field = $(this);
if(typeof field.attr('alter-data') !== 'undefined') fields.push(new Field(field));
})
}
Form.prototype = {
initiate: function(){
for(field in this.fields){
this.fields[field].calculate();
}
},
isCalculable: function(){
for(field in this.fields){
if(!this.fields[field].alterData){
return false;
}
}
return true;
}
}
var Field = function(field){
this.field = field;
this.alterData = false;
this.attach("change");
this.attach("keyup");
}
Field.prototype = {
attach: function(event){
var obj = this;
if(event == "change"){
obj.field.bind("change", function(){
return obj.calculate();
})
}
if(event == "keyup"){
obj.field.bind("keyup", function(e){
return obj.calculate();
})
}
},
calculate: function(){
var obj = this,
field = obj.field,
msgClass = "msgClass",
msgList = $(document.createElement("ul")).addClass("msgClass"),
types = field.attr("alter-data").split(" "),
container = field.parent(),
messages = [];
field.next(".msgClass").remove();
for(var type in types){
var criterion = lists.getCriteria(types[type]);
if(field.val()){
var result = criterion.insert(field.val());
container.addClass("waitingMsg");
messages.push(criterion.msg);
obj.alterData = true;
alert(result);
initializeTable(result);
}
else {
return false;
obj.alterData = false;
}
}
if(messages.length){
for(msg in messages){
msgList.append("<li>" + messages[msg] + "</li");
}
}
else{
msgList.remove();
}
}
}
$('#dashboard a').click(function(){
var currentComponent = lists.create(this);
var custom = lists.setDefaults(currentComponent);
initializeTable(custom);
});
var initializeTable = function(custom){
var defaults = {};
var custom = custom || {};
var query_string = $.extend(defaults, custom);
var params = [];
$.each(query_string, function(key,value){
params += key + ': ' + value;
})
var url = custom['url'];
$.ajax({
type: 'GET',
url: '/' + url,
data: params,
dataType: 'html',
error: function(){},
beforeSend: function(){},
complete: function() {},
success: function(response) {
listview.html(response);
}
})
}
$.extend($.fn, {
calculation: function(){
var formReady = new Form($(this));
if(formReady.isCalculable) {
formReady.initiate();
}
}
})
var form = $('fieldset');
form.calculation();
})(jQuery)
Thank you for anyone who responds. I spent a lot of time trying to make this work.
The initial problem as to why the alert() was not being triggered when Form is instantiated is because, as you can see, the elements property belongs to the Form object, not fieldset object. And as you can see in the html, I place the fields as descendents of the fieldset object, not form.