camaleon_ecommerce 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/plugins/ecommerce/switch.png +0 -0
  3. data/app/assets/javascripts/plugins/ecommerce/admin_product.js.coffee +1 -1
  4. data/app/assets/javascripts/plugins/ecommerce/admin_settings.js +16 -0
  5. data/app/assets/javascripts/plugins/ecommerce/cart.js +1 -0
  6. data/app/assets/javascripts/plugins/ecommerce/jquery.multi-select.js +535 -0
  7. data/app/assets/stylesheets/plugins/ecommerce/multi-select.css.scss +94 -0
  8. data/app/controllers/plugins/ecommerce/admin/orders_controller.rb +37 -20
  9. data/app/controllers/plugins/ecommerce/admin/settings_controller.rb +2 -2
  10. data/app/controllers/plugins/ecommerce/front/checkout_controller.rb +16 -15
  11. data/app/decorators/plugins/ecommerce/cart_decorator.rb +19 -0
  12. data/app/decorators/plugins/ecommerce/order_decorator.rb +70 -0
  13. data/app/decorators/plugins/ecommerce/product_decorator.rb +16 -9
  14. data/app/decorators/plugins/ecommerce/product_item_decorator.rb +5 -1
  15. data/app/helpers/plugins/ecommerce/ecommerce_email_helper.rb +60 -59
  16. data/app/helpers/plugins/ecommerce/ecommerce_functions_helper.rb +5 -10
  17. data/app/helpers/plugins/ecommerce/ecommerce_helper.rb +12 -3
  18. data/app/models/plugins/ecommerce/cart.rb +3 -25
  19. data/app/models/plugins/ecommerce/order.rb +0 -21
  20. data/app/models/plugins/ecommerce/payment_method.rb +4 -0
  21. data/app/models/plugins/ecommerce/shipping_method.rb +4 -1
  22. data/app/services/plugins/ecommerce/cart_service.rb +0 -9
  23. data/app/views/plugins/ecommerce/admin/orders/index.html.erb +47 -51
  24. data/app/views/plugins/ecommerce/admin/orders/show.html.erb +1 -1
  25. data/app/views/plugins/ecommerce/admin/payment_methods/form.html.erb +2 -6
  26. data/app/views/plugins/ecommerce/admin/payment_methods/index.html.erb +4 -6
  27. data/app/views/plugins/ecommerce/admin/settings/index.html.erb +60 -20
  28. data/app/views/plugins/ecommerce/admin/shipping_methods/form.html.erb +1 -5
  29. data/app/views/plugins/ecommerce/admin/shipping_methods/index.html.erb +2 -4
  30. data/app/views/plugins/ecommerce/front/checkout/cart_index.html.erb +2 -2
  31. data/app/views/plugins/ecommerce/front/checkout/index.html.erb +1 -1
  32. data/app/views/plugins/ecommerce/front/login.html.erb +1 -1
  33. data/app/views/plugins/ecommerce/front/orders/index.html.erb +2 -2
  34. data/app/views/plugins/ecommerce/front/orders/show.html.erb +13 -14
  35. data/app/views/plugins/ecommerce/partials/checkout/_details.html.erb +1 -1
  36. data/app/views/plugins/ecommerce/partials/checkout/_payments.html.erb +116 -110
  37. data/app/views/plugins/ecommerce/partials/checkout/_products_detail.html.erb +5 -2
  38. data/app/views/plugins/ecommerce/partials/checkout/_user_info.html.erb +0 -1
  39. data/app/views/plugins/ecommerce/partials/email/_billing_address.html.erb +11 -0
  40. data/app/views/plugins/ecommerce/partials/email/_product_table.html.erb +46 -0
  41. data/app/views/plugins/ecommerce/partials/email/_shipping_address.html.erb +11 -0
  42. data/app/views/{plugins/ecommerce/partials → post_types/commerce}/_cart_widget.html.erb +0 -0
  43. data/app/views/post_types/commerce/_product_info.html.erb +30 -32
  44. data/app/views/post_types/commerce/single.html.erb +9 -13
  45. data/config/camaleon_plugin.json +2 -1
  46. data/config/custom_models.rb +43 -0
  47. data/config/locales/en.yml +0 -1
  48. data/config/locales/es.yml +69 -7
  49. data/config/routes.rb +1 -0
  50. data/db/migrate/20161213222142_add_invoice_number.rb +6 -0
  51. data/db/migrate/20161214224919_remove_ecommerce_stock_field.rb +7 -0
  52. data/lib/ecommerce/engine.rb +4 -2
  53. data/lib/ecommerce/version.rb +1 -1
  54. metadata +58 -15
  55. data/app/assets/javascripts/plugins/ecommerce/jquery.creditCardValidator.js +0 -208
  56. data/app/services/plugins/ecommerce/order_service.rb +0 -26
  57. data/app/views/camaleon_cms/html_mailer/order_canceled.html.erb +0 -2
  58. data/app/views/camaleon_cms/html_mailer/order_confirmed.html.erb +0 -2
  59. data/app/views/camaleon_cms/html_mailer/order_received.html.erb +0 -5
  60. data/app/views/camaleon_cms/html_mailer/order_received_admin.html.erb +0 -3
  61. data/app/views/camaleon_cms/html_mailer/order_shipped.html.erb +0 -2
  62. data/app/views/camaleon_cms/html_mailer/recovery_cart.html.erb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0c541a7311004ac7d1612a1526fe1bbe74ba6da
