activeadmin-selleo-cms 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +13 -0
- data/Rakefile +40 -0
- data/app/admin/activeadmin_selleo_cms/locale.rb +21 -0
- data/app/admin/activeadmin_selleo_cms/page.rb +68 -0
- data/app/admin/translation.rb +35 -0
- data/app/assets/javascripts/activeadmin-selleo-cms/application.js +15 -0
- data/app/assets/javascripts/activeadmin-selleo-cms/custom.js +44 -0
- data/app/assets/javascripts/activeadmin-selleo-cms/jquery.mjs.nestedSortable.js +429 -0
- data/app/assets/stylesheets/activeadmin-selleo-cms/application.css +13 -0
- data/app/assets/stylesheets/activeadmin-selleo-cms/custom.css +59 -0
- data/app/assets/stylesheets/activeadmin-selleo-cms/jquery-ui.css +517 -0
- data/app/controllers/activeadmin_selleo_cms/application_controller.rb +9 -0
- data/app/controllers/activeadmin_selleo_cms/locales_controller.rb +8 -0
- data/app/controllers/activeadmin_selleo_cms/pages_controller.rb +15 -0
- data/app/controllers/activeadmin_selleo_cms/searches_controller.rb +8 -0
- data/app/helpers/activeadmin_selleo_cms/application_helper.rb +27 -0
- data/app/models/activeadmin_selleo_cms/layout.rb +10 -0
- data/app/models/activeadmin_selleo_cms/locale.rb +44 -0
- data/app/models/activeadmin_selleo_cms/page.rb +64 -0
- data/app/models/activeadmin_selleo_cms/search.rb +10 -0
- data/app/models/activeadmin_selleo_cms/section.rb +20 -0
- data/app/models/ckeditor/asset.rb +4 -0
- data/app/models/ckeditor/attachment_file.rb +12 -0
- data/app/models/ckeditor/picture.rb +13 -0
- data/app/models/translation.rb +25 -0
- data/app/modules/active_admin/views/index_as_list.rb +28 -0
- data/app/modules/activeadmin_selleo_cms/content_translation.rb +25 -0
- data/app/views/active_admin/resource/update.js +0 -0
- data/app/views/activeadmin_selleo_cms/pages/show.html.haml +3 -0
- data/app/views/activeadmin_selleo_cms/searches/show.html.haml +6 -0
- data/app/views/admin/pages/_fields_additional_locale.html.haml +17 -0
- data/app/views/admin/pages/_fields_current_locale.html.haml +14 -0
- data/app/views/admin/pages/_form.html.haml +65 -0
- data/app/views/admin/pages/_js.html.haml +12 -0
- data/app/views/admin/translations/update.js.haml +4 -0
- data/app/views/layouts/activeadmin_selleo_cms/application.html.erb +15 -0
- data/config/initializers/active_admin.rb +7 -0
- data/config/initializers/ckeditor.rb +18 -0
- data/config/initializers/i18n.rb +8 -0
- data/config/initializers/string_extensions.rb +5 -0
- data/config/locales/cms.en.yml +7 -0
- data/config/routes.rb +14 -0
- data/db/migrate/20121129142932_create_activeadmin_selleo_cms_pages.rb +20 -0
- data/db/migrate/20121129160200_create_activeadmin_selleo_cms_locales.rb +19 -0
- data/db/migrate/20121204112326_create_ckeditor_assets.rb +26 -0
- data/db/migrate/20121206231053_create_activeadmin_selleo_cms_sections.rb +12 -0
- data/db/migrate/20121221164723_create_activeadmin_selleo_cms_searches.rb +33 -0
- data/db/migrate/20121227222912_create_translations.rb +18 -0
- data/lib/activeadmin-selleo-cms.rb +11 -0
- data/lib/activeadmin-selleo-cms/application.rb +15 -0
- data/lib/activeadmin-selleo-cms/engine.rb +5 -0
- data/lib/activeadmin-selleo-cms/version.rb +3 -0
- data/lib/tasks/activeadmin-selleo-cms_tasks.rake +4 -0
- data/lib/tasks/i18n.rake +6 -0
- data/test/activeadmin-selleo-cms_test.rb +7 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/fixtures/activeadmin_selleo_cms/layouts.yml +11 -0
- data/test/fixtures/activeadmin_selleo_cms/page_parts.yml +11 -0
- data/test/fixtures/activeadmin_selleo_cms/pages.yml +11 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/activeadmin_selleo_cms/page_part_test.rb +9 -0
- data/test/unit/activeadmin_selleo_cms/page_test.rb +9 -0
- metadata +364 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2012 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
6
|
+
end
|
|
7
|
+
begin
|
|
8
|
+
require 'rdoc/task'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
require 'rdoc/rdoc'
|
|
11
|
+
require 'rake/rdoctask'
|
|
12
|
+
RDoc::Task = Rake::RDocTask
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
17
|
+
rdoc.title = 'ActiveadminSelleoCms'
|
|
18
|
+
rdoc.options << '--line-numbers'
|
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
|
24
|
+
load 'rails/tasks/engine.rake'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Bundler::GemHelper.install_tasks
|
|
29
|
+
|
|
30
|
+
require 'rake/testtask'
|
|
31
|
+
|
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
|
33
|
+
t.libs << 'lib'
|
|
34
|
+
t.libs << 'test'
|
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
|
36
|
+
t.verbose = false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
task :default => :test
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
ActiveAdmin.register ActiveadminSelleoCms::Locale, { as: "Locale", sort_order: 'name_asc' } do
|
|
2
|
+
config.batch_actions = false
|
|
3
|
+
|
|
4
|
+
actions :all, except: [:show, :destroy]
|
|
5
|
+
|
|
6
|
+
scope :enabled, default: true
|
|
7
|
+
scope :popular
|
|
8
|
+
scope :all
|
|
9
|
+
|
|
10
|
+
index do
|
|
11
|
+
column :name
|
|
12
|
+
column :code
|
|
13
|
+
column :enabled do |locale|
|
|
14
|
+
check_box_tag "activeadmin_selleo_cms_locale[enabled][#{locale.code}]", 1, locale.enabled, data: { route: admin_locale_path(locale), id: locale.id, resource: 'locale', attribute: 'enabled' }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
controller do
|
|
19
|
+
respond_to :html, :js
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
ActiveAdmin.register ActiveadminSelleoCms::Page, as: "Page", sort_order: "lft_asc" do
|
|
2
|
+
config.batch_actions = false
|
|
3
|
+
|
|
4
|
+
scope :all, default: true
|
|
5
|
+
|
|
6
|
+
-> {
|
|
7
|
+
ActiveadminSelleoCms::Page.roots.each do |page|
|
|
8
|
+
scope page.title do
|
|
9
|
+
ActiveadminSelleoCms::Page.where(parent_id: page.id)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
form :partial => "form"
|
|
15
|
+
|
|
16
|
+
filter :parent
|
|
17
|
+
|
|
18
|
+
index do
|
|
19
|
+
column do |page|
|
|
20
|
+
unless page.root?
|
|
21
|
+
"#{image_tag('http://placehold.it/20x15') * page.depth}".html_safe
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
column :title
|
|
25
|
+
column :show_in_menu do |page|
|
|
26
|
+
check_box_tag "activeadmin_selleo_cms_page[show_in_menu][#{page.id}]", 1, page.show_in_menu, data: { route: admin_page_path(page.id), id: page.id, resource: 'page', attribute: 'show_in_menu' }
|
|
27
|
+
end
|
|
28
|
+
column :is_published do |page|
|
|
29
|
+
check_box_tag "activeadmin_selleo_cms_page[is_published][#{page.id}]", 1, page.is_published, data: { route: admin_page_path(page.id), id: page.id, resource: 'page', attribute: 'is_published' }
|
|
30
|
+
end
|
|
31
|
+
column :created_at
|
|
32
|
+
column :updated_at
|
|
33
|
+
column :actions do |resource|
|
|
34
|
+
links ||= link_to(I18n.t('active_admin.view'), "/#{I18n.locale}/#{resource.slug}", :class => "member_link view_link", :target => "_new")
|
|
35
|
+
links << link_to(I18n.t('active_admin.edit'), edit_resource_path(resource.id), :class => "member_link edit_link")
|
|
36
|
+
links << link_to(I18n.t('active_admin.delete'), resource_path(resource.id), :method => :delete, :data => {:confirm => I18n.t('active_admin.delete_confirmation')}, :class => "member_link delete_link")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#index as: :list, download_links: false do |page|
|
|
41
|
+
# render_tree(page)
|
|
42
|
+
#end
|
|
43
|
+
|
|
44
|
+
controller do
|
|
45
|
+
respond_to :html, :js
|
|
46
|
+
|
|
47
|
+
def index
|
|
48
|
+
index! {
|
|
49
|
+
#@pages = @pages.where(parent_id: nil)
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def create
|
|
54
|
+
create! do |success, failure|
|
|
55
|
+
success.html { redirect_to admin_pages_path }
|
|
56
|
+
failure.html { render action: :new }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def update
|
|
61
|
+
update! do |success, failure|
|
|
62
|
+
success.html { redirect_to admin_pages_path }
|
|
63
|
+
failure.html { render action: :edit }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
ActiveAdmin.register Translation do
|
|
2
|
+
config.batch_actions = false
|
|
3
|
+
|
|
4
|
+
actions :index
|
|
5
|
+
|
|
6
|
+
scope :cms, default: true
|
|
7
|
+
scope :active_admin
|
|
8
|
+
scope :all
|
|
9
|
+
|
|
10
|
+
index do
|
|
11
|
+
column :key
|
|
12
|
+
-> { ActiveadminSelleoCms::Locale.enabled }.call.each do |locale|
|
|
13
|
+
column locale.name do |translation|
|
|
14
|
+
content_tag :div, class: "translation" do
|
|
15
|
+
text_field_tag "#{locale.code}[#{translation.key}]", translation.send(locale.code), data: { locale: locale.code, key: translation.key, route: admin_translations_path }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
filter :key
|
|
22
|
+
filter :value
|
|
23
|
+
|
|
24
|
+
collection_action :update, method: :put do
|
|
25
|
+
unless @translation = Translation.where(key: params[:key], locale: params[:locale]).first
|
|
26
|
+
@translation = Translation.create({key: params[:key], locale: params[:locale]}, as: :admin)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
controller do
|
|
31
|
+
def collection
|
|
32
|
+
(get_collection_ivar || set_collection_ivar(active_admin_collection)).reorder(:key).select("DISTINCT(key)")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// the compiled file.
|
|
9
|
+
//
|
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
|
12
|
+
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require_tree .
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
var slug = function(str) {
|
|
2
|
+
str = str.replace(/^\s+|\s+$/g, ''); // trim
|
|
3
|
+
str = str.toLowerCase();
|
|
4
|
+
|
|
5
|
+
// remove accents, swap ñ for n, etc
|
|
6
|
+
var from = "ąãàáäâęẽèéëêìíïîõòóöôùúüûńñçćżźśł·/_,:;";
|
|
7
|
+
var to = "aaaaaaeeeeeeiiiiooooouuuunncczzsl------";
|
|
8
|
+
for (var i=0, l=from.length ; i<l ; i++) {
|
|
9
|
+
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
|
13
|
+
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
|
14
|
+
.replace(/-+/g, '-'); // collapse dashes
|
|
15
|
+
|
|
16
|
+
return str;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
$(function(){
|
|
20
|
+
$('#translations.index input').blur(function(evt){
|
|
21
|
+
$.ajax({
|
|
22
|
+
url: $(evt.target).data('route') + '.js',
|
|
23
|
+
type: 'PUT',
|
|
24
|
+
data: { 'value': $(evt.target).attr('value'), 'locale': $(evt.target).data('locale'), 'key': $(evt.target).data('key') }
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
$('input[type="checkbox"][data-route]').change(function(){
|
|
29
|
+
_data = {}
|
|
30
|
+
_data[$(this).data('resource')] = {};
|
|
31
|
+
_data[$(this).data('resource')][$(this).data('attribute')] = $(this).is(':checked');
|
|
32
|
+
|
|
33
|
+
that = this;
|
|
34
|
+
|
|
35
|
+
$.ajax({
|
|
36
|
+
url: $(this).data('route') + '.js',
|
|
37
|
+
type: 'PUT',
|
|
38
|
+
data: _data
|
|
39
|
+
}).success(function(){
|
|
40
|
+
$(that).closest('td').effect('highlight');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
});
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* jQuery UI Nested Sortable
|
|
3
|
+
* v 1.3.5 / 21 jun 2012
|
|
4
|
+
* http://mjsarfatti.com/code/nestedSortable
|
|
5
|
+
*
|
|
6
|
+
* Depends on:
|
|
7
|
+
* jquery.ui.sortable.js 1.8+
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2010-2012 Manuele J Sarfatti
|
|
10
|
+
* Licensed under the MIT License
|
|
11
|
+
* http://www.opensource.org/licenses/mit-license.php
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
(function($) {
|
|
15
|
+
|
|
16
|
+
$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
|
|
17
|
+
|
|
18
|
+
options: {
|
|
19
|
+
tabSize: 20,
|
|
20
|
+
disableNesting: 'mjs-nestedSortable-no-nesting',
|
|
21
|
+
errorClass: 'mjs-nestedSortable-error',
|
|
22
|
+
doNotClear: false,
|
|
23
|
+
listType: 'ol',
|
|
24
|
+
maxLevels: 0,
|
|
25
|
+
protectRoot: false,
|
|
26
|
+
rootID: null,
|
|
27
|
+
rtl: false,
|
|
28
|
+
isAllowed: function(item, parent) { return true; }
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
_create: function() {
|
|
32
|
+
this.element.data('sortable', this.element.data('nestedSortable'));
|
|
33
|
+
|
|
34
|
+
if (!this.element.is(this.options.listType))
|
|
35
|
+
throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
|
|
36
|
+
|
|
37
|
+
return $.ui.sortable.prototype._create.apply(this, arguments);
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
destroy: function() {
|
|
41
|
+
this.element
|
|
42
|
+
.removeData("nestedSortable")
|
|
43
|
+
.unbind(".nestedSortable");
|
|
44
|
+
return $.ui.sortable.prototype.destroy.apply(this, arguments);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
_mouseDrag: function(event) {
|
|
48
|
+
|
|
49
|
+
//Compute the helpers position
|
|
50
|
+
this.position = this._generatePosition(event);
|
|
51
|
+
this.positionAbs = this._convertPositionTo("absolute");
|
|
52
|
+
|
|
53
|
+
if (!this.lastPositionAbs) {
|
|
54
|
+
this.lastPositionAbs = this.positionAbs;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var o = this.options;
|
|
58
|
+
|
|
59
|
+
//Do scrolling
|
|
60
|
+
if(this.options.scroll) {
|
|
61
|
+
var scrolled = false;
|
|
62
|
+
if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
|
|
63
|
+
|
|
64
|
+
if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
|
|
65
|
+
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
|
|
66
|
+
else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
|
|
67
|
+
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
|
|
68
|
+
|
|
69
|
+
if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
|
|
70
|
+
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
|
|
71
|
+
else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
|
|
72
|
+
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
|
|
73
|
+
|
|
74
|
+
} else {
|
|
75
|
+
|
|
76
|
+
if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
|
|
77
|
+
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
|
|
78
|
+
else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
|
|
79
|
+
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
|
|
80
|
+
|
|
81
|
+
if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
|
|
82
|
+
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
|
|
83
|
+
else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
|
|
84
|
+
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
|
|
89
|
+
$.ui.ddmanager.prepareOffsets(this, event);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//Regenerate the absolute position used for position checks
|
|
93
|
+
this.positionAbs = this._convertPositionTo("absolute");
|
|
94
|
+
|
|
95
|
+
// Find the top offset before rearrangement,
|
|
96
|
+
var previousTopOffset = this.placeholder.offset().top;
|
|
97
|
+
|
|
98
|
+
//Set the helper position
|
|
99
|
+
if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
|
|
100
|
+
if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
|
|
101
|
+
|
|
102
|
+
//Rearrange
|
|
103
|
+
for (var i = this.items.length - 1; i >= 0; i--) {
|
|
104
|
+
|
|
105
|
+
//Cache variables and intersection, continue if no intersection
|
|
106
|
+
var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
|
|
107
|
+
if (!intersection) continue;
|
|
108
|
+
|
|
109
|
+
if(itemElement != this.currentItem[0] //cannot intersect with itself
|
|
110
|
+
&& this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
|
|
111
|
+
&& !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
|
|
112
|
+
&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
|
|
113
|
+
//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
|
|
114
|
+
) {
|
|
115
|
+
|
|
116
|
+
$(itemElement).mouseenter();
|
|
117
|
+
|
|
118
|
+
this.direction = intersection == 1 ? "down" : "up";
|
|
119
|
+
|
|
120
|
+
if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
|
|
121
|
+
$(itemElement).mouseleave();
|
|
122
|
+
this._rearrange(event, item);
|
|
123
|
+
} else {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Clear emtpy ul's/ol's
|
|
128
|
+
this._clearEmpty(itemElement);
|
|
129
|
+
|
|
130
|
+
this._trigger("change", event, this._uiHash());
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
var parentItem = (this.placeholder[0].parentNode.parentNode &&
|
|
136
|
+
$(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
|
|
137
|
+
? $(this.placeholder[0].parentNode.parentNode)
|
|
138
|
+
: null,
|
|
139
|
+
level = this._getLevel(this.placeholder),
|
|
140
|
+
childLevels = this._getChildLevels(this.helper);
|
|
141
|
+
|
|
142
|
+
// To find the previous sibling in the list, keep backtracking until we hit a valid list item.
|
|
143
|
+
var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
|
|
144
|
+
if (previousItem != null) {
|
|
145
|
+
while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
|
|
146
|
+
if (previousItem[0].previousSibling) {
|
|
147
|
+
previousItem = $(previousItem[0].previousSibling);
|
|
148
|
+
} else {
|
|
149
|
+
previousItem = null;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// To find the next sibling in the list, keep stepping forward until we hit a valid list item.
|
|
156
|
+
var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
|
|
157
|
+
if (nextItem != null) {
|
|
158
|
+
while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
|
|
159
|
+
if (nextItem[0].nextSibling) {
|
|
160
|
+
nextItem = $(nextItem[0].nextSibling);
|
|
161
|
+
} else {
|
|
162
|
+
nextItem = null;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
var newList = document.createElement(o.listType);
|
|
169
|
+
|
|
170
|
+
this.beyondMaxLevels = 0;
|
|
171
|
+
|
|
172
|
+
// If the item is moved to the left, send it to its parent's level unless there are siblings below it.
|
|
173
|
+
if (parentItem != null && nextItem == null &&
|
|
174
|
+
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
|
|
175
|
+
!o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
|
|
176
|
+
parentItem.after(this.placeholder[0]);
|
|
177
|
+
this._clearEmpty(parentItem[0]);
|
|
178
|
+
this._trigger("change", event, this._uiHash());
|
|
179
|
+
}
|
|
180
|
+
// If the item is below a sibling and is moved to the right, make it a child of that sibling.
|
|
181
|
+
else if (previousItem != null &&
|
|
182
|
+
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
|
|
183
|
+
!o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
|
|
184
|
+
this._isAllowed(previousItem, level, level+childLevels+1);
|
|
185
|
+
if (!previousItem.children(o.listType).length) {
|
|
186
|
+
previousItem[0].appendChild(newList);
|
|
187
|
+
}
|
|
188
|
+
// If this item is being moved from the top, add it to the top of the list.
|
|
189
|
+
if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
|
|
190
|
+
previousItem.children(o.listType).prepend(this.placeholder);
|
|
191
|
+
}
|
|
192
|
+
// Otherwise, add it to the bottom of the list.
|
|
193
|
+
else {
|
|
194
|
+
previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
|
|
195
|
+
}
|
|
196
|
+
this._trigger("change", event, this._uiHash());
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this._isAllowed(parentItem, level, level+childLevels);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//Post events to containers
|
|
203
|
+
this._contactContainers(event);
|
|
204
|
+
|
|
205
|
+
//Interconnect with droppables
|
|
206
|
+
if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
|
|
207
|
+
|
|
208
|
+
//Call callbacks
|
|
209
|
+
this._trigger('sort', event, this._uiHash());
|
|
210
|
+
|
|
211
|
+
this.lastPositionAbs = this.positionAbs;
|
|
212
|
+
return false;
|
|
213
|
+
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
_mouseStop: function(event, noPropagation) {
|
|
217
|
+
|
|
218
|
+
// If the item is in a position not allowed, send it back
|
|
219
|
+
if (this.beyondMaxLevels) {
|
|
220
|
+
|
|
221
|
+
this.placeholder.removeClass(this.options.errorClass);
|
|
222
|
+
|
|
223
|
+
if (this.domPosition.prev) {
|
|
224
|
+
$(this.domPosition.prev).after(this.placeholder);
|
|
225
|
+
} else {
|
|
226
|
+
$(this.domPosition.parent).prepend(this.placeholder);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
this._trigger("revert", event, this._uiHash());
|
|
230
|
+
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Clean last empty ul/ol
|
|
234
|
+
for (var i = this.items.length - 1; i >= 0; i--) {
|
|
235
|
+
var item = this.items[i].item[0];
|
|
236
|
+
this._clearEmpty(item);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
$.ui.sortable.prototype._mouseStop.apply(this, arguments);
|
|
240
|
+
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
serialize: function(options) {
|
|
244
|
+
|
|
245
|
+
var o = $.extend({}, this.options, options),
|
|
246
|
+
items = this._getItemsAsjQuery(o && o.connected),
|
|
247
|
+
str = [];
|
|
248
|
+
|
|
249
|
+
$(items).each(function() {
|
|
250
|
+
var res = ($(o.item || this).attr(o.attribute || 'id') || '')
|
|
251
|
+
.match(o.expression || (/(.+)[-=_](.+)/)),
|
|
252
|
+
pid = ($(o.item || this).parent(o.listType)
|
|
253
|
+
.parent(o.items)
|
|
254
|
+
.attr(o.attribute || 'id') || '')
|
|
255
|
+
.match(o.expression || (/(.+)[-=_](.+)/));
|
|
256
|
+
|
|
257
|
+
if (res) {
|
|
258
|
+
str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
|
|
259
|
+
+ '='
|
|
260
|
+
+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
if(!str.length && o.key) {
|
|
265
|
+
str.push(o.key + '=');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return str.join('&');
|
|
269
|
+
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
toHierarchy: function(options) {
|
|
273
|
+
|
|
274
|
+
var o = $.extend({}, this.options, options),
|
|
275
|
+
sDepth = o.startDepthCount || 0,
|
|
276
|
+
ret = [];
|
|
277
|
+
|
|
278
|
+
$(this.element).children(o.items).each(function () {
|
|
279
|
+
var level = _recursiveItems(this);
|
|
280
|
+
ret.push(level);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return ret;
|
|
284
|
+
|
|
285
|
+
function _recursiveItems(item) {
|
|
286
|
+
var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
|
|
287
|
+
if (id) {
|
|
288
|
+
var currentItem = {"id" : id[2]};
|
|
289
|
+
if ($(item).children(o.listType).children(o.items).length > 0) {
|
|
290
|
+
currentItem.children = [];
|
|
291
|
+
$(item).children(o.listType).children(o.items).each(function() {
|
|
292
|
+
var level = _recursiveItems(this);
|
|
293
|
+
currentItem.children.push(level);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
return currentItem;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
toArray: function(options) {
|
|
302
|
+
|
|
303
|
+
var o = $.extend({}, this.options, options),
|
|
304
|
+
sDepth = o.startDepthCount || 0,
|
|
305
|
+
ret = [],
|
|
306
|
+
left = 2;
|
|
307
|
+
|
|
308
|
+
ret.push({
|
|
309
|
+
"item_id": o.rootID,
|
|
310
|
+
"parent_id": 'none',
|
|
311
|
+
"depth": sDepth,
|
|
312
|
+
"left": '1',
|
|
313
|
+
"right": ($(o.items, this.element).length + 1) * 2
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
$(this.element).children(o.items).each(function () {
|
|
317
|
+
left = _recursiveArray(this, sDepth + 1, left);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
ret = ret.sort(function(a,b){ return (a.left - b.left); });
|
|
321
|
+
|
|
322
|
+
return ret;
|
|
323
|
+
|
|
324
|
+
function _recursiveArray(item, depth, left) {
|
|
325
|
+
|
|
326
|
+
var right = left + 1,
|
|
327
|
+
id,
|
|
328
|
+
pid;
|
|
329
|
+
|
|
330
|
+
if ($(item).children(o.listType).children(o.items).length > 0) {
|
|
331
|
+
depth ++;
|
|
332
|
+
$(item).children(o.listType).children(o.items).each(function () {
|
|
333
|
+
right = _recursiveArray($(this), depth, right);
|
|
334
|
+
});
|
|
335
|
+
depth --;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
|
|
339
|
+
|
|
340
|
+
if (depth === sDepth + 1) {
|
|
341
|
+
pid = o.rootID;
|
|
342
|
+
} else {
|
|
343
|
+
var parentItem = ($(item).parent(o.listType)
|
|
344
|
+
.parent(o.items)
|
|
345
|
+
.attr(o.attribute || 'id'))
|
|
346
|
+
.match(o.expression || (/(.+)[-=_](.+)/));
|
|
347
|
+
pid = parentItem[2];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (id) {
|
|
351
|
+
ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
left = right + 1;
|
|
355
|
+
return left;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
},
|
|
359
|
+
|
|
360
|
+
_clearEmpty: function(item) {
|
|
361
|
+
|
|
362
|
+
var emptyList = $(item).children(this.options.listType);
|
|
363
|
+
if (emptyList.length && !emptyList.children().length && !this.options.doNotClear) {
|
|
364
|
+
emptyList.remove();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
_getLevel: function(item) {
|
|
370
|
+
|
|
371
|
+
var level = 1;
|
|
372
|
+
|
|
373
|
+
if (this.options.listType) {
|
|
374
|
+
var list = item.closest(this.options.listType);
|
|
375
|
+
while (list && list.length > 0 &&
|
|
376
|
+
!list.is('.ui-sortable')) {
|
|
377
|
+
level++;
|
|
378
|
+
list = list.parent().closest(this.options.listType);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return level;
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
_getChildLevels: function(parent, depth) {
|
|
386
|
+
var self = this,
|
|
387
|
+
o = this.options,
|
|
388
|
+
result = 0;
|
|
389
|
+
depth = depth || 0;
|
|
390
|
+
|
|
391
|
+
$(parent).children(o.listType).children(o.items).each(function (index, child) {
|
|
392
|
+
result = Math.max(self._getChildLevels(child, depth + 1), result);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return depth ? result + 1 : result;
|
|
396
|
+
},
|
|
397
|
+
|
|
398
|
+
_isAllowed: function(parentItem, level, levels) {
|
|
399
|
+
var o = this.options,
|
|
400
|
+
isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
|
|
401
|
+
maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
|
|
402
|
+
|
|
403
|
+
// Is the root protected?
|
|
404
|
+
// Are we trying to nest under a no-nest?
|
|
405
|
+
// Are we nesting too deep?
|
|
406
|
+
if (!o.isAllowed(this.currentItem, parentItem) ||
|
|
407
|
+
parentItem && parentItem.hasClass(o.disableNesting) ||
|
|
408
|
+
o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
|
|
409
|
+
this.placeholder.addClass(o.errorClass);
|
|
410
|
+
if (maxLevels < levels && maxLevels != 0) {
|
|
411
|
+
this.beyondMaxLevels = levels - maxLevels;
|
|
412
|
+
} else {
|
|
413
|
+
this.beyondMaxLevels = 1;
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
if (maxLevels < levels && maxLevels != 0) {
|
|
417
|
+
this.placeholder.addClass(o.errorClass);
|
|
418
|
+
this.beyondMaxLevels = levels - maxLevels;
|
|
419
|
+
} else {
|
|
420
|
+
this.placeholder.removeClass(o.errorClass);
|
|
421
|
+
this.beyondMaxLevels = 0;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
}));
|
|
427
|
+
|
|
428
|
+
$.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
|
|
429
|
+
})(jQuery);
|