Gallery – Photo Gallery and Images Gallery - Version 2.7.1

Version Description

  • New advanced gallery categories sorting section
Download this release

Release Info

Developer robosoft
Plugin Icon 128x128 Gallery – Photo Gallery and Images Gallery
Version 2.7.1
Comparing to
See all releases

Code changes from version 2.7.0 to 2.7.1

includes/extensions/categoryPage/category.class.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  * Robo Gallery
4
- * Version: 1.0
5
  * By Robosoft
6
  *
7
  * Contact: https://robosoft.co/robogallery/
@@ -18,134 +18,120 @@ class ROBO_GALLERY_CATEGORY_PAGE{
18
 
19
  protected $postType;
20
 
21
- protected $postTypeParams;
22
-
23
  protected $assetsUri;
24
 
25
  protected $currentPostOrder;
26
 
27
- public function __construct($postType){ //, array $postTypeParams
28
 
29
  $this->postType = $postType;
30
- $this->postTypeParams = array();
31
- //$this->postTypeParams = $postTypeParams;
32
- $this->assetsUri = plugin_dir_url(__FILE__);
33
-
34
 
35
- $this->enqueueScripts();
36
- // add_action("wp_ajax_hierarchy_{$this->postType}_meta_box", array($this, 'ajaxMetaBoxAttributes'));
37
 
38
- //add_action("wp_ajax_hierarchy_{$this->postType}_dialog", array($this, 'ajaxDialog'));
39
 
40
- $this->ajaxDialog ();
 
41
 
42
- add_action("wp_ajax_hierarchy_{$this->postType}_dialog_save", array($this, 'ajaxDialogSave'));
43
-
 
44
  }
45
 
 
 
 
46
 
 
 
 
47
 
48
 
49
  public function enqueueScripts(){
50
- wp_enqueue_style('wp-jquery-ui-dialog');
 
 
 
 
 
51
  wp_enqueue_style(
52
  'hierarchy-post-attributes-style',
53
  $this->assetsUri . 'css/style.css',
54
- array('wp-jquery-ui-dialog')
55
  );
 
56
 
57
  wp_enqueue_script('jquery-ui-dialog');
 
58
  wp_enqueue_script(
59
  'hierarchy-post-attributes-nestable-js',
60
  $this->assetsUri . 'js/jquery.nestable.js',
61
- array('jquery-ui-dialog'),
62
  false,
63
  true
64
  );
65
  wp_enqueue_script(
66
  'hierarchy-post-attributes-js',
67
  $this->assetsUri . 'js/script.js',
68
- array('jquery-ui-dialog', 'hierarchy-post-attributes-nestable-js'),
69
  false,
70
  true
71
  );
72
 
73
  $postTypeObject = get_post_type_object($this->postType);
 
74
  wp_localize_script(
75
  'hierarchy-post-attributes-js',
76
  'hierarchyPostAttributes',
77
  array(
78
  'ajaxUrl' => admin_url('admin-ajax.php'),
79
- 'metaBox' => array(
80
- 'action' => array(
81
- 'get' => "hierarchy_{$this->postType}_meta_box"
82
- )
83
- ),
84
- 'dialog' => array(
85
- 'title' => __(sprintf('Edit hierarchy of %s', $postTypeObject->labels->name)),
86
- 'button' => array(
87
- 'save' => array(
88
- 'label' => __('Save')
89
- ),
90
- 'cancel' => array(
91
- 'label' => __('Cancel')
92
- )
93
- ),
94
- 'action' => array(
95
- 'get' => "hierarchy_{$this->postType}_dialog",
96
- 'save' => "hierarchy_{$this->postType}_dialog_save",
97
- ),
98
  ),
99
- 'error' => array(
100
- 'title' => __('Error'),
101
- 'button' => array(
102
- 'ok' => array(
103
- 'label' => __('OK')
104
- ),
105
- )
106
  )
107
  )
108
  );
109
  }
110
 
111
 
112
-
113
-
114
-
115
 
116
  public function ajaxDialog() {
117
  $this->checkPermission();
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
- $postTree = $this->getPostTree(ROBO_GALLERY_TYPE_POST);
120
- ?>
121
- <p>
122
- <button class="save_category button button-primary"> Save</button>
123
- </p>
124
- <div class="wrapper-nestable-list" >
125
- <div class="nestable-list dd">
126
- <?php $this->theNestableList($postTree); ?>
127
- </div>
128
- <div class="nestable-list-spinner">
129
- <img src="<?php echo admin_url('/images/spinner-2x.gif') ?>" />
130
- </div>
131
- </div>
132
- <button class="save_category button button-primary"> Save</button>
133
- <?php
134
-
135
- //wp_die();
136
  }
137
 
 
138
  public function ajaxDialogSave() {
139
  $this->checkPermission();
140
 
141
  if (!isset($_POST['hierarchy_posts'])) {
142
  header('HTTP/1.0 403 Forbidden');
143
- echo 'Empty posts hierarchy data for saving';
144
  die();
145
  }
146
  if (!is_array($_POST['hierarchy_posts'])) {
147
  header('HTTP/1.0 403 Forbidden');
148
- echo 'Wrong posts hierarchy data for saving';
149
  die();
150
  }
151
 
@@ -200,22 +186,20 @@ class ROBO_GALLERY_CATEGORY_PAGE{
200
 
201
 
202
  protected function theNestableList(array $tree){
203
- ?>
204
- <ol class="dd-list">
205
- <?php foreach ($tree as $item) : ?>
206
- <li class="dd-item" data-id="<?php echo $item['post']->ID; ?>">
207
- <div class="dd-handle">
208
- <?php
209
- $title = esc_attr($item['post']->post_title);
210
- echo "{$title} [{$item['post']->ID}: {$item['post']->post_name}]" ; ?>
211
- </div>
212
- <?php if (!empty($item['children'])) : ?>
213
- <?php $this->theNestableList($item['children']); ?>
214
- <?php endif; ?>
215
- </li>
216
- <?php endforeach; ?>
217
- </ol>
218
- <?php
219
  }
220
 
221
 
1
  <?php
2
  /*
3
  * Robo Gallery
4
+ * Version: 2.7.0
5
  * By Robosoft
6
  *
7
  * Contact: https://robosoft.co/robogallery/
18
 
19
  protected $postType;
20
 
 
 
21
  protected $assetsUri;
22
 
23
  protected $currentPostOrder;
24
 
25
+ public function __construct($postType){
26
 
27
  $this->postType = $postType;
 
 
 
 
28
 
29
+ $this->assetsUri = plugin_dir_url(__FILE__);
 
30
 
31
+ add_action("wp_ajax_hierarchy_{$this->postType}_page_save", array($this, 'ajaxDialogSave'));
32
 
33
+ add_action( 'init', array($this, 'initMenu') );
34
+ }
35
 
36
+ public function showSorting(){
37
+ $this->enqueueScripts();
38
+ $this->ajaxDialog();
39
  }
40
 
41
+ public function addMenuItem(){
42
+ add_submenu_page( 'edit.php?post_type=robo_gallery_table', 'Robo Gallery Sorting', 'Sorting', 'manage_options', 'robo-gallery-category-page', array($this, 'showSorting' ) );
43
+ }
44
 
45
+ public function initMenu(){
46
+ add_action('admin_menu', array($this, 'addMenuItem'), 10);
47
+ }
48
 
49
 
50
  public function enqueueScripts(){
51
+ $screen = get_current_screen();
52
+
53
+ if ($this->postType !== $screen->post_type) {
54
+ return;
55
+ }
56
+
57
  wp_enqueue_style(
58
  'hierarchy-post-attributes-style',
59
  $this->assetsUri . 'css/style.css',
60
+ array()
61
  );
62
+ wp_enqueue_style('wp-jquery-ui-dialog');
63
 
64
  wp_enqueue_script('jquery-ui-dialog');
65
+
66
  wp_enqueue_script(
67
  'hierarchy-post-attributes-nestable-js',
68
  $this->assetsUri . 'js/jquery.nestable.js',
69
+ array(),
70
  false,
71
  true
72
  );
73
  wp_enqueue_script(
74
  'hierarchy-post-attributes-js',
75
  $this->assetsUri . 'js/script.js',
76
+ array('hierarchy-post-attributes-nestable-js'),
77
  false,
78
  true
79
  );
80
 
81
  $postTypeObject = get_post_type_object($this->postType);
82
+
83
  wp_localize_script(
84
  'hierarchy-post-attributes-js',
85
  'hierarchyPostAttributes',
86
  array(
87
  'ajaxUrl' => admin_url('admin-ajax.php'),
88
+
89
+ 'action' => array(
90
+ 'save' => "hierarchy_{$this->postType}_page_save",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  ),
92
+
93
+ 'status' => array(
94
+ 'saved' => __('Saved', 'robo-gallery'),
95
+ 'modified' => __('Modified', 'robo-gallery'),
96
+ 'saving' => __('Saving', 'robo-gallery'),
97
+ 'error' => __('Error', 'robo-gallery'),
98
+ 'ok' => __('OK', 'robo-gallery'),
99
  )
100
  )
101
  );
102
  }
103
 
104
 
 
 
 
105
 
106
  public function ajaxDialog() {
107
  $this->checkPermission();
108
+ $postTree = $this->getPostTree( $this->postType);
109
+ echo '<div class="wrap">';
110
+ echo '<h1>'.__('Robo Gallery Sorting', 'robo-gallery').
111
+ '<span id="gallery_label_status" class="title-count theme-count">'.__('No changes', 'robo-gallery').'</span>'
112
+ .'</h1> ';
113
+ echo '<div id="wrapper-nestable-list">';
114
+ echo '<button class="buttonSave button button-primary">Save</button> <br/> <br/>';
115
+ echo '<div class="nestable-list dd"> '.$this->theNestableList($postTree).' </div> ';
116
+ echo '<div class="nestable-list-spinner"> <img src="'.admin_url('/images/spinner-2x.gif').'" /> </div> ';
117
+ echo '<br/> <button class="buttonSave button button-primary">Save</button>';
118
+ echo '</div>';
119
+ echo '</div>';
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
+
124
  public function ajaxDialogSave() {
125
  $this->checkPermission();
126
 
127
  if (!isset($_POST['hierarchy_posts'])) {
128
  header('HTTP/1.0 403 Forbidden');
129
+ echo 'Error #100 Please post ticket with this Error ID into support section.';
130
  die();
131
  }
132
  if (!is_array($_POST['hierarchy_posts'])) {
133
  header('HTTP/1.0 403 Forbidden');
134
+ echo 'Error #101 Please post ticket with this Error ID into support section.';
135
  die();
136
  }
137
 
186
 
187
 
188
  protected function theNestableList(array $tree){
189
+ $returnHtml = '<ol class="dd-list">';
190
+ foreach ($tree as $item):
191
+ $returnHtml .= '<li class="dd-item" data-id="'.$item['post']->ID.'">';
192
+ $returnHtml .= '<div class="dd-handle">';
193
+ $title = esc_attr($item['post']->post_title);
194
+ $returnHtml .= "{$title} [{$item['post']->ID}: {$item['post']->post_name}]" ;
195
+ $returnHtml .= '</div>';
196
+ if (!empty($item['children'])):
197
+ $returnHtml .= $this->theNestableList($item['children']);
198
+ endif;
199
+ $returnHtml .= '</li>';
200
+ endforeach;
201
+ $returnHtml .= '</ol>';
202
+ return $returnHtml ;
 
 
203
  }
204
 
205
 
includes/extensions/categoryPage/category.init.php CHANGED
@@ -14,10 +14,13 @@
14
 
15
  if ( ! defined( 'ABSPATH' ) ) exit;
16
 
17
- /*if(!function_exists('rbs_gallery_category_init')){
18
- function rbs_gallery_category_init(){*/
19
- rbs_gallery_include('category.class.php', plugin_dir_path( __FILE__ ) );
20
- new ROBO_GALLERY_CATEGORY_PAGE( ROBO_GALLERY_TYPE_POST );
21
- /* }
 
 
22
  add_action( 'init', 'rbs_gallery_category_init' );
23
- }*/
 
14
 
15
  if ( ! defined( 'ABSPATH' ) ) exit;
16
 
17
+ rbs_gallery_include('category.class.php', plugin_dir_path( __FILE__ ) );
18
+ new ROBO_GALLERY_CATEGORY_PAGE( ROBO_GALLERY_TYPE_POST );
19
+
20
+ if(!function_exists('rbs_gallery_category_init')){
21
+ function rbs_gallery_category_init(){
22
+
23
+ }
24
  add_action( 'init', 'rbs_gallery_category_init' );
25
+ }
26
+
includes/extensions/categoryPage/css/style.css CHANGED
@@ -1,142 +1,120 @@
1
- .nestable-list.dd,
2
- .nestable-list .dd {
3
- position: relative;
4
- display: block;
5
- margin: 0;
6
- padding: 0;
7
- list-style: none;
8
- font-size: 13px;
9
- line-height: 20px;
10
- }
11
-
12
- .nestable-list .dd-list {
13
- display: block;
14
- position: relative;
15
- margin: 0;
16
- padding: 0;
17
- list-style: none;
18
- }
19
-
20
- .nestable-list .dd-list .dd-list {
21
- padding-left: 30px;
22
- }
23
-
24
- .nestable-list .dd-collapsed .dd-list {
25
- display: none;
26
- }
27
-
28
- .nestable-list .dd-item,
29
- .nestable-list .dd-empty,
30
- .nestable-list .dd-placeholder {
31
- display: block;
32
- position: relative;
33
- margin: 0;
34
- padding: 0;
35
- min-height: 20px;
36
- font-size: 13px;
37
- line-height: 20px;
38
- }
39
-
40
- .nestable-list .dd-handle {
41
- display: block;
42
- height: 30px;
43
- margin: 5px 0;
44
- padding: 5px 10px;
45
- color: #333;
46
- text-decoration: none;
47
- font-weight: bold;
48
- border: 1px solid #ccc;
49
- background: #fafafa;
50
- background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
51
- background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
52
- background: linear-gradient(top, #fafafa 0%, #eee 100%);
53
- -webkit-border-radius: 3px;
54
- border-radius: 3px;
55
- box-sizing: border-box;
56
- -moz-box-sizing: border-box;
57
- }
58
-
59
- .nestable-list .dd-handle:hover {
60
  color: #2ea8e5;
61
- background: #fff;
62
- }
63
-
64
- .nestable-list .dd-item > button {
65
- display: block;
66
- position: relative;
67
- cursor: pointer;
68
- float: left;
69
- width: 25px;
70
- height: 20px;
71
- margin: 5px 0;
72
- padding: 0;
73
- text-indent: 100%;
74
- white-space: nowrap;
75
- overflow: hidden;
76
- border: 0;
77
- background: transparent;
78
- font-size: 12px;
79
- line-height: 1;
80
- text-align: center;
81
- font-weight: bold;
82
- }
83
-
84
- .nestable-list .dd-item > button:before {
85
- content: '+';
86
  display: block;
87
  position: absolute;
88
  width: 100%;
89
  text-align: center;
90
- text-indent: 0;
91
- }
92
-
93
- .nestable-list .dd-item > button[data-action="collapse"]:before {
94
- content: '-';
95
- }
96
-
97
- .nestable-list .dd-placeholder,
98
- .nestable-list .dd-empty {
99
- margin: 5px 0;
100
- padding: 0;
101
- min-height: 30px;
102
- background: #f2fbff;
103
- border: 1px dashed #b6bcbf;
104
- box-sizing: border-box;
105
- -moz-box-sizing: border-box;
106
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
- .nestable-list .dd-empty {
109
- border: 1px dashed #bbb;
110
- min-height: 100px;
111
- background-color: #e5e5e5;
112
- background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
113
- -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
114
- background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
115
- -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
116
- background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
117
- linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
118
- background-size: 60px 60px;
119
- background-position: 0 0, 30px 30px;
120
- }
121
-
122
- .nestable-list .dd-dragel {
123
- position: absolute;
124
- pointer-events: none;
125
- z-index: 9999;
126
- }
127
-
128
- .nestable-list .dd-dragel > .dd-item .dd-handle {
129
- margin-top: 0;
130
- }
131
-
132
- .nestable-list .dd-dragel .dd-handle {
133
- -webkit-box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, .1);
134
- box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, .1);
135
- }
136
 
137
  /* EXTRA STYLE */
138
- #hierarchy-post-attributes-metabox .actions {
139
- text-align: right;
 
140
  }
141
 
142
  .wrapper-nestable-list {
@@ -146,16 +124,9 @@
146
  }
147
  .nestable-list-spinner {
148
  display: none;
149
- position: absolute;
150
- top: 0;
151
- left: 0;
152
- width: 100%;
153
- height: 100%;
154
- background: rgba(255, 255, 255, 0.5);
155
- }
156
- .nestable-list-spinner img {
157
- position: absolute;
158
- top: 50%;
159
- left: 50%;
160
- margin: -20px 0 0 -20px;
161
  }
 
 
 
 
 
1
+ html .dd {
2
+ position: relative;
3
+ display: block;
4
+ margin: 0;
5
+ padding: 0;
6
+ list-style: none;
7
+ font-size: 13px;
8
+ line-height: 20px; }
9
+
10
+ html .dd-list {
11
+ display: block;
12
+ position: relative;
13
+ margin: 0;
14
+ padding: 0;
15
+ list-style: none; }
16
+ html .dd-list .dd-list{
17
+ padding-left: 30px; }
18
+
19
+ html .dd-item,
20
+ html .dd-empty,
21
+ html .dd-placeholder {
22
+ display: block;
23
+ position: relative;
24
+ margin: 0;
25
+ padding: 0;
26
+ min-height: 20px;
27
+ font-size: 13px;
28
+ line-height: 20px; }
29
+
30
+ html .dd-handle {
31
+ display: block;
32
+ height: 30px;
33
+ margin: 5px 0;
34
+ padding: 5px 10px;
35
+ color: #333;
36
+ text-decoration: none;
37
+ font-weight: bold;
38
+ border: 1px solid #ccc;
39
+ background: #fafafa;
40
+ border-radius: 3px;
41
+ box-sizing: border-box; }
42
+ html .dd-handle:hover {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  color: #2ea8e5;
44
+ background: #fff; }
45
+
46
+ html .dd-item > button {
47
+ position: relative;
48
+ cursor: pointer;
49
+ float: left;
50
+ width: 25px;
51
+ height: 20px;
52
+ margin: 5px 0;
53
+ padding: 0;
54
+ text-indent: 100%;
55
+ white-space: nowrap;
56
+ overflow: hidden;
57
+ border: 0;
58
+ background: transparent;
59
+ font-size: 12px;
60
+ line-height: 1;
61
+ text-align: center;
62
+ font-weight: bold; }
63
+ html .dd-item > button:before {
 
 
 
 
 
64
  display: block;
65
  position: absolute;
66
  width: 100%;
67
  text-align: center;
68
+ text-indent: 0; }
69
+ html .dd-item > button.dd-expand:before {
70
+ content: '+'; }
71
+ html .dd-item > button.dd-collapse:before {
72
+ content: '-'; }
73
+
74
+ html .dd-expand {
75
+ display: none; }
76
+
77
+ html .dd-collapsed .dd-list,
78
+ html .dd-collapsed .dd-collapse {
79
+ display: none; }
80
+
81
+ html .dd-collapsed .dd-expand {
82
+ display: block; }
83
+
84
+ html .dd-empty,
85
+ html .dd-placeholder {
86
+ margin: 5px 0;
87
+ padding: 0;
88
+ min-height: 30px;
89
+ background: #f2fbff;
90
+ border: 1px dashed #b6bcbf;
91
+ box-sizing: border-box;
92
+ -moz-box-sizing: border-box; }
93
+
94
+ html .dd-empty {
95
+ border: 1px dashed #bbb;
96
+ min-height: 100px;
97
+ background-color: #e5e5e5;
98
+ background-size: 60px 60px;
99
+ background-position: 0 0, 30px 30px; }
100
+
101
+ html .dd-dragel {
102
+ position: absolute;
103
+ pointer-events: none;
104
+ z-index: 9999; }
105
+ html .dd-dragel > .dd-item .dd-handle {
106
+ margin-top: 0; }
107
+ html .dd-dragel .dd-handle {
108
+ box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1); }
109
+
110
+ html .dd-nochildren .dd-placeholder{
111
+ display: none; }
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
  /* EXTRA STYLE */
115
+ #wrapper-nestable-list{
116
+ background: rgba(255, 255, 255, 0.5);
117
+ padding: 20px;
118
  }
119
 
120
  .wrapper-nestable-list {
124
  }
125
  .nestable-list-spinner {
126
  display: none;
 
 
 
 
 
 
 
 
 
 
 
 
127
  }
128
+ .nestable-list-spinner img {}
129
+
130
+ .nestable-list .dd-handle:hover{
131
+ cursor: move;
132
+ }
includes/extensions/categoryPage/js/jquery.nestable.js CHANGED
@@ -1,9 +1,8 @@
1
  /*!
2
- * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
3
- * Dual-licensed under the BSD or MIT licenses
4
  */
5
- ;(function($, window, document, undefined)
6
- {
7
  var hasTouch = 'ontouchstart' in document;
8
 
9
  /**
@@ -11,9 +10,8 @@
11
  * events are normally disabled on the dragging element to avoid conflicts
12
  * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
13
  */
14
- var hasPointerEvents = (function()
15
- {
16
- var el = document.createElement('div'),
17
  docEl = document.documentElement;
18
  if (!('pointerEvents' in el.style)) {
19
  return false;
@@ -27,36 +25,97 @@
27
  })();
28
 
29
  var defaults = {
30
- listNodeName : 'ol',
31
- itemNodeName : 'li',
32
- rootClass : 'dd',
33
- listClass : 'dd-list',
34
- itemClass : 'dd-item',
35
- dragClass : 'dd-dragel',
36
- handleClass : 'dd-handle',
37
- collapsedClass : 'dd-collapsed',
38
- placeClass : 'dd-placeholder',
39
- noDragClass : 'dd-nodrag',
40
- emptyClass : 'dd-empty',
41
- expandBtnHTML : '<button data-action="expand" type="button">Expand</button>',
42
- collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>',
43
- group : 0,
44
- maxDepth : 5,
45
- threshold : 20
46
- };
47
-
48
- function Plugin(element, options)
49
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  this.w = $(document);
51
  this.el = $(element);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  this.options = $.extend({}, defaults, options);
 
 
 
 
 
 
53
  this.init();
54
  }
55
 
56
  Plugin.prototype = {
57
 
58
- init: function()
59
- {
60
  var list = this;
61
 
62
  list.reset();
@@ -65,17 +124,28 @@
65
 
66
  list.placeEl = $('<div class="' + list.options.placeClass + '"/>');
67
 
68
- $.each(this.el.find(list.options.itemNodeName), function(k, el) {
69
- list.setParent($(el));
 
 
 
 
 
 
70
  });
71
 
 
 
 
 
 
72
  list.el.on('click', 'button', function(e) {
73
  if (list.dragEl) {
74
  return;
75
  }
76
  var target = $(e.currentTarget),
77
  action = target.data('action'),
78
- item = target.parent(list.options.itemNodeName);
79
  if (action === 'collapse') {
80
  list.collapseItem(item);
81
  }
@@ -84,8 +154,7 @@
84
  }
85
  });
86
 
87
- var onStartEvent = function(e)
88
- {
89
  var handle = $(e.target);
90
  if (!handle.hasClass(list.options.handleClass)) {
91
  if (handle.closest('.' + list.options.noDragClass).length) {
@@ -93,7 +162,6 @@
93
  }
94
  handle = handle.closest('.' + list.options.handleClass);
95
  }
96
-
97
  if (!handle.length || list.dragEl) {
98
  return;
99
  }
@@ -107,19 +175,17 @@
107
  list.dragStart(e.touches ? e.touches[0] : e);
108
  };
109
 
110
- var onMoveEvent = function(e)
111
- {
112
  if (list.dragEl) {
113
  e.preventDefault();
114
  list.dragMove(e.touches ? e.touches[0] : e);
115
  }
116
  };
117
 
118
- var onEndEvent = function(e)
119
- {
120
  if (list.dragEl) {
121
  e.preventDefault();
122
- list.dragStop(e.touches ? e.touches[0] : e);
123
  }
124
  };
125
 
@@ -134,145 +200,489 @@
134
  list.w.on('mousemove', onMoveEvent);
135
  list.w.on('mouseup', onEndEvent);
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  },
138
 
139
- serialize: function()
140
  {
141
- var data,
142
- depth = 0,
143
- list = this;
144
- step = function(level, depth)
145
- {
146
- var array = [ ],
147
- items = level.children(list.options.itemNodeName);
148
- items.each(function()
149
- {
150
- var li = $(this),
151
- item = $.extend({}, li.data()),
152
- sub = li.children(list.options.listNodeName);
153
- if (sub.length) {
154
- item.children = step(sub, depth + 1);
155
- }
156
- array.push(item);
157
- });
158
- return array;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  };
160
- data = step(list.el.find(list.options.listNodeName).first(), depth);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  return data;
162
  },
163
 
164
- serialise: function()
165
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  return this.serialize();
167
  },
168
 
169
- reset: function()
170
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  this.mouse = {
172
- offsetX : 0,
173
- offsetY : 0,
174
- startX : 0,
175
- startY : 0,
176
- lastX : 0,
177
- lastY : 0,
178
- nowX : 0,
179
- nowY : 0,
180
- distX : 0,
181
- distY : 0,
182
- dirAx : 0,
183
- dirX : 0,
184
- dirY : 0,
185
- lastDirX : 0,
186
- lastDirY : 0,
187
- distAxX : 0,
188
- distAxY : 0
189
  };
190
- this.isTouch = false;
191
- this.moving = false;
192
- this.dragEl = null;
193
  this.dragRootEl = null;
194
- this.dragDepth = 0;
195
  this.hasNewRoot = false;
196
- this.pointEl = null;
197
  },
198
 
199
- expandItem: function(li)
200
- {
201
  li.removeClass(this.options.collapsedClass);
202
- li.children('[data-action="expand"]').hide();
203
- li.children('[data-action="collapse"]').show();
204
- li.children(this.options.listNodeName).show();
205
  },
206
 
207
- collapseItem: function(li)
208
- {
209
  var lists = li.children(this.options.listNodeName);
210
  if (lists.length) {
211
  li.addClass(this.options.collapsedClass);
212
- li.children('[data-action="collapse"]').hide();
213
- li.children('[data-action="expand"]').show();
214
- li.children(this.options.listNodeName).hide();
215
  }
216
  },
217
 
218
- expandAll: function()
219
- {
220
  var list = this;
221
  list.el.find(list.options.itemNodeName).each(function() {
222
  list.expandItem($(this));
223
  });
224
  },
225
 
226
- collapseAll: function()
227
- {
228
  var list = this;
229
  list.el.find(list.options.itemNodeName).each(function() {
230
  list.collapseItem($(this));
231
  });
232
  },
233
 
234
- setParent: function(li)
235
- {
236
- if (li.children(this.options.listNodeName).length) {
 
 
237
  li.prepend($(this.options.expandBtnHTML));
238
  li.prepend($(this.options.collapseBtnHTML));
239
  }
240
- li.children('[data-action="expand"]').hide();
241
  },
242
 
243
- unsetParent: function(li)
244
- {
245
  li.removeClass(this.options.collapsedClass);
246
  li.children('[data-action]').remove();
247
  li.children(this.options.listNodeName).remove();
248
  },
249
 
250
- dragStart: function(e)
251
- {
252
- var mouse = this.mouse,
253
- target = $(e.target),
254
  dragItem = target.closest(this.options.itemNodeName);
255
 
 
 
 
 
 
 
 
 
 
 
256
  this.placeEl.css('height', dragItem.height());
257
 
258
- mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
259
- mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
260
  mouse.startX = mouse.lastX = e.pageX;
261
  mouse.startY = mouse.lastY = e.pageY;
262
 
263
  this.dragRootEl = this.el;
264
-
265
  this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
266
- this.dragEl.css('width', dragItem.width());
 
 
267
 
 
 
268
  dragItem.after(this.placeEl);
269
  dragItem[0].parentNode.removeChild(dragItem[0]);
270
  dragItem.appendTo(this.dragEl);
271
 
272
  $(document.body).append(this.dragEl);
273
  this.dragEl.css({
274
- 'left' : e.pageX - mouse.offsetX,
275
- 'top' : e.pageY - mouse.offsetY
276
  });
277
  // total depth of dragging item
278
  var i, depth,
@@ -285,37 +695,121 @@
285
  }
286
  },