4
- data.tar.gz: a4a62e0f80a8f9ae124417580584a325c4a98a7f
3
+ metadata.gz: 436534b2963d95852bb682a0a2fa1b237be80aad
4
+ data.tar.gz: 6c4c232bfb068c1e300969535074f3025a59efc7
5
5
  SHA512:
6
- metadata.gz: adff56c87875152cd91047a8a2180b90c0d0b69b3dffb873d0b202c7063755d182c5dd4a1785e47e8800d8fd8de232683a5ffecbd9a75fa9b5f73cfa0151c2ac
7
- data.tar.gz: 803c28e4d16fa6786a3710db1d9a06d2812d2a58f16b05cb3312626dcb67513bfe75203175ca52596fe9d6e030cd68a3fd66e6532f38212450bcf48cf9d450b9
6
+ metadata.gz: fa16eb22fdab95a19feecd545f92950531db1d437a33a8af5f267d3956e174fa376c275e4276dd991562d52f7f379a99e772c04d598060e23f28dcb5dd1fed4e
7
+ data.tar.gz: d14a3696c44535637cce378b31d977335698f81c8c3aa8f2bc6749bf63cac85b75a702ca6c50731fd4b64e97a299aceef5397a8daa05cc2c20f77802bee03322
@@ -86,7 +86,7 @@ $ ->
86
86
 
87
87
  # check the variation status and disable or enable some custom fields
88
88
  check_variation_status = ->
89
- fields = ['ecommerce_sku', 'ecommerce_price', 'ecommerce_weight', 'ecommerce_stock', 'ecommerce_qty']
89
+ fields = ['ecommerce_sku', 'ecommerce_price', 'ecommerce_weight', 'ecommerce_stock', 'ecommerce_qty', 'ecommerce_photos']
90
90
  if product_variations.find('.product_variation').length > 0 # is a variation product
91
91
  for key in fields
92
92
  p_field = form.find('.c-field-group .item-custom-field[data-field-key="'+key+'"]')
@@ -0,0 +1,16 @@
1
+ //= require ./jquery.multi-select
2
+ //= require_self
3
+ jQuery(function(){
4
+ var form = $('#ecommerce_settings_form');
5
+ form.find('select[multiple], .masked_select').not('#setting_visitor_unit_currencies, #setting_shipping_countries').selectpicker();
6
+ form.find('#setting_visitor_unit_currencies').multiSelect({keepOrder: true});
7
+ form.find('#setting_shipping_countries').multiSelect();
8
+ setTimeout(function(){ form.find('textarea.editor.translate-item').tinymce(cama_get_tinymce_settings({height: 220})) }, 100);
9
+ form.find('.shipping_countries_link').click(function(){
10
+ if($(this).hasClass('select_all'))
11
+ form.find('#setting_shipping_countries').multiSelect('select_all');
12
+ else
13
+ form.find('#setting_shipping_countries').multiSelect('deselect_all');
14
+ return false;
15
+ });
16
+ });
@@ -30,6 +30,7 @@ function cama_checkout_actions(){
30
30
  steps.filter('.active').next().trigger('next_step');
31
31
  }).complete(function(){
32
32
  $(form).fadeTo("fast", 1);
33
+ $(window).scrollTop($('#cama_checkout_view').offset().top);
33
34
  }).error(function(e){
34
35
  alert(e.responseText);
35
36
  });
