Skip to content

Instantly share code, notes, and snippets.

@EdwardIII
Created April 3, 2013 22:03
Show Gist options
  • Save EdwardIII/5305863 to your computer and use it in GitHub Desktop.
Save EdwardIII/5305863 to your computer and use it in GitHub Desktop.
ko.bindingHandlers.disableAndThrob = {
update: function(element, valueAccessor){
var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
if(valueUnwrapped){
$(element).attr('disabled', 'disabled');
$(element).before('<img src="/assets/images/loading.gif" width="16" height="16" class="loading-throbber">');
}
}
}
ko.validation.init({
messagesOnModified: true,
registerExtenders: true,
insertMessages: false,
decorateElement: true,
parseInputAttributes: true,
messageTemplate: null,
errorElementClass: 'error',
errorMessageClass: 'error',
grouping: {
deep: true,
observable: true
}
});
ko.observableArray.fn.callChildMethod = function(methodName) {
var allItems = this()
for (var i = 0; i < allItems.length; i++) {
        var current = allItems[i][methodName];
}
return this;
}
function Guest(){
var self = this;
self.name = ko.observable('');
self.enableValidation = function(){
self.name.extend({
required: { message: 'Please enter names for all guests' }
});
}
}
var EventVm = function (the_event){
var self = this;
self.id = ko.observable(the_event.id);
self.name = ko.observable(the_event.name);
self.start_date_raw = ko.observable(the_event.start_date);
self.organiser = ko.observable(the_event.organiser.name);
self.start_date = ko.computed(function(){
var m = moment(self.start_date_raw(), 'YYYY-MM-DD');
return m.format("dddd D MMMM YYYY");
})
}
var PersonalDetails = function(ticketTypes){
var self = this;
self.ticketTypes = ticketTypes;
self.newsletterSignupChecked = ko.observable(false);
self.name = ko.observable('').extend({
required: { message: 'Name is required' }
});
self.email = ko.observable('').extend({
required: { message: 'Email is required' }
});
}
function TicketType(type) {
var self = this;
self.ticket_id = type.id;
self.name = type.name;
self.price = type.price;
self.quantity = type.quantity;
self.remaining = type.remaining;
self.numGuests = ko.observable(0);
self.guests = ko.observableArray([]);
self.hasGuests = ko.computed(function(){
return (self.numGuests() > 0) ? true : false;
});
self.removeGuest = function(guest){
self.guests.remove(guest);
}
self.numGuests.subscribe(function(num) {
var currNum = self.guests().length;
if (num > currNum) {
for (var i = currNum; i < num; i++) {
self.guests.push( new Guest() );
}
}
else if (num < currNum) {
self.guests.splice(num, currNum - num);
}
});
self.enableGuestValidation = ko.observable(function(){
_.map(self.guests(), function(guest){
guest.enableValidation();
})
});
}
function OrderVM() {
var self = this;
self.saving = ko.observable(false);
self.loadTypes = function(types) {
self.ticketTypes([]);
self.ticketTypes( ko.utils.arrayMap(types, function(ticketType) {
return new TicketType(ticketType);
}));
}
self.ticketTypes = ko.observableArray();
self.ticketQuantityTotal = function(){
return _.reduce(self.ticketTypes(), function(memo, ticket){
var lastQty = parseInt(memo.numGuests()) || 0;
var thisQty = parseInt(ticket.numGuests()) || 0;
return lastQty + thisQty;
})
}
self.the_event = ko.observable();
self.loadEvent = function(the_event){
if(the_event.attributes){ // Check for a backbone model
self.the_event( new EventVm(the_event.attributes) );
}else{ // Already a knockout object with observable properties
self.the_event( the_event );
self.loadTypes( the_event.tickets() )
}
}
self._enableGuestsValidation = function (){
_.map(self.ticketTypes(), function(ticket){
ticket.enableGuestValidation();
});
return self.ticketTypes;
}
self.steps = ko.observableArray([
{
template: function(){ return 'ticket_types' },
model: self.ticketTypes,
fullWidth: function(){ return true; }
},
{
template: function(){ return 'personal_details_template' },
model: new PersonalDetails(self.ticketTypes),
fullWidth: function(){ return false; }
},
{
template: function(){ return 'ticket_guests' },
model: self.ticketTypes, //.callChildMethod(),
fullWidth: function(){ return false; }
},
]);
self.currentStep = ko.observable(self.steps()[0]);
self.currentIndex = ko.computed(function(){
return _.indexOf(self.steps(), self.currentStep());
});
self.errors = ko.validation.group(self.currentStep());
self.currentStep.subscribe(function(){
self.errors = ko.validation.group(self.currentStep());
});
self.goNext = function(){
// TODO: Migrate to use knockout validate
if(self.currentStep().template() == 'ticket_types' && self.ticketQuantityTotal() < 1){
var err = 'Please enter quantity for at least one ticket to purchase';
alert(err);
}else{
if(!self.errors().length){
self.currentStep(self.steps()[self.currentIndex() + 1]);
}else{
self.errors.showAllMessages()
}
}
}
self.resetAndGoNext = function(){
self.currentStep(self.steps()[0]);
self.goNext();
}
self.getTemplate = function(data) {
return self.currentStep().template();
};
self.canGoNext = ko.dependentObservable(function() {
return self.currentIndex() < self.steps().length - 1;
});
self.isLastStep = ko.computed(function() {
return (self.currentIndex() == self.steps().length - 1) ? true : false;
});
self.getByTemplateName = function(template_name){
return _.find(self.steps(), function(s){ return s.template() == template_name; })
}
self.guestNamesValid = ko.computed(function(){
var ticketsWithGuests = _.filter(self.ticketTypes(), function(ticket){ return (ticket.hasGuests()) });
var guests = _.flatten( _.map(ticketsWithGuests, function(ticket){ return ticket.guests() }) );
var allGuestsHaveNames = _.every(guests, function(guest){
console.log('guest.name');
console.log(guest.name());
return guest.name != undefined && guest.name() != '' });
return allGuestsHaveNames;
//return false;
});
self.savingAndValid = ko.computed(function(){
return (self.saving() && self.guestNamesValid);
});
self.guestNamesValid.subscribe(function(data){
console.log('subscription');
console.log(data);
})
self.save = function() {
if(!self.errors().length && self.guestNamesValid()){
self.saving(true);
$.post('/process_order_json/', { data:
ko.toJSON({
event_id: self.the_event().id,
ticketTypes: self.getByTemplateName('ticket_types').model,
personalDetails: self.getByTemplateName('personal_details_template').model
})
}, function(data){
if(data.success){
location.href=data.redirect_url
}
});
}else{
self.errors.showAllMessages();
if(!self.guestNamesValid()) alert ("Please enter names for all your guests");
}
}
self.fullWidth = ko.computed(function(){
return self.currentStep().fullWidth()
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment