diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index 689507aecf..4fa014780d 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -14,6 +14,7 @@ //= require angular-resource //= require angular-animate //= require angular-sanitize +//= require angular-ui //= require admin/spree_backend //= require admin/spree_auth //= require admin/spree_paypal_express diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycles_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycles_controller.js.coffee index 63f5902efa..e1c2b994c2 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycles_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycles_controller.js.coffee @@ -7,7 +7,7 @@ angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, C compileData = -> for schedule in $scope.schedules - Dereferencer.dereference(schedule.order_cycles, OrderCycles.orderCyclesByID) + Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID) for orderCycle in $scope.orderCycles coordinator = Enterprises.byID[orderCycle.coordinator.id] orderCycle.coordinator = coordinator if coordinator? @@ -21,7 +21,7 @@ angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, C # NOTE: this is using the Enterprises service from the admin.enterprises module RequestMonitor.load ($scope.enterprises = Enterprises.index(action: "visible", ams_prefix: "basic")).$promise $scope.schedules = Schedules.index() - RequestMonitor.load ($scope.orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}")).$promise + $scope.orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}") RequestMonitor.load $q.all([$scope.enterprises.$promise, $scope.schedules.$promise, $scope.orderCycles.$promise]).then -> compileData() $scope.$watch 'order_cycles_form.$dirty', (newVal, oldVal) -> @@ -29,8 +29,8 @@ angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, C $scope.showMore = (days) -> $scope.ordersCloseAtLimit -= days - existingIDs = Object.keys(OrderCycles.orderCyclesByID) - RequestMonitor.load (orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}", "q[id_not_in][]": existingIDs)).$promise + existingIDs = Object.keys(OrderCycles.byID) + orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}", "q[id_not_in][]": existingIDs) orderCycles.$promise.then -> $scope.orderCycles.push(orderCycle) for orderCycle in orderCycles compileData() diff --git a/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee b/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee index 0b472a6b39..2fac4a4b4f 100644 --- a/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee @@ -1,16 +1,9 @@ -angular.module("admin.orderCycles").directive 'orderCyclesSelector', (OrderCycles, Schedules) -> +angular.module("admin.orderCycles").directive 'orderCyclesSelector', (OrderCycles, RequestMonitor) -> restrict: 'C' templateUrl: 'admin/order_cycles_selector.html' link: (scope, element, attr) -> - scope.selectedOrderCycles = (orderCycle for id, orderCycle of OrderCycles.orderCyclesByID when orderCycle.id in scope.schedule.order_cycle_ids) - scope.availableOrderCycles = (orderCycle for id, orderCycle of OrderCycles.orderCyclesByID when orderCycle.id not in scope.schedule.order_cycle_ids) - - element.find('#available-order-cycles .order-cycles').sortable + scope.availableOptions = connectWith: '#selected-order-cycles .order-cycles' - element.find('#selected-order-cycles .order-cycles').sortable + scope.selectedOptions = connectWith: '#available-order-cycles .order-cycles' - receive: (event, ui) -> - scope.schedule.order_cycle_ids = $('#selected-order-cycles .order-cycles').children('.order-cycle').map((i, element) -> $(element).scope().orderCycle.id).get() - remove: (event, ui) -> - scope.schedule.order_cycle_ids = $('#selected-order-cycles .order-cycles').children('.order-cycle').map((i, element) -> $(element).scope().orderCycle.id).get() diff --git a/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee b/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee index 4c66a5886e..0bb665ae00 100644 --- a/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee @@ -1,7 +1,8 @@ -angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compile, $injector, $templateCache, DialogDefaults, Schedules) -> +angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compile, $injector, $templateCache, DialogDefaults, OrderCycles, Schedules) -> restrict: 'A' scope: scheduleId: '@' + showMore: '&' link: (scope, element, attr) -> # Link opening of dialog to click event on element element.bind 'click', (e) -> @@ -10,6 +11,9 @@ angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compi id: existing?.id name: existing?.name || '' order_cycle_ids: existing?.order_cycle_ids || [] + scope.selectedOrderCycles = [] + scope.selectedOrderCycles.push orderCycle for orderCycle in (existing?.order_cycles || []) + scope.availableOrderCycles = (orderCycle for id, orderCycle of OrderCycles.byID when orderCycle.id not in scope.schedule.order_cycle_ids) scope.submitted = false scope.errors = [] # Compile modal template @@ -24,11 +28,16 @@ angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compi scope.template.dialog('close') return + scope.loadMore = -> + scope.showMore().then -> + scope.availableOrderCycles = (orderCycle for id, orderCycle of OrderCycles.byID when orderCycle.id not in scope.schedule.order_cycle_ids) + scope.submit = -> scope.schedule_form.$setPristine() scope.submitted = true scope.errors = [] - return scope.errors.push("Please select at least one order cycle") unless scope.schedule.order_cycle_ids.length > 0 + return scope.errors.push("Please select at least one order cycle") unless scope.selectedOrderCycles.length > 0 + scope.schedule.order_cycle_ids = scope.selectedOrderCycles.map (oc) -> oc.id if scope.schedule_form.$valid method = if scope.schedule.id? then Schedules.update else Schedules.add method(scope.schedule).$promise.then (data) -> diff --git a/app/assets/javascripts/admin/order_cycles/order_cycles.js.erb.coffee b/app/assets/javascripts/admin/order_cycles/order_cycles.js.erb.coffee index d43bcc2ad6..802ce43cc3 100644 --- a/app/assets/javascripts/admin/order_cycles/order_cycles.js.erb.coffee +++ b/app/assets/javascripts/admin/order_cycles/order_cycles.js.erb.coffee @@ -1,4 +1,4 @@ -angular.module('admin.orderCycles', ['admin.utils', 'admin.indexUtils', 'admin.enterprises', 'ngTagsInput']) +angular.module('admin.orderCycles', ['ui.sortable', 'ngTagsInput', 'admin.indexUtils', 'admin.enterprises']) .config ($httpProvider) -> $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content') diff --git a/app/assets/javascripts/admin/order_cycles/services/schedules.js.coffee b/app/assets/javascripts/admin/order_cycles/services/schedules.js.coffee index 932818ea26..750398739d 100644 --- a/app/assets/javascripts/admin/order_cycles/services/schedules.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/schedules.js.coffee @@ -6,15 +6,16 @@ angular.module("admin.orderCycles").factory "Schedules", ($q, RequestMonitor, Sc add: (params) => ScheduleResource.create params, (schedule) => @byID[schedule.id] = schedule if schedule.id? - Dereferencer.dereference(schedule.order_cycles, OrderCycles.orderCyclesByID) + Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID) orderCycle.schedules.push(schedule) for orderCycle in schedule.order_cycles update: (params) => ScheduleResource.update params, (schedule) => if schedule.id? - Dereferencer.dereference(schedule.order_cycles, OrderCycles.orderCyclesByID) + Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID) for orderCycle in @byID[schedule.id].order_cycles when orderCycle.id not in schedule.order_cycle_ids - orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id + if orderCycle.schedules # Only if we need to update the schedules + orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id for orderCycle in schedule.order_cycles when orderCycle.id not in @byID[schedule.id].order_cycle_ids orderCycle.schedules.push(@byID[schedule.id]) angular.extend(@byID[schedule.id], schedule) diff --git a/app/assets/javascripts/admin/resources/services/order_cycles.js.coffee b/app/assets/javascripts/admin/resources/services/order_cycles.js.coffee index 4feeb980db..8f2bed23f1 100644 --- a/app/assets/javascripts/admin/resources/services/order_cycles.js.coffee +++ b/app/assets/javascripts/admin/resources/services/order_cycles.js.coffee @@ -1,4 +1,4 @@ -angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource, StatusMessage, Enterprises, blankOption) -> +angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource, StatusMessage) -> new class OrderCycles all: [] byID: {} @@ -15,7 +15,7 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy data load: (orderCycles) -> - for orderCycle in orderCycles + for orderCycle in orderCycles when orderCycle.id not in Object.keys(@byID) @all.push orderCycle @byID[orderCycle.id] = orderCycle @pristineByID[orderCycle.id] = angular.copy(orderCycle) @@ -32,15 +32,17 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy saveChanges: (form) -> changed = {} - for id, orderCycle of @orderCyclesByID when not @saved(orderCycle) + for id, orderCycle of @byID when not @saved(orderCycle) changed[Object.keys(changed).length] = @changesFor(orderCycle) if Object.keys(changed).length > 0 StatusMessage.display('progress', "Saving...") OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed } }, (data) => for orderCycle in data - angular.extend(@orderCyclesByID[orderCycle.id], orderCycle) + delete orderCycle.coordinator + delete orderCycle.producers + delete orderCycle.distributors + angular.extend(@byID[orderCycle.id], orderCycle) angular.extend(@pristineByID[orderCycle.id], orderCycle) - @linkToEnterprises(orderCycle) form.$setPristine() if form? StatusMessage.display('success', "Order cycles have been updated.") , (response) => diff --git a/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml b/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml index 8ecaceb103..d4ef1dcb96 100644 --- a/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml +++ b/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml @@ -1,11 +1,11 @@ #available-order-cycles Available - .order-cycles + .order-cycles{ ui: { sortable: 'availableOptions' }, ng: { model: "availableOrderCycles" } } .order-cycle{ ng: { repeat: 'orderCycle in availableOrderCycles' } } {{ orderCycle.name }} #selected-order-cycles Selected - .order-cycles + .order-cycles{ ui: { sortable: 'selectedOptions' }, ng: { model: "selectedOrderCycles" } } .order-cycle{ ng: { repeat: 'orderCycle in selectedOrderCycles' } } {{ orderCycle.name }} .error{ ng: { repeat: "error in errors", bind: "error" } } diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index d4b1242f36..eea64f7fc9 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -37,10 +37,13 @@ module Admin def check_editable_order_cycle_ids return unless params[:schedule][:order_cycle_ids] requested = params[:schedule][:order_cycle_ids] - existing = @schedule.order_cycle_ids - permitted = OrderCycle.where(id: params[:schedule][:order_cycle_ids] + existing).merge(OrderCycle.managed_by(spree_current_user)).pluck(:id) - params[:schedule][:order_cycle_ids] |= (existing - permitted) - params[:schedule][:order_cycle_ids] -= (requested - permitted) + existing = @schedule.persisted? ? @schedule.order_cycle_ids : [] + permitted = OrderCycle.where(id: params[:schedule][:order_cycle_ids] | existing).merge(OrderCycle.managed_by(spree_current_user)).pluck(:id) + result = existing + result |= (requested & permitted) # add any requested & permitted ids + result -= ((result & permitted) - requested) # remove any existing and permitted ids that were not specifically requested + params[:schedule][:order_cycle_ids] = result + @object.order_cycle_ids = result end def permissions diff --git a/app/serializers/api/admin/schedule_serializer.rb b/app/serializers/api/admin/schedule_serializer.rb index 63010ca429..20207c4e97 100644 --- a/app/serializers/api/admin/schedule_serializer.rb +++ b/app/serializers/api/admin/schedule_serializer.rb @@ -1,7 +1,7 @@ class Api::Admin::ScheduleSerializer < ActiveModel::Serializer attributes :id, :name, :order_cycle_ids, :viewing_as_coordinator - has_many :order_cycles, serializer: Api::Admin::IdSerializer + has_many :order_cycles, serializer: Api::Admin::IdNameSerializer def viewing_as_coordinator options[:editable_schedule_ids].include? object.id diff --git a/spec/controllers/admin/schedules_controller_spec.rb b/spec/controllers/admin/schedules_controller_spec.rb index bd45cac0b0..ccfda525eb 100644 --- a/spec/controllers/admin/schedules_controller_spec.rb +++ b/spec/controllers/admin/schedules_controller_spec.rb @@ -59,7 +59,8 @@ describe Admin::SchedulesController, type: :controller do let!(:coordinated_order_cycle2) { create(:simple_order_cycle, coordinator: managed_enterprise ) } let!(:uncoordinated_order_cycle) { create(:simple_order_cycle, coordinator: create(:enterprise) ) } let!(:uncoordinated_order_cycle2) { create(:simple_order_cycle, coordinator: create(:enterprise)) } - let!(:coordinated_schedule) { create(:schedule, order_cycles: [coordinated_order_cycle, uncoordinated_order_cycle] ) } + let!(:uncoordinated_order_cycle3) { create(:simple_order_cycle, coordinator: create(:enterprise)) } + let!(:coordinated_schedule) { create(:schedule, order_cycles: [coordinated_order_cycle, uncoordinated_order_cycle, uncoordinated_order_cycle3] ) } let!(:uncoordinated_schedule) { create(:schedule, order_cycles: [uncoordinated_order_cycle] ) } context "json" do @@ -79,11 +80,11 @@ describe Admin::SchedulesController, type: :controller do end it "allows me to add/remove only order cycles I coordinate to/from the schedule" do - order_cycle_ids = [coordinated_order_cycle2.id, uncoordinated_order_cycle2.id ] + order_cycle_ids = [coordinated_order_cycle2.id, uncoordinated_order_cycle2.id, uncoordinated_order_cycle3.id ] spree_put :update, format: :json, id: coordinated_schedule.id, schedule: { order_cycle_ids: order_cycle_ids } expect(assigns(:schedule)).to eq coordinated_schedule # coordinated_order_cycle2 is added, uncoordinated_order_cycle is NOT removed - expect(coordinated_schedule.reload.order_cycles).to include coordinated_order_cycle2, uncoordinated_order_cycle + expect(coordinated_schedule.reload.order_cycles).to include coordinated_order_cycle2, uncoordinated_order_cycle, uncoordinated_order_cycle3 # coordinated_order_cycle is removed, uncoordinated_order_cycle2 is NOT added expect(coordinated_schedule.reload.order_cycles).to_not include coordinated_order_cycle, uncoordinated_order_cycle2 end diff --git a/spec/features/admin/schedules_spec.rb b/spec/features/admin/schedules_spec.rb index b2f49e93ca..a39967a534 100644 --- a/spec/features/admin/schedules_spec.rb +++ b/spec/features/admin/schedules_spec.rb @@ -8,12 +8,11 @@ feature 'Schedules', js: true do let(:user) { create(:user) } let(:managed_enterprise) { create(:distributor_enterprise, owner: user) } let(:unmanaged_enterprise) { create(:distributor_enterprise) } - let!(:weekly_schedule) { create(:schedule, name: 'Weekly') } - let!(:fortnightly_schedule) { create(:schedule, name: 'Fortnightly') } - let!(:oc1) { create(:order_cycle, coordinator: managed_enterprise, name: 'oc1', schedules: [weekly_schedule]) } - let!(:oc2) { create(:order_cycle, coordinator: managed_enterprise, name: 'oc2', schedules: [weekly_schedule]) } - let!(:oc3) { create(:order_cycle, coordinator: managed_enterprise, name: 'oc3', schedules: [weekly_schedule]) } - let!(:oc4) { create(:order_cycle, coordinator: unmanaged_enterprise, name: 'oc4', schedules: [weekly_schedule]) } + let!(:oc1) { create(:simple_order_cycle, coordinator: managed_enterprise, name: 'oc1') } + let!(:oc2) { create(:simple_order_cycle, coordinator: managed_enterprise, name: 'oc2') } + let!(:oc3) { create(:simple_order_cycle, coordinator: managed_enterprise, name: 'oc3') } + let!(:oc4) { create(:simple_order_cycle, coordinator: unmanaged_enterprise, name: 'oc4') } + let!(:weekly_schedule) { create(:schedule, name: 'Weekly', order_cycles: [oc1, oc2, oc3, oc4]) } before { login_to_admin_as user } @@ -52,11 +51,7 @@ feature 'Schedules', js: true do end describe "updating existing schedules" do - use_short_wait - before do - oc1.update_attributes(schedule_ids: [weekly_schedule.id, fortnightly_schedule.id]) - oc3.update_attributes(schedule_ids: [weekly_schedule.id, fortnightly_schedule.id]) - end + let!(:fortnightly_schedule) { create(:schedule, name: 'Fortnightly', order_cycles: [oc1, oc3]) } it "immediately shows updated schedule lists for order cycles" do click_link 'Order Cycles' diff --git a/spec/javascripts/application_spec.js b/spec/javascripts/application_spec.js index eed37bf99e..7fdc77597c 100644 --- a/spec/javascripts/application_spec.js +++ b/spec/javascripts/application_spec.js @@ -4,6 +4,7 @@ //= require angular-mocks //= require angular-cookies //= require angular-backstretch.js +//= require angular-ui //= require angularjs-file-upload //= require lodash.underscore.js //= require angular-flash.min.js diff --git a/spec/javascripts/unit/admin/order_cycles/controllers/order_cycles_controller_spec.js.coffee b/spec/javascripts/unit/admin/order_cycles/controllers/order_cycles_controller_spec.js.coffee index ecac5dadff..4c36884c0a 100644 --- a/spec/javascripts/unit/admin/order_cycles/controllers/order_cycles_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/order_cycles/controllers/order_cycles_controller_spec.js.coffee @@ -41,7 +41,7 @@ describe "OrderCyclesCtrl", -> it "has not received/stored any data yet", -> expect(Enterprises.byID["5"]).toBeUndefined() - expect(OrderCycles.orderCyclesByID["4"]).toBeUndefined() + expect(OrderCycles.byID["4"]).toBeUndefined() expect(Schedules.byID["7"]).toBeUndefined() describe "after data is returned", -> @@ -54,11 +54,11 @@ describe "OrderCyclesCtrl", -> it "stores enterprises, order cycle and schedules in a list that is accessible by id", -> expect(Enterprises.byID["5"]).toBeDefined() - expect(OrderCycles.orderCyclesByID["4"]).toBeDefined() + expect(OrderCycles.byID["4"]).toBeDefined() expect(Schedules.byID["7"]).toBeDefined() it "gets order cycles, with dereferenced coordinator, shops and producers, schedules", -> - oc = OrderCycles.orderCyclesByID["4"] + oc = OrderCycles.byID["4"] s = Schedules.byID["7"] expect(scope.orderCycles).toDeepEqual [oc] expect(oc.coordinator).toDeepEqual coordinator diff --git a/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee b/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee index f1e2c95959..f1b12ecd1d 100644 --- a/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee +++ b/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee @@ -36,7 +36,7 @@ describe "OrderCycles service", -> it "returns an array of orderCycles", -> expect(result).toDeepEqual response - describe "when no params are passed", -> + describe "when params are passed", -> beforeEach -> params = { someParam: 'someVal'} $httpBackend.expectGET('/admin/order_cycles.json?someParam=someVal').respond 200, response diff --git a/vendor/assets/javascripts/angular-ui.js b/vendor/assets/javascripts/angular-ui.js new file mode 100644 index 0000000000..c433014ddc --- /dev/null +++ b/vendor/assets/javascripts/angular-ui.js @@ -0,0 +1 @@ +//= require_tree ./angular-ui diff --git a/vendor/assets/javascripts/angular-ui/sortable.min.js b/vendor/assets/javascripts/angular-ui/sortable.min.js new file mode 100644 index 0000000000..3a1d326770 --- /dev/null +++ b/vendor/assets/javascripts/angular-ui/sortable.min.js @@ -0,0 +1,8 @@ +/** + * angular-ui-sortable - This directive allows you to jQueryUI Sortable. + * @version v0.14.3 - 2016-06-30 + * @link http://angular-ui.github.com + * @license MIT + */ + +!function(a,b,c){"use strict";b.module("ui.sortable",[]).value("uiSortableConfig",{items:"> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]"}).directive("uiSortable",["uiSortableConfig","$timeout","$log",function(a,d,e){return{require:"?ngModel",scope:{ngModel:"=",uiSortable:"="},link:function(f,g,h,i){function j(a,b){var c=a&&"function"==typeof a,d=b&&"function"==typeof b;return c&&d?function(){a.apply(this,arguments),b.apply(this,arguments)}:d?b:a}function k(a){var b=a.data("ui-sortable");return b&&"object"==typeof b&&"ui-sortable"===b.widgetFullName?b:null}function l(b,c){return B[b]?("stop"===b&&(c=j(c,function(){f.$apply()}),c=j(c,t)),c=j(B[b],c)):C[b]&&(c=C[b](c)),c||("items"===b?c=a.items:"ui-model-items"===b&&(c=a.items)),c}function m(a,d,e){function f(a,b){b in z||(z[b]=null)}b.forEach(B,f);var g=null;if(d){var h;b.forEach(d,function(d,e){if(!(a&&e in a)){if(e in A)return void("ui-floating"===e?z[e]="auto":z[e]=l(e,c));h||(h=b.element.ui.sortable().options);var f=h[e];f=l(e,f),g||(g={}),g[e]=f,z[e]=f}})}return b.forEach(a,function(a,b){return b in A?("ui-floating"!==b||a!==!1&&a!==!0||!e||(e.floating=a),void(z[b]=l(b,a))):(a=l(b,a),g||(g={}),g[b]=a,void(z[b]=a))}),g}function n(a){var c=a.sortable("option","placeholder");if(c&&c.element&&"function"==typeof c.element){var d=c.element();return d=b.element(d)}return null}function o(a,b){var c=z["ui-model-items"].replace(/[^,]*>/g,""),d=a.find('[class="'+b.attr("class")+'"]:not('+c+")");return d}function p(a,b){var c=a.sortable("option","helper");return"clone"===c||"function"==typeof c&&b.item.sortable.isCustomHelperUsed()}function q(a,b,c){var d=null;return p(a,b)&&"parent"===a.sortable("option","appendTo")&&(d=c.last()),d}function r(a){return/left|right/.test(a.css("float"))||/inline|table-cell/.test(a.css("display"))}function s(a,b){for(var c=null,d=0;d