///
///
/* HTML5 Page: Holding.html - SignalR Hub and Knockout extenders */
$(function () {
function itemViewModel(id, KeyName, Flag, Amount, Number, Birthday, owner)
{
this.id = ko.observable(id); /*Therefore use .peek() */
this.KeyName = ko.observable(KeyName).extend({ required: " Please Enter A Key Name" });
this.Flag = ko.observable(Flag);
this.Amount = ko.observable(Amount ).extend({ numberFloat: "" });
this.Number = ko.observable(Number ).extend({ numbersOnly: " Digits Only" });
this.Birthday = ko.observable(Birthday);
//alert("itemViewModel("+Birthday+")");
this.removeHolding = function() { owner.deleteSelected(this.id); }
var self = this;
this.KeyName.subscribe( function( newValue ){ owner.updateRecord(ko.toJS(self), self.KeyName); } );
this.Flag.subscribe(function (newValue) { owner.updateRecord(ko.toJS(self), null); } );
this.Amount.subscribe(function (newValue) { owner.updateRecord(ko.toJS(self), self.Amount); } );
this.Number.subscribe(function (newValue) { owner.updateRecord(ko.toJS(self), self.Number); } );
this.Birthday.subscribe(function (newValue) { owner.updateRecord(ko.toJS(self), null); } );
}
function holdingViewModel()
{
var self = this;
self.ListingOA = ko.observableArray([]);
self.workingList = ko.observableArray(); // The declaration for Paginated data storing .
self.pageRowSize = ko.observable(5); // The Default No of Rows on the Table.
self.currentPage = ko.observable(0); // The current Page.
self.totalPages = function () { var totpages = self.ListingOA().length / self.pageRowSize() || 1; return Math.ceil(totpages); }
self.nextPage = function () { if (self.currentPage() < self.totalPages() - 1) { self.currentPage(self.currentPage() + 1); } }
self.backPage = function () { if (self.currentPage() > 0) { self.currentPage(self.currentPage() - 1); } }
self.homePage = function () { self.currentPage(0); }
self.lastPage = function () { self.currentPage(self.totalPages() - 1); }
self.sortToggle = function (h, e) {
if (self.defaultSort === h) { h.ascending = !h.ascending; } //toggle across asc and desc Soring
else { self.defaultSort = h; } //first click store as the default action
var key = self.defaultSort.sortKeyName;
var keyAB = self.defaultSort.rule;
var sortingAsc = function (l, r) {
return l[key].peek() < r[key].peek() ? -1 : l[key].peek() > r[key].peek() ? 1 : l[key].peek() == r[key].peek() ? 0 : 0;
};
var sortingDesc = function (l, r) {
return l[key].peek() > r[key].peek() ? -1 : l[key].peek() < r[key].peek() ? 1 : l[key].peek() == r[key].peek() ? 0 : 0;
};
var sortingAscD = function (l, r) {
return moment(l[key].peek()).format('YYYYMMDD') < moment(r[key].peek()).format('YYYYMMDD') ? -1 :
moment(l[key].peek()).format('YYYYMMDD') > moment(r[key].peek()).format('YYYYMMDD') ? 1 :
l[key] == r[key] ? 0 : 0;
};
var sortingDescD = function (l, r) {
return moment(l[key].peek()).format('YYYYMMDD') > moment(r[key].peek()).format('YYYYMMDD') ? -1 :
moment(l[key].peek()).format('YYYYMMDD') < moment(r[key].peek()).format('YYYYMMDD') ? 1 :
l[key] == r[key] ? 0 : 0;
};
var sorting = self.defaultSort.ascending ? keyAB == 'A' ? sortingAsc : sortingAscD : keyAB == 'A' ? sortingDesc : sortingDescD; // The Sorting Condition
// return l[key] == r[key] ? 0 : (l[key] < r[key] ? -1 : 1)
self.workingList.sort(sorting); // Apply the effect on the Array
};
// Logic for displaying number of rows in the table [computed] replaces [dependentObservable]
self.page = ko.computed
(
function () {
if (self.pageRowSize() == "all") {
self.workingList( self.ListingOA.slice(0) );
}
else {
var pgSize = parseInt(self.pageRowSize(), 10);
var first = pgSize * self.currentPage(), last = first + pgSize;
self.workingList( self.ListingOA.slice(first, last) );
}
},
this /* self? */
);
self.tableHeadersCaptions = ko.observableArray([
{ caption: 'Id', sortKeyName: 'id', ascending: true, rule: 'A' },
{ caption: 'KeyName', sortKeyName: 'KeyName', ascending: true, rule: 'A' },
{ caption: 'Flag', sortKeyName: 'Flag', ascending: true, rule: 'A' },
{ caption: 'Amount', sortKeyName: 'Amount', ascending: true, rule: 'A' },
{ caption: 'Number', sortKeyName: 'Number', ascending: true, rule: 'A' },
{ caption: 'Birthday', sortKeyName: 'Birthday', ascending: true, rule: 'D' } /* sort the date using moment ansi string ccyymmdd */
]);
self.defaultSort = self.tableHeadersCaptions[0];
this.hub = $.connection.holdingHub; /* camelCode: personHub.getAll()|PersonHub.GetAll */
this.formKeyName = ko.observable();
this.formFlag = ko.observable();
this.formAmount = ko.observable();
this.formNumber = ko.observable();
this.formBirthday = ko.observable();
//alert("holdingViewModel()" + this.formBirthday );
//var ListingOA = self.ListingOA;
var notify = true;
this.init = function() {
this.hub.server.getAll(); /* camelCode: personHub.getAll()|PersonHub.GetAll */
}
this.deleteSelected = function(id) {
this.hub.server.delete(id.peek());
}
this.createHolding = function() {
document.getElementById("save").focus();/*Free type "dd-MMM-ccyy" press "Add" knockout, moment or jQuery.datepicker() needs to lose focus*/
var oRecord = {
KeyName: this.formKeyName(),
Flag: this.formFlag(),
Amount: this.formAmount(),
Number: this.formNumber(),
Birthday: this.formBirthday()
};
//alert("createHolding()" + this.formBirthday);
this.hub.server.add(oRecord).done( function() {
console.log('Holding Record Saved!');
}).fail(function(error) {
console.warn(error);
});
var now = new Date();
var today = moment(now).format('DD-MMM-YYYY');
this.formKeyName(''); /*[schtml]*/
this.formFlag('');
this.formAmount('');
this.formNumber('');
this.formBirthday(today); /*[schtml]*/
//document.getElementById("Birthday").focus();
document.getElementById("Number").focus();
document.getElementById("Amount").focus();
document.getElementById("Flag").focus();
document.getElementById("KeyName").focus();
}
this.updateRecord = function( oRecord, observe )
{
if (notify)
{
var isOK = (observe != null) ? !observe.hasError() : true;
if (isOK) {
//var kFilter = /[A-z]/g;
//if (!kFilter.test(oRecord.Amount)) /* /[-+]?[0-9]*\.?[0-9]+/ /[A-z]/g */
this.hub.server.update(oRecord);
}
}
}
this.hub.client.allItemsRetrieved = function( itemsMap ) {
var records = ko.utils.arrayMap(itemsMap, function (oItem) {
return new itemViewModel(oItem.Id, oItem.KeyName, oItem.Flag, oItem.Amount, oItem.Number,
oItem.Birthday, self) });
self.ListingOA(records);
};
this.hub.client.recordCreated = function (oItem) {
self.ListingOA.push(new itemViewModel(oItem.Id, oItem.KeyName, oItem.Flag,
oItem.Amount, oItem.Number, oItem.Birthday, self));
};
this.hub.client.recordRemoved = function( id ) {
var record = ko.utils.arrayFilter(self.ListingOA(), function (value) { return value.id.peek() == id; })[0];
self.ListingOA.remove( record );
};
this.hub.client.recordUpdated = function( changedRecord ) {
var record = ko.utils.arrayFilter(self.ListingOA(), function (value) { return value.id.peek() == changedRecord.Id; })[0];
notify = false;
//alert("recordUpdate() ko: " + record.Birthday.peek() + "fromHub: " + changedRecord.Birthday);
record.KeyName( changedRecord.KeyName );
record.Flag(changedRecord.Flag);
if (parseFloat(record.Amount.peek()) != changedRecord.Amount)
record.Amount( changedRecord.Amount);
record.Number(changedRecord.Number);
record.Birthday(changedRecord.Birthday);
notify = true;
};
this.hub.client.issueError = function( error ) {
$("#error").text(error);
};
}
$('.numbersOnly').keyup(function (event) {
this.value = this.value.replace(/\D+/g, '');
});
$('.decimalsOnly').keyup(function (event) {
if ((/[-+]?[0-9]*\.?[0-9]+./.test(this.value)) != true) {
if ((/^[0-9]+$/.test(this.value)) != true)
this.value = this.value.replace(/[^0-9\.]/g, '');
}
else
{
//var dot = (event.key == "." || event.char == "." || event.keyCode == 190);
var c, d = 0, bFail = false;
for (var n = 0; n < this.value.length && !bFail; n++) {
c = this.value.charAt(n);
if (c < '0' || c > '9') {
if (c == '.') { d++; if (d > 1) bFail = true; }
else if (c == '-') { if (n > 0) bFail = true; }
else { bFail = true; }
}
}
if (bFail==true)
this.value = this.value.replace(/\D+/g, '');
}
});
//if (!Modernizr.inputtypes.datetime) {
$("input[type='datetime']").datepicker({ dateFormat: "dd-M-yy" });
/* [DisplayFormat(ApplyFormatInEditMode=true, DataFormatString = "{0:dd-MMM-yyyy}")] */
/* The Opera Browser Has A Built In datetimepicker, Issue on Edit - Razor ? [jquery.unobtrusive*;jquery.validate*] BUG_BEAR|WHAT_THIS|CLEAN_UP|DEVELOPER|MANUAL */
//}
ko.extenders.required = function(target, overrideMessage) {
//add some sub-observables to our observable
target.hasError = ko.observable();
target.validationMessage = ko.observable();
/* define a validation function */
function validate( newValue ) {
//var current = target();
//var writeValue = "banana";
//target.notifySubscribers(valueToWrite);
//target.getSubscriptionsCount();
var bFail = (newValue && newValue.length > 0)? false: true;
target.hasError(bFail);
target.validationMessage( !bFail ? "" : overrideMessage || "This field is required");
}
validate(target()); //initial validation
target.subscribe(validate); //validate whenever the value changes
return target; // the original observable
};
ko.extenders.numbersOnly = function (target, overrideMessage) {
target.hasError = ko.observable();
target.validationMessage = ko.observable();
function validate(newValue) {
var bFail=false;
for (var n=0;n '9');
}
target.hasError(bFail);
target.validationMessage( !bFail ? "" : overrideMessage || "The Field Is Digit Only");
}
validate(target());
target.subscribe(validate);
return target;
};
ko.extenders.numberFloat = function (target, overrideMessage) {
target.hasError = ko.observable();
target.validationMessage = ko.observable();
function validate(newValue) {
var c,d=0,bFail=false;
for (var n=0;n '9')
{
if (c == '.') { d++; if (d > 1) bFail = true; }
else if (c == '-') { if (n > 0) bFail = true; }
else { bFail = true; }
}
}
target.hasError(bFail);
target.validationMessage(!bFail ? "" : overrideMessage || "The Field Is Not Numeric [-0.1234]");
}
validate(target()); //initial validation
target.subscribe(validate); //validate whenever the value changes
//return the original observable
return target;
};
/* This Looks To Be The One: MUPPET */
ko.bindingHandlers.dateString = {
init : function(element, valueAccessor) {
//attach an event handler to our dom element to handle user input
element.onchange = function(){
var value = valueAccessor(); //get our observable
//set our observable to the parsed date from the input
value( moment(element.value, 'DD-MMM-YYYY').toDate() );
};
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
if (valueUnwrapped) {
if (element.value!=null)
element.value = moment(valueUnwrapped).format('DD-MMM-YYYY');
else
element.innerHTML = moment(valueUnwrapped).format('DD-MMM-YYYY');
}
}
};
var viewModel = new holdingViewModel();
ko.applyBindings(viewModel);
new /*window. */FocusLabel(document.getElementById('HoldingForm'));
$.connection.hub.start( function () { viewModel.init(); } );
});
/*
$("#tablesorter-demo").tablesorter({
sortList: [[0, 0], [2, 1]],
widgets: ['zebra']
});
*/
/*
ko.bindingHandlers.numericText = {
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
precision = ko.utils.unwrapObservable(allBindingsAccessor().precision) || ko.bindingHandlers.numericText.defaultPrecision,
formattedValue = value.toFixed(precision);
ko.bindingHandlers.text.update(element, function () { return formattedValue; });
},
defaultPrecision: 2
};
*/
/*
ko.extenders.numeric = function (target, precision) {
//create a writeable computed observable to intercept writes to our observable
var result = ko.computed({
read: target, //always return the original observables value
write: function (newValue)
{
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current)
{
target(valueToWrite);
}
else
{
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current)
{
target.notifySubscribers(valueToWrite);
}
}
}
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
*/