artfully_ose 1.2.0.pre.27 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +4 -6
- data/app/assets/javascripts/application.js +39 -0
- data/app/assets/javascripts/boxoffice.js +558 -0
- data/app/assets/javascripts/custom/kits-config.js +33 -0
- data/app/assets/javascripts/sales-console.js +29 -24
- data/app/assets/javascripts/store/store.js +11 -0
- data/app/assets/stylesheets/application.sass +66 -52
- data/app/assets/stylesheets/bootstrap-overrides.css +1 -1
- data/app/assets/stylesheets/boxoffice.css.scss +258 -0
- data/app/assets/stylesheets/pages/bootstrap-responsive.css +1109 -0
- data/app/assets/stylesheets/sass/store.sass +52 -62
- data/app/assets/stylesheets/storefront.css +1 -1
- data/app/concerns/itemable.rb +1 -1
- data/app/concerns/pdf_generation.rb +1 -11
- data/app/concerns/search_by_dates.rb +20 -0
- data/app/controllers/events_controller.rb +1 -0
- data/app/controllers/export_controller.rb +11 -1
- data/app/controllers/imports_controller.rb +2 -3
- data/app/controllers/member_cards_controller.rb +2 -3
- data/app/controllers/orders_controller.rb +42 -0
- data/app/controllers/organizations_controller.rb +1 -0
- data/app/controllers/passes_reports_controller.rb +21 -1
- data/app/controllers/regular_donation_kits_controller.rb +32 -0
- data/app/controllers/store/donations_controller.rb +19 -1
- data/app/controllers/store/orders_controller.rb +15 -5
- data/app/helpers/artfully_ose_helper.rb +28 -18
- data/app/models/database_views/item_view.rb +41 -0
- data/app/models/event.rb +10 -2
- data/app/models/ext/integrations.rb +5 -0
- data/app/models/fee_strategy.rb +47 -1
- data/app/models/imports/events_import.rb +6 -7
- data/app/models/item.rb +4 -3
- data/app/models/job/order_processor.rb +4 -3
- data/app/models/kit.rb +18 -0
- data/app/models/kits/regular_donation_kit.rb +51 -9
- data/app/models/member.rb +4 -3
- data/app/models/membership.rb +1 -2
- data/app/models/membership_sale_search.rb +2 -20
- data/app/models/membership_type.rb +1 -2
- data/app/models/order.rb +29 -1
- data/app/models/order_handler.rb +4 -3
- data/app/models/organization.rb +17 -9
- data/app/models/pass.rb +18 -17
- data/app/models/pass_sale_search.rb +18 -0
- data/app/models/pass_type.rb +7 -2
- data/app/models/passes_report.rb +117 -0
- data/app/models/sale_search.rb +3 -21
- data/app/models/user.rb +1 -2
- data/app/serializers/show_serializer.rb +15 -0
- data/app/views/contributions/index.html.haml +2 -2
- data/app/views/events/_header.html.haml +1 -0
- data/app/views/events/_ticket_type_fields.html.haml +31 -15
- data/app/views/events/edit.html.haml +6 -1
- data/app/views/imports/_export_links.html.haml +3 -0
- data/app/views/imports/donations/_pending.html.haml +24 -6
- data/app/views/imports/events/_pending.html.haml +16 -5
- data/app/views/imports/index.html.haml +6 -4
- data/app/views/imports/people/_pending.html.haml +20 -25
- data/app/views/layouts/storefront.html.haml +9 -5
- data/app/views/order_mailer/confirmation_for.html.haml +11 -5
- data/app/views/order_mailer/confirmation_for_refund.html.haml +6 -2
- data/app/views/order_mailer/confirmation_for_refund.text.haml +4 -3
- data/app/views/orders/membership.html.haml +15 -19
- data/app/views/orders/passes.html.haml +97 -0
- data/app/views/orders/sales.html.haml +2 -2
- data/app/views/organizations/_form.html.haml +4 -37
- data/app/views/pass_types/index.html.haml +1 -1
- data/app/views/passes_reports/index.html.haml +79 -1
- data/app/views/people/show.html.haml +16 -15
- data/app/views/regular_donation_kits/edit.html.haml +140 -0
- data/app/views/store/checkouts/thanks.html.haml +14 -6
- data/app/views/store/donations/index.html.haml +19 -2
- data/app/views/store/events/calendar.html.haml +1 -0
- data/app/views/store/events/index.html.haml +1 -0
- data/app/views/store/events/show.html.haml +1 -0
- data/app/views/store/events/single_show.html.haml +2 -0
- data/app/views/store/orders/show.html.haml +10 -10
- data/app/views/store/passes/index.html.haml +2 -2
- data/app/views/store/shared/_donate_form.html.haml +31 -12
- data/app/views/store/shared/_small_donate_form.html.haml +22 -0
- data/app/views/users/invitations/edit.html.haml +3 -42
- data/config/locales/en.yml +3 -1
- data/config/routes.rb +4 -1
- data/db/migrate/20140603200735_add_subtitle_to_events.rb +5 -0
- data/lib/artfully_ose/version.rb +1 -1
- data/spec/factories/kit_factories.rb +5 -4
- metadata +25 -13
- data/app/assets/javascripts/box-office.js +0 -262
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzQ0Mzk5NzQ5YWJhNDFmODY4Y2IwOGQ3NTA3NjM0NWM1ZTU5ODA4Zg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NmIzYzg4MmIzY2E2N2RmZmJhNDg2MTg4YWJkMjk3MGNiNzJlYmY5ZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Mjg5NjUwZjUzZWUxNGI4NzA0NTk1MzgxMjFjYjE0OTNiMmI3OGY3OTFjYTBj
|
10
|
+
NTM0ZWNlNjA4MDU2NGJhYzNkMzNhNDhkNDA3NDYxNDQ5MDIzNDAwZTNmNjA1
|
11
|
+
YTcyNjZkN2MyN2MxZTRlN2JiY2FhZjQxYTk2ZTcyZjU2ZWM3M2M=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjRlZDM3N2VkZjEzZGViMDMwNGE1Y2NmZDM3ZDE5NjIzMDM0MDU2MGRhZTUx
|
14
|
+
NjFhYTA2MWE3YTg4MzkxNDA4NDYzZjBjYzkzN2IxZTIyNjExYTMxNjE0M2Zl
|
15
|
+
NTBlNzM5OTk1OWI3OWM4MjJlYzg2NjMyMmE1YTVjYTk3NmFiMDc=
|
data/README.md
CHANGED
@@ -6,6 +6,10 @@ Welcome to Artful.ly OSE
|
|
6
6
|
|
7
7
|
Artful.ly Open Source Edition is the core code of the Artful.ly app downloadable for free and ready for you to roll up your sleeves and build a custom management system for your arts business. The Artful.ly OSE framework gives software developers a base from which they can add features, integrate with other apps, and much more!
|
8
8
|
|
9
|
+
## A Note About Contributing
|
10
|
+
|
11
|
+
Because of a variety of factors, we cannot accept pull requests on this repo. We're working to get this resolved.
|
12
|
+
|
9
13
|
## Before You Begin
|
10
14
|
|
11
15
|
You'll want the following running on your machine:
|
@@ -20,9 +24,3 @@ Artful.ly Open Source Engine is a Rails Engine. **It is not intended to be moun
|
|
20
24
|
## Branch strategy
|
21
25
|
|
22
26
|
Master is the current development branch. Every effort is made to make master tidy and working at all times but it is the edge and problems do happen. For any stable production applications, you'll *absolutely* want to be pointing to a published, stable gem. A list can be found [on Rubygems](https://rubygems.org/gems/artfully_ose)
|
23
|
-
|
24
|
-
## Contributors
|
25
|
-
|
26
|
-
Gary Moore - Lead Developer at Fractured Atlas
|
27
|
-
|
28
|
-
Clinton Judy - Open Source Lead at Fractured Atlas
|
@@ -629,3 +629,42 @@ function togglePrintPreview(){
|
|
629
629
|
printStyles.attr("media","all");
|
630
630
|
}
|
631
631
|
}
|
632
|
+
|
633
|
+
$('.btn-delete-preset-amount').live('click',function(){
|
634
|
+
$(this).closest('tr').remove();
|
635
|
+
return false;
|
636
|
+
});
|
637
|
+
|
638
|
+
$( ".btn-add-preset-amount" ).click(function() {
|
639
|
+
$('#fixed_gift_error').empty();
|
640
|
+
if($.isNumeric($('#input-preset-amount').val())) {
|
641
|
+
$('#table-preset-amount tr').last().after(
|
642
|
+
'<tr>' +
|
643
|
+
'<td>$' +
|
644
|
+
$('#input-preset-amount').val() +
|
645
|
+
'<input name=\"donation_preset[]\" type=\"hidden\" value=\"' + $('#input-preset-amount').val() +'">' +
|
646
|
+
'</td>' +
|
647
|
+
'<td><button class="btn-delete-preset-amount">Delete</button></td>' +
|
648
|
+
'</tr>');
|
649
|
+
} else {
|
650
|
+
$('#fixed_gift_error').append($(document.createElement('div'))
|
651
|
+
.addClass('error')
|
652
|
+
.addClass('alert-error')
|
653
|
+
.html('<span>Please enter a number!</span>'));
|
654
|
+
}
|
655
|
+
$('#input-preset-amount').val("");
|
656
|
+
return false;
|
657
|
+
});
|
658
|
+
|
659
|
+
$( '#widget_type_donations' ).click(function() {
|
660
|
+
$("#preset-amount").show();
|
661
|
+
$("#widget-event").hide();
|
662
|
+
});
|
663
|
+
$( '#widget_type_event' ).click(function() {
|
664
|
+
$("#preset-amount").hide();
|
665
|
+
$("#widget-event").show();
|
666
|
+
});
|
667
|
+
$( '#widget_type_both' ).click(function() {
|
668
|
+
$("#preset-amount").show();
|
669
|
+
$("#widget-event").show();
|
670
|
+
});
|
@@ -0,0 +1,558 @@
|
|
1
|
+
//= require store/jquery.validate
|
2
|
+
//= require_self
|
3
|
+
|
4
|
+
$(function() {
|
5
|
+
sliderOffset = $('.navbar').width()+100;
|
6
|
+
$('#boxoffice').css({right:-sliderOffset});
|
7
|
+
$('#doorlist').css({left:-sliderOffset});
|
8
|
+
|
9
|
+
setPageHeight();
|
10
|
+
|
11
|
+
// moving between door list and box office
|
12
|
+
$('.page-nav li a').click(function() {
|
13
|
+
switchBetweenBoxofficeAndDoorlist($(this).attr('href'));
|
14
|
+
return false;
|
15
|
+
});
|
16
|
+
|
17
|
+
// focus on search bar for doorlist
|
18
|
+
$('input#search').focus();
|
19
|
+
|
20
|
+
// set doorlist progress bar
|
21
|
+
updateProgressBar();
|
22
|
+
|
23
|
+
// clicking + or - buttons for tickets
|
24
|
+
$('a.add').click(function() {
|
25
|
+
var field = $(this).prev();
|
26
|
+
var currentVal = parseInt(field.val());
|
27
|
+
if (isNaN(currentVal)) { currentVal = 0 };
|
28
|
+
var newVal = currentVal + 1;
|
29
|
+
var limit = parseInt(field.attr('data-remaining'));
|
30
|
+
if (newVal <= limit) {
|
31
|
+
$(this).siblings('.ticket-type').find('.remaining').text(limit-newVal);
|
32
|
+
field.val(newVal).trigger('change');
|
33
|
+
}
|
34
|
+
});
|
35
|
+
$('a.subtract').click(function() {
|
36
|
+
var field = $(this).next();
|
37
|
+
var currentVal = parseInt(field.val());
|
38
|
+
if (isNaN(currentVal)) { currentVal = 1 };
|
39
|
+
var newVal = currentVal - 1;
|
40
|
+
var limit = parseInt(field.attr('data-remaining'));
|
41
|
+
var remain = limit-newVal;
|
42
|
+
if (newVal >= 0) {
|
43
|
+
field.val(newVal).trigger('change');
|
44
|
+
if (remain >=0) {
|
45
|
+
$(this).siblings('.ticket-type').find('.remaining').text();
|
46
|
+
}
|
47
|
+
}
|
48
|
+
});
|
49
|
+
|
50
|
+
// typing in a ticket quantity
|
51
|
+
$('.ticket-quantity').keyup(function() {
|
52
|
+
var field = $(this);
|
53
|
+
var val = parseInt(field.val());
|
54
|
+
var limit = parseInt(field.attr('data-remaining'));
|
55
|
+
if (isNaN(val) || val < 0) {
|
56
|
+
field.val(0);
|
57
|
+
$(this).select();
|
58
|
+
} else {
|
59
|
+
if (val > limit) { val = limit };
|
60
|
+
field.val(val);
|
61
|
+
$(this).siblings('.ticket-type').find('.remaining').text(limit-val);
|
62
|
+
}
|
63
|
+
});
|
64
|
+
// highlight the whole input field
|
65
|
+
$('.ticket-quantity').click(function () {
|
66
|
+
$(this).select();
|
67
|
+
});
|
68
|
+
|
69
|
+
// discount codes are not case-sensitive
|
70
|
+
$('#order-discount').keyup(function() {
|
71
|
+
$('#order-discount').val($('#order-discount').val().toUpperCase());
|
72
|
+
});
|
73
|
+
|
74
|
+
UPDATING_TOTAL_REQUEST = null;
|
75
|
+
$(".ticket :input, #order-discount, #order-donation").bind("keyup change", function(e) {
|
76
|
+
var spinner = $('#order-total .loading');
|
77
|
+
var total = $('#order-total .message');
|
78
|
+
spinner.show();
|
79
|
+
total.hide();
|
80
|
+
|
81
|
+
// if a previous request is still being processed
|
82
|
+
// abort and don't listen for response
|
83
|
+
if(UPDATING_TOTAL_REQUEST) UPDATING_TOTAL_REQUEST.abort();
|
84
|
+
|
85
|
+
// wait 1 second after change
|
86
|
+
delay(function(){
|
87
|
+
|
88
|
+
var params = $('.boxoffice-form').serialize();
|
89
|
+
delete params['commit']; // dont actually purchase
|
90
|
+
|
91
|
+
UPDATING_TOTAL_REQUEST = $.post( $('.boxoffice-form').attr('action'), params)
|
92
|
+
.done(function(response) {
|
93
|
+
updateTotal(response);
|
94
|
+
})
|
95
|
+
.fail(function(jqXHR, textStatus, errorThrown) {
|
96
|
+
if(textStatus != 'abort') total.text('An error has occured. Please try again.');
|
97
|
+
})
|
98
|
+
.always(function(data, textStatus, errorThrown) {
|
99
|
+
if(textStatus != 'abort') {
|
100
|
+
total.show();
|
101
|
+
spinner.hide();
|
102
|
+
UPDATING_TOTAL_REQUEST = null;
|
103
|
+
}
|
104
|
+
});
|
105
|
+
|
106
|
+
}, 1000 );
|
107
|
+
});
|
108
|
+
|
109
|
+
// select payment type
|
110
|
+
$(".payment-select").on("click", "a.btn", function() {
|
111
|
+
$('.payment-fields').hide();
|
112
|
+
$('label span.required').hide();
|
113
|
+
|
114
|
+
if($(this).hasClass('active')) {
|
115
|
+
$('.payment-select a.btn').removeClass('active');
|
116
|
+
$('#payment_method').val('');
|
117
|
+
|
118
|
+
} else {
|
119
|
+
$('.payment-select a.btn').removeClass('active');
|
120
|
+
$(this).addClass('active');
|
121
|
+
var payment = $(this).attr('data-payment-select');
|
122
|
+
$('#payment_method').val(payment);
|
123
|
+
|
124
|
+
if(payment == 'credit'){
|
125
|
+
$('#credit-fields').show();
|
126
|
+
$('#credit_card_number').focus();
|
127
|
+
$('label span.email-required').show();
|
128
|
+
$('label span.name-required').show();
|
129
|
+
$('label span.contact-required').show();
|
130
|
+
} else if(payment == 'comp') {
|
131
|
+
$('label span.name-required').show();
|
132
|
+
} else if(payment == 'check') {
|
133
|
+
$('#check-fields').show();
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
$('#payment_method').trigger('change') // trigger change so form validness can be checked
|
138
|
+
});
|
139
|
+
|
140
|
+
$('#doorlist.page').on('click', 'tr.buyer', function() {
|
141
|
+
$('tr.buyer').removeClass('active');
|
142
|
+
$(this).addClass('active');
|
143
|
+
$('.buyer-details').hide();
|
144
|
+
$('#buyer-details').html($(this).find('.buyer-details-hidden').html());
|
145
|
+
// set height to height of page so it has it's own scroll
|
146
|
+
offset = parseInt($('#buyer-details').css('top'), 10) + $('#buyer-details .content').position().top;
|
147
|
+
$('#buyer-details .content').css({height: ($(window).height() - offset) });
|
148
|
+
$('#buyer-details').fadeIn(100);
|
149
|
+
});
|
150
|
+
|
151
|
+
$('#doorlist.page').on('click', '.door-list-checkbox', function() {
|
152
|
+
var checkbox = $(this);
|
153
|
+
buyerId = checkbox.attr('data-buyer-id');
|
154
|
+
ticketId = checkbox.attr('data-ticket-id');
|
155
|
+
checked = checkbox.is(':checked');
|
156
|
+
collection = checked ? 'validated' : 'unvalidated';
|
157
|
+
|
158
|
+
// check the duplicated checkbox
|
159
|
+
$("[data-ticket-id="+ticketId+"]").attr('checked', checked);
|
160
|
+
|
161
|
+
// set the visual marker at the beginning of the row
|
162
|
+
var icon = $("tr.buyer[data-buyer-id="+buyerId+"]").find('.remaining-ticket-indicator')
|
163
|
+
available_tickets = $(":checkbox[data-buyer-id="+buyerId+"]:not(:checked)").length;
|
164
|
+
unavailable_tickets = $(":checkbox[data-buyer-id="+buyerId+"]:checked").length;
|
165
|
+
|
166
|
+
icon.removeClass(); // remove current icon
|
167
|
+
icon.addClass('remaining-ticket-indicator');
|
168
|
+
|
169
|
+
if(available_tickets == 0) {
|
170
|
+
icon.addClass('fa fa-circle');
|
171
|
+
} else if(unavailable_tickets == 0) {
|
172
|
+
icon.addClass('fa fa-circle-o');
|
173
|
+
} else {
|
174
|
+
icon.addClass('fa fa-adjust');
|
175
|
+
}
|
176
|
+
|
177
|
+
updateProgressBar();
|
178
|
+
|
179
|
+
$.ajax({
|
180
|
+
type: "PUT",
|
181
|
+
url: '/tickets/'+ticketId+'/'+collection+'.json'
|
182
|
+
});
|
183
|
+
});
|
184
|
+
|
185
|
+
$('tr.buyer:first').click();
|
186
|
+
|
187
|
+
// search doorlist
|
188
|
+
$("#page-holder").on("keyup", "#live_search", function(){
|
189
|
+
// Retrieve the input field text
|
190
|
+
var filter = $(this).val();
|
191
|
+
|
192
|
+
// Loop through the buyers list
|
193
|
+
$("tr.buyer").each(function(){
|
194
|
+
// If the list item does not contain the text phrase hide it
|
195
|
+
if ($(this).attr('data-search-blob').search(new RegExp(filter, "i")) < 0) {
|
196
|
+
$(this).hide();
|
197
|
+
} else {
|
198
|
+
$(this).show();
|
199
|
+
}
|
200
|
+
});
|
201
|
+
|
202
|
+
// if only 1 buyer remains, activate it
|
203
|
+
if ($("tr.buyer:visible").length === 1) {
|
204
|
+
$("tr.buyer:visible").click();
|
205
|
+
// dismiss ios keyboard
|
206
|
+
// $('input:focus').blur();
|
207
|
+
}
|
208
|
+
});
|
209
|
+
|
210
|
+
$("#user-info #person_first_name").autocomplete({
|
211
|
+
minLength: 1,
|
212
|
+
source: function(request, response) {
|
213
|
+
$.getJSON("/people?utf8=%E2%9C%93&commit=Search", { search: request.term }, function(people) {
|
214
|
+
$('#person_first_name').popover('destroy');
|
215
|
+
var responsePeople = new Array();
|
216
|
+
|
217
|
+
$.each(people, function (i, person) {
|
218
|
+
person = cleanJsonPerson(person)
|
219
|
+
responsePeople[i] = "<li data-person-id='"+person.id+"' data-person-email='"+person.email+"'>";
|
220
|
+
responsePeople[i] += "<h4><span class='first-name'>"+person.first_name+"</span> <span class='last-name'>"+person.last_name+"</span></h4>";
|
221
|
+
if(person.company_name) { responsePeople[i] += "<span class='company-name'>"+person.company_name+"</span>" }
|
222
|
+
responsePeople[i] += "</li>";
|
223
|
+
});
|
224
|
+
|
225
|
+
if(responsePeople.length) {
|
226
|
+
$('#person_first_name').popover({
|
227
|
+
content: responsePeople,
|
228
|
+
html: true,
|
229
|
+
title: 'Existing people',
|
230
|
+
position: 'left',
|
231
|
+
trigger: 'manual',
|
232
|
+
container:'#existing-user-popover'
|
233
|
+
});
|
234
|
+
$('#person_first_name').popover('show');
|
235
|
+
}
|
236
|
+
|
237
|
+
response(null)
|
238
|
+
});
|
239
|
+
}
|
240
|
+
});
|
241
|
+
|
242
|
+
$('#existing-user-popover').on('click', 'li', function() {
|
243
|
+
person = $(this);
|
244
|
+
$('#person_first_name').val(person.find('.first-name').text());
|
245
|
+
$('#person_last_name').val(person.find('.last-name').text());
|
246
|
+
$('#person_email').val(person.attr('data-person-email'));
|
247
|
+
$('#person_id').val(person.attr('data-person-id'));
|
248
|
+
$('#person_first_name').popover('destroy');
|
249
|
+
validateForm();
|
250
|
+
return false;
|
251
|
+
});
|
252
|
+
|
253
|
+
// If they enter a custom email address (or change what was autocompleted, we have to clear the person id)
|
254
|
+
$("#user-info input").change( function () {
|
255
|
+
$("input#person_id").val("");
|
256
|
+
$('#person_first_name').popover('destroy');
|
257
|
+
})
|
258
|
+
|
259
|
+
// handle swipe from a magtek card reader
|
260
|
+
$('#credit_card_number').keyup(function() {
|
261
|
+
var val = $(this).val();
|
262
|
+
if (val.slice(0,2) === '%B') {
|
263
|
+
length = 0;
|
264
|
+
|
265
|
+
// there is a delay the data being entered in the field after a swipe
|
266
|
+
// make sure we wait until it is all there
|
267
|
+
do {
|
268
|
+
val = $(this).val();
|
269
|
+
setTimeout(length = val.length, 100);
|
270
|
+
} while (length < val.length);
|
271
|
+
|
272
|
+
// shamlessly lifted from
|
273
|
+
// https://github.com/fracturedatlas/swiper/
|
274
|
+
tracks = val.match(/^%(.*)\?;(.*)\?$/);
|
275
|
+
if (tracks) {
|
276
|
+
raw_track1 = tracks[1];
|
277
|
+
track1_groups = raw_track1.match(/^(.)(\d*)\^([^\/]*)\/(.*)\^(..)(..)(.*)$/);
|
278
|
+
$('#credit_card_number').val(track1_groups[2]);
|
279
|
+
|
280
|
+
month = track1_groups[6];
|
281
|
+
if (month[0] === '0') { month = month[1] }; // removing leading zero for select
|
282
|
+
$('#credit_card_month').val(month);
|
283
|
+
|
284
|
+
year = track1_groups[5];
|
285
|
+
if (year.length === 2) { year = '20'+year }; // add '20' for select
|
286
|
+
$('#credit_card_year').val(year);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
});
|
290
|
+
|
291
|
+
// disable submit button until form is valid
|
292
|
+
$('.boxoffice-form input').change(function() {
|
293
|
+
validateForm();
|
294
|
+
});
|
295
|
+
|
296
|
+
$('.boxoffice-form').validate({
|
297
|
+
submitHandler: function(form) {
|
298
|
+
processForm(form);
|
299
|
+
},
|
300
|
+
highlight: function(element, errorClass) {
|
301
|
+
$(element).closest('.control-group').addClass(errorClass);
|
302
|
+
},
|
303
|
+
unhighlight: function(element, errorClass) {
|
304
|
+
$(element).closest('.control-group').removeClass(errorClass);
|
305
|
+
},
|
306
|
+
ignore: ".ignore-validation",
|
307
|
+
messages: {
|
308
|
+
total: null,
|
309
|
+
payment_method: 'Please select a payment method.',
|
310
|
+
},
|
311
|
+
rules: {
|
312
|
+
'total': {
|
313
|
+
required: true
|
314
|
+
},
|
315
|
+
'payment_method': {
|
316
|
+
required: function(element) {
|
317
|
+
return (
|
318
|
+
parseFloat($('#total').val()) > 0.0
|
319
|
+
)
|
320
|
+
}
|
321
|
+
},
|
322
|
+
'person[first_name]': {
|
323
|
+
required: function(element) {
|
324
|
+
return (
|
325
|
+
$('#payment_method').val() === 'credit' ||
|
326
|
+
$('#payment_method').val() === 'comp'
|
327
|
+
)
|
328
|
+
}
|
329
|
+
},
|
330
|
+
'person[last_name]': {
|
331
|
+
required: function(element) {
|
332
|
+
return (
|
333
|
+
$('#payment_method').val() === 'credit' ||
|
334
|
+
$('#payment_method').val() === 'comp'
|
335
|
+
)
|
336
|
+
}
|
337
|
+
},
|
338
|
+
'person[email]': {
|
339
|
+
email: true,
|
340
|
+
required: function(element) {
|
341
|
+
return (
|
342
|
+
$('#payment_method').val() === 'credit' &&
|
343
|
+
!$.trim($('#person_phone').val()).length // empty?
|
344
|
+
)
|
345
|
+
}
|
346
|
+
},
|
347
|
+
'person[phone]': {
|
348
|
+
required: function(element) {
|
349
|
+
return (
|
350
|
+
$('#payment_method').val() === 'credit' &&
|
351
|
+
!$.trim($('#person_email').val()).length // empty?
|
352
|
+
)
|
353
|
+
}
|
354
|
+
},
|
355
|
+
'credit_card[number]': {
|
356
|
+
creditcard: true,
|
357
|
+
required: function(element) {
|
358
|
+
return (
|
359
|
+
$('#payment_method').val() === 'credit'
|
360
|
+
)
|
361
|
+
}
|
362
|
+
},
|
363
|
+
}
|
364
|
+
});
|
365
|
+
});
|
366
|
+
|
367
|
+
// called after a successful purchase
|
368
|
+
function clearBoxOfficeForm() {
|
369
|
+
$(":input:not([type=button],[type=submit],[type=checkbox],button,[name=authenticity_token])").val('');
|
370
|
+
$('#auto_check_in[type=checkbox]').prop('checked', false);
|
371
|
+
$('input.ticket-quantity').val('0');
|
372
|
+
$('.payment-select a.btn').removeClass('active');
|
373
|
+
$('#payment_method').val('');
|
374
|
+
$('#order-total .message').text('$0.00 Total');
|
375
|
+
$('.discount .message').hide();
|
376
|
+
$('#person_first_name').popover('destroy');
|
377
|
+
$('#checkout-now-button').attr('disabled','disabled');
|
378
|
+
};
|
379
|
+
|
380
|
+
// called after valid form is submitted
|
381
|
+
function processForm(form) {
|
382
|
+
var f = $(form);
|
383
|
+
var modalHeader = $('#submit-confirmation .modal-header h3');
|
384
|
+
var modalBody = $('#submit-confirmation .modal-body .content');
|
385
|
+
var spinner = $('#submit-confirmation .modal-body .loading');
|
386
|
+
modalHeader.text('Processing...');
|
387
|
+
modalBody.text('');
|
388
|
+
spinner.show();
|
389
|
+
$('.modal-close').hide();
|
390
|
+
|
391
|
+
$('#submit-confirmation').modal({keyboard:false, backdrop:'static'});
|
392
|
+
|
393
|
+
$.post( f.attr('action'), f.serialize())
|
394
|
+
.done(function(response) {
|
395
|
+
var message = '';
|
396
|
+
if (response['message']) { message += response['message'] };
|
397
|
+
if (response['error']) { message += response['error'] };
|
398
|
+
|
399
|
+
if(response['sale_made']) {
|
400
|
+
modalHeader.text('Purchase Complete');
|
401
|
+
clearBoxOfficeForm();
|
402
|
+
updateRemainingTickets(response['ticket_types']);
|
403
|
+
updateDoorlist(response['buyer']['id']);
|
404
|
+
} else {
|
405
|
+
modalHeader.text('Error');
|
406
|
+
}
|
407
|
+
modalBody.text(message);
|
408
|
+
})
|
409
|
+
.fail(function() {
|
410
|
+
modalHeader.text('An error has occured.');
|
411
|
+
modalBody.text('Please try your purchase again.');
|
412
|
+
})
|
413
|
+
.always(function() {
|
414
|
+
spinner.hide();
|
415
|
+
$('.modal-close').show();
|
416
|
+
});
|
417
|
+
};
|
418
|
+
|
419
|
+
// called after valid form is submitted
|
420
|
+
function updateRemainingTickets(ticket_types) {
|
421
|
+
$.each( ticket_types, function( key, ticket ) {
|
422
|
+
var row = $('.ticket[data-ticket-id='+ticket.id+']');
|
423
|
+
var input = row.find('input');
|
424
|
+
|
425
|
+
$('.remaining[data-ticket-id='+ticket.id+']').text(ticket.available);
|
426
|
+
row.attr('data-remaining', ticket.available);
|
427
|
+
input.attr('data-remaining', ticket.available);
|
428
|
+
|
429
|
+
if(ticket.available > 0) {
|
430
|
+
input.removeAttr('disabled');
|
431
|
+
row.removeClass('unavailable');
|
432
|
+
} else {
|
433
|
+
// TODO see if these are in your current cart before disabling
|
434
|
+
// input.attr('disabled', 'disabled');
|
435
|
+
// row.addClass('unavailable');
|
436
|
+
}
|
437
|
+
});
|
438
|
+
};
|
439
|
+
|
440
|
+
// utility
|
441
|
+
function cleanJsonPerson(jsonPerson) {
|
442
|
+
jsonPerson.first_name = ( jsonPerson.first_name == null ? "" : jsonPerson.first_name );
|
443
|
+
jsonPerson.last_name = ( jsonPerson.last_name == null ? "" : jsonPerson.last_name );
|
444
|
+
jsonPerson.email = ( jsonPerson.email == null ? "" : jsonPerson.email );
|
445
|
+
jsonPerson.company_name = ( jsonPerson.company_name == null ? "" : jsonPerson.company_name );
|
446
|
+
return jsonPerson
|
447
|
+
};
|
448
|
+
|
449
|
+
function updateSelectedPerson(personId, personFirstName, personLastName, personEmail) {
|
450
|
+
$("input#person_id").val(personId);
|
451
|
+
$("input#person_first_name").val(personFirstName);
|
452
|
+
$("input#person_last_name").val(personLastName);
|
453
|
+
$("input#person_email").val(personEmail);
|
454
|
+
};
|
455
|
+
|
456
|
+
|
457
|
+
// when a ticket, donation, or discount code is changed
|
458
|
+
function updateTotal(response) {
|
459
|
+
var total = $('#order-total .message');
|
460
|
+
total.text(response['total']*0.01);
|
461
|
+
total.formatCurrency({symbol:'$'});
|
462
|
+
total.text(total.text() + ' Total');
|
463
|
+
|
464
|
+
// invalidate form if no tickets and total 0
|
465
|
+
if ((response['tickets'].length > 0) || (response['total'] > 0)) {
|
466
|
+
$('input#total').val(response['total']);
|
467
|
+
} else {
|
468
|
+
$('input#total').val('');
|
469
|
+
}
|
470
|
+
// trigger change so form validness can be checked;
|
471
|
+
$('input#total').trigger('change');
|
472
|
+
|
473
|
+
// update "remaining tickets"
|
474
|
+
updateRemainingTickets(response['ticket_types']);
|
475
|
+
|
476
|
+
// handle discount
|
477
|
+
handleDiscount(response)
|
478
|
+
};
|
479
|
+
|
480
|
+
function handleDiscount(response) {
|
481
|
+
var discountMessage = $('.discount .message');
|
482
|
+
discountMessage.show();
|
483
|
+
if(response['discount_error']) {
|
484
|
+
// something incorrect with discount code
|
485
|
+
discountMessage.text(response['discount_error']);
|
486
|
+
} else if(response['discount_amount'] > 0) {
|
487
|
+
// success, discount greater than 0
|
488
|
+
discountMessage.text(response['discount_amount']*-0.01);
|
489
|
+
discountMessage.formatCurrency({symbol:'$'});
|
490
|
+
discountMessage.text(discountMessage.text() + ' discount');
|
491
|
+
} else if($.trim($('#order-discount').val()).length) {
|
492
|
+
// success but discount < 0 and something in discount input
|
493
|
+
discountMessage.text('No valid discount found.');
|
494
|
+
} else {
|
495
|
+
discountMessage.hide();
|
496
|
+
}
|
497
|
+
}
|
498
|
+
|
499
|
+
// change doorlist progress bar
|
500
|
+
function updateProgressBar() {
|
501
|
+
all_available_tickets = $("#door-list-table :checkbox:not(:checked)").length;
|
502
|
+
all_unavailable_tickets = $("#door-list-table :checkbox:checked").length;
|
503
|
+
total_tickets = all_available_tickets+all_unavailable_tickets;
|
504
|
+
width = ((all_unavailable_tickets/total_tickets) * 100)+'%';
|
505
|
+
$('.progress .bar').css({width:width});
|
506
|
+
$('.progress .bar').text(all_unavailable_tickets+'/'+total_tickets+' checked in');
|
507
|
+
};
|
508
|
+
|
509
|
+
// animate transition
|
510
|
+
function switchBetweenBoxofficeAndDoorlist(selectedId) {
|
511
|
+
$('.page-nav li').removeClass('active');
|
512
|
+
$('[href='+selectedId+']').parent('li').addClass('active');
|
513
|
+
|
514
|
+
if(selectedId=='#doorlist') {
|
515
|
+
$('#boxoffice').animate({right:-sliderOffset}, 200)
|
516
|
+
$('#doorlist').animate({left:0}, 200)
|
517
|
+
} else {
|
518
|
+
$('#doorlist').animate({left:-sliderOffset}, 200)
|
519
|
+
$('#boxoffice').animate({right:0}, 200)
|
520
|
+
}
|
521
|
+
}
|
522
|
+
|
523
|
+
function updateDoorlist(buyerId) {
|
524
|
+
$('#doorlist.page').fadeOut();
|
525
|
+
jQuery.get($('#doorlist.page').attr('data-partial-href'), function(data) {
|
526
|
+
$('#doorlist.page').html(data);
|
527
|
+
updateProgressBar();
|
528
|
+
setPageHeight();
|
529
|
+
$('#doorlist.page').fadeIn();
|
530
|
+
$('tr.buyer[data-buyer-id='+buyerId+']').click();
|
531
|
+
})
|
532
|
+
}
|
533
|
+
|
534
|
+
// height of the page has to be set manually
|
535
|
+
// because the boxoffice and doorlist pages are positioned absolute (so they can slide)
|
536
|
+
function setPageHeight() {
|
537
|
+
$('#page-holder').css({
|
538
|
+
height: Math.max($('#boxoffice').height(), $('#doorlist').height()) + 300
|
539
|
+
});
|
540
|
+
}
|
541
|
+
|
542
|
+
function validateForm() {
|
543
|
+
if($('.boxoffice-form').valid()) {
|
544
|
+
$('#checkout-now-button').removeAttr('disabled');
|
545
|
+
$('#checkout-now-button').addClass('btn-success');
|
546
|
+
} else {
|
547
|
+
$('#checkout-now-button').attr('disabled','disabled');
|
548
|
+
$('#checkout-now-button').removeClass('btn-success');
|
549
|
+
}
|
550
|
+
}
|
551
|
+
|
552
|
+
var delay = (function(){
|
553
|
+
var timer = 0;
|
554
|
+
return function(callback, ms){
|
555
|
+
clearTimeout (timer);
|
556
|
+
timer = setTimeout(callback, ms);
|
557
|
+
};
|
558
|
+
})();
|