@@ -0,0 +1,535 @@
1
+ /*
2
+ * MultiSelect v0.9.12
3
+ * Copyright (c) 2012 Louis Cuny
4
+ *
5
+ * This program is free software. It comes without any warranty, to
6
+ * the extent permitted by applicable law. You can redistribute it
7
+ * and/or modify it under the terms of the Do What The Fuck You Want
8
+ * To Public License, Version 2, as published by Sam Hocevar. See
9
+ * http://sam.zoy.org/wtfpl/COPYING for more details.
10
+ */
11
+
12
+ !function ($) {
13
+
14
+ "use strict";
15
+
16
+
17
+ /* MULTISELECT CLASS DEFINITION
18
+ * ====================== */
19
+
20
+ var MultiSelect = function (element, options) {
21
+ this.options = options;
22
+ this.$element = $(element);
23
+ this.$container = $('<div/>', { 'class': "ms-container" });
24
+ this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' });
25
+ this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' });
26
+ this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
27
+ this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
28
+ this.scrollTo = 0;
29
+ this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')';
30
+ };
31
+
32
+ MultiSelect.prototype = {
33
+ constructor: MultiSelect,
34
+
35
+ init: function(){
36
+ var that = this,
37
+ ms = this.$element;
38
+
39
+ if (ms.next('.ms-container').length === 0){
40
+ ms.css({ position: 'absolute', left: '-9999px' });
41
+ ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');
42
+ this.$container.attr('id', 'ms-'+ms.attr('id'));
43
+ this.$container.addClass(that.options.cssClass);
44
+ ms.find('option').each(function(){
45
+ that.generateLisFromOption(this);
46
+ });
47
+
48
+ this.$selectionUl.find('.ms-optgroup-label').hide();
49
+
50
+ if (that.options.selectableHeader){
51
+ that.$selectableContainer.append(that.options.selectableHeader);
52
+ }
53
+ that.$selectableContainer.append(that.$selectableUl);
54
+ if (that.options.selectableFooter){
55
+ that.$selectableContainer.append(that.options.selectableFooter);
56
+ }
57
+
58
+ if (that.options.selectionHeader){
59
+ that.$selectionContainer.append(that.options.selectionHeader);
60
+ }
61
+ that.$selectionContainer.append(that.$selectionUl);
62
+ if (that.options.selectionFooter){
63
+ that.$selectionContainer.append(that.options.selectionFooter);
64
+ }
65
+
66
+ that.$container.append(that.$selectableContainer);
67
+ that.$container.append(that.$selectionContainer);
68
+ ms.after(that.$container);
69
+
70
+ that.activeMouse(that.$selectableUl);
71
+ that.activeKeyboard(that.$selectableUl);
72
+
73
+ var action = that.options.dblClick ? 'dblclick' : 'click';
74
+
75
+ that.$selectableUl.on(action, '.ms-elem-selectable', function(){
76
+ that.select($(this).data('ms-value'));
77
+ });
78
+ that.$selectionUl.on(action, '.ms-elem-selection', function(){
79
+ that.deselect($(this).data('ms-value'));
80
+ });
81
+
82
+ that.activeMouse(that.$selectionUl);
83
+ that.activeKeyboard(that.$selectionUl);
84
+
85
+ ms.on('focus', function(){
86
+ that.$selectableUl.focus();
87
+ })
88
+ }
89
+
90
+ var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get();
91
+ that.select(selectedValues, 'init');
92
+
93
+ if (typeof that.options.afterInit === 'function') {
94
+ that.options.afterInit.call(this, this.$container);
95
+ }
96
+ },
97
+
98
+ 'generateLisFromOption' : function(option, index, $container){
99
+ var that = this,
100
+ ms = that.$element,
101
+ attributes = "",
102
+ $option = $(option);
103
+
104
+ for (var cpt = 0; cpt < option.attributes.length; cpt++){
105
+ var attr = option.attributes[cpt];
106
+
107
+ if(attr.name !== 'value' && attr.name !== 'disabled'){
108
+ attributes += attr.name+'="'+attr.value+'" ';
109
+ }
110
+ }
111
+ var selectableLi = $('<li '+attributes+'><span>'+that.escapeHTML($option.text())+'</span></li>'),
112
+ selectedLi = selectableLi.clone(),
113
+ value = $option.val(),
114
+ elementId = that.sanitize(value);
115
+
116
+ selectableLi
117
+ .data('ms-value', value)
118
+ .addClass('ms-elem-selectable')
119
+ .attr('id', elementId+'-selectable');
120
+
121
+ selectedLi
122
+ .data('ms-value', value)
123
+ .addClass('ms-elem-selection')
124
+ .attr('id', elementId+'-selection')
125
+ .hide();
126
+
127
+ if ($option.prop('disabled') || ms.prop('disabled')){
128
+ selectedLi.addClass(that.options.disabledClass);
129
+ selectableLi.addClass(that.options.disabledClass);
130
+ }
131
+
132
+ var $optgroup = $option.parent('optgroup');
133
+
134
+ if ($optgroup.length > 0){
135
+ var optgroupLabel = $optgroup.attr('label'),
136
+ optgroupId = that.sanitize(optgroupLabel),
137
+ $selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),
138
+ $selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);
139
+
140
+ if ($selectableOptgroup.length === 0){
141
+ var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>',
142
+ optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>';
143
+
144
+ $selectableOptgroup = $(optgroupContainerTpl);
145
+ $selectionOptgroup = $(optgroupContainerTpl);
146
+ $selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId);
147
+ $selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId);
148
+ $selectableOptgroup.append($(optgroupTpl));
149
+ $selectionOptgroup.append($(optgroupTpl));
150
+ if (that.options.selectableOptgroup){
151
+ $selectableOptgroup.find('.ms-optgroup-label').on('click', function(){
152
+ var values = $optgroup.children(':not(:selected, :disabled)').map(function(){ return $(this).val() }).get();
153
+ that.select(values);
154
+ });
155
+ $selectionOptgroup.find('.ms-optgroup-label').on('click', function(){
156
+ var values = $optgroup.children(':selected:not(:disabled)').map(function(){ return $(this).val() }).get();
157
+ that.deselect(values);
158
+ });
159
+ }
160
+ that.$selectableUl.append($selectableOptgroup);
161
+ that.$selectionUl.append($selectionOptgroup);
162
+ }
163
+ index = index == undefined ? $selectableOptgroup.find('ul').children().length : index + 1;
164
+ selectableLi.insertAt(index, $selectableOptgroup.children());
165
+ selectedLi.insertAt(index, $selectionOptgroup.children());
166
+ } else {
167
+ index = index == undefined ? that.$selectableUl.children().length : index;
168
+
169
+ selectableLi.insertAt(index, that.$selectableUl);
170
+ selectedLi.insertAt(index, that.$selectionUl);
171
+ }
172
+ },
173
+
174
+ 'addOption' : function(options){
175
+ var that = this;
176
+
177
+ if (options.value !== undefined && options.value !== null){
178
+ options = [options];
179
+ }
180
+ $.each(options, function(index, option){
181
+ if (option.value !== undefined && option.value !== null &&
182
+ that.$element.find("option[value='"+option.value+"']").length === 0){
183
+ var $option = $('<option value="'+option.value+'">'+option.text+'</option>'),
184
+ index = parseInt((typeof option.index === 'undefined' ? that.$element.children().length : option.index)),
185
+ $container = option.nested == undefined ? that.$element : $("optgroup[label='"+option.nested+"']")
186
+
187
+ $option.insertAt(index, $container);
188
+ that.generateLisFromOption($option.get(0), index, option.nested);
189
+ }
190
+ })
191
+ },
192
+
193
+ 'escapeHTML' : function(text){
194
+ return $("<div>").text(text).html();
195
+ },
196
+
197
+ 'activeKeyboard' : function($list){
198
+ var that = this;
199
+
200
+ $list.on('focus', function(){
201
+ $(this).addClass('ms-focus');
202
+ })
203
+ .on('blur', function(){
204
+ $(this).removeClass('ms-focus');
205
+ })
206
+ .on('keydown', function(e){
207
+ switch (e.which) {
208
+ case 40:
209
+ case 38:
210
+ e.preventDefault();
211
+ e.stopPropagation();
212
+ that.moveHighlight($(this), (e.which === 38) ? -1 : 1);
213
+ return;
214
+ case 37:
215
+ case 39:
216
+ e.preventDefault();
217
+ e.stopPropagation();
218
+ that.switchList($list);
219
+ return;
220
+ case 9:
221
+ if(that.$element.is('[tabindex]')){
222
+ e.preventDefault();
223
+ var tabindex = parseInt(that.$element.attr('tabindex'), 10);
224
+ tabindex = (e.shiftKey) ? tabindex-1 : tabindex+1;
225
+ $('[tabindex="'+(tabindex)+'"]').focus();
226
+ return;
227
+ }else{
228
+ if(e.shiftKey){
229
+ that.$element.trigger('focus');
230
+ }
231
+ }
232
+ }
233
+ if($.inArray(e.which, that.options.keySelect) > -1){
234
+ e.preventDefault();
235
+ e.stopPropagation();
236
+ that.selectHighlighted($list);
237
+ return;
238
+ }
239
+ });
240
+ },
241
+
242
+ 'moveHighlight': function($list, direction){
243
+ var $elems = $list.find(this.elemsSelector),
244
+ $currElem = $elems.filter('.ms-hover'),
245
+ $nextElem = null,
246
+ elemHeight = $elems.first().outerHeight(),
247
+ containerHeight = $list.height(),
248
+ containerSelector = '#'+this.$container.prop('id');
249
+
250
+ $elems.removeClass('ms-hover');
251
+ if (direction === 1){ // DOWN
252
+
253
+ $nextElem = $currElem.nextAll(this.elemsSelector).first();
254
+ if ($nextElem.length === 0){
255
+ var $optgroupUl = $currElem.parent();
256
+
257
+ if ($optgroupUl.hasClass('ms-optgroup')){
258
+ var $optgroupLi = $optgroupUl.parent(),
259
+ $nextOptgroupLi = $optgroupLi.next(':visible');
260
+
261
+ if ($nextOptgroupLi.length > 0){
262
+ $nextElem = $nextOptgroupLi.find(this.elemsSelector).first();
263
+ } else {
264
+ $nextElem = $elems.first();
265
+ }
266
+ } else {
267
+ $nextElem = $elems.first();
268
+ }
269
+ }
270
+ } else if (direction === -1){ // UP
271
+
272
+ $nextElem = $currElem.prevAll(this.elemsSelector).first();
273
+ if ($nextElem.length === 0){
274
+ var $optgroupUl = $currElem.parent();
275
+
276
+ if ($optgroupUl.hasClass('ms-optgroup')){
277
+ var $optgroupLi = $optgroupUl.parent(),
278
+ $prevOptgroupLi = $optgroupLi.prev(':visible');
279
+
280
+ if ($prevOptgroupLi.length > 0){
281
+ $nextElem = $prevOptgroupLi.find(this.elemsSelector).last();
282
+ } else {
283
+ $nextElem = $elems.last();
284
+ }
285
+ } else {
286
+ $nextElem = $elems.last();
287
+ }
288
+ }
289
+ }
290
+ if ($nextElem.length > 0){
291
+ $nextElem.addClass('ms-hover');
292
+ var scrollTo = $list.scrollTop() + $nextElem.position().top -
293
+ containerHeight / 2 + elemHeight / 2;
294
+
295
+ $list.scrollTop(scrollTo);
296
+ }
297
+ },
298
+
299
+ 'selectHighlighted' : function($list){
300
+ var $elems = $list.find(this.elemsSelector),
301
+ $highlightedElem = $elems.filter('.ms-hover').first();
302
+
303
+ if ($highlightedElem.length > 0){
304
+ if ($list.parent().hasClass('ms-selectable')){
305
+ this.select($highlightedElem.data('ms-value'));
306
+ } else {
307
+ this.deselect($highlightedElem.data('ms-value'));
308
+ }
309
+ $elems.removeClass('ms-hover');
310
+ }
311
+ },
312
+
313
+ 'switchList' : function($list){
314
+ $list.blur();
315
+ this.$container.find(this.elemsSelector).removeClass('ms-hover');
316
+ if ($list.parent().hasClass('ms-selectable')){
317
+ this.$selectionUl.focus();
318
+ } else {
319
+ this.$selectableUl.focus();
320
+ }
321
+ },
322
+
323
+ 'activeMouse' : function($list){
324
+ var that = this;
325
+
326
+ this.$container.on('mouseenter', that.elemsSelector, function(){
327
+ $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover');
328
+ $(this).addClass('ms-hover');
329
+ });
330
+
331
+ this.$container.on('mouseleave', that.elemsSelector, function () {
332
+ $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover');;
333
+ });
334
+ },
335
+
336
+ 'refresh' : function() {
337
+ this.destroy();
338
+ this.$element.multiSelect(this.options);
339
+ },
340
+
341
+ 'destroy' : function(){
342
+ $("#ms-"+this.$element.attr("id")).remove();
343
+ this.$element.css('position', '').css('left', '')
344
+ this.$element.removeData('multiselect');
345
+ },
346
+
347
+ 'select' : function(value, method){
348
+ if (typeof value === 'string'){ value = [value]; }
349
+
350
+ var that = this,
351
+ ms = this.$element,
352
+ msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
353
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
354
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
355
+ options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });
356
+
357
+ if (method === 'init'){
358
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
359
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection');
360
+ }
361
+
362
+ if (selectables.length > 0){
363
+ selectables.addClass('ms-selected').hide();
364
+ selections.addClass('ms-selected').show();
365
+
366
+ options.prop('selected', true);
367
+
368
+ that.$container.find(that.elemsSelector).removeClass('ms-hover');
369
+
370
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
371
+ if (selectableOptgroups.length > 0){
372
+ selectableOptgroups.each(function(){
373
+ var selectablesLi = $(this).find('.ms-elem-selectable');
374
+ if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){
375
+ $(this).find('.ms-optgroup-label').hide();
376
+ }
377
+ });
378
+
379
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
380
+ selectionOptgroups.each(function(){
381
+ var selectionsLi = $(this).find('.ms-elem-selection');
382
+ if (selectionsLi.filter('.ms-selected').length > 0){
383
+ $(this).find('.ms-optgroup-label').show();
384
+ }
385
+ });
386
+ } else {
387
+ if (that.options.keepOrder && method !== 'init'){
388
+ var selectionLiLast = that.$selectionUl.find('.ms-selected');
389
+ if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) {
390
+ selections.insertAfter(selectionLiLast.last());
391
+ }
392
+ }
393
+ }
394
+ if (method !== 'init'){
395
+ ms.trigger('change');
396
+ if (typeof that.options.afterSelect === 'function') {
397
+ that.options.afterSelect.call(this, value);
398
+ }
399
+ }
400
+ }
401
+ },
402
+
403
+ 'deselect' : function(value){
404
+ if (typeof value === 'string'){ value = [value]; }
405
+
406
+ var that = this,
407
+ ms = this.$element,
408
+ msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
409
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
410
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected').filter(':not(.'+that.options.disabledClass+')'),
411
+ options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });
412
+
413
+ if (selections.length > 0){
414
+ selectables.removeClass('ms-selected').show();
415
+ selections.removeClass('ms-selected').hide();
416
+ options.prop('selected', false);
417
+
418
+ that.$container.find(that.elemsSelector).removeClass('ms-hover');
419
+
420
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
421
+ if (selectableOptgroups.length > 0){
422
+ selectableOptgroups.each(function(){
423
+ var selectablesLi = $(this).find('.ms-elem-selectable');
424
+ if (selectablesLi.filter(':not(.ms-selected)').length > 0){
425
+ $(this).find('.ms-optgroup-label').show();
426
+ }
427
+ });
428
+
429
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
430
+ selectionOptgroups.each(function(){
431
+ var selectionsLi = $(this).find('.ms-elem-selection');
432
+ if (selectionsLi.filter('.ms-selected').length === 0){
433
+ $(this).find('.ms-optgroup-label').hide();
434
+ }
435
+ });
436
+ }
437
+ ms.trigger('change');
438
+ if (typeof that.options.afterDeselect === 'function') {
439
+ that.options.afterDeselect.call(this, value);
440
+ }
441
+ }
442
+ },
443
+
444
+ 'select_all' : function(){
445
+ var ms = this.$element,
446
+ values = ms.val();
447
+
448
+ ms.find('option:not(":disabled")').prop('selected', true);
449
+ this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide();
450
+ this.$selectionUl.find('.ms-optgroup-label').show();
451
+ this.$selectableUl.find('.ms-optgroup-label').hide();
452
+ this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show();
453
+ this.$selectionUl.focus();
454
+ ms.trigger('change');
455
+ if (typeof this.options.afterSelect === 'function') {
456
+ var selectedValues = $.grep(ms.val(), function(item){
457
+ return $.inArray(item, values) < 0;
458
+ });
459
+ this.options.afterSelect.call(this, selectedValues);
460
+ }
461
+ },
462
+
463
+ 'deselect_all' : function(){
464
+ var ms = this.$element,
465
+ values = ms.val();
466
+
467
+ ms.find('option').prop('selected', false);
468
+ this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
469
+ this.$selectionUl.find('.ms-optgroup-label').hide();
470
+ this.$selectableUl.find('.ms-optgroup-label').show();
471
+ this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
472
+ this.$selectableUl.focus();
473
+ ms.trigger('change');
474
+ if (typeof this.options.afterDeselect === 'function') {
475
+ this.options.afterDeselect.call(this, values);
476
+ }
477
+ },
478
+
479
+ sanitize: function(value){
480
+ var hash = 0, i, character;
481
+ if (value.length == 0) return hash;
482
+ var ls = 0;
483
+ for (i = 0, ls = value.length; i < ls; i++) {
484
+ character = value.charCodeAt(i);
485
+ hash = ((hash<<5)-hash)+character;
486
+ hash |= 0; // Convert to 32bit integer
487
+ }
488
+ return hash;
489
+ }
490
+ };
491
+
492
+ /* MULTISELECT PLUGIN DEFINITION
493
+ * ======================= */
494
+
495
+ $.fn.multiSelect = function () {
496
+ var option = arguments[0],
497
+ args = arguments;
498
+
499
+ return this.each(function () {
500
+ var $this = $(this),
501
+ data = $this.data('multiselect'),
502
+ options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option);
503
+
504
+ if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); }
505
+
506
+ if (typeof option === 'string'){
507
+ data[option](args[1]);
508
+ } else {
509
+ data.init();
510
+ }
511
+ });
512
+ };
513
+
514
+ $.fn.multiSelect.defaults = {
515
+ keySelect: [32],
516
+ selectableOptgroup: false,
517
+ disabledClass : 'disabled',
518
+ dblClick : false,
519
+ keepOrder: false,
520
+ cssClass: ''
521
+ };
522
+
523
+ $.fn.multiSelect.Constructor = MultiSelect;
524
+
525
+ $.fn.insertAt = function(index, $parent) {
526
+ return this.each(function() {
527
+ if (index === 0) {
528
+ $parent.prepend(this);
529
+ } else {
530
+ $parent.children().eq(index - 1).after(this);
531
+ }
532
+ });
533
+ }
534
+
535
+ }(window.jQuery);