287
 
288
- dragStop: function(e)
289
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  var el = this.dragEl.children(this.options.itemNodeName).first();
 
291
  el[0].parentNode.removeChild(el[0]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  this.placeEl.replaceWith(el);
293
 
294
- this.dragEl.remove();
295
- this.el.trigger('change');
296
  if (this.hasNewRoot) {
 
 
 
 
 
 
 
 
 
297
  this.dragRootEl.trigger('change');
298
  }
 
 
 
299
  this.reset();
300
  },
301
 
302
- dragMove: function(e)
303
- {
304
  var list, parent, prev, next, depth,
305
- opt = this.options,
306
  mouse = this.mouse;
307
 
308
  this.dragEl.css({
309
- 'left' : e.pageX - mouse.offsetX,
310
- 'top' : e.pageY - mouse.offsetY
311
  });
312
 
313
  // mouse position last events
314
  mouse.lastX = mouse.nowX;
315
  mouse.lastY = mouse.nowY;
316
  // mouse position this events
317
- mouse.nowX = e.pageX;
318
- mouse.nowY = e.pageY;
319
  // distance mouse moved between events
320
  mouse.distX = mouse.nowX - mouse.lastX;
321
  mouse.distY = mouse.nowY - mouse.lastY;
@@ -326,20 +820,62 @@
326
  mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
327
  mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
328
  // axis mouse is now moving on
329
- var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
330
 
331
  // do nothing on first move
332
  if (!mouse.moving) {
333
- mouse.dirAx = newAx;
334
  mouse.moving = true;
335
  return;
336
  }
337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  // calc distance moved on this axis (and direction)
339
  if (mouse.dirAx !== newAx) {
340
  mouse.distAxX = 0;
341
  mouse.distAxY = 0;
342
- } else {
 
343
  mouse.distAxX += Math.abs(mouse.distX);
344
  if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
345
  mouse.distAxX = 0;
@@ -358,8 +894,8 @@
358
  // reset move distance on x-axis for new phase
359
  mouse.distAxX = 0;
360
  prev = this.placeEl.prev(opt.itemNodeName);
361
- // increase horizontal level if previous sibling exists and is not collapsed
362
- if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
363
  // cannot increase level when item above is collapsed
364
  list = prev.find(opt.listNodeName).last();
365
  // check if depth limit has reached
@@ -367,11 +903,9 @@
367
  if (depth + this.dragDepth <= opt.maxDepth) {
368
  // create new sub-level if one doesn't exist
369
  if (!list.length) {
370
- list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);
371
- list.append(this.placeEl);
372
- prev.append(list);
373
- this.setParent(prev);
374
- } else {
375
  // else append to next level up
376
  list = prev.children(opt.listNodeName).last();
377
  list.append(this.placeEl);
@@ -403,7 +937,7 @@
403
  this.dragEl[0].style.visibility = 'visible';
404
  }
405
  if (this.pointEl.hasClass(opt.handleClass)) {
406
- this.pointEl = this.pointEl.parent(opt.itemNodeName);
407
  }
408
  if (this.pointEl.hasClass(opt.emptyClass)) {
409
  isEmpty = true;
@@ -414,7 +948,7 @@
414
 
415
  // find parent list of item under cursor
416
  var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
417
- isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
418
 
419
  /**
420
  * move vertical
@@ -424,13 +958,19 @@
424
  if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
425
  return;
426
  }
 
 
 
 
 
 
427
  // check depth limit
428
  depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
429
  if (depth > opt.maxDepth) {
430
  return;
431
  }
432
  var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
433
- parent = this.placeEl.parent();
434
  // if empty create new list to replace empty placeholder
435
  if (isEmpty) {
436
  list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
@@ -447,33 +987,51 @@
447
  this.unsetParent(parent.parent());
448
  }
449
  if (!this.dragRootEl.find(opt.itemNodeName).length) {
450
- this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>');
451
  }
452
  // parent root list has changed
 
453
  if (isNewRoot) {
454
- this.dragRootEl = pointElRoot;
455
  this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
456
  }
457
  }
 
 
 
 
458
  }
459
-
460
  };
461
 
462
- $.fn.nestable = function(params)
463
- {
464
  var lists = this,
465
- retval = this;
 
466
 
467
- lists.each(function()
468
- {
 
 
 
 
469
  var plugin = $(this).data("nestable");
470
 
471
  if (!plugin) {
 
472
  $(this).data("nestable", new Plugin(this, params));
473
- $(this).data("nestable-id", new Date().getTime());
474
- } else {
 
475
  if (typeof params === 'string' && typeof plugin[params] === 'function') {
476
- retval = plugin[params]();
 
 
 
 
 
 
 
 
 
477
  }
478
  }
479
  });
1
  /*!
2
+ * Nestable jQuery Plugin - Copyright (c) 2014 Ramon Smit - https://github.com/RamonSmit/Nestable
 
3
  */
4
+
5
+ (function($, window, document, undefined) {
6
  var hasTouch = 'ontouchstart' in document;
7
 
8
  /**
10
  * events are normally disabled on the dragging element to avoid conflicts
11
  * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
12
  */
13
+ var hasPointerEvents = (function() {
14
+ var el = document.createElement('div'),
 
15
  docEl = document.documentElement;
16
  if (!('pointerEvents' in el.style)) {
17
  return false;
25
  })();
26
 
27
  var defaults = {
28
+ contentCallback: function(item) {return item.content || '' ? item.content : item.id;},
29
+ listNodeName: 'ol',
30
+ itemNodeName: 'li',
31
+ handleNodeName: 'div',
32
+ contentNodeName: 'span',
33
+ rootClass: 'dd',
34
+ listClass: 'dd-list',
35
+ itemClass: 'dd-item',
36
+ dragClass: 'dd-dragel',
37
+ handleClass: 'dd-handle',
38
+ contentClass: 'dd-content',
39
+ collapsedClass: 'dd-collapsed',
40
+ placeClass: 'dd-placeholder',
41
+ noDragClass: 'dd-nodrag',
42
+ noChildrenClass: 'dd-nochildren',
43
+ emptyClass: 'dd-empty',
44
+ expandBtnHTML: '<button class="dd-expand" data-action="expand" type="button">Expand</button>',
45
+ collapseBtnHTML: '<button class="dd-collapse" data-action="collapse" type="button">Collapse</button>',
46
+ group: 0,
47
+ maxDepth: 5,
48
+ threshold: 20,
49
+ fixedDepth: false, //fixed item's depth
50
+ fixed: false,
51
+ includeContent: false,
52
+ scroll: false,
53
+ scrollSensitivity: 1,
54
+ scrollSpeed: 5,
55
+ scrollTriggers: {
56
+ top: 40,
57
+ left: 40,
58
+ right: -40,
59
+ bottom: -40
60
+ },
61
+ callback: function(l, e, p) {},
62
+ onDragStart: function(l, e, p) {},
63
+ beforeDragStop: function(l, e, p) {},
64
+ listRenderer: function(children, options) {
65
+ var html = '<' + options.listNodeName + ' class="' + options.listClass + '">';
66
+ html += children;
67
+ html += '</' + options.listNodeName + '>';
68
+
69
+ return html;
70
+ },
71
+ itemRenderer: function(item_attrs, content, children, options, item) {
72
+ var item_attrs_string = $.map(item_attrs, function(value, key) {
73
+ return ' ' + key + '="' + value + '"';
74
+ }).join(' ');
75
+
76
+ var html = '<' + options.itemNodeName + item_attrs_string + '>';
77
+ html += '<' + options.handleNodeName + ' class="' + options.handleClass + '">';
78
+ html += '<' + options.contentNodeName + ' class="' + options.contentClass + '">';
79
+ html += content;
80
+ html += '</' + options.contentNodeName + '>';
81
+ html += '</' + options.handleNodeName + '>';
82
+ html += children;
83
+ html += '</' + options.itemNodeName + '>';
84
+
85
+ return html;
86
+ }
87
+ };
88
+
89
+ function Plugin(element, options) {
90
  this.w = $(document);
91
  this.el = $(element);
92
+ options = options || defaults;
93
+
94
+ if (options.rootClass !== undefined && options.rootClass !== 'dd') {
95
+ options.listClass = options.listClass ? options.listClass : options.rootClass + '-list';
96
+ options.itemClass = options.itemClass ? options.itemClass : options.rootClass + '-item';
97
+ options.dragClass = options.dragClass ? options.dragClass : options.rootClass + '-dragel';
98
+ options.handleClass = options.handleClass ? options.handleClass : options.rootClass + '-handle';
99
+ options.collapsedClass = options.collapsedClass ? options.collapsedClass : options.rootClass + '-collapsed';
100
+ options.placeClass = options.placeClass ? options.placeClass : options.rootClass + '-placeholder';
101
+ options.noDragClass = options.noDragClass ? options.noDragClass : options.rootClass + '-nodrag';
102
+ options.noChildrenClass = options.noChildrenClass ? options.noChildrenClass : options.rootClass + '-nochildren';
103
+ options.emptyClass = options.emptyClass ? options.emptyClass : options.rootClass + '-empty';
104
+ }
105
+
106
  this.options = $.extend({}, defaults, options);
107
+
108
+ // build HTML from serialized JSON if passed
109
+ if (this.options.json !== undefined) {
110
+ this._build();
111
+ }
112
+
113
  this.init();
114
  }
115
 
116
  Plugin.prototype = {
117
 
118
+ init: function() {
 
119
  var list = this;
120
 
121
  list.reset();
124
 
125
  list.placeEl = $('<div class="' + list.options.placeClass + '"/>');
126
 
127
+ var items = this.el.find(list.options.itemNodeName);
128
+ $.each(items, function(k, el) {
129
+ var item = $(el),
130
+ parent = item.parent();
131
+ list.setParent(item);
132
+ if (parent.hasClass(list.options.collapsedClass)) {
133
+ list.collapseItem(parent.parent());
134
+ }
135
  });
136
 
137
+ // Append the .dd-empty div if the list don't have any items on init
138
+ if (!items.length) {
139
+ this.appendEmptyElement(this.el);
140
+ }
141
+
142
  list.el.on('click', 'button', function(e) {
143
  if (list.dragEl) {
144
  return;
145
  }
146
  var target = $(e.currentTarget),
147
  action = target.data('action'),
148
+ item = target.parents(list.options.itemNodeName).eq(0);
149
  if (action === 'collapse') {
150
  list.collapseItem(item);
151
  }
154
  }
155
  });
156
 
157
+ var onStartEvent = function(e) {
 
158
  var handle = $(e.target);
159
  if (!handle.hasClass(list.options.handleClass)) {
160
  if (handle.closest('.' + list.options.noDragClass).length) {
162
  }
163
  handle = handle.closest('.' + list.options.handleClass);
164
  }
 
165
  if (!handle.length || list.dragEl) {
166
  return;
167
  }
175
  list.dragStart(e.touches ? e.touches[0] : e);
176
  };
177
 
178
+ var onMoveEvent = function(e) {
 
179
  if (list.dragEl) {
180
  e.preventDefault();
181
  list.dragMove(e.touches ? e.touches[0] : e);
182
  }
183
  };
184
 
185
+ var onEndEvent = function(e) {
 
186
  if (list.dragEl) {
187
  e.preventDefault();
188
+ list.dragStop(e.touches ? e.changedTouches[0] : e);
189
  }
190
  };
191
 
200
  list.w.on('mousemove', onMoveEvent);
201
  list.w.on('mouseup', onEndEvent);
202
 
203
+ var destroyNestable = function()
204
+ {
205
+ if (hasTouch) {
206
+ list.el[0].removeEventListener('touchstart', onStartEvent, false);
207
+ window.removeEventListener('touchmove', onMoveEvent, false);
208
+ window.removeEventListener('touchend', onEndEvent, false);
209
+ window.removeEventListener('touchcancel', onEndEvent, false);
210
+ }
211
+
212
+ list.el.off('mousedown', onStartEvent);
213
+ list.w.off('mousemove', onMoveEvent);
214
+ list.w.off('mouseup', onEndEvent);
215
+
216
+ list.el.off('click');
217
+ list.el.unbind('destroy-nestable');
218
+
219
+ list.el.data("nestable", null);
220
+ };
221
+
222
+ list.el.bind('destroy-nestable', destroyNestable);
223
+
224
  },
225
 
226
+ destroy: function ()
227
  {
228
+ this.el.trigger('destroy-nestable');
229
+ },
230
+
231
+ add: function (item)
232
+ {
233
+ var listClassSelector = '.' + this.options.listClass;
234
+ var tree = $(this.el).children(listClassSelector);
235
+
236
+ if (item.parent_id !== undefined) {
237
+ tree = tree.find('[data-id="' + item.parent_id + '"]');
238
+ delete item.parent_id;
239
+
240
+ if (tree.children(listClassSelector).length === 0) {
241
+ tree = tree.append(this.options.listRenderer('', this.options));
242
+ }
243
+
244
+ tree = tree.find(listClassSelector);
245
+ this.setParent(tree.parent());
246
+ }
247
+
248
+ tree.append(this._buildItem(item, this.options));
249
+ },
250
+
251
+ replace: function (item)
252
+ {
253
+ var html = this._buildItem(item, this.options);
254
+
255
+ this._getItemById(item.id)
256
+ .replaceWith(html);
257
+ },
258
+
259
+ //use fade = 'fade' to fadeout item before removing.
260
+ //by using time(string/msecs), you can control animation speed, default is jq 'slow'
261
+ remove: function (itemId, fade, time)
262
+ {
263
+ var opts = this.options,
264
+ el = this.el,
265
+ item = this._getItemById(itemId);
266
+
267
+ //animation time
268
+ time = time || 'slow';
269
+
270
+ //removes item and additional elements from list
271
+ function removeItem(item) {
272
+
273
+ // remove item
274
+ item = item || this;
275
+ item.remove();
276
+
277
+ // remove empty children lists
278
+ var emptyListsSelector = '.' + opts.listClass
279
+ + ' .' + opts.listClass + ':not(:has(*))';
280
+ $(el).find(emptyListsSelector).remove();
281
+
282
+ // remove buttons if parents do not have children
283
+ var buttonsSelector = '[data-action="expand"], [data-action="collapse"]';
284
+ $(el).find(buttonsSelector).each(function() {
285
+ var siblings = $(this).siblings('.' + opts.listClass);
286
+ if (siblings.length === 0) {
287
+ $(this).remove();
288
+ }
289
+ });
290
+ }
291
+
292
+ //Setting fade to true, adds fadeOut effect to removing.
293
+ if (fade === 'fade') {
294
+ item.fadeOut(time, removeItem);
295
+ }
296
+ else {
297
+ removeItem(item);
298
+ }
299
+ },
300
+
301
+ _getItemById: function(itemId) {
302
+ return $(this.el).children('.' + this.options.listClass)
303
+ .find('[data-id="' + itemId + '"]');
304
+ },
305
+
306
+ _build: function() {
307
+ var json = this.options.json;
308
+
309
+ if (typeof json === 'string') {
310
+ json = JSON.parse(json);
311
+ }
312
+
313
+ $(this.el).html(this._buildList(json, this.options));
314
+ },
315
+
316
+ _buildList: function(items, options) {
317
+ if (!items) {
318
+ return '';
319
+ }
320
+
321
+ var children = '';
322
+ var that = this;
323
+
324
+ $.each(items, function(index, sub) {
325
+ children += that._buildItem(sub, options);
326
+ });
327
+
328
+ return options.listRenderer(children, options);
329
+ },
330
+
331
+ _buildItem: function(item, options) {
332
+ function escapeHtml(text) {
333
+ var map = {
334
+ '&': '&amp;',
335
+ '<': '&lt;',
336
+ '>': '&gt;',
337
+ '"': '&quot;',
338
+ "'": '&#039;'
339
  };
340
+
341
+ return text + "".replace(/[&<>"']/g, function(m) { return map[m]; });
342
+ }
343
+
344
+ function filterClasses(classes) {
345
+ var new_classes = {};
346
+
347
+ for (var k in classes) {
348
+ // Remove duplicates
349
+ new_classes[classes[k]] = classes[k];
350
+ }
351
+
352
+ return new_classes;
353
+ }
354
+
355
+ function createClassesString(item, options) {
356
+ var classes = item.classes || {};
357
+
358
+ if (typeof classes === 'string') {
359
+ classes = [classes];
360
+ }
361
+
362
+ var item_classes = filterClasses(classes);
363
+ item_classes[options.itemClass] = options.itemClass;
364
+
365
+ // create class string
366
+ return $.map(item_classes, function(val) {
367
+ return val;
368
+ }).join(' ');
369
+ }
370
+
371
+ function createDataAttrs(attr) {
372
+ attr = $.extend({}, attr);
373
+
374
+ delete attr.children;
375
+ delete attr.classes;
376
+ delete attr.content;
377
+
378
+ var data_attrs = {};
379
+
380
+ $.each(attr, function(key, value) {
381
+ if (typeof value === 'object') {
382
+ value = JSON.stringify(value);
383
+ }
384
+
385
+ data_attrs["data-" + key] = escapeHtml(value);
386
+ });
387
+
388
+ return data_attrs;
389
+ }
390
+
391
+ var item_attrs = createDataAttrs(item);
392
+ item_attrs["class"] = createClassesString(item, options);
393
+
394
+ var content = options.contentCallback(item);
395
+ var children = this._buildList(item.children, options);
396
+ var html = $(options.itemRenderer(item_attrs, content, children, options, item));
397
+
398
+ this.setParent(html);
399
+
400
+ return html[0].outerHTML;
401
+ },
402
+
403
+ serialize: function() {
404
+ var data, list = this, step = function(level) {
405
+ var array = [],
406
+ items = level.children(list.options.itemNodeName);
407
+ items.each(function() {
408
+ var li = $(this),
409
+ item = $.extend({}, li.data()),
410
+ sub = li.children(list.options.listNodeName);
411
+
412
+ if (list.options.includeContent) {
413
+ var content = li.find('.' + list.options.contentClass).html();
414
+
415
+ if (content) {
416
+ item.content = content;
417
+ }
418
+ }
419
+
420
+ if (sub.length) {
421
+ item.children = step(sub);
422
+ }
423
+ array.push(item);
424
+ });
425
+ return array;
426
+ };
427
+ data = step(list.el.find(list.options.listNodeName).first());
428
  return data;
429
  },
430
 
431
+ asNestedSet: function() {
432
+ var list = this, o = list.options, depth = -1, ret = [], lft = 1;
433
+ var items = list.el.find(o.listNodeName).first().children(o.itemNodeName);
434
+
435
+ items.each(function () {
436
+ lft = traverse(this, depth + 1, lft);
437
+ });
438
+
439
+ ret = ret.sort(function(a,b){ return (a.lft - b.lft); });
440
+ return ret;
441
+
442
+ function traverse(item, depth, lft) {
443
+ var rgt = lft + 1, id, pid;
444
+
445
+ if ($(item).children(o.listNodeName).children(o.itemNodeName).length > 0 ) {
446
+ depth++;
447
+ $(item).children(o.listNodeName).children(o.itemNodeName).each(function () {
448
+ rgt = traverse($(this), depth, rgt);
449
+ });
450
+ depth--;
451
+ }
452
+
453
+ id = $(item).attr('data-id');
454
+ if (isInt(id)) {
455
+ id = parseInt(id);
456
+ }
457
+
458
+ pid = $(item).parent(o.listNodeName).parent(o.itemNodeName).attr('data-id') || '';
459
+ if (isInt(pid)) {
460
+ id = parseInt(pid);
461
+ }
462
+
463
+ if (id) {
464
+ ret.push({"id": id, "parent_id": pid, "depth": depth, "lft": lft, "rgt": rgt});
465
+ }
466
+
467
+ lft = rgt + 1;
468
+ return lft;
469
+ }
470
+
471
+ function isInt(value) {
472
+ return $.isNumeric(value) && Math.floor(value) == value;
473
+ }
474
+ },
475
+
476
+ returnOptions: function() {
477
+ return this.options;
478
+ },
479
+
480
+ serialise: function() {
481
  return this.serialize();
482
  },
483
 
484
+ toHierarchy: function(options) {
485
+
486
+ var o = $.extend({}, this.options, options),
487
+ ret = [];
488
+
489
+ $(this.element).children(o.items).each(function() {
490
+ var level = _recursiveItems(this);
491
+ ret.push(level);
492
+ });
493
+
494
+ return ret;
495
+
496
+ function _recursiveItems(item) {
497
+ var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
498
+ if (id) {
499
+ var currentItem = {
500
+ "id": id[2]
501
+ };
502
+ if ($(item).children(o.listType).children(o.items).length > 0) {
503
+ currentItem.children = [];
504
+ $(item).children(o.listType).children(o.items).each(function() {
505
+ var level = _recursiveItems(this);
506
+ currentItem.children.push(level);
507
+ });
508
+ }
509
+ return currentItem;
510
+ }
511
+ }
512
+ },
513
+
514
+ toArray: function() {
515
+
516
+ var o = $.extend({}, this.options, this),
517
+ sDepth = o.startDepthCount || 0,
518
+ ret = [],
519
+ left = 2,
520
+ list = this,
521
+ element = list.el.find(list.options.listNodeName).first();
522
+
523
+ var items = element.children(list.options.itemNodeName);
524
+ items.each(function() {
525
+ left = _recursiveArray($(this), sDepth + 1, left);
526
+ });
527
+
528
+ ret = ret.sort(function(a, b) {
529
+ return (a.left - b.left);
530
+ });
531
+
532
+ return ret;
533
+
534
+ function _recursiveArray(item, depth, left) {
535
+
536
+ var right = left + 1,
537
+ id,
538
+ pid;
539
+
540
+ if (item.children(o.options.listNodeName).children(o.options.itemNodeName).length > 0) {
541
+ depth++;
542
+ item.children(o.options.listNodeName).children(o.options.itemNodeName).each(function() {
543
+ right = _recursiveArray($(this), depth, right);
544
+ });
545
+ depth--;
546
+ }
547
+
548
+ id = item.data().id;
549
+
550
+
551
+ if (depth === sDepth + 1) {
552
+ pid = o.rootID;
553
+ } else {
554
+
555
+ var parentItem = (item.parent(o.options.listNodeName)
556
+ .parent(o.options.itemNodeName)
557
+ .data());
558
+ pid = parentItem.id;
559
+
560
+ }
561
+
562
+ if (id) {
563
+ ret.push({
564
+ "id": id,
565
+ "parent_id": pid,
566
+ "depth": depth,
567
+ "left": left,
568
+ "right": right
569
+ });
570
+ }
571
+
572
+ left = right + 1;
573
+ return left;
574
+ }
575
+
576
+ },
577
+
578
+ reset: function() {
579
  this.mouse = {
580
+ offsetX: 0,
581
+ offsetY: 0,
582
+ startX: 0,
583
+ startY: 0,
584
+ lastX: 0,
585
+ lastY: 0,
586
+ nowX: 0,
587
+ nowY: 0,
588
+ distX: 0,
589
+ distY: 0,
590
+ dirAx: 0,
591
+ dirX: 0,
592
+ dirY: 0,
593
+ lastDirX: 0,
594
+ lastDirY: 0,
595
+ distAxX: 0,
596
+ distAxY: 0
597
  };
598
+ this.isTouch = false;
599
+ this.moving = false;
600
+ this.dragEl = null;
601
  this.dragRootEl = null;
602
+ this.dragDepth = 0;
603
  this.hasNewRoot = false;
604
+ this.pointEl = null;
605
  },
606
 
607
+ expandItem: function(li) {
 
608
  li.removeClass(this.options.collapsedClass);
 
 
 
609
  },
610
 
611
+ collapseItem: function(li) {
 
612
  var lists = li.children(this.options.listNodeName);
613
  if (lists.length) {
614
  li.addClass(this.options.collapsedClass);
 
 
 
615
  }
616
  },
617
 
618
+ expandAll: function() {
 
619
  var list = this;
620
  list.el.find(list.options.itemNodeName).each(function() {
621
  list.expandItem($(this));
622
  });
623
  },
624
 
625
+ collapseAll: function() {
 
626
  var list = this;
627
  list.el.find(list.options.itemNodeName).each(function() {
628
  list.collapseItem($(this));
629
  });
630
  },
631
 
632
+ setParent: function(li) {
633
+ //Check if li is an element of itemNodeName type and has children
634
+ if (li.is(this.options.itemNodeName) && li.children(this.options.listNodeName).length) {
635
+ // make sure NOT showing two or more sets data-action buttons
636
+ li.children('[data-action]').remove();
637
  li.prepend($(this.options.expandBtnHTML));
638
  li.prepend($(this.options.collapseBtnHTML));
639
  }
 
640
  },
641
 
642
+ unsetParent: function(li) {
 
643
  li.removeClass(this.options.collapsedClass);
644
  li.children('[data-action]').remove();
645
  li.children(this.options.listNodeName).remove();
646
  },
647
 
648
+ dragStart: function(e) {
649
+ var mouse = this.mouse,
650
+ target = $(e.target),
 
651
  dragItem = target.closest(this.options.itemNodeName);
652
 
653
+ var position = {};
654
+ position.top = e.pageY;
655
+ position.left = e.pageX;
656
+
657
+ var continueExecution = this.options.onDragStart.call(this, this.el, dragItem, position);
658
+
659
+ if (typeof continueExecution !== 'undefined' && continueExecution === false) {
660
+ return;
661
+ }
662
+
663
  this.placeEl.css('height', dragItem.height());
664
 
665
+ mouse.offsetX = e.pageX - dragItem.offset().left;
666
+ mouse.offsetY = e.pageY - dragItem.offset().top;
667
  mouse.startX = mouse.lastX = e.pageX;
668
  mouse.startY = mouse.lastY = e.pageY;
669
 
670
  this.dragRootEl = this.el;
 
671
  this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
672
+ this.dragEl.css('width', dragItem.outerWidth());
673
+
674
+ this.setIndexOfItem(dragItem);
675
 
676
+ // fix for zepto.js
677
+ //dragItem.after(this.placeEl).detach().appendTo(this.dragEl);
678
  dragItem.after(this.placeEl);
679
  dragItem[0].parentNode.removeChild(dragItem[0]);
680
  dragItem.appendTo(this.dragEl);
681
 
682
  $(document.body).append(this.dragEl);
683
  this.dragEl.css({
684
+ 'left': e.pageX - mouse.offsetX,
685
+ 'top': e.pageY - mouse.offsetY
686
  });
687
  // total depth of dragging item
688
  var i, depth,
695
  }
696
  },
697
 
698
+ //Create sublevel.
699
+ // element : element which become parent
700
+ // item : something to place into new sublevel
701
+ createSubLevel: function(element, item) {
702
+ var list = $('<' + this.options.listNodeName + '/>').addClass(this.options.listClass);
703
+ if (item) list.append(item);
704
+ element.append(list);
705
+ this.setParent(element);
706
+ return list;
707
+ },
708
+
709
+ setIndexOfItem: function(item, index) {
710
+ index = index || [];
711
+
712
+ index.unshift(item.index());
713
+
714
+ if ($(item[0].parentNode)[0] !== this.dragRootEl[0]) {
715
+ this.setIndexOfItem($(item[0].parentNode), index);
716
+ }
717
+ else {
718
+ this.dragEl.data('indexOfItem', index);
719
+ }
720
+ },
721
+
722
+ restoreItemAtIndex: function(dragElement, indexArray) {
723
+ var currentEl = this.el,
724
+ lastIndex = indexArray.length - 1;
725
+
726
+ //Put drag element at current element position.
727
+ function placeElement(currentEl, dragElement) {
728
+ if (indexArray[lastIndex] === 0) {
729
+ $(currentEl).prepend(dragElement.clone());
730
+ } else {
731
+ $(currentEl.children[indexArray[lastIndex] - 1]).after(dragElement.clone());
732
+ }
733
+ }
734
+ //Diggin through indexArray to get home for dragElement.
735
+ for (var i = 0; i < indexArray.length; i++) {
736
+ if (lastIndex === parseInt(i)) {
737
+ placeElement(currentEl, dragElement);
738
+ return;
739
+ }
740
+ //element can have no indexes, so we have to use conditional here to avoid errors.
741
+ //if element doesn't exist we defenetly need to add new list.
742
+ var element = (currentEl[0]) ? currentEl[0] : currentEl;
743
+ var nextEl = element.children[indexArray[i]];
744
+ currentEl = (!nextEl) ? this.createSubLevel($(element)) : nextEl;
745
+ }
746
+ },
747
+
748
+ dragStop: function(e) {
749
+ // fix for zepto.js
750
+ //this.placeEl.replaceWith(this.dragEl.children(this.options.itemNodeName + ':first').detach());
751
+ var position = {
752
+ top : e.pageY,
753
+ left : e.pageX
754
+ };
755
+ //Get indexArray of item at drag start.
756
+ var srcIndex = this.dragEl.data('indexOfItem');
757
+
758
  var el = this.dragEl.children(this.options.itemNodeName).first();
759
+
760
  el[0].parentNode.removeChild(el[0]);
761
+
762
+ this.dragEl.remove(); //Remove dragEl, cause it can affect on indexing in html collection.
763
+
764
+ //Before drag stop callback
765
+ var continueExecution = this.options.beforeDragStop.call(this, this.el, el, this.placeEl.parent());
766
+ if (typeof continueExecution !== 'undefined' && continueExecution === false) {
767
+ var parent = this.placeEl.parent();
768
+ this.placeEl.remove();
769
+ if (!parent.children().length) {
770
+ this.unsetParent(parent.parent());
771
+ }
772
+ this.restoreItemAtIndex(el, srcIndex);
773
+ this.reset();
774
+ return;
775
+ }
776
+
777
  this.placeEl.replaceWith(el);
778
 
 
 
779
  if (this.hasNewRoot) {
780
+ if (this.options.fixed === true) {
781
+ this.restoreItemAtIndex(el, srcIndex);
782
+ }
783
+ else {
784
+ this.el.trigger('lostItem');
785
+ }
786
+ this.dragRootEl.trigger('gainedItem');
787
+ }
788
+ else {
789
  this.dragRootEl.trigger('change');
790
  }
791
+
792
+ this.options.callback.call(this, this.dragRootEl, el, position);
793
+
794
  this.reset();
795
  },
796
 
797
+ dragMove: function(e) {
 
798
  var list, parent, prev, next, depth,
799
+ opt = this.options,
800
  mouse = this.mouse;
801
 
802
  this.dragEl.css({
803
+ 'left': e.pageX - mouse.offsetX,
804
+ 'top': e.pageY - mouse.offsetY
805
  });
806
 
807
  // mouse position last events
808
  mouse.lastX = mouse.nowX;
809
  mouse.lastY = mouse.nowY;
810
  // mouse position this events
811
+ mouse.nowX = e.pageX;
812
+ mouse.nowY = e.pageY;
813
  // distance mouse moved between events
814
  mouse.distX = mouse.nowX - mouse.lastX;
815
  mouse.distY = mouse.nowY - mouse.lastY;
820
  mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
821
  mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
822
  // axis mouse is now moving on
823
+ var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
824
 
825
  // do nothing on first move
826
  if (!mouse.moving) {
827
+ mouse.dirAx = newAx;
828
  mouse.moving = true;
829
  return;
830
  }
831
 
832
+ // do scrolling if enable
833
+ if (opt.scroll) {
834
+ if (typeof window.jQuery.fn.scrollParent !== 'undefined') {
835
+ var scrolled = false;
836
+ var scrollParent = this.el.scrollParent()[0];
837
+ if (scrollParent !== document && scrollParent.tagName !== 'HTML') {
838
+ if ((opt.scrollTriggers.bottom + scrollParent.offsetHeight) - e.pageY < opt.scrollSensitivity)
839
+ scrollParent.scrollTop = scrolled = scrollParent.scrollTop + opt.scrollSpeed;
840
+ else if (e.pageY - opt.scrollTriggers.top < opt.scrollSensitivity)
841
+ scrollParent.scrollTop = scrolled = scrollParent.scrollTop - opt.scrollSpeed;
842
+
843
+ if ((opt.scrollTriggers.right + scrollParent.offsetWidth) - e.pageX < opt.scrollSensitivity)
844
+ scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + opt.scrollSpeed;
845
+ else if (e.pageX - opt.scrollTriggers.left < opt.scrollSensitivity)
846
+ scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - opt.scrollSpeed;
847
+ } else {
848
+ if (e.pageY - $(document).scrollTop() < opt.scrollSensitivity)
849
+ scrolled = $(document).scrollTop($(document).scrollTop() - opt.scrollSpeed);
850
+ else if ($(window).height() - (e.pageY - $(document).scrollTop()) < opt.scrollSensitivity)
851
+ scrolled = $(document).scrollTop($(document).scrollTop() + opt.scrollSpeed);
852
+
853
+ if (e.pageX - $(document).scrollLeft() < opt.scrollSensitivity)
854
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - opt.scrollSpeed);
855
+ else if ($(window).width() - (e.pageX - $(document).scrollLeft()) < opt.scrollSensitivity)
856
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + opt.scrollSpeed);
857
+ }
858
+ } else {
859
+ console.warn('To use scrolling you need to have scrollParent() function, check documentation for more information');
860
+ }
861
+ }
862
+
863
+ if (this.scrollTimer) {
864
+ clearTimeout(this.scrollTimer);
865
+ }
866
+
867
+ if (opt.scroll && scrolled) {
868
+ this.scrollTimer = setTimeout(function() {
869
+ $(window).trigger(e);
870
+ }, 10);
871
+ }
872
+
873
  // calc distance moved on this axis (and direction)
874
  if (mouse.dirAx !== newAx) {
875
  mouse.distAxX = 0;
876
  mouse.distAxY = 0;
877
+ }
878
+ else {
879
  mouse.distAxX += Math.abs(mouse.distX);
880
  if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
881
  mouse.distAxX = 0;
894
  // reset move distance on x-axis for new phase
895
  mouse.distAxX = 0;
896
  prev = this.placeEl.prev(opt.itemNodeName);
897
+ // increase horizontal level if previous sibling exists, is not collapsed, and can have children
898
+ if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass) && !prev.hasClass(opt.noChildrenClass)) {
899
  // cannot increase level when item above is collapsed
900
  list = prev.find(opt.listNodeName).last();
901
  // check if depth limit has reached
903
  if (depth + this.dragDepth <= opt.maxDepth) {
904
  // create new sub-level if one doesn't exist
905
  if (!list.length) {
906
+ this.createSubLevel(prev, this.placeEl);
907
+ }
908
+ else {
 
 
909
  // else append to next level up
910
  list = prev.children(opt.listNodeName).last();
911
  list.append(this.placeEl);
937
  this.dragEl[0].style.visibility = 'visible';
938
  }
939
  if (this.pointEl.hasClass(opt.handleClass)) {
940
+ this.pointEl = this.pointEl.closest(opt.itemNodeName);
941
  }
942
  if (this.pointEl.hasClass(opt.emptyClass)) {
943
  isEmpty = true;
948
 
949
  // find parent list of item under cursor
950
  var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
951
+ isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
952
 
953
  /**
954
  * move vertical
958
  if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
959
  return;
960
  }
961
+
962
+ // fixed item's depth, use for some list has specific type, eg:'Volume, Section, Chapter ...'
963
+ if (this.options.fixedDepth && this.dragDepth + 1 !== this.pointEl.parents(opt.listNodeName).length) {
964
+ return;
965
+ }
966
+
967
  // check depth limit
968
  depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
969
  if (depth > opt.maxDepth) {
970
  return;
971
  }
972
  var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
973
+ parent = this.placeEl.parent();
974
  // if empty create new list to replace empty placeholder
975
  if (isEmpty) {
976
  list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
987
  this.unsetParent(parent.parent());
988
  }
989
  if (!this.dragRootEl.find(opt.itemNodeName).length) {
990
+ this.appendEmptyElement(this.dragRootEl);
991
  }
992
  // parent root list has changed
993
+ this.dragRootEl = pointElRoot;
994
  if (isNewRoot) {
 
995
  this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
996
  }
997
  }
998
+ },
999
+ // Append the .dd-empty div to the list so it can be populated and styled
1000
+ appendEmptyElement: function(element) {
1001
+ element.append('<div class="' + this.options.emptyClass + '"/>');
1002
  }
 
1003
  };
1004
 
1005
+ $.fn.nestable = function(params) {
 
1006
  var lists = this,
1007
+ retval = this,
1008
+ args = arguments;
1009
 
1010
+ if (!('Nestable' in window)) {
1011
+ window.Nestable = {};
1012
+ Nestable.counter = 0;
1013
+ }
1014
+
1015
+ lists.each(function() {
1016
  var plugin = $(this).data("nestable");
1017
 
1018
  if (!plugin) {
1019
+ Nestable.counter++;
1020
  $(this).data("nestable", new Plugin(this, params));
1021
+ $(this).data("nestable-id", Nestable.counter);
1022
+ }
1023
+ else {
1024
  if (typeof params === 'string' && typeof plugin[params] === 'function') {
1025
+ if (args.length > 1){
1026
+ var pluginArgs = [];
1027
+ for (var i = 1; i < args.length; i++) {
1028
+ pluginArgs.push(args[i]);
1029
+ }
1030
+ retval = plugin[params].apply(plugin, pluginArgs);
1031
+ }
1032
+ else {
1033
+ retval = plugin[params]();
1034
+ }
1035
  }
1036
  }
1037
  });
includes/extensions/categoryPage/js/script.js CHANGED
@@ -1,55 +1,88 @@
1
  ;(function ($, undefined){
2
 
3
 
4
- function DialogEdit() {
5
- this.$element = $('.wrapper-nestable-list');
 
 
 
 
 
 
 
 
 
6
  this.$nestableList = this.$element.find('.nestable-list');
7
- this.$nestableList.nestable({group: 1, maxDepth: 100});
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  this.init();
10
  }
11
  DialogEdit.prototype = {
12
  init: function() {
13
  var self = this;
14
- $('.save_category').click(function(event) {
15
- event.preventDefault();
16
- self.save() ;
17
- });
18
- },
19
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  save : function () {
21
  var self = this,
22
  hierarchyPosts = this.$nestableList.nestable('serialise');
23
 
24
  self.spinner(true);
 
 
 
25
  $.ajax({
26
  url: hierarchyPostAttributes.ajaxUrl,
27
  method: 'post',
28
  data: {
29
- action: hierarchyPostAttributes.dialog.action.save,
30
  hierarchy_posts: hierarchyPosts
31
  },
32
  success: function (response) {
33
  self.spinner(false);
34
- self.destroy();
 
 
35
  },
36
  error: function (jqXHR) {
37
- self.destroy();
38
  new DialogError(jqXHR.responseText);
39
  }
40
  });
41
  },
42
-
43
  spinner: function(isShow) {
44
  if (isShow) {
45
- var $spinner = this.$element.find('.nestable-list-spinner').clone();
46
- $spinner.appendTo(this.$element.closest('.ui-dialog.ui-widget')).show();
47
  } else {
48
- this.$element.find('.nestable-list-spinner').remove();
49
  }
50
  },
51
-
 
 
52
  destroy: function () {
 
53
  this.$element.dialog('close');
54
  this.$element.remove();
55
  }
@@ -66,13 +99,13 @@
66
  self.$element.appendTo('body');
67
  self.$element.dialog({
68
  'dialogClass' : 'wp-dialog',
69
- 'title': hierarchyPostAttributes.error.title,
70
  'modal' : true,
71
  'autoOpen' : true,
72
  'closeOnEscape' : false,
73
  'buttons' : [
74
  {
75
- 'text' : hierarchyPostAttributes.error.button.ok.label,
76
  'class' : 'button',
77
  'click' : function() { return self.destroy(); }
78
  }
@@ -87,6 +120,6 @@
87
  };
88
 
89
  $(document).ready(function() {
90
- new DialogEdit();
91
  });
92
  }(jQuery));
1
  ;(function ($, undefined){
2
 
3
 
4
+ function DialogEdit(options) {
5
+ var self = this;
6
+
7
+ this.$element = $('#wrapper-nestable-list');
8
+
9
+ this.$spinner = $('.nestable-list-spinner');
10
+
11
+ this.$status = $('#gallery_label_status');
12
+
13
+ this.$edit = this.$element.find('.buttonSave');
14
+
15
  this.$nestableList = this.$element.find('.nestable-list');
16
+
17
+ this.$nestableList.nestable({
18
+ group: 1,
19
+ maxDepth: 100,
20
+ callback: function(l,e){
21
+ // l is the main container
22
+ // e is the element that was moved
23
+ self.statusUpdate(hierarchyPostAttributes.status.modified);
24
+ }
25
+ });
26
+
27
+ window['catDialogClick'] = 0 ;
28
 
29
  this.init();
30
  }
31
  DialogEdit.prototype = {
32
  init: function() {
33
  var self = this;
 
 
 
 
 
34
 
35
+ self.$edit.click( function(){
36
+ if( window['catDialogClick'] == 0 ){
37
+ window['catDialogClick'] = 1;
38
+ return self.save();
39
+ } else {
40
+ return false;
41
+ }
42
+ });
43
+ //self.show();
44
+
45
+ },
46
+
47
  save : function () {
48
  var self = this,
49
  hierarchyPosts = this.$nestableList.nestable('serialise');
50
 
51
  self.spinner(true);
52
+ self.statusUpdate(hierarchyPostAttributes.status.saving);
53
+ self.$nestableList.hide();
54
+
55
  $.ajax({
56
  url: hierarchyPostAttributes.ajaxUrl,
57
  method: 'post',
58
  data: {
59
+ action: hierarchyPostAttributes.action.save,
60
  hierarchy_posts: hierarchyPosts
61
  },
62
  success: function (response) {
63
  self.spinner(false);
64
+ self.$nestableList.show();
65
+ window['catDialogClick'] = 0;;
66
+ self.statusUpdate(hierarchyPostAttributes.status.saved);
67
  },
68
  error: function (jqXHR) {
69
+ self.statusUpdate( hierarchyPostAttributes.status.error);
70
  new DialogError(jqXHR.responseText);
71
  }
72
  });
73
  },
 
74
  spinner: function(isShow) {
75
  if (isShow) {
76
+ this.$spinner.show();
 
77
  } else {
78
+ this.$spinner.hide();
79
  }
80
  },
81
+ statusUpdate: function(text) {
82
+ this.$status.text(text);
83
+ },
84
  destroy: function () {
85
+ window['catDialogClick'] = 0;
86
  this.$element.dialog('close');
87
  this.$element.remove();
88
  }
99
  self.$element.appendTo('body');
100
  self.$element.dialog({
101
  'dialogClass' : 'wp-dialog',
102
+ 'title': hierarchyPostAttributes.status.error,
103
  'modal' : true,
104
  'autoOpen' : true,
105
  'closeOnEscape' : false,
106
  'buttons' : [
107
  {
108
+ 'text' : hierarchyPostAttributes.status.ok,
109
  'class' : 'button',
110
  'click' : function() { return self.destroy(); }
111
  }
120
  };
121
 
122
  $(document).ready(function() {
123
+ new DialogEdit( {} );
124
  });
125
  }(jQuery));
includes/rbs_gallery_init.php CHANGED
@@ -187,10 +187,12 @@ if(!function_exists('rbs_gallery_main_init')){
187
  /* category init */
188
  if(
189
  !get_option(ROBO_GALLERY_PREFIX.'categoryShow', 0) &&
190
- !( isset($_GET['page']) && $_GET['page'] == 'robo-gallery-cat' )
191
  ){
192
  rbs_gallery_include('category/category.init.php', ROBO_GALLERY_EXTENSIONS_PATH);
193
  }
 
 
194
 
195
  /* stats init */
196
  rbs_gallery_include('stats/stats.init.php', ROBO_GALLERY_EXTENSIONS_PATH);
187
  /* category init */
188
  if(
189
  !get_option(ROBO_GALLERY_PREFIX.'categoryShow', 0) &&
190
+ !( isset($_GET['page']) && $_GET['page'] != 'robo-gallery-cat' )
191
  ){
192
  rbs_gallery_include('category/category.init.php', ROBO_GALLERY_EXTENSIONS_PATH);
193
  }
194
+
195
+ rbs_gallery_include('categoryPage/category.init.php', ROBO_GALLERY_EXTENSIONS_PATH);
196
 
197
  /* stats init */
198
  rbs_gallery_include('stats/stats.init.php', ROBO_GALLERY_EXTENSIONS_PATH);
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://robosoft.co/robogallery
4
  Tags: gallery, photo gallery, images gallery, gallery images, wordpress gallery plugin, responsive gallery, categories gallery, Polaroid gallery, gallery lightbox, portfolio gallery, video gallery, Gallery Plugin, Robo Gallery
5
  Requires at least: 3.3
6
  Tested up to: 4.8
7
- Stable tag: 2.7.0
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -259,6 +259,9 @@ If any problem occurs, please contact us.
259
 
260
  == Changelog ==
261
 
 
 
 
262
  = 2.7.0 =
263
  * New super gallery cache function
264
 
@@ -422,6 +425,9 @@ If any problem occurs, please contact us.
422
 
423
  == Upgrade Notice ==
424
 
 
 
 
425
  = 2.7.0 =
426
  New super gallery cache function
427
 
4
  Tags: gallery, photo gallery, images gallery, gallery images, wordpress gallery plugin, responsive gallery, categories gallery, Polaroid gallery, gallery lightbox, portfolio gallery, video gallery, Gallery Plugin, Robo Gallery
5
  Requires at least: 3.3
6
  Tested up to: 4.8
7
+ Stable tag: 2.7.1
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
259
 
260
  == Changelog ==
261
 
262
+ = 2.7.1 =
263
+ * New advanced gallery categories sorting section
264
+
265
  = 2.7.0 =
266
  * New super gallery cache function
267
 
425
 
426
  == Upgrade Notice ==
427
 
428
+ = 2.7.1 =
429
+ New advanced gallery categories sorting section
430
+
431
  = 2.7.0 =
432
  New super gallery cache function
433
 
robogallery.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Robo Gallery
4
  Plugin URI: https://robosoft.co/wordpress-gallery-plugin
5
  Description: Gallery modes photo gallery, images gallery, video gallery, Polaroid gallery, gallery lighbox, portfolio gallery, responsive gallery
6
- Version: 2.7.0
7
  Author: RoboSoft
8
  Author URI: https://robosoft.co/wordpress-gallery-plugin
9
  License: GPLv3 or later
@@ -15,12 +15,12 @@ if(!defined('WPINC'))die;
15
  if(!defined("ABSPATH"))exit;
16
 
17
  define("ROBO_GALLERY", 1);
18
- define("ROBO_GALLERY_VERSION", '2.7.0');
19
 
20
  if( !defined("ROBO_GALLERY_PATH") ) define("ROBO_GALLERY_PATH", plugin_dir_path( __FILE__ ));
21
 
22
  define("ROBO_GALLERY_SPECIAL", 1);
23
- define("ROBO_GALLERY_EVENT_DATE", '2017-10-14');
24
  define("ROBO_GALLERY_EVENT_HOUR", 48);
25
 
26
  add_action( 'plugins_loaded', 'rbs_gallery_load_textdomain' );
3
  Plugin Name: Robo Gallery
4
  Plugin URI: https://robosoft.co/wordpress-gallery-plugin
5
  Description: Gallery modes photo gallery, images gallery, video gallery, Polaroid gallery, gallery lighbox, portfolio gallery, responsive gallery
6
+ Version: 2.7.1
7
  Author: RoboSoft
8
  Author URI: https://robosoft.co/wordpress-gallery-plugin
9
  License: GPLv3 or later
15
  if(!defined("ABSPATH"))exit;
16
 
17
  define("ROBO_GALLERY", 1);
18
+ define("ROBO_GALLERY_VERSION", '2.7.1');
19
 
20
  if( !defined("ROBO_GALLERY_PATH") ) define("ROBO_GALLERY_PATH", plugin_dir_path( __FILE__ ));
21
 
22
  define("ROBO_GALLERY_SPECIAL", 1);
23
+ define("ROBO_GALLERY_EVENT_DATE", '2017-10-28');
24
  define("ROBO_GALLERY_EVENT_HOUR", 48);
25
 
26
  add_action( 'plugins_loaded', 'rbs_gallery_load_textdomain' );