Capability Manager Enhanced - Version 2.4.3

Version Description

  • 12 Jul 2022 =
    • Fixed : Capabilities conflict with Advanced Custom Fields #494
    • Fixed : Issue with editor features when options is not array #495
    • Update : Add checkbox for the "Allowed Editors" feature #498
    • Update : Add support for TaxoPress on the Capabilities screen #500
    • Update : Use 3 clicks approach for all boxes in Capabilities #497
    • Fixed : Uncaught TypeError: in_array(): Argument #2 ($haystack) must be of type array, null given. #513
    • Fixed : Hide Invalid Capabilities if empty #490
Download this release

Release Info

Developer olatechpro
Plugin Icon 128x128 Capability Manager Enhanced
Version 2.4.3
Comparing to
See all releases

Code changes from version 2.4.1 to 2.4.3

Files changed (56) hide show
  1. capsman-enhanced.php +2 -2
  2. common/css/admin.css +59 -131
  3. common/css/pressshack-admin.css +0 -21
  4. common/css/profile.css +7 -0
  5. common/js/admin.dev.js +232 -32
  6. common/js/admin.js +22 -1
  7. common/js/profile.js +49 -1
  8. common/libs/jquery/jquery-ui.js +19057 -0
  9. composer.json +1 -1
  10. composer.lock +130 -119
  11. includes/admin-load.php +95 -8
  12. includes/admin.php +416 -237
  13. includes/backup.php +70 -96
  14. includes/features/admin-features.php +5 -5
  15. includes/features/editor-features-classic.php +58 -2
  16. includes/features/editor-features-gutenberg.php +56 -2
  17. includes/features/editor-features.php +25 -11
  18. includes/features/restrict-editor-features.php +161 -35
  19. includes/functions.php +62 -0
  20. includes/manager.php +6 -6
  21. includes/roles/class/class-pp-roles-actions.php +24 -0
  22. includes/roles/class/class-pp-roles-admin.php +312 -70
  23. includes/roles/css/pp-roles-admin.css +171 -0
  24. includes/roles/js/pp-roles-admin.js +154 -0
  25. includes/roles/roles-functions.php +2 -0
  26. languages/capsman-enhanced-fr_FR.mo +0 -0
  27. languages/capsman-enhanced-fr_FR.po +1179 -1477
  28. languages/capsman-enhanced-it_IT.mo +0 -0
  29. languages/capsman-enhanced-it_IT.po +525 -347
  30. loco.xml +0 -19
  31. readme.txt +32 -1
  32. vendor/composer/InstalledVersions.php +0 -2
  33. vendor/composer/autoload_classmap.php +1 -1
  34. vendor/composer/autoload_files.php +1 -1
  35. vendor/composer/autoload_namespaces.php +1 -1
  36. vendor/composer/autoload_psr4.php +1 -1
  37. vendor/composer/autoload_real.php +27 -4
  38. vendor/composer/installed.json +38 -27
  39. vendor/composer/installed.php +16 -16
  40. vendor/pimple/pimple/.gitignore +0 -3
  41. vendor/pimple/pimple/CHANGELOG +0 -59
  42. vendor/pimple/pimple/README.rst +0 -326
  43. vendor/pimple/pimple/composer.json +0 -29
  44. vendor/pimple/pimple/phpunit.xml.dist +0 -14
  45. vendor/psr/container/.gitignore +0 -3
  46. vendor/psr/container/README.md +0 -5
  47. vendor/psr/container/composer.json +0 -27
  48. vendor/publishpress/publishpress-instance-protection/.gitattributes +54 -0
  49. vendor/publishpress/publishpress-instance-protection/README.md +2 -0
  50. vendor/publishpress/publishpress-instance-protection/core/InstanceChecker.php +1 -1
  51. vendor/publishpress/wordpress-banners/BannersMain.php +6 -4
  52. vendor/publishpress/wordpress-banners/assets/css/style.css +21 -0
  53. vendor/publishpress/wordpress-reviews/.gitignore +0 -4
  54. vendor/publishpress/wordpress-reviews/README.md +0 -197
  55. vendor/publishpress/wordpress-reviews/composer.json +0 -46
  56. vendor/publishpress/wordpress-reviews/composer.lock +0 -1127
capsman-enhanced.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: PublishPress Capabilities
4
  * Plugin URI: https://publishpress.com/capability-manager/
5
  * Description: Manage WordPress role definitions, per-site or network-wide. Organizes post capabilities by post type and operation.
6
- * Version: 2.4.1
7
  * Author: PublishPress
8
  * Author URI: https://publishpress.com/
9
  * Text Domain: capsman-enhanced
@@ -44,7 +44,7 @@ if (class_exists('PublishPressInstanceProtection\\Config')) {
44
  }
45
 
46
  if (!defined('CAPSMAN_VERSION')) {
47
- define('CAPSMAN_VERSION', '2.4.1');
48
  define('CAPSMAN_ENH_VERSION', CAPSMAN_VERSION);
49
  define('PUBLISHPRESS_CAPS_VERSION', CAPSMAN_VERSION);
50
  }
3
  * Plugin Name: PublishPress Capabilities
4
  * Plugin URI: https://publishpress.com/capability-manager/
5
  * Description: Manage WordPress role definitions, per-site or network-wide. Organizes post capabilities by post type and operation.
6
+ * Version: 2.4.3
7
  * Author: PublishPress
8
  * Author URI: https://publishpress.com/
9
  * Text Domain: capsman-enhanced
44
  }
45
 
46
  if (!defined('CAPSMAN_VERSION')) {
47
+ define('CAPSMAN_VERSION', '2.4.3');
48
  define('CAPSMAN_ENH_VERSION', CAPSMAN_VERSION);
49
  define('PUBLISHPRESS_CAPS_VERSION', CAPSMAN_VERSION);
50
  }
common/css/admin.css CHANGED
@@ -104,7 +104,8 @@ cursor: pointer;
104
  }
105
 
106
  table.cme-checklist tr td input[type="checkbox"] {
107
- margin-right: 10px !important;
 
108
  }
109
 
110
  h3.cme-cap-section {
@@ -116,11 +117,23 @@ text-decoration: none;
116
  }
117
 
118
  span.cap-x, a.cme-neg-all {
119
- color: red;
120
- font-size: 1.5em;
121
- padding-left: 1px;
122
- padding-right: 1px;
123
- vertical-align: middle;
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
 
126
  a.cme-switch-all {
@@ -144,7 +157,7 @@ td.cap-neg label span {
144
  color: red;
145
  }
146
 
147
- td.cap-neg input {
148
  display:none;
149
  }
150
 
@@ -328,8 +341,6 @@ div.publishpress-caps-backup th {
328
  width: 140px;
329
  }
330
 
331
- div.publishpress-caps-backup p.description {max-width:620px !important;}
332
-
333
  div.publishpress-caps-backup #cme_select_restore_div {height:250px;}
334
  div.publishpress-caps-backup #cme_select_restore {
335
  list-style:none;
@@ -357,7 +368,8 @@ div.publishpress-caps-backup #cme_select_restore li:nth-child(even){
357
  }
358
 
359
  div.cme-selected-backup-caption {
360
- padding-left: 5px;
 
361
  }
362
 
363
  div.pp-caps-backup-button {
@@ -366,11 +378,15 @@ div.pp-caps-backup-button {
366
 
367
  div.cme-restore-button {
368
  margin-top: 25px;
369
- padding-left: 5px;
370
  }
371
 
372
- div.publishpress-caps-backup td.cme-backup-info{
373
- padding:0;
 
 
 
 
 
374
  }
375
 
376
  div.cme-show-backup {
@@ -430,10 +446,6 @@ div.publishpress-caps-backup td.cme-backup-info .cme-negate {
430
  content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIG1lZXQiIHZpZXdCb3g9IjAgMCAyMCAyMCIgc3R5bGU9Ii1tcy10cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7IHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7Ij48cGF0aCBkPSJNMTQuOTUgNi40NkwxMS40MSAxMGwzLjU0IDMuNTRsLTEuNDEgMS40MUwxMCAxMS40MmwtMy41MyAzLjUzbC0xLjQyLTEuNDJMOC41OCAxMEw1LjA1IDYuNDdsMS40Mi0xLjQyTDEwIDguNThsMy41NC0zLjUzeiIgZmlsbD0iI2RjMTQzYyIvPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0icmdiYSgwLCAwLCAwLCAwKSIgLz48L3N2Zz4=");
431
  }
432
 
433
- #ppcb-tab-reset p {
434
- text-align:center;
435
- }
436
-
437
  .publishpress-caps-backup span.pp-caps-warning {
438
  color:red;
439
  }
@@ -599,120 +611,6 @@ body.capabilities_page_pp-capabilities-admin-features .pp-capability-menus-selec
599
  background: #f6f7f7;
600
  }
601
 
602
- /* Roles screen */
603
-
604
- .roles-capabilities-title {
605
- font-weight: bold !important;
606
- padding-left: 0 !important;
607
- }
608
- .pp-role-edit-wrap #publishing-action {
609
- text-align: unset !important;
610
- float: unset !important;
611
- }
612
-
613
- .pp-roles-delete-botton {
614
- color: red !important;
615
- border-color: red !important;
616
- }
617
-
618
- .ppc-roles-section {
619
- min-height: 370px;
620
- }
621
-
622
- #poststuff .ppc-roles-section.postbox .inside {
623
- margin-left: 0 !important;
624
- margin-top: 0 !important;
625
- padding-left: 0 !important;
626
- }
627
-
628
- .ppc-roles-section input[type=text],
629
- .ppc-roles-section input[type=number],
630
- .ppc-roles-section select {
631
- width: 300px;
632
- }
633
-
634
- .ppc-roles-section #poststuff {
635
- min-height: 600px;
636
- }
637
-
638
- ul.ppc-roles-tab {
639
- margin: 0;
640
- width: 20%;
641
- float: left;
642
- line-height: 1em;
643
- padding: 0 0 10px;
644
- position: relative;
645
- background-color: #fafafa;
646
- border-right: 1px solid #eee;
647
- box-sizing: border-box;
648
- min-height: 363px;
649
- }
650
- .ppc-roles-tab-content {
651
- float: left;
652
- width: 80%;
653
- min-height: 275px;
654
- box-sizing: border-box;
655
- padding-left: 10px;
656
- }
657
-
658
-
659
- ul.ppc-roles-tab li {
660
- margin: 0;
661
- padding: 0;
662
- display: block;
663
- position: relative;
664
- }
665
- ul.ppc-roles-tab li a {
666
- margin: 0;
667
- padding: 10px;
668
- display: block;
669
- box-shadow: none;
670
- text-decoration: none;
671
- line-height: 20px!important;
672
- border-bottom: 1px solid #eee;
673
- }
674
-
675
- ul.ppc-roles-tab li a span {
676
- margin-right: .618em;
677
- }
678
-
679
- ul.ppc-roles-tab li a span.dashicons {
680
- margin-left: 0;
681
- font-size: 15px;
682
- }
683
- ul.ppc-roles-tab li.active a {
684
- color: #555;
685
- position: relative;
686
- background-color: #eee;
687
- }
688
-
689
- .ppc-roles-sidebar ul.pp-roles-capabilities li {
690
- margin-bottom: 0;
691
- }
692
-
693
- .ppc-roles-sidebar ul.pp-roles-capabilities li::before {
694
- font-family: Dashicons;
695
- font-weight: 400;
696
- text-transform: none;
697
- line-height: 1;
698
- -webkit-font-smoothing: antialiased;
699
- content: "\f12a";
700
- font-variant: normal;
701
- text-decoration: none;
702
- color: green;
703
- }
704
- .roles-capabilities-load-more,
705
- .roles-capabilities-load-less {
706
- cursor: pointer;
707
- color: #2271b1;
708
- text-decoration: underline;
709
- }
710
-
711
- .ppc-roles-section .red-warning {
712
- color: red;
713
- font-weight: bold;
714
- }
715
-
716
  /* Filters */
717
  .ppc-filter-wrapper {
718
  float: right;
@@ -728,6 +626,21 @@ ul.ppc-roles-tab li.active a {
728
  margin-top: 20px;
729
  }
730
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
731
  /* ====================================================== Main Screen */
732
 
733
  #ppc-capabilities-wrapper {
@@ -830,6 +743,17 @@ ul.ppc-roles-tab li.active a {
830
  }
831
  }
832
 
 
 
 
 
 
 
 
 
 
 
 
833
  @media (max-width: 782px) {
834
 
835
  table.cme-checklist.form-table tr td {
@@ -849,4 +773,8 @@ ul.ppc-roles-tab li.active a {
849
  line-height: 24px;
850
  }
851
 
 
 
 
 
852
  }
104
  }
105
 
106
  table.cme-checklist tr td input[type="checkbox"] {
107
+ margin-right: 10px !important;
108
+ vertical-align: bottom;
109
  }
110
 
111
  h3.cme-cap-section {
117
  }
118
 
119
  span.cap-x, a.cme-neg-all {
120
+ color: red;
121
+ font-size: 1.5em;
122
+ padding-left: 1px;
123
+ padding-right: 2px;
124
+ vertical-align: middle;
125
+ -webkit-touch-callout: none; /* iOS Safari */
126
+ -webkit-user-select: none; /* Safari */
127
+ -khtml-user-select: none; /* Konqueror HTML */
128
+ -moz-user-select: none; /* Old versions of Firefox */
129
+ -ms-user-select: none; /* Internet Explorer/Edge */
130
+ user-select: none; /* Non-prefixed version, currently
131
+ supported by Chrome, Edge, Opera and Firefox */
132
+ }
133
+
134
+ .single-checkbox-table span.cap-x {
135
+ line-height: 0.7;
136
+ margin-right: 10.5px;
137
  }
138
 
139
  a.cme-switch-all {
157
  color: red;
158
  }
159
 
160
+ td.cap-neg input:not(.excluded-input) {
161
  display:none;
162
  }
163
 
341
  width: 140px;
342
  }
343
 
 
 
344
  div.publishpress-caps-backup #cme_select_restore_div {height:250px;}
345
  div.publishpress-caps-backup #cme_select_restore {
346
  list-style:none;
368
  }
369
 
370
  div.cme-selected-backup-caption {
371
+ color: #686868;
372
+ font-size: 0.9em;
373
  }
374
 
375
  div.pp-caps-backup-button {
378
 
379
  div.cme-restore-button {
380
  margin-top: 25px;
 
381
  }
382
 
383
+ #akmin div.cme-restore-button input.button-primary {
384
+ margin-right: 10px;
385
+ }
386
+
387
+ div.publishpress-caps-backup td.cme-backup-list,
388
+ div.publishpress-caps-backup td.cme-backup-info {
389
+ padding: 0;
390
  }
391
 
392
  div.cme-show-backup {
446
  content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIG1lZXQiIHZpZXdCb3g9IjAgMCAyMCAyMCIgc3R5bGU9Ii1tcy10cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7IHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7Ij48cGF0aCBkPSJNMTQuOTUgNi40NkwxMS40MSAxMGwzLjU0IDMuNTRsLTEuNDEgMS40MUwxMCAxMS40MmwtMy41MyAzLjUzbC0xLjQyLTEuNDJMOC41OCAxMEw1LjA1IDYuNDdsMS40Mi0xLjQyTDEwIDguNThsMy41NC0zLjUzeiIgZmlsbD0iI2RjMTQzYyIvPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0icmdiYSgwLCAwLCAwLCAwKSIgLz48L3N2Zz4=");
447
  }
448
 
 
 
 
 
449
  .publishpress-caps-backup span.pp-caps-warning {
450
  color:red;
451
  }
611
  background: #f6f7f7;
612
  }
613
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  /* Filters */
615
  .ppc-filter-wrapper {
616
  float: right;
626
  margin-top: 20px;
627
  }
628
 
629
+ /* ====================================================== Backup screen */
630
+
631
+ .publishpress-caps-backup table#akmin td.content {
632
+ padding: 0;
633
+ }
634
+
635
+ .ppc-postbox {
636
+ padding: 20px;
637
+ margin: 20px 0;
638
+ }
639
+
640
+ .ppc-postbox > h2 {
641
+ margin-top: 0;
642
+ }
643
+
644
  /* ====================================================== Main Screen */
645
 
646
  #ppc-capabilities-wrapper {
743
  }
744
  }
745
 
746
+ @media (min-width: 783px) {
747
+
748
+ div.publishpress-caps-backup td.cme-backup-list {
749
+ width: 50%;
750
+ }
751
+
752
+ div.publishpress-caps-backup td.cme-backup-info {
753
+ padding: 0 0 0 20px;
754
+ }
755
+ }
756
+
757
  @media (max-width: 782px) {
758
 
759
  table.cme-checklist.form-table tr td {
773
  line-height: 24px;
774
  }
775
 
776
+ div.publishpress-caps-backup td.cme-backup-info{
777
+ padding: 0;
778
+ margin-top: 30px;
779
+ }
780
  }
common/css/pressshack-admin.css CHANGED
@@ -148,27 +148,6 @@
148
  border-style: solid;
149
  }
150
 
151
- .pressshack-admin-wrapper .button-primary {
152
- background-color: #FFB300;
153
- border-color: #C58C07;
154
- color: #754D26;
155
-
156
- text-shadow: none;
157
- }
158
-
159
- .pressshack-admin-wrapper .button-primary:hover,
160
- .pressshack-admin-wrapper .button-primary:active,
161
- .pressshack-admin-wrapper .button-primary:focus {
162
- background-color: #F3AC04;
163
- border-color: #C58C07;
164
- color: #333;
165
- outline: none;
166
- box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
167
- -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
168
- -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
169
- -o-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
170
- }
171
-
172
  .pressshack-admin-wrapper .button:not(.notice-dismiss):hover,
173
  .pressshack-admin-wrapper .button:not(.notice-dismiss):active,
174
  .pressshack-admin-wrapper .button:not(.notice-dismiss):focus {
148
  border-style: solid;
149
  }
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  .pressshack-admin-wrapper .button:not(.notice-dismiss):hover,
152
  .pressshack-admin-wrapper .button:not(.notice-dismiss):active,
153
  .pressshack-admin-wrapper .button:not(.notice-dismiss):focus {
common/css/profile.css CHANGED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ tr.user-role-wrap #pp_roles_chosen li.search-choice {
2
+ cursor: move !important;
3
+ }
4
+
5
+ tr.user-role-wrap .chosen-choice-click .chosen-drop {
6
+ display: none !important;
7
+ }
common/js/admin.dev.js CHANGED
@@ -13,6 +13,12 @@ jQuery(document).ready( function($) {
13
  $(this).after('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');
14
 
15
  $('input[name="' + cap_name_attr + '"]').closest('td').removeClass('cap-yes').removeClass('cap-no').addClass('cap-neg');
 
 
 
 
 
 
16
 
17
  return false;
18
  });
@@ -33,6 +39,26 @@ jQuery(document).ready( function($) {
33
  $('input[name="' + cap_name_attr + '"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
34
  $('input[name="' + cap_name_attr + '"]').prop('checked',false).parent().find('input.cme-negation-input').remove();
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  return false;
37
  });
38
 
@@ -195,45 +221,219 @@ jQuery(document).ready( function($) {
195
  });
196
 
197
  /**
198
- * Roles capabilities load less button
199
  */
200
- $(document).on('click', '.roles-capabilities-load-less', function (event) {
201
- event.preventDefault();
202
-
203
- $('.roles-capabilities-load-less').hide();
204
 
205
- $('.roles-capabilities-load-more').show();
206
-
207
- $('ul.pp-roles-capabilities li').hide();
 
 
 
 
 
 
 
208
 
209
- $('ul.pp-roles-capabilities').children().slice(0, 6).show();
 
 
 
 
210
 
211
- window.scrollTo({ top: 0, behavior: 'smooth' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  });
213
-
214
- /**
215
- * Capabilities role slug validation
216
- */
217
- $('.ppc-roles-tab-content input[name="role_slug"]').on('keyup', function (e) {
218
- is_role_slug_exist();
219
- });
220
 
221
- if ($('#pp-role-slug-exists').length > 0) {
222
- is_role_slug_exist();
223
- }
224
-
225
- function is_role_slug_exist() {
226
- if ($('.ppc-roles-tab-content input[name="role_slug"]').attr('readonly') !== 'readonly') {
227
- var value = $('.ppc-roles-tab-content input[name="role_slug"]').val();
228
- var slugexists = $('#pp-role-slug-exists')
229
- var all_roles = $('.ppc-roles-all-roles').val();
230
- var role_array = all_roles.split(',');
231
- if (role_array.includes(value)) {
232
- slugexists.show();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  } else {
234
- slugexists.hide();
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
- }
237
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
 
239
  });
13
  $(this).after('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');
14
 
15
  $('input[name="' + cap_name_attr + '"]').closest('td').removeClass('cap-yes').removeClass('cap-no').addClass('cap-neg');
16
+
17
+ if ($(this).closest('tr').hasClass('unfiltered_upload')) {
18
+ $('input[name="caps[upload_files]"]').closest('td').addClass('cap-neg');
19
+ $('input[name="caps[upload_files]"]').closest('td').append('<input type="hidden" class="cme-negation-input" name="caps[upload_files]" value="" />');
20
+ $('input[name="caps[upload_files]"]').parent().next('a.neg-cap:visible').click();
21
+ }
22
 
23
  return false;
24
  });
39
  $('input[name="' + cap_name_attr + '"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
40
  $('input[name="' + cap_name_attr + '"]').prop('checked',false).parent().find('input.cme-negation-input').remove();
41
 
42
+ if ($(this).closest('td').hasClass('capability-checkbox-rotate')) {
43
+ $(this).closest('td').find('input[type="checkbox"]').prop('checked', true);
44
+
45
+ if ($(this).closest('td').hasClass('upload_files')) {
46
+ $('tr.unfiltered_upload').find('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
47
+ $('tr.unfiltered_upload').find('input[type="checkbox"]').prop('checked',false);
48
+ $('tr.unfiltered_upload').find('input.cme-negation-input').remove();
49
+ $('input[name="caps[unfiltered_upload]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
50
+ $('input[name="caps[unfiltered_upload]"]').prop('checked', true).parent().find('input.cme-negation-input').remove();
51
+ }
52
+ }
53
+
54
+ if ($(this).closest('td').find('input[type="checkbox"]').hasClass('pp-single-action-rotate')) {
55
+ $(this).closest('td').find('input[type="checkbox"]').prop('checked', true);
56
+ }
57
+
58
+ if ($(this).closest('tr').hasClass('unfiltered_upload')) {
59
+ $('input[name="caps[upload_files]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
60
+ $('input[name="caps[upload_files]"]').prop('checked', true).parent().find('input.cme-negation-input').remove();
61
+ }
62
  return false;
63
  });
64
 
221
  });
222
 
223
  /**
224
+ * Capabilities single box click
225
  */
226
+ $(document).on('change', '.capability-checkbox-rotate input[type="checkbox"]', function (event) {
 
 
 
227
 
228
+ let clicked_box = $(this);
229
+ let mark_box_as_x = false;
230
+ let mark_box_as_checked = false;
231
+ let mark_box_as_unchecked = false;
232
+
233
+ if (!clicked_box.prop('checked')) {
234
+ mark_box_as_unchecked = true;
235
+ } else if (clicked_box.prop('checked')) {
236
+ mark_box_as_checked = true;
237
+ }
238
 
239
+ if (mark_box_as_checked && clicked_box.hasClass('interacted')) {
240
+ mark_box_as_checked = false;
241
+ mark_box_as_unchecked = false;
242
+ mark_box_as_x = true;
243
+ }
244
 
245
+ if (mark_box_as_unchecked) {
246
+ clicked_box.prop('checked', false);
247
+ if (clicked_box.closest('td').hasClass('upload_files')) {
248
+ $('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked', false);
249
+ }
250
+ } else if (mark_box_as_checked) {
251
+ clicked_box.prop('checked', true);
252
+ if (clicked_box.closest('td').hasClass('upload_files')) {
253
+ $('tr.unfiltered_upload').find('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
254
+ $('tr.unfiltered_upload').find('input[type="checkbox"]').prop('checked',false);
255
+ $('tr.unfiltered_upload').find('input.cme-negation-input').remove();
256
+ $('input[name="caps[unfiltered_upload]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
257
+ $('input[name="caps[unfiltered_upload]"]').prop('checked', true).parent().find('input.cme-negation-input').remove();
258
+ $('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked', true);
259
+ }
260
+ } else if (mark_box_as_x) {
261
+ if (clicked_box.closest('td').hasClass('upload_files')) {
262
+ $('tr.unfiltered_upload').find('a.neg-cap').trigger('click');
263
+ }
264
+ clicked_box.prop('checked', false);
265
+ //perform X action if state is blank
266
+ var box_parent = clicked_box.closest('td');
267
+ box_parent.addClass('cap-neg');
268
+ var cap_name_attr = box_parent.find('input[type="checkbox"]').attr('name');
269
+ box_parent.append('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');
270
+ $('input[name="' + cap_name_attr + '"]').parent().next('a.neg-cap:visible').click();
271
+ }
272
+ clicked_box.addClass('interacted');
273
  });
 
 
 
 
 
 
 
274
 
275
+ /**
276
+ * Capabilities checkmark rotate
277
+ */
278
+ $(document).on('click', '.pp-row-action-rotate', function (event) {
279
+ event.preventDefault();
280
+ let clicked_box = $(this);
281
+ var checked_fields = false;
282
+ var unchecked_fields = false;
283
+ var all_checkbox = 0;
284
+ var negative_checkbox = 0;
285
+
286
+ //determine if we should check or uncheck based on current input state
287
+ clicked_box.closest('tr').find('input[type="checkbox"]').each(function () {
288
+ if (!$(this).hasClass('excluded-input') && !$(this).prop('checked')) {
289
+ all_checkbox++;
290
+ unchecked_fields = true;
291
+ } else if (!$(this).hasClass('excluded-input') && $(this).prop('checked')) {
292
+ all_checkbox++;
293
+ checked_fields = true;
294
+ }
295
+ if ($(this).closest('td').hasClass('cap-neg')) {
296
+ negative_checkbox++;
297
+ }
298
+ });
299
+
300
+ if ((checked_fields && unchecked_fields) || (negative_checkbox >= all_checkbox)) {
301
+ checked_fields = true;
302
+ unchecked_fields = false;
303
+ } else if (!checked_fields && unchecked_fields && !clicked_box.hasClass('interacted')) {
304
+ checked_fields = true;
305
+ unchecked_fields = false;
306
+ } else if (checked_fields && !unchecked_fields) {
307
+ checked_fields = false;
308
+ unchecked_fields = true;
309
+ } else {
310
+ checked_fields = false;
311
+ unchecked_fields = false;
312
+ }
313
+
314
+
315
+ if (checked_fields) {
316
+ //perform checked action
317
+ clicked_box.closest('tr').find('td').filter('td[class!="cap-unreg"]').each(function () {
318
+ $(this).closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
319
+ $(this).parent().find('input[type="checkbox"]').prop('checked',true);
320
+ $(this).parent().find('input.cme-negation-input').remove();
321
+ // Also apply for any other checkboxes with the same name
322
+ var cap_name_attr = $(this).next('input[type="checkbox"]').attr('name');
323
+
324
+ if (!cap_name_attr) {
325
+ cap_name_attr = $(this).next('label').find('input[type="checkbox"]').attr('name');
326
+ }
327
+
328
+ $('input[name="' + cap_name_attr + '"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
329
+ $('input[name="' + cap_name_attr + '"]').prop('checked', true).parent().find('input.cme-negation-input').remove();
330
+ if ($(this).closest('td').hasClass('upload_files')) {
331
+ $('tr.unfiltered_upload').find('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
332
+ $('tr.unfiltered_upload').find('input[type="checkbox"]').prop('checked',false);
333
+ $('tr.unfiltered_upload').find('input.cme-negation-input').remove();
334
+ $('input[name="caps[unfiltered_upload]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
335
+ $('input[name="caps[unfiltered_upload]"]').prop('checked', true).parent().find('input.cme-negation-input').remove();
336
+ $('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked', true);
337
+ }
338
+ });
339
+ } else if (unchecked_fields) {
340
+ //perform blank action if state is checked
341
+ clicked_box.closest('tr').find('td').filter('td[class!="cap-unreg"]').each(function () {
342
+ $(this).closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
343
+ $(this).parent().find('input[type="checkbox"]').prop('checked',false);
344
+ $(this).parent().find('input.cme-negation-input').remove();
345
+ // Also apply for any other checkboxes with the same name
346
+ var cap_name_attr = $(this).next('input[type="checkbox"]').attr('name');
347
+
348
+ if (!cap_name_attr) {
349
+ cap_name_attr = $(this).next('label').find('input[type="checkbox"]').attr('name');
350
+ }
351
+
352
+ $('input[name="' + cap_name_attr + '"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
353
+ $('input[name="' + cap_name_attr + '"]').prop('checked', false).parent().find('input.cme-negation-input').remove();
354
+ if ($(this).closest('td').hasClass('upload_files')) {
355
+ $('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked', false);
356
+ }
357
+ });
358
  } else {
359
+ //perform X action if state is blank
360
+ clicked_box.closest('tr').find('td[class!="cap-neg"]').filter('td[class!="cap-unreg"]').each(function () {
361
+ $(this).addClass('cap-neg');
362
+
363
+ var cap_name_attr = $(this).find('input[type="checkbox"]').attr('name');
364
+ $(this).append('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');
365
+
366
+ $('input[name="' + cap_name_attr + '"]').parent().next('a.neg-cap:visible').click();
367
+ if ($(this).closest('td').hasClass('upload_files')) {
368
+ $('tr.unfiltered_upload').find('a.neg-cap').trigger('click');
369
+ }
370
+ });
371
  }
372
+
373
+ clicked_box.addClass('interacted');
374
+
375
+ });
376
+
377
+
378
+ /**
379
+ * unfiltered_upload change sync
380
+ */
381
+ $(document).on('change', 'tr.unfiltered_upload input[name="caps[unfiltered_upload]"]', function (event) {
382
+
383
+ let clicked_box = $(this);
384
+
385
+ if (clicked_box.prop('checked')) {
386
+ $('input[name="caps[upload_files]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
387
+ $('input[name="caps[upload_files]"]').prop('checked', true).parent().find('input.cme-negation-input').remove();
388
+ } else if (!clicked_box.prop('checked')) {
389
+ $('input[name="caps[upload_files]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');
390
+ $('input[name="caps[upload_files]"]').prop('checked', false).parent().find('input.cme-negation-input').remove();
391
+ }
392
+
393
+ });
394
+
395
+ /**
396
+ * Other capabilities checkmark rotate
397
+ */
398
+ $(document).on('click', '.pp-single-action-rotate', function (event) {
399
+
400
+ let clicked_input = $(this);
401
+ var checked_fields = false;
402
+ var unchecked_fields = false;
403
+
404
+ //determine if we should check or uncheck based on current input state
405
+ if (clicked_input.prop('checked')) {
406
+ unchecked_fields = true;
407
+ } else if (!clicked_input.prop('checked')) {
408
+ checked_fields = true;
409
+ }
410
+
411
+ if ((checked_fields && unchecked_fields)) {
412
+ checked_fields = true;
413
+ unchecked_fields = false;
414
+ } else if (!checked_fields && unchecked_fields && !clicked_input.hasClass('interacted')) {
415
+ checked_fields = true;
416
+ unchecked_fields = false;
417
+ } else if (checked_fields && !unchecked_fields) {
418
+ checked_fields = false;
419
+ unchecked_fields = true;
420
+ } else {
421
+ checked_fields = false;
422
+ unchecked_fields = false;
423
+ }
424
+
425
+
426
+ if (!checked_fields && !unchecked_fields) {
427
+ //perform X action if state is blank
428
+ event.preventDefault();
429
+ clicked_input.closest('td').find('a.neg-cap').click();
430
+ }
431
+
432
+ clicked_input.addClass('interacted');
433
+
434
+ if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
435
+ document.getSelection().empty();
436
+ }
437
+ });
438
 
439
  });
common/js/admin.js CHANGED
@@ -1 +1,22 @@
1
- jQuery(document).ready(function(e){function t(){if("readonly"!==e('.ppc-roles-tab-content input[name="role_slug"]').attr("readonly")){var t=e('.ppc-roles-tab-content input[name="role_slug"]').val(),i=e("#pp-role-slug-exists");e(".ppc-roles-all-roles").val().split(",").includes(t)?i.show():i.hide()}}e("a.neg-cap").attr("title",cmeAdmin.negationCaption),e("a.neg-type-caps").attr("title",cmeAdmin.typeCapsNegationCaption),e("td.cap-unreg").attr("title",cmeAdmin.typeCapUnregistered),e("a.normal-cap").attr("title",cmeAdmin.switchableCaption),e("span.cap-x").attr("title",cmeAdmin.capNegated),e('table.cme-checklist input[class!="cme-check-all"]').not(":disabled").attr("title",cmeAdmin.chkCaption),e("table.cme-checklist a.neg-cap").click(function(t){e(this).closest("td").removeClass("cap-yes").removeClass("cap-no").addClass("cap-neg");var i=e(this).parent().find('input[type="checkbox"]').attr("name");return e(this).after('<input type="hidden" class="cme-negation-input" name="'+i+'" value="" />'),e('input[name="'+i+'"]').closest("td").removeClass("cap-yes").removeClass("cap-no").addClass("cap-neg"),!1}),e(document).on("click","table.cme-typecaps span.cap-x,table.cme-checklist span.cap-x,table.cme-checklist td.cap-neg span",function(t){e(this).closest("td").removeClass("cap-neg").removeClass("cap-yes").addClass("cap-no"),e(this).parent().find('input[type="checkbox"]').prop("checked",!1),e(this).parent().find("input.cme-negation-input").remove();var i=e(this).next('input[type="checkbox"]').attr("name");return i||(i=e(this).next("label").find('input[type="checkbox"]').attr("name")),e('input[name="'+i+'"]').parent().closest("td").removeClass("cap-neg").removeClass("cap-yes").addClass("cap-no"),e('input[name="'+i+'"]').prop("checked",!1).parent().find("input.cme-negation-input").remove(),!1}),e("#publishpress_caps_form").bind("keypress",function(t){if(13==t.keyCode)return e(document.activeElement).parent().find('input[type="submit"]').first().click(),!1}),e("input.cme-check-all").click(function(t){e(this).closest("table").find('input[type="checkbox"][disabled!="disabled"]:visible').prop("checked",e(this).is(":checked"))}),e("a.cme-neg-all").click(function(t){return e(this).closest("table").find("a.neg-cap:visible").click(),!1}),e("a.cme-switch-all").click(function(t){return e(this).closest("table").find("td.cap-neg span").click(),!1}),e("table.cme-typecaps a.neg-type-caps").click(function(t){return e(this).closest("tr").find('td[class!="cap-neg"]').filter('td[class!="cap-unreg"]').each(function(){e(this).addClass("cap-neg");var t=e(this).find('input[type="checkbox"]').attr("name");e(this).append('<input type="hidden" class="cme-negation-input" name="'+t+'" value="" />'),e('input[name="'+t+'"]').parent().next("a.neg-cap:visible").click()}),!1}),e("table.cme-typecaps th").click(function(){var t=e(this).index(),i=!e(this).prop("checked_all");if(e(this).hasClass("term-cap"))var a='[class*="term-cap"]';else a='[class*="post-cap"]';var s=e(this).closest("table").find("tr td"+a+":nth-child("+(t+1)+') input[type="checkbox"]:visible');e(s).each(function(t,a){e('input[name="'+e(this).attr("name")+'"]').prop("checked",i)}),e(this).prop("checked_all",i)}),e("a.cme-fix-read-cap").click(function(){return e('input[name="caps[read]"]').prop("checked",!0),e('input[name="SaveRole"]').trigger("click"),!1}),e(".ppc-filter-select").each(function(){var t=e(this),i=new Array;e(this).parent().siblings("table").find("tbody").find("tr").each(function(){i.push({value:e(this).attr("class"),text:e(this).find(".cap_type").text()})}),i.forEach(function(i,a){t.append(e("<option>",{value:i.value,text:i.text}))})}),e(".ppc-filter-select").prop("selectedIndex",0),e(".ppc-filter-select-reset").click(function(){e(this).prev(".ppc-filter-select").prop("selectedIndex",0),e(this).parent().siblings("table").find("tr").show()}),e(".ppc-filter-select").change(function(){e(this).val()?(e(this).parent().siblings("table").find("tr").hide(),e(this).parent().siblings("table").find("thead tr:first-child").show(),e(this).parent().siblings("table").find("tr."+e(this).val()).show()):e(this).parent().siblings("table").find("tr").show()}),e(".ppc-filter-text").val(""),e(".ppc-filter-text-reset").click(function(){e(this).prev(".ppc-filter-text").val(""),e(this).parent().siblings("table").find("tr").show(),e(this).parent().siblings(".ppc-filter-no-results").hide()}),e(".ppc-filter-text").keyup(function(){var t=e(this).val().trim().replace(/\s+/g,"_");e(this).parent().siblings("table").find("tr").hide(),e(this).parent().siblings("table").find('tr[class*="'+t+'"]').show(),e(this).parent().siblings("table").find("tr.cme-bulk-select").hide(),0===e(this).val().length&&e(this).parent().siblings("table").find("tr").show(),0===e(this).parent().siblings("table").find("tr:visible").length?e(this).parent().siblings(".ppc-filter-no-results").show():e(this).parent().siblings(".ppc-filter-no-results").hide()}),e(document).on("click",".ppc-roles-tab li",function(t){t.preventDefault();var i=e(this).attr("data-tab");e(".ppc-roles-tab li").removeClass("active"),e(this).addClass("active"),e(".pp-roles-tab-tr").hide(),e(".pp-roles-"+i+"-tab").show()}),e(document).on("click",".roles-capabilities-load-more",function(t){t.preventDefault(),e(".roles-capabilities-load-more").hide(),e(".roles-capabilities-load-less").show(),e("ul.pp-roles-capabilities li").show()}),e(document).on("click",".roles-capabilities-load-less",function(t){t.preventDefault(),e(".roles-capabilities-load-less").hide(),e(".roles-capabilities-load-more").show(),e("ul.pp-roles-capabilities li").hide(),e("ul.pp-roles-capabilities").children().slice(0,6).show(),window.scrollTo({top:0,behavior:"smooth"})}),e('.ppc-roles-tab-content input[name="role_slug"]').on("keyup",function(e){t()}),e("#pp-role-slug-exists").length>0&&t()});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($){$('a.neg-cap').attr('title',cmeAdmin.negationCaption);$('a.neg-type-caps').attr('title',cmeAdmin.typeCapsNegationCaption);$('td.cap-unreg').attr('title',cmeAdmin.typeCapUnregistered);$('a.normal-cap').attr('title',cmeAdmin.switchableCaption);$('span.cap-x').attr('title',cmeAdmin.capNegated);$('table.cme-checklist input[class!="cme-check-all"]').not(':disabled').attr('title',cmeAdmin.chkCaption);$('table.cme-checklist a.neg-cap').click(function(e){$(this).closest('td').removeClass('cap-yes').removeClass('cap-no').addClass('cap-neg');var cap_name_attr=$(this).parent().find('input[type="checkbox"]').attr('name');$(this).after('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');$('input[name="'+cap_name_attr+'"]').closest('td').removeClass('cap-yes').removeClass('cap-no').addClass('cap-neg');if($(this).closest('tr').hasClass('unfiltered_upload')){$('input[name="caps[upload_files]"]').closest('td').addClass('cap-neg');$('input[name="caps[upload_files]"]').closest('td').append('<input type="hidden" class="cme-negation-input" name="caps[upload_files]" value="" />');$('input[name="caps[upload_files]"]').parent().next('a.neg-cap:visible').click();}
2
+ return false;});$(document).on('click','table.cme-typecaps span.cap-x,table.cme-checklist span.cap-x,table.cme-checklist td.cap-neg span',function(e){$(this).closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$(this).parent().find('input[type="checkbox"]').prop('checked',false);$(this).parent().find('input.cme-negation-input').remove();var cap_name_attr=$(this).next('input[type="checkbox"]').attr('name');if(!cap_name_attr){cap_name_attr=$(this).next('label').find('input[type="checkbox"]').attr('name');}
3
+ $('input[name="'+cap_name_attr+'"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="'+cap_name_attr+'"]').prop('checked',false).parent().find('input.cme-negation-input').remove();if($(this).closest('td').hasClass('capability-checkbox-rotate')){$(this).closest('td').find('input[type="checkbox"]').prop('checked',true);if($(this).closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('tr.unfiltered_upload').find('input[type="checkbox"]').prop('checked',false);$('tr.unfiltered_upload').find('input.cme-negation-input').remove();$('input[name="caps[unfiltered_upload]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="caps[unfiltered_upload]"]').prop('checked',true).parent().find('input.cme-negation-input').remove();}}
4
+ if($(this).closest('td').find('input[type="checkbox"]').hasClass('pp-single-action-rotate')){$(this).closest('td').find('input[type="checkbox"]').prop('checked',true);}
5
+ if($(this).closest('tr').hasClass('unfiltered_upload')){$('input[name="caps[upload_files]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="caps[upload_files]"]').prop('checked',true).parent().find('input.cme-negation-input').remove();}
6
+ return false;});$("#publishpress_caps_form").bind("keypress",function(e){if(e.keyCode==13){$(document.activeElement).parent().find('input[type="submit"]').first().click();return false;}});$('input.cme-check-all').click(function(e){$(this).closest('table').find('input[type="checkbox"][disabled!="disabled"]:visible').prop('checked',$(this).is(":checked"));});$('a.cme-neg-all').click(function(e){$(this).closest('table').find('a.neg-cap:visible').click();return false;});$('a.cme-switch-all').click(function(e){$(this).closest('table').find('td.cap-neg span').click();return false;});$('table.cme-typecaps a.neg-type-caps').click(function(e){$(this).closest('tr').find('td[class!="cap-neg"]').filter('td[class!="cap-unreg"]').each(function(){$(this).addClass('cap-neg');var cap_name_attr=$(this).find('input[type="checkbox"]').attr('name');$(this).append('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');$('input[name="'+cap_name_attr+'"]').parent().next('a.neg-cap:visible').click();});return false;});$('table.cme-typecaps th').click(function(){var columnNo=$(this).index();var check_val=!$(this).prop('checked_all');if($(this).hasClass('term-cap'))
7
+ var class_sel='[class*="term-cap"]';else
8
+ var class_sel='[class*="post-cap"]';var chks=$(this).closest("table").find("tr td"+class_sel+":nth-child("+(columnNo+1)+') input[type="checkbox"]:visible');$(chks).each(function(i,e){$('input[name="'+$(this).attr('name')+'"]').prop('checked',check_val);});$(this).prop('checked_all',check_val);});$('a.cme-fix-read-cap').click(function(){$('input[name="caps[read]"]').prop('checked',true);$('input[name="SaveRole"]').trigger('click');return false;});$('.ppc-filter-select').each(function(){var filter=$(this)
9
+ var options=new Array();$(this).parent().siblings('table').find('tbody').find('tr').each(function(){options.push({value:$(this).attr('class'),text:$(this).find('.cap_type').text()});});options.forEach(function(option,index){filter.append($('<option>',{value:option.value,text:option.text}));});});$('.ppc-filter-select').prop('selectedIndex',0);$('.ppc-filter-select-reset').click(function(){$(this).prev('.ppc-filter-select').prop('selectedIndex',0);$(this).parent().siblings('table').find('tr').show();});$('.ppc-filter-select').change(function(){if($(this).val()){$(this).parent().siblings('table').find('tr').hide();$(this).parent().siblings('table').find('thead tr:first-child').show();$(this).parent().siblings('table').find('tr.'+$(this).val()).show();}else{$(this).parent().siblings('table').find('tr').show();}});$('.ppc-filter-text').val('');$('.ppc-filter-text-reset').click(function(){$(this).prev('.ppc-filter-text').val('');$(this).parent().siblings('table').find('tr').show();$(this).parent().siblings('.ppc-filter-no-results').hide();});$('.ppc-filter-text').keyup(function(){var search_text=$(this).val();var search_class=search_text.trim().replace(/\s+/g,'_');$(this).parent().siblings('table').find('tr').hide();$(this).parent().siblings('table').find('tr[class*="'+search_class+'"]').show();$(this).parent().siblings('table').find('tr.cme-bulk-select').hide();if($(this).val().length===0){$(this).parent().siblings('table').find('tr').show();}
10
+ if($(this).parent().siblings('table').find('tr:visible').length===0){$(this).parent().siblings('.ppc-filter-no-results').show();}else{$(this).parent().siblings('.ppc-filter-no-results').hide();}});$(document).on('click','.ppc-roles-tab li',function(event){event.preventDefault();var clicked_tab=$(this).attr('data-tab');$('.ppc-roles-tab li').removeClass('active');$(this).addClass('active');$('.pp-roles-tab-tr').hide();$('.pp-roles-'+clicked_tab+'-tab').show();});$(document).on('click','.roles-capabilities-load-more',function(event){event.preventDefault();$('.roles-capabilities-load-more').hide();$('.roles-capabilities-load-less').show();$('ul.pp-roles-capabilities li').show();});$(document).on('change','.capability-checkbox-rotate input[type="checkbox"]',function(event){let clicked_box=$(this);let mark_box_as_x=false;let mark_box_as_checked=false;let mark_box_as_unchecked=false;if(!clicked_box.prop('checked')){mark_box_as_unchecked=true;}else if(clicked_box.prop('checked')){mark_box_as_checked=true;}
11
+ if(mark_box_as_checked&&clicked_box.hasClass('interacted')){mark_box_as_checked=false;mark_box_as_unchecked=false;mark_box_as_x=true;}
12
+ if(mark_box_as_unchecked){clicked_box.prop('checked',false);if(clicked_box.closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked',false);}}else if(mark_box_as_checked){clicked_box.prop('checked',true);if(clicked_box.closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('tr.unfiltered_upload').find('input[type="checkbox"]').prop('checked',false);$('tr.unfiltered_upload').find('input.cme-negation-input').remove();$('input[name="caps[unfiltered_upload]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="caps[unfiltered_upload]"]').prop('checked',true).parent().find('input.cme-negation-input').remove();$('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked',true);}}else if(mark_box_as_x){if(clicked_box.closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('a.neg-cap').trigger('click');}
13
+ clicked_box.prop('checked',false);var box_parent=clicked_box.closest('td');box_parent.addClass('cap-neg');var cap_name_attr=box_parent.find('input[type="checkbox"]').attr('name');box_parent.append('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');$('input[name="'+cap_name_attr+'"]').parent().next('a.neg-cap:visible').click();}
14
+ clicked_box.addClass('interacted');});$(document).on('click','.pp-row-action-rotate',function(event){event.preventDefault();let clicked_box=$(this);var checked_fields=false;var unchecked_fields=false;var all_checkbox=0;var negative_checkbox=0;clicked_box.closest('tr').find('input[type="checkbox"]').each(function(){if(!$(this).hasClass('excluded-input')&&!$(this).prop('checked')){all_checkbox++;unchecked_fields=true;}else if(!$(this).hasClass('excluded-input')&&$(this).prop('checked')){all_checkbox++;checked_fields=true;}
15
+ if($(this).closest('td').hasClass('cap-neg')){negative_checkbox++;}});if((checked_fields&&unchecked_fields)||(negative_checkbox>=all_checkbox)){checked_fields=true;unchecked_fields=false;}else if(!checked_fields&&unchecked_fields&&!clicked_box.hasClass('interacted')){checked_fields=true;unchecked_fields=false;}else if(checked_fields&&!unchecked_fields){checked_fields=false;unchecked_fields=true;}else{checked_fields=false;unchecked_fields=false;}
16
+ if(checked_fields){clicked_box.closest('tr').find('td').filter('td[class!="cap-unreg"]').each(function(){$(this).closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$(this).parent().find('input[type="checkbox"]').prop('checked',true);$(this).parent().find('input.cme-negation-input').remove();var cap_name_attr=$(this).next('input[type="checkbox"]').attr('name');if(!cap_name_attr){cap_name_attr=$(this).next('label').find('input[type="checkbox"]').attr('name');}
17
+ $('input[name="'+cap_name_attr+'"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="'+cap_name_attr+'"]').prop('checked',true).parent().find('input.cme-negation-input').remove();if($(this).closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('tr.unfiltered_upload').find('input[type="checkbox"]').prop('checked',false);$('tr.unfiltered_upload').find('input.cme-negation-input').remove();$('input[name="caps[unfiltered_upload]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="caps[unfiltered_upload]"]').prop('checked',true).parent().find('input.cme-negation-input').remove();$('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked',true);}});}else if(unchecked_fields){clicked_box.closest('tr').find('td').filter('td[class!="cap-unreg"]').each(function(){$(this).closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$(this).parent().find('input[type="checkbox"]').prop('checked',false);$(this).parent().find('input.cme-negation-input').remove();var cap_name_attr=$(this).next('input[type="checkbox"]').attr('name');if(!cap_name_attr){cap_name_attr=$(this).next('label').find('input[type="checkbox"]').attr('name');}
18
+ $('input[name="'+cap_name_attr+'"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="'+cap_name_attr+'"]').prop('checked',false).parent().find('input.cme-negation-input').remove();if($(this).closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('input[name="caps[unfiltered_upload]"]').prop('checked',false);}});}else{clicked_box.closest('tr').find('td[class!="cap-neg"]').filter('td[class!="cap-unreg"]').each(function(){$(this).addClass('cap-neg');var cap_name_attr=$(this).find('input[type="checkbox"]').attr('name');$(this).append('<input type="hidden" class="cme-negation-input" name="'+cap_name_attr+'" value="" />');$('input[name="'+cap_name_attr+'"]').parent().next('a.neg-cap:visible').click();if($(this).closest('td').hasClass('upload_files')){$('tr.unfiltered_upload').find('a.neg-cap').trigger('click');}});}
19
+ clicked_box.addClass('interacted');});$(document).on('change','tr.unfiltered_upload input[name="caps[unfiltered_upload]"]',function(event){let clicked_box=$(this);if(clicked_box.prop('checked')){$('input[name="caps[upload_files]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="caps[upload_files]"]').prop('checked',true).parent().find('input.cme-negation-input').remove();}else if(!clicked_box.prop('checked')){$('input[name="caps[upload_files]"]').parent().closest('td').removeClass('cap-neg').removeClass('cap-yes').addClass('cap-no');$('input[name="caps[upload_files]"]').prop('checked',false).parent().find('input.cme-negation-input').remove();}});$(document).on('click','.pp-single-action-rotate',function(event){let clicked_input=$(this);var checked_fields=false;var unchecked_fields=false;if(clicked_input.prop('checked')){unchecked_fields=true;}else if(!clicked_input.prop('checked')){checked_fields=true;}
20
+ if((checked_fields&&unchecked_fields)){checked_fields=true;unchecked_fields=false;}else if(!checked_fields&&unchecked_fields&&!clicked_input.hasClass('interacted')){checked_fields=true;unchecked_fields=false;}else if(checked_fields&&!unchecked_fields){checked_fields=false;unchecked_fields=true;}else{checked_fields=false;unchecked_fields=false;}
21
+ if(!checked_fields&&!unchecked_fields){event.preventDefault();clicked_input.closest('td').find('a.neg-cap').click();}
22
+ clicked_input.addClass('interacted');if(navigator.userAgent.toLowerCase().indexOf('firefox')>-1){document.getSelection().empty();}});});
common/js/profile.js CHANGED
@@ -13,7 +13,8 @@ jQuery(function ($) {
13
  $field.hide();
14
 
15
  // Convert the roles field into multiselect
16
- $newField.prop('multiple', true);
 
17
 
18
  // $newField.attr('name', 'role[]');
19
 
@@ -27,8 +28,55 @@ jQuery(function ($) {
27
  }
28
  });
29
  });
 
 
 
 
 
 
 
 
 
30
 
 
 
 
 
31
  $newField.chosen({
32
  'width': '25em'
33
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  });
13
  $field.hide();
14
 
15
  // Convert the roles field into multiselect
16
+ $newField.prop('multiple', true);
17
+ $newField.after('<p class="description">' + ppCapabilitiesProfileData.role_description + '</p>');
18
 
19
  // $newField.attr('name', 'role[]');
20
 
28
  }
29
  });
30
  });
31
+
32
+ /**
33
+ * loop role options and change selected role position
34
+ */
35
+ $.each(ppCapabilitiesProfileData.selected_roles.reverse(), function (i, role) {
36
+ var options = $('#pp_roles option');
37
+ var position = $("#pp_roles option[value='" + role + "']").index();
38
+ $(options[position]).insertBefore(options.eq(0));
39
+ });
40
 
41
+ //add hidden option as first option to enable sorting selection
42
+ $("#pp_roles").prepend('<option style="display:none;"></option>');
43
+
44
+ //init chosen.js
45
  $newField.chosen({
46
  'width': '25em'
47
  });
48
+
49
+ /**
50
+ * Make role sortable
51
+ */
52
+ $(".user-role-wrap .chosen-choices").sortable();
53
+
54
+ /**
55
+ * Force role option re-order before profile form submission
56
+ */
57
+ $('form#your-profile').submit(function () {
58
+ var options = $('#pp_roles option');
59
+ $(".user-role-wrap .chosen-choices .search-choice .search-choice-close").each(function () {
60
+ var select_position = $(this).attr('data-option-array-index');
61
+ $(options[select_position]).insertBefore(options.eq(0));
62
+ });
63
+ });
64
+
65
+ /**
66
+ * Add class to chosen container on chouce click
67
+ */
68
+ $(document).on( 'mousedown', '.user-role-wrap .chosen-choices .search-choice', function() {
69
+ $(this).closest('.chosen-container').addClass('chosen-choice-click');
70
+ });
71
+
72
+ /**
73
+ * Remove chosen container class on click inside input
74
+ */
75
+
76
+ $(document).on( 'mousedown', '.user-role-wrap .chosen-choices', function(e) {
77
+ if (!e.target.parentElement.classList.contains('search-choice')) {
78
+ $(this).closest('.chosen-container').removeClass('chosen-choice-click');
79
+ }
80
+ });
81
+
82
  });
common/libs/jquery/jquery-ui.js ADDED
@@ -0,0 +1,19057 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.13.1 - 2022-01-20
2
+ * http://jqueryui.com
3
+ * Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
4
+ * Copyright jQuery Foundation and other contributors; Licensed MIT */
5
+
6
+ ( function( factory ) {
7
+ "use strict";
8
+
9
+ if ( typeof define === "function" && define.amd ) {
10
+
11
+ // AMD. Register as an anonymous module.
12
+ define( [ "jquery" ], factory );
13
+ } else {
14
+
15
+ // Browser globals
16
+ factory( jQuery );
17
+ }
18
+ } )( function( $ ) {
19
+ "use strict";
20
+
21
+ $.ui = $.ui || {};
22
+
23
+ var version = $.ui.version = "1.13.1";
24
+
25
+
26
+ /*!
27
+ * jQuery UI Widget 1.13.1
28
+ * http://jqueryui.com
29
+ *
30
+ * Copyright jQuery Foundation and other contributors
31
+ * Released under the MIT license.
32
+ * http://jquery.org/license
33
+ */
34
+
35
+ //>>label: Widget
36
+ //>>group: Core
37
+ //>>description: Provides a factory for creating stateful widgets with a common API.
38
+ //>>docs: http://api.jqueryui.com/jQuery.widget/
39
+ //>>demos: http://jqueryui.com/widget/
40
+
41
+
42
+ var widgetUuid = 0;
43
+ var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44
+ var widgetSlice = Array.prototype.slice;
45
+
46
+ $.cleanData = ( function( orig ) {
47
+ return function( elems ) {
48
+ var events, elem, i;
49
+ for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
50
+
51
+ // Only trigger remove when necessary to save time
52
+ events = $._data( elem, "events" );
53
+ if ( events && events.remove ) {
54
+ $( elem ).triggerHandler( "remove" );
55
+ }
56
+ }
57
+ orig( elems );
58
+ };
59
+ } )( $.cleanData );
60
+
61
+ $.widget = function( name, base, prototype ) {
62
+ var existingConstructor, constructor, basePrototype;
63
+
64
+ // ProxiedPrototype allows the provided prototype to remain unmodified
65
+ // so that it can be used as a mixin for multiple widgets (#8876)
66
+ var proxiedPrototype = {};
67
+
68
+ var namespace = name.split( "." )[ 0 ];
69
+ name = name.split( "." )[ 1 ];
70
+ var fullName = namespace + "-" + name;
71
+
72
+ if ( !prototype ) {
73
+ prototype = base;
74
+ base = $.Widget;
75
+ }
76
+
77
+ if ( Array.isArray( prototype ) ) {
78
+ prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
79
+ }
80
+
81
+ // Create selector for plugin
82
+ $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
83
+ return !!$.data( elem, fullName );
84
+ };
85
+
86
+ $[ namespace ] = $[ namespace ] || {};
87
+ existingConstructor = $[ namespace ][ name ];
88
+ constructor = $[ namespace ][ name ] = function( options, element ) {
89
+
90
+ // Allow instantiation without "new" keyword
91
+ if ( !this || !this._createWidget ) {
92
+ return new constructor( options, element );
93
+ }
94
+
95
+ // Allow instantiation without initializing for simple inheritance
96
+ // must use "new" keyword (the code above always passes args)
97
+ if ( arguments.length ) {
98
+ this._createWidget( options, element );
99
+ }
100
+ };
101
+
102
+ // Extend with the existing constructor to carry over any static properties
103
+ $.extend( constructor, existingConstructor, {
104
+ version: prototype.version,
105
+
106
+ // Copy the object used to create the prototype in case we need to
107
+ // redefine the widget later
108
+ _proto: $.extend( {}, prototype ),
109
+
110
+ // Track widgets that inherit from this widget in case this widget is
111
+ // redefined after a widget inherits from it
112
+ _childConstructors: []
113
+ } );
114
+
115
+ basePrototype = new base();
116
+
117
+ // We need to make the options hash a property directly on the new instance
118
+ // otherwise we'll modify the options hash on the prototype that we're
119
+ // inheriting from
120
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
121
+ $.each( prototype, function( prop, value ) {
122
+ if ( typeof value !== "function" ) {
123
+ proxiedPrototype[ prop ] = value;
124
+ return;
125
+ }
126
+ proxiedPrototype[ prop ] = ( function() {
127
+ function _super() {
128
+ return base.prototype[ prop ].apply( this, arguments );
129
+ }
130
+
131
+ function _superApply( args ) {
132
+ return base.prototype[ prop ].apply( this, args );
133
+ }
134
+
135
+ return function() {
136
+ var __super = this._super;
137
+ var __superApply = this._superApply;
138
+ var returnValue;
139
+
140
+ this._super = _super;
141
+ this._superApply = _superApply;
142
+
143
+ returnValue = value.apply( this, arguments );
144
+
145
+ this._super = __super;
146
+ this._superApply = __superApply;
147
+
148
+ return returnValue;
149
+ };
150
+ } )();
151
+ } );
152
+ constructor.prototype = $.widget.extend( basePrototype, {
153
+
154
+ // TODO: remove support for widgetEventPrefix
155
+ // always use the name + a colon as the prefix, e.g., draggable:start
156
+ // don't prefix for widgets that aren't DOM-based
157
+ widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
158
+ }, proxiedPrototype, {
159
+ constructor: constructor,
160
+ namespace: namespace,
161
+ widgetName: name,
162
+ widgetFullName: fullName
163
+ } );
164
+
165
+ // If this widget is being redefined then we need to find all widgets that
166
+ // are inheriting from it and redefine all of them so that they inherit from
167
+ // the new version of this widget. We're essentially trying to replace one
168
+ // level in the prototype chain.
169
+ if ( existingConstructor ) {
170
+ $.each( existingConstructor._childConstructors, function( i, child ) {
171
+ var childPrototype = child.prototype;
172
+
173
+ // Redefine the child widget using the same prototype that was
174
+ // originally used, but inherit from the new version of the base
175
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
176
+ child._proto );
177
+ } );
178
+
179
+ // Remove the list of existing child constructors from the old constructor
180
+ // so the old child constructors can be garbage collected
181
+ delete existingConstructor._childConstructors;
182
+ } else {
183
+ base._childConstructors.push( constructor );
184
+ }
185
+
186
+ $.widget.bridge( name, constructor );
187
+
188
+ return constructor;
189
+ };
190
+
191
+ $.widget.extend = function( target ) {
192
+ var input = widgetSlice.call( arguments, 1 );
193
+ var inputIndex = 0;
194
+ var inputLength = input.length;
195
+ var key;
196
+ var value;
197
+
198
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
199
+ for ( key in input[ inputIndex ] ) {
200
+ value = input[ inputIndex ][ key ];
201
+ if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
202
+
203
+ // Clone objects
204
+ if ( $.isPlainObject( value ) ) {
205
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
206
+ $.widget.extend( {}, target[ key ], value ) :
207
+
208
+ // Don't extend strings, arrays, etc. with objects
209
+ $.widget.extend( {}, value );
210
+
211
+ // Copy everything else by reference
212
+ } else {
213
+ target[ key ] = value;
214
+ }
215
+ }
216
+ }
217
+ }
218
+ return target;
219
+ };
220
+
221
+ $.widget.bridge = function( name, object ) {
222
+ var fullName = object.prototype.widgetFullName || name;
223
+ $.fn[ name ] = function( options ) {
224
+ var isMethodCall = typeof options === "string";
225
+ var args = widgetSlice.call( arguments, 1 );
226
+ var returnValue = this;
227
+
228
+ if ( isMethodCall ) {
229
+
230
+ // If this is an empty collection, we need to have the instance method
231
+ // return undefined instead of the jQuery instance
232
+ if ( !this.length && options === "instance" ) {
233
+ returnValue = undefined;
234
+ } else {
235
+ this.each( function() {
236
+ var methodValue;
237
+ var instance = $.data( this, fullName );
238
+
239
+ if ( options === "instance" ) {
240
+ returnValue = instance;
241
+ return false;
242
+ }
243
+
244
+ if ( !instance ) {
245
+ return $.error( "cannot call methods on " + name +
246
+ " prior to initialization; " +
247
+ "attempted to call method '" + options + "'" );
248
+ }
249
+
250
+ if ( typeof instance[ options ] !== "function" ||
251
+ options.charAt( 0 ) === "_" ) {
252
+ return $.error( "no such method '" + options + "' for " + name +
253
+ " widget instance" );
254
+ }
255
+
256
+ methodValue = instance[ options ].apply( instance, args );
257
+
258
+ if ( methodValue !== instance && methodValue !== undefined ) {
259
+ returnValue = methodValue && methodValue.jquery ?
260
+ returnValue.pushStack( methodValue.get() ) :
261
+ methodValue;
262
+ return false;
263
+ }
264
+ } );
265
+ }
266
+ } else {
267
+
268
+ // Allow multiple hashes to be passed on init
269
+ if ( args.length ) {
270
+ options = $.widget.extend.apply( null, [ options ].concat( args ) );
271
+ }
272
+
273
+ this.each( function() {
274
+ var instance = $.data( this, fullName );
275
+ if ( instance ) {
276
+ instance.option( options || {} );
277
+ if ( instance._init ) {
278
+ instance._init();
279
+ }
280
+ } else {
281
+ $.data( this, fullName, new object( options, this ) );
282
+ }
283
+ } );
284
+ }
285
+
286
+ return returnValue;
287
+ };
288
+ };
289
+
290
+ $.Widget = function( /* options, element */ ) {};
291
+ $.Widget._childConstructors = [];
292
+
293
+ $.Widget.prototype = {
294
+ widgetName: "widget",
295
+ widgetEventPrefix: "",
296
+ defaultElement: "<div>",
297
+
298
+ options: {
299
+ classes: {},
300
+ disabled: false,
301
+
302
+ // Callbacks
303
+ create: null
304
+ },
305
+
306
+ _createWidget: function( options, element ) {
307
+ element = $( element || this.defaultElement || this )[ 0 ];
308
+ this.element = $( element );
309
+ this.uuid = widgetUuid++;
310
+ this.eventNamespace = "." + this.widgetName + this.uuid;
311
+
312
+ this.bindings = $();
313
+ this.hoverable = $();
314
+ this.focusable = $();
315
+ this.classesElementLookup = {};
316
+
317
+ if ( element !== this ) {
318
+ $.data( element, this.widgetFullName, this );
319
+ this._on( true, this.element, {
320
+ remove: function( event ) {
321
+ if ( event.target === element ) {
322
+ this.destroy();
323
+ }
324
+ }
325
+ } );
326
+ this.document = $( element.style ?
327
+
328
+ // Element within the document
329
+ element.ownerDocument :
330
+
331
+ // Element is window or document
332
+ element.document || element );
333
+ this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334
+ }
335
+
336
+ this.options = $.widget.extend( {},
337
+ this.options,
338
+ this._getCreateOptions(),
339
+ options );
340
+
341
+ this._create();
342
+
343
+ if ( this.options.disabled ) {
344
+ this._setOptionDisabled( this.options.disabled );
345
+ }
346
+
347
+ this._trigger( "create", null, this._getCreateEventData() );
348
+ this._init();
349
+ },
350
+
351
+ _getCreateOptions: function() {
352
+ return {};
353
+ },
354
+
355
+ _getCreateEventData: $.noop,
356
+
357
+ _create: $.noop,
358
+
359
+ _init: $.noop,
360
+
361
+ destroy: function() {
362
+ var that = this;
363
+
364
+ this._destroy();
365
+ $.each( this.classesElementLookup, function( key, value ) {
366
+ that._removeClass( value, key );
367
+ } );
368
+
369
+ // We can probably remove the unbind calls in 2.0
370
+ // all event bindings should go through this._on()
371
+ this.element
372
+ .off( this.eventNamespace )
373
+ .removeData( this.widgetFullName );
374
+ this.widget()
375
+ .off( this.eventNamespace )
376
+ .removeAttr( "aria-disabled" );
377
+
378
+ // Clean up events and states
379
+ this.bindings.off( this.eventNamespace );
380
+ },
381
+
382
+ _destroy: $.noop,
383
+
384
+ widget: function() {
385
+ return this.element;
386
+ },
387
+
388
+ option: function( key, value ) {
389
+ var options = key;
390
+ var parts;
391
+ var curOption;
392
+ var i;
393
+
394
+ if ( arguments.length === 0 ) {
395
+
396
+ // Don't return a reference to the internal hash
397
+ return $.widget.extend( {}, this.options );
398
+ }
399
+
400
+ if ( typeof key === "string" ) {
401
+
402
+ // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403
+ options = {};
404
+ parts = key.split( "." );
405
+ key = parts.shift();
406
+ if ( parts.length ) {
407
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408
+ for ( i = 0; i < parts.length - 1; i++ ) {
409
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410
+ curOption = curOption[ parts[ i ] ];
411
+ }
412
+ key = parts.pop();
413
+ if ( arguments.length === 1 ) {
414
+ return curOption[ key ] === undefined ? null : curOption[ key ];
415
+ }
416
+ curOption[ key ] = value;
417
+ } else {
418
+ if ( arguments.length === 1 ) {
419
+ return this.options[ key ] === undefined ? null : this.options[ key ];
420
+ }
421
+ options[ key ] = value;
422
+ }
423
+ }
424
+
425
+ this._setOptions( options );
426
+
427
+ return this;
428
+ },
429
+
430
+ _setOptions: function( options ) {
431
+ var key;
432
+
433
+ for ( key in options ) {
434
+ this._setOption( key, options[ key ] );
435
+ }
436
+
437
+ return this;
438
+ },
439
+
440
+ _setOption: function( key, value ) {
441
+ if ( key === "classes" ) {
442
+ this._setOptionClasses( value );
443
+ }
444
+
445
+ this.options[ key ] = value;
446
+
447
+ if ( key === "disabled" ) {
448
+ this._setOptionDisabled( value );
449
+ }
450
+
451
+ return this;
452
+ },
453
+
454
+ _setOptionClasses: function( value ) {
455
+ var classKey, elements, currentElements;
456
+
457
+ for ( classKey in value ) {
458
+ currentElements = this.classesElementLookup[ classKey ];
459
+ if ( value[ classKey ] === this.options.classes[ classKey ] ||
460
+ !currentElements ||
461
+ !currentElements.length ) {
462
+ continue;
463
+ }
464
+
465
+ // We are doing this to create a new jQuery object because the _removeClass() call
466
+ // on the next line is going to destroy the reference to the current elements being
467
+ // tracked. We need to save a copy of this collection so that we can add the new classes
468
+ // below.
469
+ elements = $( currentElements.get() );
470
+ this._removeClass( currentElements, classKey );
471
+
472
+ // We don't use _addClass() here, because that uses this.options.classes
473
+ // for generating the string of classes. We want to use the value passed in from
474
+ // _setOption(), this is the new value of the classes option which was passed to
475
+ // _setOption(). We pass this value directly to _classes().
476
+ elements.addClass( this._classes( {
477
+ element: elements,
478
+ keys: classKey,
479
+ classes: value,
480
+ add: true
481
+ } ) );
482
+ }
483
+ },
484
+
485
+ _setOptionDisabled: function( value ) {
486
+ this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487
+
488
+ // If the widget is becoming disabled, then nothing is interactive
489
+ if ( value ) {
490
+ this._removeClass( this.hoverable, null, "ui-state-hover" );
491
+ this._removeClass( this.focusable, null, "ui-state-focus" );
492
+ }
493
+ },
494
+
495
+ enable: function() {
496
+ return this._setOptions( { disabled: false } );
497
+ },
498
+
499
+ disable: function() {
500
+ return this._setOptions( { disabled: true } );
501
+ },
502
+
503
+ _classes: function( options ) {
504
+ var full = [];
505
+ var that = this;
506
+
507
+ options = $.extend( {
508
+ element: this.element,
509
+ classes: this.options.classes || {}
510
+ }, options );
511
+
512
+ function bindRemoveEvent() {
513
+ var nodesToBind = [];
514
+
515
+ options.element.each( function( _, element ) {
516
+ var isTracked = $.map( that.classesElementLookup, function( elements ) {
517
+ return elements;
518
+ } )
519
+ .some( function( elements ) {
520
+ return elements.is( element );
521
+ } );
522
+
523
+ if ( !isTracked ) {
524
+ nodesToBind.push( element );
525
+ }
526
+ } );
527
+
528
+ that._on( $( nodesToBind ), {
529
+ remove: "_untrackClassesElement"
530
+ } );
531
+ }
532
+
533
+ function processClassString( classes, checkOption ) {
534
+ var current, i;
535
+ for ( i = 0; i < classes.length; i++ ) {
536
+ current = that.classesElementLookup[ classes[ i ] ] || $();
537
+ if ( options.add ) {
538
+ bindRemoveEvent();
539
+ current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
540
+ } else {
541
+ current = $( current.not( options.element ).get() );
542
+ }
543
+ that.classesElementLookup[ classes[ i ] ] = current;
544
+ full.push( classes[ i ] );
545
+ if ( checkOption && options.classes[ classes[ i ] ] ) {
546
+ full.push( options.classes[ classes[ i ] ] );
547
+ }
548
+ }
549
+ }
550
+
551
+ if ( options.keys ) {
552
+ processClassString( options.keys.match( /\S+/g ) || [], true );
553
+ }
554
+ if ( options.extra ) {
555
+ processClassString( options.extra.match( /\S+/g ) || [] );
556
+ }
557
+
558
+ return full.join( " " );
559
+ },
560
+
561
+ _untrackClassesElement: function( event ) {
562
+ var that = this;
563
+ $.each( that.classesElementLookup, function( key, value ) {
564
+ if ( $.inArray( event.target, value ) !== -1 ) {
565
+ that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
566
+ }
567
+ } );
568
+
569
+ this._off( $( event.target ) );
570
+ },
571
+
572
+ _removeClass: function( element, keys, extra ) {
573
+ return this._toggleClass( element, keys, extra, false );
574
+ },
575
+
576
+ _addClass: function( element, keys, extra ) {
577
+ return this._toggleClass( element, keys, extra, true );
578
+ },
579
+
580
+ _toggleClass: function( element, keys, extra, add ) {
581
+ add = ( typeof add === "boolean" ) ? add : extra;
582
+ var shift = ( typeof element === "string" || element === null ),
583
+ options = {
584
+ extra: shift ? keys : extra,
585
+ keys: shift ? element : keys,
586
+ element: shift ? this.element : element,
587
+ add: add
588
+ };
589
+ options.element.toggleClass( this._classes( options ), add );
590
+ return this;
591
+ },
592
+
593
+ _on: function( suppressDisabledCheck, element, handlers ) {
594
+ var delegateElement;
595
+ var instance = this;
596
+
597
+ // No suppressDisabledCheck flag, shuffle arguments
598
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
599
+ handlers = element;
600
+ element = suppressDisabledCheck;
601
+ suppressDisabledCheck = false;
602
+ }
603
+
604
+ // No element argument, shuffle and use this.element
605
+ if ( !handlers ) {
606
+ handlers = element;
607
+ element = this.element;
608
+ delegateElement = this.widget();
609
+ } else {
610
+ element = delegateElement = $( element );
611
+ this.bindings = this.bindings.add( element );
612
+ }
613
+
614
+ $.each( handlers, function( event, handler ) {
615
+ function handlerProxy() {
616
+
617
+ // Allow widgets to customize the disabled handling
618
+ // - disabled as an array instead of boolean
619
+ // - disabled class as method for disabling individual parts
620
+ if ( !suppressDisabledCheck &&
621
+ ( instance.options.disabled === true ||
622
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
623
+ return;
624
+ }
625
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
626
+ .apply( instance, arguments );
627
+ }
628
+
629
+ // Copy the guid so direct unbinding works
630
+ if ( typeof handler !== "string" ) {
631
+ handlerProxy.guid = handler.guid =
632
+ handler.guid || handlerProxy.guid || $.guid++;
633
+ }
634
+
635
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ );
636
+ var eventName = match[ 1 ] + instance.eventNamespace;
637
+ var selector = match[ 2 ];
638
+
639
+ if ( selector ) {
640
+ delegateElement.on( eventName, selector, handlerProxy );
641
+ } else {
642
+ element.on( eventName, handlerProxy );
643
+ }
644
+ } );
645
+ },
646
+
647
+ _off: function( element, eventName ) {
648
+ eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
649
+ this.eventNamespace;
650
+ element.off( eventName );
651
+
652
+ // Clear the stack to avoid memory leaks (#10056)
653
+ this.bindings = $( this.bindings.not( element ).get() );
654
+ this.focusable = $( this.focusable.not( element ).get() );
655
+ this.hoverable = $( this.hoverable.not( element ).get() );
656
+ },
657
+
658
+ _delay: function( handler, delay ) {
659
+ function handlerProxy() {
660
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
661
+ .apply( instance, arguments );
662
+ }
663
+ var instance = this;
664
+ return setTimeout( handlerProxy, delay || 0 );
665
+ },
666
+
667
+ _hoverable: function( element ) {
668
+ this.hoverable = this.hoverable.add( element );
669
+ this._on( element, {
670
+ mouseenter: function( event ) {
671
+ this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
672
+ },
673
+ mouseleave: function( event ) {
674
+ this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
675
+ }
676
+ } );
677
+ },
678
+
679
+ _focusable: function( element ) {
680
+ this.focusable = this.focusable.add( element );
681
+ this._on( element, {
682
+ focusin: function( event ) {
683
+ this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
684
+ },
685
+ focusout: function( event ) {
686
+ this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
687
+ }
688
+ } );
689
+ },
690
+
691
+ _trigger: function( type, event, data ) {
692
+ var prop, orig;
693
+ var callback = this.options[ type ];
694
+
695
+ data = data || {};
696
+ event = $.Event( event );
697
+ event.type = ( type === this.widgetEventPrefix ?
698
+ type :
699
+ this.widgetEventPrefix + type ).toLowerCase();
700
+
701
+ // The original event may come from any element
702
+ // so we need to reset the target on the new event
703
+ event.target = this.element[ 0 ];
704
+
705
+ // Copy original event properties over to the new event
706
+ orig = event.originalEvent;
707
+ if ( orig ) {
708
+ for ( prop in orig ) {
709
+ if ( !( prop in event ) ) {
710
+ event[ prop ] = orig[ prop ];
711
+ }
712
+ }
713
+ }
714
+
715
+ this.element.trigger( event, data );
716
+ return !( typeof callback === "function" &&
717
+ callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
718
+ event.isDefaultPrevented() );
719
+ }
720
+ };
721
+
722
+ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
723
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
724
+ if ( typeof options === "string" ) {
725
+ options = { effect: options };
726
+ }
727
+
728
+ var hasOptions;
729
+ var effectName = !options ?
730
+ method :
731
+ options === true || typeof options === "number" ?
732
+ defaultEffect :
733
+ options.effect || defaultEffect;
734
+
735
+ options = options || {};
736
+ if ( typeof options === "number" ) {
737
+ options = { duration: options };
738
+ } else if ( options === true ) {
739
+ options = {};
740
+ }
741
+
742
+ hasOptions = !$.isEmptyObject( options );
743
+ options.complete = callback;
744
+
745
+ if ( options.delay ) {
746
+ element.delay( options.delay );
747
+ }
748
+
749
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
750
+ element[ method ]( options );
751
+ } else if ( effectName !== method && element[ effectName ] ) {
752
+ element[ effectName ]( options.duration, options.easing, callback );
753
+ } else {
754
+ element.queue( function( next ) {
755
+ $( this )[ method ]();
756
+ if ( callback ) {
757
+ callback.call( element[ 0 ] );
758
+ }
759
+ next();
760
+ } );
761
+ }
762
+ };
763
+ } );
764
+
765
+ var widget = $.widget;
766
+
767
+
768
+ /*!
769
+ * jQuery UI Position 1.13.1
770
+ * http://jqueryui.com
771
+ *
772
+ * Copyright jQuery Foundation and other contributors
773
+ * Released under the MIT license.
774
+ * http://jquery.org/license
775
+ *
776
+ * http://api.jqueryui.com/position/
777
+ */
778
+
779
+ //>>label: Position
780
+ //>>group: Core
781
+ //>>description: Positions elements relative to other elements.
782
+ //>>docs: http://api.jqueryui.com/position/
783
+ //>>demos: http://jqueryui.com/position/
784
+
785
+
786
+ ( function() {
787
+ var cachedScrollbarWidth,
788
+ max = Math.max,
789
+ abs = Math.abs,
790
+ rhorizontal = /left|center|right/,
791
+ rvertical = /top|center|bottom/,
792
+ roffset = /[\+\-]\d+(\.[\d]+)?%?/,
793
+ rposition = /^\w+/,
794
+ rpercent = /%$/,
795
+ _position = $.fn.position;
796
+
797
+ function getOffsets( offsets, width, height ) {
798
+ return [
799
+ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
800
+ parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
801
+ ];
802
+ }
803
+
804
+ function parseCss( element, property ) {
805
+ return parseInt( $.css( element, property ), 10 ) || 0;
806
+ }
807
+
808
+ function isWindow( obj ) {
809
+ return obj != null && obj === obj.window;
810
+ }
811
+
812
+ function getDimensions( elem ) {
813
+ var raw = elem[ 0 ];
814
+ if ( raw.nodeType === 9 ) {
815
+ return {
816
+ width: elem.width(),
817
+ height: elem.height(),
818
+ offset: { top: 0, left: 0 }
819
+ };
820
+ }
821
+ if ( isWindow( raw ) ) {
822
+ return {
823
+ width: elem.width(),
824
+ height: elem.height(),
825
+ offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
826
+ };
827
+ }
828
+ if ( raw.preventDefault ) {
829
+ return {
830
+ width: 0,
831
+ height: 0,
832
+ offset: { top: raw.pageY, left: raw.pageX }
833
+ };
834
+ }
835
+ return {
836
+ width: elem.outerWidth(),
837
+ height: elem.outerHeight(),
838
+ offset: elem.offset()
839
+ };
840
+ }
841
+
842
+ $.position = {
843
+ scrollbarWidth: function() {
844
+ if ( cachedScrollbarWidth !== undefined ) {
845
+ return cachedScrollbarWidth;
846
+ }
847
+ var w1, w2,
848
+ div = $( "<div style=" +
849
+ "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
850
+ "<div style='height:300px;width:auto;'></div></div>" ),
851
+ innerDiv = div.children()[ 0 ];
852
+
853
+ $( "body" ).append( div );
854
+ w1 = innerDiv.offsetWidth;
855
+ div.css( "overflow", "scroll" );
856
+
857
+ w2 = innerDiv.offsetWidth;
858
+
859
+ if ( w1 === w2 ) {
860
+ w2 = div[ 0 ].clientWidth;
861
+ }
862
+
863
+ div.remove();
864
+
865
+ return ( cachedScrollbarWidth = w1 - w2 );
866
+ },
867
+ getScrollInfo: function( within ) {
868
+ var overflowX = within.isWindow || within.isDocument ? "" :
869
+ within.element.css( "overflow-x" ),
870
+ overflowY = within.isWindow || within.isDocument ? "" :
871
+ within.element.css( "overflow-y" ),
872
+ hasOverflowX = overflowX === "scroll" ||
873
+ ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
874
+ hasOverflowY = overflowY === "scroll" ||
875
+ ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
876
+ return {
877
+ width: hasOverflowY ? $.position.scrollbarWidth() : 0,
878
+ height: hasOverflowX ? $.position.scrollbarWidth() : 0
879
+ };
880
+ },
881
+ getWithinInfo: function( element ) {
882
+ var withinElement = $( element || window ),
883
+ isElemWindow = isWindow( withinElement[ 0 ] ),
884
+ isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
885
+ hasOffset = !isElemWindow && !isDocument;
886
+ return {
887
+ element: withinElement,
888
+ isWindow: isElemWindow,
889
+ isDocument: isDocument,
890
+ offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
891
+ scrollLeft: withinElement.scrollLeft(),
892
+ scrollTop: withinElement.scrollTop(),
893
+ width: withinElement.outerWidth(),
894
+ height: withinElement.outerHeight()
895
+ };
896
+ }
897
+ };
898
+
899
+ $.fn.position = function( options ) {
900
+ if ( !options || !options.of ) {
901
+ return _position.apply( this, arguments );
902
+ }
903
+
904
+ // Make a copy, we don't want to modify arguments
905
+ options = $.extend( {}, options );
906
+
907
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
908
+
909
+ // Make sure string options are treated as CSS selectors
910
+ target = typeof options.of === "string" ?
911
+ $( document ).find( options.of ) :
912
+ $( options.of ),
913
+
914
+ within = $.position.getWithinInfo( options.within ),
915
+ scrollInfo = $.position.getScrollInfo( within ),
916
+ collision = ( options.collision || "flip" ).split( " " ),
917
+ offsets = {};
918
+
919
+ dimensions = getDimensions( target );
920
+ if ( target[ 0 ].preventDefault ) {
921
+
922
+ // Force left top to allow flipping
923
+ options.at = "left top";
924
+ }
925
+ targetWidth = dimensions.width;
926
+ targetHeight = dimensions.height;
927
+ targetOffset = dimensions.offset;
928
+
929
+ // Clone to reuse original targetOffset later
930
+ basePosition = $.extend( {}, targetOffset );
931
+
932
+ // Force my and at to have valid horizontal and vertical positions
933
+ // if a value is missing or invalid, it will be converted to center
934
+ $.each( [ "my", "at" ], function() {
935
+ var pos = ( options[ this ] || "" ).split( " " ),
936
+ horizontalOffset,
937
+ verticalOffset;
938
+
939
+ if ( pos.length === 1 ) {
940
+ pos = rhorizontal.test( pos[ 0 ] ) ?
941
+ pos.concat( [ "center" ] ) :
942
+ rvertical.test( pos[ 0 ] ) ?
943
+ [ "center" ].concat( pos ) :
944
+ [ "center", "center" ];
945
+ }
946
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
947
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
948
+
949
+ // Calculate offsets
950
+ horizontalOffset = roffset.exec( pos[ 0 ] );
951
+ verticalOffset = roffset.exec( pos[ 1 ] );
952
+ offsets[ this ] = [
953
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
954
+ verticalOffset ? verticalOffset[ 0 ] : 0
955
+ ];
956
+
957
+ // Reduce to just the positions without the offsets
958
+ options[ this ] = [
959
+ rposition.exec( pos[ 0 ] )[ 0 ],
960
+ rposition.exec( pos[ 1 ] )[ 0 ]
961
+ ];
962
+ } );
963
+
964
+ // Normalize collision option
965
+ if ( collision.length === 1 ) {
966
+ collision[ 1 ] = collision[ 0 ];
967
+ }
968
+
969
+ if ( options.at[ 0 ] === "right" ) {
970
+ basePosition.left += targetWidth;
971
+ } else if ( options.at[ 0 ] === "center" ) {
972
+ basePosition.left += targetWidth / 2;
973
+ }
974
+
975
+ if ( options.at[ 1 ] === "bottom" ) {
976
+ basePosition.top += targetHeight;
977
+ } else if ( options.at[ 1 ] === "center" ) {
978
+ basePosition.top += targetHeight / 2;
979
+ }
980
+
981
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
982
+ basePosition.left += atOffset[ 0 ];
983
+ basePosition.top += atOffset[ 1 ];
984
+
985
+ return this.each( function() {
986
+ var collisionPosition, using,
987
+ elem = $( this ),
988
+ elemWidth = elem.outerWidth(),
989
+ elemHeight = elem.outerHeight(),
990
+ marginLeft = parseCss( this, "marginLeft" ),
991
+ marginTop = parseCss( this, "marginTop" ),
992
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
993
+ scrollInfo.width,
994
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
995
+ scrollInfo.height,
996
+ position = $.extend( {}, basePosition ),
997
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
998
+
999
+ if ( options.my[ 0 ] === "right" ) {
1000
+ position.left -= elemWidth;
1001
+ } else if ( options.my[ 0 ] === "center" ) {
1002
+ position.left -= elemWidth / 2;
1003
+ }
1004
+
1005
+ if ( options.my[ 1 ] === "bottom" ) {
1006
+ position.top -= elemHeight;
1007
+ } else if ( options.my[ 1 ] === "center" ) {
1008
+ position.top -= elemHeight / 2;
1009
+ }
1010
+
1011
+ position.left += myOffset[ 0 ];
1012
+ position.top += myOffset[ 1 ];
1013
+
1014
+ collisionPosition = {
1015
+ marginLeft: marginLeft,
1016
+ marginTop: marginTop
1017
+ };
1018
+
1019
+ $.each( [ "left", "top" ], function( i, dir ) {
1020
+ if ( $.ui.position[ collision[ i ] ] ) {
1021
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
1022
+ targetWidth: targetWidth,
1023
+ targetHeight: targetHeight,
1024
+ elemWidth: elemWidth,
1025
+ elemHeight: elemHeight,
1026
+ collisionPosition: collisionPosition,
1027
+ collisionWidth: collisionWidth,
1028
+ collisionHeight: collisionHeight,
1029
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1030
+ my: options.my,
1031
+ at: options.at,
1032
+ within: within,
1033
+ elem: elem
1034
+ } );
1035
+ }
1036
+ } );
1037
+
1038
+ if ( options.using ) {
1039
+
1040
+ // Adds feedback as second argument to using callback, if present
1041
+ using = function( props ) {
1042
+ var left = targetOffset.left - position.left,
1043
+ right = left + targetWidth - elemWidth,
1044
+ top = targetOffset.top - position.top,
1045
+ bottom = top + targetHeight - elemHeight,
1046
+ feedback = {
1047
+ target: {
1048
+ element: target,
1049
+ left: targetOffset.left,
1050
+ top: targetOffset.top,
1051
+ width: targetWidth,
1052
+ height: targetHeight
1053
+ },
1054
+ element: {
1055
+ element: elem,
1056
+ left: position.left,
1057
+ top: position.top,
1058
+ width: elemWidth,
1059
+ height: elemHeight
1060
+ },
1061
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1062
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1063
+ };
1064
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1065
+ feedback.horizontal = "center";
1066
+ }
1067
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1068
+ feedback.vertical = "middle";
1069
+ }
1070
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1071
+ feedback.important = "horizontal";
1072
+ } else {
1073
+ feedback.important = "vertical";
1074
+ }
1075
+ options.using.call( this, props, feedback );
1076
+ };
1077
+ }
1078
+
1079
+ elem.offset( $.extend( position, { using: using } ) );
1080
+ } );
1081
+ };
1082
+
1083
+ $.ui.position = {
1084
+ fit: {
1085
+ left: function( position, data ) {
1086
+ var within = data.within,
1087
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1088
+ outerWidth = within.width,
1089
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1090
+ overLeft = withinOffset - collisionPosLeft,
1091
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1092
+ newOverRight;
1093
+
1094
+ // Element is wider than within
1095
+ if ( data.collisionWidth > outerWidth ) {
1096
+
1097
+ // Element is initially over the left side of within
1098
+ if ( overLeft > 0 && overRight <= 0 ) {
1099
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1100
+ withinOffset;
1101
+ position.left += overLeft - newOverRight;
1102
+
1103
+ // Element is initially over right side of within
1104
+ } else if ( overRight > 0 && overLeft <= 0 ) {
1105
+ position.left = withinOffset;
1106
+
1107
+ // Element is initially over both left and right sides of within
1108
+ } else {
1109
+ if ( overLeft > overRight ) {
1110
+ position.left = withinOffset + outerWidth - data.collisionWidth;
1111
+ } else {
1112
+ position.left = withinOffset;
1113
+ }
1114
+ }
1115
+
1116
+ // Too far left -> align with left edge
1117
+ } else if ( overLeft > 0 ) {
1118
+ position.left += overLeft;
1119
+
1120
+ // Too far right -> align with right edge
1121
+ } else if ( overRight > 0 ) {
1122
+ position.left -= overRight;
1123
+
1124
+ // Adjust based on position and margin
1125
+ } else {
1126
+ position.left = max( position.left - collisionPosLeft, position.left );
1127
+ }
1128
+ },
1129
+ top: function( position, data ) {
1130
+ var within = data.within,
1131
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1132
+ outerHeight = data.within.height,
1133
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
1134
+ overTop = withinOffset - collisionPosTop,
1135
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1136
+ newOverBottom;
1137
+
1138
+ // Element is taller than within
1139
+ if ( data.collisionHeight > outerHeight ) {
1140
+
1141
+ // Element is initially over the top of within
1142
+ if ( overTop > 0 && overBottom <= 0 ) {
1143
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1144
+ withinOffset;
1145
+ position.top += overTop - newOverBottom;
1146
+
1147
+ // Element is initially over bottom of within
1148
+ } else if ( overBottom > 0 && overTop <= 0 ) {
1149
+ position.top = withinOffset;
1150
+
1151
+ // Element is initially over both top and bottom of within
1152
+ } else {
1153
+ if ( overTop > overBottom ) {
1154
+ position.top = withinOffset + outerHeight - data.collisionHeight;
1155
+ } else {
1156
+ position.top = withinOffset;
1157
+ }
1158
+ }
1159
+
1160
+ // Too far up -> align with top
1161
+ } else if ( overTop > 0 ) {
1162
+ position.top += overTop;
1163
+
1164
+ // Too far down -> align with bottom edge
1165
+ } else if ( overBottom > 0 ) {
1166
+ position.top -= overBottom;
1167
+
1168
+ // Adjust based on position and margin
1169
+ } else {
1170
+ position.top = max( position.top - collisionPosTop, position.top );
1171
+ }
1172
+ }
1173
+ },
1174
+ flip: {
1175
+ left: function( position, data ) {
1176
+ var within = data.within,
1177
+ withinOffset = within.offset.left + within.scrollLeft,
1178
+ outerWidth = within.width,
1179
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1180
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1181
+ overLeft = collisionPosLeft - offsetLeft,
1182
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1183
+ myOffset = data.my[ 0 ] === "left" ?
1184
+ -data.elemWidth :
1185
+ data.my[ 0 ] === "right" ?
1186
+ data.elemWidth :
1187
+ 0,
1188
+ atOffset = data.at[ 0 ] === "left" ?
1189
+ data.targetWidth :
1190
+ data.at[ 0 ] === "right" ?
1191
+ -data.targetWidth :
1192
+ 0,
1193
+ offset = -2 * data.offset[ 0 ],
1194
+ newOverRight,
1195
+ newOverLeft;
1196
+
1197
+ if ( overLeft < 0 ) {
1198
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1199
+ outerWidth - withinOffset;
1200
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1201
+ position.left += myOffset + atOffset + offset;
1202
+ }
1203
+ } else if ( overRight > 0 ) {
1204
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1205
+ atOffset + offset - offsetLeft;
1206
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1207
+ position.left += myOffset + atOffset + offset;
1208
+ }
1209
+ }
1210
+ },
1211
+ top: function( position, data ) {
1212
+ var within = data.within,
1213
+ withinOffset = within.offset.top + within.scrollTop,
1214
+ outerHeight = within.height,
1215
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1216
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
1217
+ overTop = collisionPosTop - offsetTop,
1218
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1219
+ top = data.my[ 1 ] === "top",
1220
+ myOffset = top ?
1221
+ -data.elemHeight :
1222
+ data.my[ 1 ] === "bottom" ?
1223
+ data.elemHeight :
1224
+ 0,
1225
+ atOffset = data.at[ 1 ] === "top" ?
1226
+ data.targetHeight :
1227
+ data.at[ 1 ] === "bottom" ?
1228
+ -data.targetHeight :
1229
+ 0,
1230
+ offset = -2 * data.offset[ 1 ],
1231
+ newOverTop,
1232
+ newOverBottom;
1233
+ if ( overTop < 0 ) {
1234
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1235
+ outerHeight - withinOffset;
1236
+ if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1237
+ position.top += myOffset + atOffset + offset;
1238
+ }
1239
+ } else if ( overBottom > 0 ) {
1240
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1241
+ offset - offsetTop;
1242
+ if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1243
+ position.top += myOffset + atOffset + offset;
1244
+ }
1245
+ }
1246
+ }
1247
+ },
1248
+ flipfit: {
1249
+ left: function() {
1250
+ $.ui.position.flip.left.apply( this, arguments );
1251
+ $.ui.position.fit.left.apply( this, arguments );
1252
+ },
1253
+ top: function() {
1254
+ $.ui.position.flip.top.apply( this, arguments );
1255
+ $.ui.position.fit.top.apply( this, arguments );
1256
+ }
1257
+ }
1258
+ };
1259
+
1260
+ } )();
1261
+
1262
+ var position = $.ui.position;
1263
+
1264
+
1265
+ /*!
1266
+ * jQuery UI :data 1.13.1
1267
+ * http://jqueryui.com
1268
+ *
1269
+ * Copyright jQuery Foundation and other contributors
1270
+ * Released under the MIT license.
1271
+ * http://jquery.org/license
1272
+ */
1273
+
1274
+ //>>label: :data Selector
1275
+ //>>group: Core
1276
+ //>>description: Selects elements which have data stored under the specified key.
1277
+ //>>docs: http://api.jqueryui.com/data-selector/
1278
+
1279
+
1280
+ var data = $.extend( $.expr.pseudos, {
1281
+ data: $.expr.createPseudo ?
1282
+ $.expr.createPseudo( function( dataName ) {
1283
+ return function( elem ) {
1284
+ return !!$.data( elem, dataName );
1285
+ };
1286
+ } ) :
1287
+
1288
+ // Support: jQuery <1.8
1289
+ function( elem, i, match ) {
1290
+ return !!$.data( elem, match[ 3 ] );
1291
+ }
1292
+ } );
1293
+
1294
+ /*!
1295
+ * jQuery UI Disable Selection 1.13.1
1296
+ * http://jqueryui.com
1297
+ *
1298
+ * Copyright jQuery Foundation and other contributors
1299
+ * Released under the MIT license.
1300
+ * http://jquery.org/license
1301
+ */
1302
+
1303
+ //>>label: disableSelection
1304
+ //>>group: Core
1305
+ //>>description: Disable selection of text content within the set of matched elements.
1306
+ //>>docs: http://api.jqueryui.com/disableSelection/
1307
+
1308
+ // This file is deprecated
1309
+
1310
+ var disableSelection = $.fn.extend( {
1311
+ disableSelection: ( function() {
1312
+ var eventType = "onselectstart" in document.createElement( "div" ) ?
1313
+ "selectstart" :
1314
+ "mousedown";
1315
+
1316
+ return function() {
1317
+ return this.on( eventType + ".ui-disableSelection", function( event ) {
1318
+ event.preventDefault();
1319
+ } );
1320
+ };
1321
+ } )(),
1322
+
1323
+ enableSelection: function() {
1324
+ return this.off( ".ui-disableSelection" );
1325
+ }
1326
+ } );
1327
+
1328
+
1329
+
1330
+ // Create a local jQuery because jQuery Color relies on it and the
1331
+ // global may not exist with AMD and a custom build (#10199).
1332
+ // This module is a noop if used as a regular AMD module.
1333
+ // eslint-disable-next-line no-unused-vars
1334
+ var jQuery = $;
1335
+
1336
+
1337
+ /*!
1338
+ * jQuery Color Animations v2.2.0
1339
+ * https://github.com/jquery/jquery-color
1340
+ *
1341
+ * Copyright OpenJS Foundation and other contributors
1342
+ * Released under the MIT license.
1343
+ * http://jquery.org/license
1344
+ *
1345
+ * Date: Sun May 10 09:02:36 2020 +0200
1346
+ */
1347
+
1348
+
1349
+
1350
+ var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1351
+ "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1352
+
1353
+ class2type = {},
1354
+ toString = class2type.toString,
1355
+
1356
+ // plusequals test for += 100 -= 100
1357
+ rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1358
+
1359
+ // a set of RE's that can match strings and generate color tuples.
1360
+ stringParsers = [ {
1361
+ re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1362
+ parse: function( execResult ) {
1363
+ return [
1364
+ execResult[ 1 ],
1365
+ execResult[ 2 ],
1366
+ execResult[ 3 ],
1367
+ execResult[ 4 ]
1368
+ ];
1369
+ }
1370
+ }, {
1371
+ re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1372
+ parse: function( execResult ) {
1373
+ return [
1374
+ execResult[ 1 ] * 2.55,
1375
+ execResult[ 2 ] * 2.55,
1376
+ execResult[ 3 ] * 2.55,
1377
+ execResult[ 4 ]
1378
+ ];
1379
+ }
1380
+ }, {
1381
+
1382
+ // this regex ignores A-F because it's compared against an already lowercased string
1383
+ re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1384
+ parse: function( execResult ) {
1385
+ return [
1386
+ parseInt( execResult[ 1 ], 16 ),
1387
+ parseInt( execResult[ 2 ], 16 ),
1388
+ parseInt( execResult[ 3 ], 16 ),
1389
+ execResult[ 4 ] ?
1390
+ ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1391
+ 1
1392
+ ];
1393
+ }
1394
+ }, {
1395
+
1396
+ // this regex ignores A-F because it's compared against an already lowercased string
1397
+ re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1398
+ parse: function( execResult ) {
1399
+ return [
1400
+ parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1401
+ parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1402
+ parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1403
+ execResult[ 4 ] ?
1404
+ ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1405
+ .toFixed( 2 ) :
1406
+ 1
1407
+ ];
1408
+ }
1409
+ }, {
1410
+ re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1411
+ space: "hsla",
1412
+ parse: function( execResult ) {
1413
+ return [
1414
+ execResult[ 1 ],
1415
+ execResult[ 2 ] / 100,
1416
+ execResult[ 3 ] / 100,
1417
+ execResult[ 4 ]
1418
+ ];
1419
+ }
1420
+ } ],
1421
+
1422
+ // jQuery.Color( )
1423
+ color = jQuery.Color = function( color, green, blue, alpha ) {
1424
+ return new jQuery.Color.fn.parse( color, green, blue, alpha );
1425
+ },
1426
+ spaces = {
1427
+ rgba: {
1428
+ props: {
1429
+ red: {
1430
+ idx: 0,
1431
+ type: "byte"
1432
+ },
1433
+ green: {
1434
+ idx: 1,
1435
+ type: "byte"
1436
+ },
1437
+ blue: {
1438
+ idx: 2,
1439
+ type: "byte"
1440
+ }
1441
+ }
1442
+ },
1443
+
1444
+ hsla: {
1445
+ props: {
1446
+ hue: {
1447
+ idx: 0,
1448
+ type: "degrees"
1449
+ },
1450
+ saturation: {
1451
+ idx: 1,
1452
+ type: "percent"
1453
+ },
1454
+ lightness: {
1455
+ idx: 2,
1456
+ type: "percent"
1457
+ }
1458
+ }
1459
+ }
1460
+ },
1461
+ propTypes = {
1462
+ "byte": {
1463
+ floor: true,
1464
+ max: 255
1465
+ },
1466
+ "percent": {
1467
+ max: 1
1468
+ },
1469
+ "degrees": {
1470
+ mod: 360,
1471
+ floor: true
1472
+ }
1473
+ },
1474
+ support = color.support = {},
1475
+
1476
+ // element for support tests
1477
+ supportElem = jQuery( "<p>" )[ 0 ],
1478
+
1479
+ // colors = jQuery.Color.names
1480
+ colors,
1481
+
1482
+ // local aliases of functions called often
1483
+ each = jQuery.each;
1484
+
1485
+ // determine rgba support immediately
1486
+ supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
1487
+ support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
1488
+
1489
+ // define cache name and alpha properties
1490
+ // for rgba and hsla spaces
1491
+ each( spaces, function( spaceName, space ) {
1492
+ space.cache = "_" + spaceName;
1493
+ space.props.alpha = {
1494
+ idx: 3,
1495
+ type: "percent",
1496
+ def: 1
1497
+ };
1498
+ } );
1499
+
1500
+ // Populate the class2type map
1501
+ jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1502
+ function( _i, name ) {
1503
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
1504
+ } );
1505
+
1506
+ function getType( obj ) {
1507
+ if ( obj == null ) {
1508
+ return obj + "";
1509
+ }
1510
+
1511
+ return typeof obj === "object" ?
1512
+ class2type[ toString.call( obj ) ] || "object" :
1513
+ typeof obj;
1514
+ }
1515
+
1516
+ function clamp( value, prop, allowEmpty ) {
1517
+ var type = propTypes[ prop.type ] || {};
1518
+
1519
+ if ( value == null ) {
1520
+ return ( allowEmpty || !prop.def ) ? null : prop.def;
1521
+ }
1522
+
1523
+ // ~~ is an short way of doing floor for positive numbers
1524
+ value = type.floor ? ~~value : parseFloat( value );
1525
+
1526
+ // IE will pass in empty strings as value for alpha,
1527
+ // which will hit this case
1528
+ if ( isNaN( value ) ) {
1529
+ return prop.def;
1530
+ }
1531
+
1532
+ if ( type.mod ) {
1533
+
1534
+ // we add mod before modding to make sure that negatives values
1535
+ // get converted properly: -10 -> 350
1536
+ return ( value + type.mod ) % type.mod;
1537
+ }
1538
+
1539
+ // for now all property types without mod have min and max
1540
+ return Math.min( type.max, Math.max( 0, value ) );
1541
+ }
1542
+
1543
+ function stringParse( string ) {
1544
+ var inst = color(),
1545
+ rgba = inst._rgba = [];
1546
+
1547
+ string = string.toLowerCase();
1548
+
1549
+ each( stringParsers, function( _i, parser ) {
1550
+ var parsed,
1551
+ match = parser.re.exec( string ),
1552
+ values = match && parser.parse( match ),
1553
+ spaceName = parser.space || "rgba";
1554
+
1555
+ if ( values ) {
1556
+ parsed = inst[ spaceName ]( values );
1557
+
1558
+ // if this was an rgba parse the assignment might happen twice
1559
+ // oh well....
1560
+ inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1561
+ rgba = inst._rgba = parsed._rgba;
1562
+
1563
+ // exit each( stringParsers ) here because we matched
1564
+ return false;
1565
+ }
1566
+ } );
1567
+
1568
+ // Found a stringParser that handled it
1569
+ if ( rgba.length ) {
1570
+
1571
+ // if this came from a parsed string, force "transparent" when alpha is 0
1572
+ // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1573
+ if ( rgba.join() === "0,0,0,0" ) {
1574
+ jQuery.extend( rgba, colors.transparent );
1575
+ }
1576
+ return inst;
1577
+ }
1578
+
1579
+ // named colors
1580
+ return colors[ string ];
1581
+ }
1582
+
1583
+ color.fn = jQuery.extend( color.prototype, {
1584
+ parse: function( red, green, blue, alpha ) {
1585
+ if ( red === undefined ) {
1586
+ this._rgba = [ null, null, null, null ];
1587
+ return this;
1588
+ }
1589
+ if ( red.jquery || red.nodeType ) {
1590
+ red = jQuery( red ).css( green );
1591
+ green = undefined;
1592
+ }
1593
+
1594
+ var inst = this,
1595
+ type = getType( red ),
1596
+ rgba = this._rgba = [];
1597
+
1598
+ // more than 1 argument specified - assume ( red, green, blue, alpha )
1599
+ if ( green !== undefined ) {
1600
+ red = [ red, green, blue, alpha ];
1601
+ type = "array";
1602
+ }
1603
+
1604
+ if ( type === "string" ) {
1605
+ return this.parse( stringParse( red ) || colors._default );
1606
+ }
1607
+
1608
+ if ( type === "array" ) {
1609
+ each( spaces.rgba.props, function( _key, prop ) {
1610
+ rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1611
+ } );
1612
+ return this;
1613
+ }
1614
+
1615
+ if ( type === "object" ) {
1616
+ if ( red instanceof color ) {
1617
+ each( spaces, function( _spaceName, space ) {
1618
+ if ( red[ space.cache ] ) {
1619
+ inst[ space.cache ] = red[ space.cache ].slice();
1620
+ }
1621
+ } );
1622
+ } else {
1623
+ each( spaces, function( _spaceName, space ) {
1624
+ var cache = space.cache;
1625
+ each( space.props, function( key, prop ) {
1626
+
1627
+ // if the cache doesn't exist, and we know how to convert
1628
+ if ( !inst[ cache ] && space.to ) {
1629
+
1630
+ // if the value was null, we don't need to copy it
1631
+ // if the key was alpha, we don't need to copy it either
1632
+ if ( key === "alpha" || red[ key ] == null ) {
1633
+ return;
1634
+ }
1635
+ inst[ cache ] = space.to( inst._rgba );
1636
+ }
1637
+
1638
+ // this is the only case where we allow nulls for ALL properties.
1639
+ // call clamp with alwaysAllowEmpty
1640
+ inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1641
+ } );
1642
+
1643
+ // everything defined but alpha?
1644
+ if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
1645
+
1646
+ // use the default of 1
1647
+ if ( inst[ cache ][ 3 ] == null ) {
1648
+ inst[ cache ][ 3 ] = 1;
1649
+ }
1650
+
1651
+ if ( space.from ) {
1652
+ inst._rgba = space.from( inst[ cache ] );
1653
+ }
1654
+ }
1655
+ } );
1656
+ }
1657
+ return this;
1658
+ }
1659
+ },
1660
+ is: function( compare ) {
1661
+ var is = color( compare ),
1662
+ same = true,
1663
+ inst = this;
1664
+
1665
+ each( spaces, function( _, space ) {
1666
+ var localCache,
1667
+ isCache = is[ space.cache ];
1668
+ if ( isCache ) {
1669
+ localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1670
+ each( space.props, function( _, prop ) {
1671
+ if ( isCache[ prop.idx ] != null ) {
1672
+ same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1673
+ return same;
1674
+ }
1675
+ } );
1676
+ }
1677
+ return same;
1678
+ } );
1679
+ return same;
1680
+ },
1681
+ _space: function() {
1682
+ var used = [],
1683
+ inst = this;
1684
+ each( spaces, function( spaceName, space ) {
1685
+ if ( inst[ space.cache ] ) {
1686
+ used.push( spaceName );
1687
+ }
1688
+ } );
1689
+ return used.pop();
1690
+ },
1691
+ transition: function( other, distance ) {
1692
+ var end = color( other ),
1693
+ spaceName = end._space(),
1694
+ space = spaces[ spaceName ],
1695
+ startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1696
+ start = startColor[ space.cache ] || space.to( startColor._rgba ),
1697
+ result = start.slice();
1698
+
1699
+ end = end[ space.cache ];
1700
+ each( space.props, function( _key, prop ) {
1701
+ var index = prop.idx,
1702
+ startValue = start[ index ],
1703
+ endValue = end[ index ],
1704
+ type = propTypes[ prop.type ] || {};
1705
+
1706
+ // if null, don't override start value
1707
+ if ( endValue === null ) {
1708
+ return;
1709
+ }
1710
+
1711
+ // if null - use end
1712
+ if ( startValue === null ) {
1713
+ result[ index ] = endValue;
1714
+ } else {
1715
+ if ( type.mod ) {
1716
+ if ( endValue - startValue > type.mod / 2 ) {
1717
+ startValue += type.mod;
1718
+ } else if ( startValue - endValue > type.mod / 2 ) {
1719
+ startValue -= type.mod;
1720
+ }
1721
+ }
1722
+ result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1723
+ }
1724
+ } );
1725
+ return this[ spaceName ]( result );
1726
+ },
1727
+ blend: function( opaque ) {
1728
+
1729
+ // if we are already opaque - return ourself
1730
+ if ( this._rgba[ 3 ] === 1 ) {
1731
+ return this;
1732
+ }
1733
+
1734
+ var rgb = this._rgba.slice(),
1735
+ a = rgb.pop(),
1736
+ blend = color( opaque )._rgba;
1737
+
1738
+ return color( jQuery.map( rgb, function( v, i ) {
1739
+ return ( 1 - a ) * blend[ i ] + a * v;
1740
+ } ) );
1741
+ },
1742
+ toRgbaString: function() {
1743
+ var prefix = "rgba(",
1744
+ rgba = jQuery.map( this._rgba, function( v, i ) {
1745
+ if ( v != null ) {
1746
+ return v;
1747
+ }
1748
+ return i > 2 ? 1 : 0;
1749
+ } );
1750
+
1751
+ if ( rgba[ 3 ] === 1 ) {
1752
+ rgba.pop();
1753
+ prefix = "rgb(";
1754
+ }
1755
+
1756
+ return prefix + rgba.join() + ")";
1757
+ },
1758
+ toHslaString: function() {
1759
+ var prefix = "hsla(",
1760
+ hsla = jQuery.map( this.hsla(), function( v, i ) {
1761
+ if ( v == null ) {
1762
+ v = i > 2 ? 1 : 0;
1763
+ }
1764
+
1765
+ // catch 1 and 2
1766
+ if ( i && i < 3 ) {
1767
+ v = Math.round( v * 100 ) + "%";
1768
+ }
1769
+ return v;
1770
+ } );
1771
+
1772
+ if ( hsla[ 3 ] === 1 ) {
1773
+ hsla.pop();
1774
+ prefix = "hsl(";
1775
+ }
1776
+ return prefix + hsla.join() + ")";
1777
+ },
1778
+ toHexString: function( includeAlpha ) {
1779
+ var rgba = this._rgba.slice(),
1780
+ alpha = rgba.pop();
1781
+
1782
+ if ( includeAlpha ) {
1783
+ rgba.push( ~~( alpha * 255 ) );
1784
+ }
1785
+
1786
+ return "#" + jQuery.map( rgba, function( v ) {
1787
+
1788
+ // default to 0 when nulls exist
1789
+ v = ( v || 0 ).toString( 16 );
1790
+ return v.length === 1 ? "0" + v : v;
1791
+ } ).join( "" );
1792
+ },
1793
+ toString: function() {
1794
+ return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
1795
+ }
1796
+ } );
1797
+ color.fn.parse.prototype = color.fn;
1798
+
1799
+ // hsla conversions adapted from:
1800
+ // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1801
+
1802
+ function hue2rgb( p, q, h ) {
1803
+ h = ( h + 1 ) % 1;
1804
+ if ( h * 6 < 1 ) {
1805
+ return p + ( q - p ) * h * 6;
1806
+ }
1807
+ if ( h * 2 < 1 ) {
1808
+ return q;
1809
+ }
1810
+ if ( h * 3 < 2 ) {
1811
+ return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1812
+ }
1813
+ return p;
1814
+ }
1815
+
1816
+ spaces.hsla.to = function( rgba ) {
1817
+ if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1818
+ return [ null, null, null, rgba[ 3 ] ];
1819
+ }
1820
+ var r = rgba[ 0 ] / 255,
1821
+ g = rgba[ 1 ] / 255,
1822
+ b = rgba[ 2 ] / 255,
1823
+ a = rgba[ 3 ],
1824
+ max = Math.max( r, g, b ),
1825
+ min = Math.min( r, g, b ),
1826
+ diff = max - min,
1827
+ add = max + min,
1828
+ l = add * 0.5,
1829
+ h, s;
1830
+
1831
+ if ( min === max ) {
1832
+ h = 0;
1833
+ } else if ( r === max ) {
1834
+ h = ( 60 * ( g - b ) / diff ) + 360;
1835
+ } else if ( g === max ) {
1836
+ h = ( 60 * ( b - r ) / diff ) + 120;
1837
+ } else {
1838
+ h = ( 60 * ( r - g ) / diff ) + 240;
1839
+ }
1840
+
1841
+ // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1842
+ // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1843
+ if ( diff === 0 ) {
1844
+ s = 0;
1845
+ } else if ( l <= 0.5 ) {
1846
+ s = diff / add;
1847
+ } else {
1848
+ s = diff / ( 2 - add );
1849
+ }
1850
+ return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1851
+ };
1852
+
1853
+ spaces.hsla.from = function( hsla ) {
1854
+ if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1855
+ return [ null, null, null, hsla[ 3 ] ];
1856
+ }
1857
+ var h = hsla[ 0 ] / 360,
1858
+ s = hsla[ 1 ],
1859
+ l = hsla[ 2 ],
1860
+ a = hsla[ 3 ],
1861
+ q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1862
+ p = 2 * l - q;
1863
+
1864
+ return [
1865
+ Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1866
+ Math.round( hue2rgb( p, q, h ) * 255 ),
1867
+ Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1868
+ a
1869
+ ];
1870
+ };
1871
+
1872
+
1873
+ each( spaces, function( spaceName, space ) {
1874
+ var props = space.props,
1875
+ cache = space.cache,
1876
+ to = space.to,
1877
+ from = space.from;
1878
+
1879
+ // makes rgba() and hsla()
1880
+ color.fn[ spaceName ] = function( value ) {
1881
+
1882
+ // generate a cache for this space if it doesn't exist
1883
+ if ( to && !this[ cache ] ) {
1884
+ this[ cache ] = to( this._rgba );
1885
+ }
1886
+ if ( value === undefined ) {
1887
+ return this[ cache ].slice();
1888
+ }
1889
+
1890
+ var ret,
1891
+ type = getType( value ),
1892
+ arr = ( type === "array" || type === "object" ) ? value : arguments,
1893
+ local = this[ cache ].slice();
1894
+
1895
+ each( props, function( key, prop ) {
1896
+ var val = arr[ type === "object" ? key : prop.idx ];
1897
+ if ( val == null ) {
1898
+ val = local[ prop.idx ];
1899
+ }
1900
+ local[ prop.idx ] = clamp( val, prop );
1901
+ } );
1902
+
1903
+ if ( from ) {
1904
+ ret = color( from( local ) );
1905
+ ret[ cache ] = local;
1906
+ return ret;
1907
+ } else {
1908
+ return color( local );
1909
+ }
1910
+ };
1911
+
1912
+ // makes red() green() blue() alpha() hue() saturation() lightness()
1913
+ each( props, function( key, prop ) {
1914
+
1915
+ // alpha is included in more than one space
1916
+ if ( color.fn[ key ] ) {
1917
+ return;
1918
+ }
1919
+ color.fn[ key ] = function( value ) {
1920
+ var local, cur, match, fn,
1921
+ vtype = getType( value );
1922
+
1923
+ if ( key === "alpha" ) {
1924
+ fn = this._hsla ? "hsla" : "rgba";
1925
+ } else {
1926
+ fn = spaceName;
1927
+ }
1928
+ local = this[ fn ]();
1929
+ cur = local[ prop.idx ];
1930
+
1931
+ if ( vtype === "undefined" ) {
1932
+ return cur;
1933
+ }
1934
+
1935
+ if ( vtype === "function" ) {
1936
+ value = value.call( this, cur );
1937
+ vtype = getType( value );
1938
+ }
1939
+ if ( value == null && prop.empty ) {
1940
+ return this;
1941
+ }
1942
+ if ( vtype === "string" ) {
1943
+ match = rplusequals.exec( value );
1944
+ if ( match ) {
1945
+ value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1946
+ }
1947
+ }
1948
+ local[ prop.idx ] = value;
1949
+ return this[ fn ]( local );
1950
+ };
1951
+ } );
1952
+ } );
1953
+
1954
+ // add cssHook and .fx.step function for each named hook.
1955
+ // accept a space separated string of properties
1956
+ color.hook = function( hook ) {
1957
+ var hooks = hook.split( " " );
1958
+ each( hooks, function( _i, hook ) {
1959
+ jQuery.cssHooks[ hook ] = {
1960
+ set: function( elem, value ) {
1961
+ var parsed, curElem,
1962
+ backgroundColor = "";
1963
+
1964
+ if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
1965
+ value = color( parsed || value );
1966
+ if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
1967
+ curElem = hook === "backgroundColor" ? elem.parentNode : elem;
1968
+ while (
1969
+ ( backgroundColor === "" || backgroundColor === "transparent" ) &&
1970
+ curElem && curElem.style
1971
+ ) {
1972
+ try {
1973
+ backgroundColor = jQuery.css( curElem, "backgroundColor" );
1974
+ curElem = curElem.parentNode;
1975
+ } catch ( e ) {
1976
+ }
1977
+ }
1978
+
1979
+ value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
1980
+ backgroundColor :
1981
+ "_default" );
1982
+ }
1983
+
1984
+ value = value.toRgbaString();
1985
+ }
1986
+ try {
1987
+ elem.style[ hook ] = value;
1988
+ } catch ( e ) {
1989
+
1990
+ // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
1991
+ }
1992
+ }
1993
+ };
1994
+ jQuery.fx.step[ hook ] = function( fx ) {
1995
+ if ( !fx.colorInit ) {
1996
+ fx.start = color( fx.elem, hook );
1997
+ fx.end = color( fx.end );
1998
+ fx.colorInit = true;
1999
+ }
2000
+ jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
2001
+ };
2002
+ } );
2003
+
2004
+ };
2005
+
2006
+ color.hook( stepHooks );
2007
+
2008
+ jQuery.cssHooks.borderColor = {
2009
+ expand: function( value ) {
2010
+ var expanded = {};
2011
+
2012
+ each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
2013
+ expanded[ "border" + part + "Color" ] = value;
2014
+ } );
2015
+ return expanded;
2016
+ }
2017
+ };
2018
+
2019
+ // Basic color names only.
2020
+ // Usage of any of the other color names requires adding yourself or including
2021
+ // jquery.color.svg-names.js.
2022
+ colors = jQuery.Color.names = {
2023
+
2024
+ // 4.1. Basic color keywords
2025
+ aqua: "#00ffff",
2026
+ black: "#000000",
2027
+ blue: "#0000ff",
2028
+ fuchsia: "#ff00ff",
2029
+ gray: "#808080",
2030
+ green: "#008000",
2031
+ lime: "#00ff00",
2032
+ maroon: "#800000",
2033
+ navy: "#000080",
2034
+ olive: "#808000",
2035
+ purple: "#800080",
2036
+ red: "#ff0000",
2037
+ silver: "#c0c0c0",
2038
+ teal: "#008080",
2039
+ white: "#ffffff",
2040
+ yellow: "#ffff00",
2041
+
2042
+ // 4.2.3. "transparent" color keyword
2043
+ transparent: [ null, null, null, 0 ],
2044
+
2045
+ _default: "#ffffff"
2046
+ };
2047
+
2048
+
2049
+ /*!
2050
+ * jQuery UI Effects 1.13.1
2051
+ * http://jqueryui.com
2052
+ *
2053
+ * Copyright jQuery Foundation and other contributors
2054
+ * Released under the MIT license.
2055
+ * http://jquery.org/license
2056
+ */
2057
+
2058
+ //>>label: Effects Core
2059
+ //>>group: Effects
2060
+ /* eslint-disable max-len */
2061
+ //>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2062
+ /* eslint-enable max-len */
2063
+ //>>docs: http://api.jqueryui.com/category/effects-core/
2064
+ //>>demos: http://jqueryui.com/effect/
2065
+
2066
+
2067
+ var dataSpace = "ui-effects-",
2068
+ dataSpaceStyle = "ui-effects-style",
2069
+ dataSpaceAnimated = "ui-effects-animated";
2070
+
2071
+ $.effects = {
2072
+ effect: {}
2073
+ };
2074
+
2075
+ /******************************************************************************/
2076
+ /****************************** CLASS ANIMATIONS ******************************/
2077
+ /******************************************************************************/
2078
+ ( function() {
2079
+
2080
+ var classAnimationActions = [ "add", "remove", "toggle" ],
2081
+ shorthandStyles = {
2082
+ border: 1,
2083
+ borderBottom: 1,
2084
+ borderColor: 1,
2085
+ borderLeft: 1,
2086
+ borderRight: 1,
2087
+ borderTop: 1,
2088
+ borderWidth: 1,
2089
+ margin: 1,
2090
+ padding: 1
2091
+ };
2092
+
2093
+ $.each(
2094
+ [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2095
+ function( _, prop ) {
2096
+ $.fx.step[ prop ] = function( fx ) {
2097
+ if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2098
+ jQuery.style( fx.elem, prop, fx.end );
2099
+ fx.setAttr = true;
2100
+ }
2101
+ };
2102
+ }
2103
+ );
2104
+
2105
+ function camelCase( string ) {
2106
+ return string.replace( /-([\da-z])/gi, function( all, letter ) {
2107
+ return letter.toUpperCase();
2108
+ } );
2109
+ }
2110
+
2111
+ function getElementStyles( elem ) {
2112
+ var key, len,
2113
+ style = elem.ownerDocument.defaultView ?
2114
+ elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
2115
+ elem.currentStyle,
2116
+ styles = {};
2117
+
2118
+ if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
2119
+ len = style.length;
2120
+ while ( len-- ) {
2121
+ key = style[ len ];
2122
+ if ( typeof style[ key ] === "string" ) {
2123
+ styles[ camelCase( key ) ] = style[ key ];
2124
+ }
2125
+ }
2126
+
2127
+ // Support: Opera, IE <9
2128
+ } else {
2129
+ for ( key in style ) {
2130
+ if ( typeof style[ key ] === "string" ) {
2131
+ styles[ key ] = style[ key ];
2132
+ }
2133
+ }
2134
+ }
2135
+
2136
+ return styles;
2137
+ }
2138
+
2139
+ function styleDifference( oldStyle, newStyle ) {
2140
+ var diff = {},
2141
+ name, value;
2142
+
2143
+ for ( name in newStyle ) {
2144
+ value = newStyle[ name ];
2145
+ if ( oldStyle[ name ] !== value ) {
2146
+ if ( !shorthandStyles[ name ] ) {
2147
+ if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2148
+ diff[ name ] = value;
2149
+ }
2150
+ }
2151
+ }
2152
+ }
2153
+
2154
+ return diff;
2155
+ }
2156
+
2157
+ // Support: jQuery <1.8
2158
+ if ( !$.fn.addBack ) {
2159
+ $.fn.addBack = function( selector ) {
2160
+ return this.add( selector == null ?
2161
+ this.prevObject : this.prevObject.filter( selector )
2162
+ );
2163
+ };
2164
+ }
2165
+
2166
+ $.effects.animateClass = function( value, duration, easing, callback ) {
2167
+ var o = $.speed( duration, easing, callback );
2168
+
2169
+ return this.queue( function() {
2170
+ var animated = $( this ),
2171
+ baseClass = animated.attr( "class" ) || "",
2172
+ applyClassChange,
2173
+ allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2174
+
2175
+ // Map the animated objects to store the original styles.
2176
+ allAnimations = allAnimations.map( function() {
2177
+ var el = $( this );
2178
+ return {
2179
+ el: el,
2180
+ start: getElementStyles( this )
2181
+ };
2182
+ } );
2183
+
2184
+ // Apply class change
2185
+ applyClassChange = function() {
2186
+ $.each( classAnimationActions, function( i, action ) {
2187
+ if ( value[ action ] ) {
2188
+ animated[ action + "Class" ]( value[ action ] );
2189
+ }
2190
+ } );
2191
+ };
2192
+ applyClassChange();
2193
+
2194
+ // Map all animated objects again - calculate new styles and diff
2195
+ allAnimations = allAnimations.map( function() {
2196
+ this.end = getElementStyles( this.el[ 0 ] );
2197
+ this.diff = styleDifference( this.start, this.end );
2198
+ return this;
2199
+ } );
2200
+
2201
+ // Apply original class
2202
+ animated.attr( "class", baseClass );
2203
+
2204
+ // Map all animated objects again - this time collecting a promise
2205
+ allAnimations = allAnimations.map( function() {
2206
+ var styleInfo = this,
2207
+ dfd = $.Deferred(),
2208
+ opts = $.extend( {}, o, {
2209
+ queue: false,
2210
+ complete: function() {
2211
+ dfd.resolve( styleInfo );
2212
+ }
2213
+ } );
2214
+
2215
+ this.el.animate( this.diff, opts );
2216
+ return dfd.promise();
2217
+ } );
2218
+
2219
+ // Once all animations have completed:
2220
+ $.when.apply( $, allAnimations.get() ).done( function() {
2221
+
2222
+ // Set the final class
2223
+ applyClassChange();
2224
+
2225
+ // For each animated element,
2226
+ // clear all css properties that were animated
2227
+ $.each( arguments, function() {
2228
+ var el = this.el;
2229
+ $.each( this.diff, function( key ) {
2230
+ el.css( key, "" );
2231
+ } );
2232
+ } );
2233
+
2234
+ // This is guarnteed to be there if you use jQuery.speed()
2235
+ // it also handles dequeuing the next anim...
2236
+ o.complete.call( animated[ 0 ] );
2237
+ } );
2238
+ } );
2239
+ };
2240
+
2241
+ $.fn.extend( {
2242
+ addClass: ( function( orig ) {
2243
+ return function( classNames, speed, easing, callback ) {
2244
+ return speed ?
2245
+ $.effects.animateClass.call( this,
2246
+ { add: classNames }, speed, easing, callback ) :
2247
+ orig.apply( this, arguments );
2248
+ };
2249
+ } )( $.fn.addClass ),
2250
+
2251
+ removeClass: ( function( orig ) {
2252
+ return function( classNames, speed, easing, callback ) {
2253
+ return arguments.length > 1 ?
2254
+ $.effects.animateClass.call( this,
2255
+ { remove: classNames }, speed, easing, callback ) :
2256
+ orig.apply( this, arguments );
2257
+ };
2258
+ } )( $.fn.removeClass ),
2259
+
2260
+ toggleClass: ( function( orig ) {
2261
+ return function( classNames, force, speed, easing, callback ) {
2262
+ if ( typeof force === "boolean" || force === undefined ) {
2263
+ if ( !speed ) {
2264
+
2265
+ // Without speed parameter
2266
+ return orig.apply( this, arguments );
2267
+ } else {
2268
+ return $.effects.animateClass.call( this,
2269
+ ( force ? { add: classNames } : { remove: classNames } ),
2270
+ speed, easing, callback );
2271
+ }
2272
+ } else {
2273
+
2274
+ // Without force parameter
2275
+ return $.effects.animateClass.call( this,
2276
+ { toggle: classNames }, force, speed, easing );
2277
+ }
2278
+ };
2279
+ } )( $.fn.toggleClass ),
2280
+
2281
+ switchClass: function( remove, add, speed, easing, callback ) {
2282
+ return $.effects.animateClass.call( this, {
2283
+ add: add,
2284
+ remove: remove
2285
+ }, speed, easing, callback );
2286
+ }
2287
+ } );
2288
+
2289
+ } )();
2290
+
2291
+ /******************************************************************************/
2292
+ /*********************************** EFFECTS **********************************/
2293
+ /******************************************************************************/
2294
+
2295
+ ( function() {
2296
+
2297
+ if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2298
+ $.expr.pseudos.animated = ( function( orig ) {
2299
+ return function( elem ) {
2300
+ return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2301
+ };
2302
+ } )( $.expr.pseudos.animated );
2303
+ }
2304
+
2305
+ if ( $.uiBackCompat !== false ) {
2306
+ $.extend( $.effects, {
2307
+
2308
+ // Saves a set of properties in a data storage
2309
+ save: function( element, set ) {
2310
+ var i = 0, length = set.length;
2311
+ for ( ; i < length; i++ ) {
2312
+ if ( set[ i ] !== null ) {
2313
+ element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2314
+ }
2315
+ }
2316
+ },
2317
+
2318
+ // Restores a set of previously saved properties from a data storage
2319
+ restore: function( element, set ) {
2320
+ var val, i = 0, length = set.length;
2321
+ for ( ; i < length; i++ ) {
2322
+ if ( set[ i ] !== null ) {
2323
+ val = element.data( dataSpace + set[ i ] );
2324
+ element.css( set[ i ], val );
2325
+ }
2326
+ }
2327
+ },
2328
+
2329
+ setMode: function( el, mode ) {
2330
+ if ( mode === "toggle" ) {
2331
+ mode = el.is( ":hidden" ) ? "show" : "hide";
2332
+ }
2333
+ return mode;
2334
+ },
2335
+
2336
+ // Wraps the element around a wrapper that copies position properties
2337
+ createWrapper: function( element ) {
2338
+
2339
+ // If the element is already wrapped, return it
2340
+ if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2341
+ return element.parent();
2342
+ }
2343
+
2344
+ // Wrap the element
2345
+ var props = {
2346
+ width: element.outerWidth( true ),
2347
+ height: element.outerHeight( true ),
2348
+ "float": element.css( "float" )
2349
+ },
2350
+ wrapper = $( "<div></div>" )
2351
+ .addClass( "ui-effects-wrapper" )
2352
+ .css( {
2353
+ fontSize: "100%",
2354
+ background: "transparent",
2355
+ border: "none",
2356
+ margin: 0,
2357
+ padding: 0
2358
+ } ),
2359
+
2360
+ // Store the size in case width/height are defined in % - Fixes #5245
2361
+ size = {
2362
+ width: element.width(),
2363
+ height: element.height()
2364
+ },
2365
+ active = document.activeElement;
2366
+
2367
+ // Support: Firefox
2368
+ // Firefox incorrectly exposes anonymous content
2369
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2370
+ try {
2371
+ // eslint-disable-next-line no-unused-expressions
2372
+ active.id;
2373
+ } catch ( e ) {
2374
+ active = document.body;
2375
+ }
2376
+
2377
+ element.wrap( wrapper );
2378
+
2379
+ // Fixes #7595 - Elements lose focus when wrapped.
2380
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2381
+ $( active ).trigger( "focus" );
2382
+ }
2383
+
2384
+ // Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2385
+ // lose the reference to the wrapped element
2386
+ wrapper = element.parent();
2387
+
2388
+ // Transfer positioning properties to the wrapper
2389
+ if ( element.css( "position" ) === "static" ) {
2390
+ wrapper.css( { position: "relative" } );
2391
+ element.css( { position: "relative" } );
2392
+ } else {
2393
+ $.extend( props, {
2394
+ position: element.css( "position" ),
2395
+ zIndex: element.css( "z-index" )
2396
+ } );
2397
+ $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2398
+ props[ pos ] = element.css( pos );
2399
+ if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2400
+ props[ pos ] = "auto";
2401
+ }
2402
+ } );
2403
+ element.css( {
2404
+ position: "relative",
2405
+ top: 0,
2406
+ left: 0,
2407
+ right: "auto",
2408
+ bottom: "auto"
2409
+ } );
2410
+ }
2411
+ element.css( size );
2412
+
2413
+ return wrapper.css( props ).show();
2414
+ },
2415
+
2416
+ removeWrapper: function( element ) {
2417
+ var active = document.activeElement;
2418
+
2419
+ if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2420
+ element.parent().replaceWith( element );
2421
+
2422
+ // Fixes #7595 - Elements lose focus when wrapped.
2423
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2424
+ $( active ).trigger( "focus" );
2425
+ }
2426
+ }
2427
+
2428
+ return element;
2429
+ }
2430
+ } );
2431
+ }
2432
+
2433
+ $.extend( $.effects, {
2434
+ version: "1.13.1",
2435
+
2436
+ define: function( name, mode, effect ) {
2437
+ if ( !effect ) {
2438
+ effect = mode;
2439
+ mode = "effect";
2440
+ }
2441
+
2442
+ $.effects.effect[ name ] = effect;
2443
+ $.effects.effect[ name ].mode = mode;
2444
+
2445
+ return effect;
2446
+ },
2447
+
2448
+ scaledDimensions: function( element, percent, direction ) {
2449
+ if ( percent === 0 ) {
2450
+ return {
2451
+ height: 0,
2452
+ width: 0,
2453
+ outerHeight: 0,
2454
+ outerWidth: 0
2455
+ };
2456
+ }
2457
+
2458
+ var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2459
+ y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2460
+
2461
+ return {
2462
+ height: element.height() * y,
2463
+ width: element.width() * x,
2464
+ outerHeight: element.outerHeight() * y,
2465
+ outerWidth: element.outerWidth() * x
2466
+ };
2467
+
2468
+ },
2469
+
2470
+ clipToBox: function( animation ) {
2471
+ return {
2472
+ width: animation.clip.right - animation.clip.left,
2473
+ height: animation.clip.bottom - animation.clip.top,
2474
+ left: animation.clip.left,
2475
+ top: animation.clip.top
2476
+ };
2477
+ },
2478
+
2479
+ // Injects recently queued functions to be first in line (after "inprogress")
2480
+ unshift: function( element, queueLength, count ) {
2481
+ var queue = element.queue();
2482
+
2483
+ if ( queueLength > 1 ) {
2484
+ queue.splice.apply( queue,
2485
+ [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2486
+ }
2487
+ element.dequeue();
2488
+ },
2489
+
2490
+ saveStyle: function( element ) {
2491
+ element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2492
+ },
2493
+
2494
+ restoreStyle: function( element ) {
2495
+ element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2496
+ element.removeData( dataSpaceStyle );
2497
+ },
2498
+
2499
+ mode: function( element, mode ) {
2500
+ var hidden = element.is( ":hidden" );
2501
+
2502
+ if ( mode === "toggle" ) {
2503
+ mode = hidden ? "show" : "hide";
2504
+ }
2505
+ if ( hidden ? mode === "hide" : mode === "show" ) {
2506
+ mode = "none";
2507
+ }
2508
+ return mode;
2509
+ },
2510
+
2511
+ // Translates a [top,left] array into a baseline value
2512
+ getBaseline: function( origin, original ) {
2513
+ var y, x;
2514
+
2515
+ switch ( origin[ 0 ] ) {
2516
+ case "top":
2517
+ y = 0;
2518
+ break;
2519
+ case "middle":
2520
+ y = 0.5;
2521
+ break;
2522
+ case "bottom":
2523
+ y = 1;
2524
+ break;
2525
+ default:
2526
+ y = origin[ 0 ] / original.height;
2527
+ }
2528
+
2529
+ switch ( origin[ 1 ] ) {
2530
+ case "left":
2531
+ x = 0;
2532
+ break;
2533
+ case "center":
2534
+ x = 0.5;
2535
+ break;
2536
+ case "right":
2537
+ x = 1;
2538
+ break;
2539
+ default:
2540
+ x = origin[ 1 ] / original.width;
2541
+ }
2542
+
2543
+ return {
2544
+ x: x,
2545
+ y: y
2546
+ };
2547
+ },
2548
+
2549
+ // Creates a placeholder element so that the original element can be made absolute
2550
+ createPlaceholder: function( element ) {
2551
+ var placeholder,
2552
+ cssPosition = element.css( "position" ),
2553
+ position = element.position();
2554
+
2555
+ // Lock in margins first to account for form elements, which
2556
+ // will change margin if you explicitly set height
2557
+ // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2558
+ // Support: Safari
2559
+ element.css( {
2560
+ marginTop: element.css( "marginTop" ),
2561
+ marginBottom: element.css( "marginBottom" ),
2562
+ marginLeft: element.css( "marginLeft" ),
2563
+ marginRight: element.css( "marginRight" )
2564
+ } )
2565
+ .outerWidth( element.outerWidth() )
2566
+ .outerHeight( element.outerHeight() );
2567
+
2568
+ if ( /^(static|relative)/.test( cssPosition ) ) {
2569
+ cssPosition = "absolute";
2570
+
2571
+ placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2572
+
2573
+ // Convert inline to inline block to account for inline elements
2574
+ // that turn to inline block based on content (like img)
2575
+ display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2576
+ "inline-block" :
2577
+ "block",
2578
+ visibility: "hidden",
2579
+
2580
+ // Margins need to be set to account for margin collapse
2581
+ marginTop: element.css( "marginTop" ),
2582
+ marginBottom: element.css( "marginBottom" ),
2583
+ marginLeft: element.css( "marginLeft" ),
2584
+ marginRight: element.css( "marginRight" ),
2585
+ "float": element.css( "float" )
2586
+ } )
2587
+ .outerWidth( element.outerWidth() )
2588
+ .outerHeight( element.outerHeight() )
2589
+ .addClass( "ui-effects-placeholder" );
2590
+
2591
+ element.data( dataSpace + "placeholder", placeholder );
2592
+ }
2593
+
2594
+ element.css( {
2595
+ position: cssPosition,
2596
+ left: position.left,
2597
+ top: position.top
2598
+ } );
2599
+
2600
+ return placeholder;
2601
+ },
2602
+
2603
+ removePlaceholder: function( element ) {
2604
+ var dataKey = dataSpace + "placeholder",
2605
+ placeholder = element.data( dataKey );
2606
+
2607
+ if ( placeholder ) {
2608
+ placeholder.remove();
2609
+ element.removeData( dataKey );
2610
+ }
2611
+ },
2612
+
2613
+ // Removes a placeholder if it exists and restores
2614
+ // properties that were modified during placeholder creation
2615
+ cleanUp: function( element ) {
2616
+ $.effects.restoreStyle( element );
2617
+ $.effects.removePlaceholder( element );
2618
+ },
2619
+
2620
+ setTransition: function( element, list, factor, value ) {
2621
+ value = value || {};
2622
+ $.each( list, function( i, x ) {
2623
+ var unit = element.cssUnit( x );
2624
+ if ( unit[ 0 ] > 0 ) {
2625
+ value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2626
+ }
2627
+ } );
2628
+ return value;
2629
+ }
2630
+ } );
2631
+
2632
+ // Return an effect options object for the given parameters:
2633
+ function _normalizeArguments( effect, options, speed, callback ) {
2634
+
2635
+ // Allow passing all options as the first parameter
2636
+ if ( $.isPlainObject( effect ) ) {
2637
+ options = effect;
2638
+ effect = effect.effect;
2639
+ }
2640
+
2641
+ // Convert to an object
2642
+ effect = { effect: effect };
2643
+
2644
+ // Catch (effect, null, ...)
2645
+ if ( options == null ) {
2646
+ options = {};
2647
+ }
2648
+
2649
+ // Catch (effect, callback)
2650
+ if ( typeof options === "function" ) {
2651
+ callback = options;
2652
+ speed = null;
2653
+ options = {};
2654
+ }
2655
+
2656
+ // Catch (effect, speed, ?)
2657
+ if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2658
+ callback = speed;
2659
+ speed = options;
2660
+ options = {};
2661
+ }
2662
+
2663
+ // Catch (effect, options, callback)
2664
+ if ( typeof speed === "function" ) {
2665
+ callback = speed;
2666
+ speed = null;
2667
+ }
2668
+
2669
+ // Add options to effect
2670
+ if ( options ) {
2671
+ $.extend( effect, options );
2672
+ }
2673
+
2674
+ speed = speed || options.duration;
2675
+ effect.duration = $.fx.off ? 0 :
2676
+ typeof speed === "number" ? speed :
2677
+ speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2678
+ $.fx.speeds._default;
2679
+
2680
+ effect.complete = callback || options.complete;
2681
+
2682
+ return effect;
2683
+ }
2684
+
2685
+ function standardAnimationOption( option ) {
2686
+
2687
+ // Valid standard speeds (nothing, number, named speed)
2688
+ if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2689
+ return true;
2690
+ }
2691
+
2692
+ // Invalid strings - treat as "normal" speed
2693
+ if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2694
+ return true;
2695
+ }
2696
+
2697
+ // Complete callback
2698
+ if ( typeof option === "function" ) {
2699
+ return true;
2700
+ }
2701
+
2702
+ // Options hash (but not naming an effect)
2703
+ if ( typeof option === "object" && !option.effect ) {
2704
+ return true;
2705
+ }
2706
+
2707
+ // Didn't match any standard API
2708
+ return false;
2709
+ }
2710
+
2711
+ $.fn.extend( {
2712
+ effect: function( /* effect, options, speed, callback */ ) {
2713
+ var args = _normalizeArguments.apply( this, arguments ),
2714
+ effectMethod = $.effects.effect[ args.effect ],
2715
+ defaultMode = effectMethod.mode,
2716
+ queue = args.queue,
2717
+ queueName = queue || "fx",
2718
+ complete = args.complete,
2719
+ mode = args.mode,
2720
+ modes = [],
2721
+ prefilter = function( next ) {
2722
+ var el = $( this ),
2723
+ normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2724
+
2725
+ // Sentinel for duck-punching the :animated pseudo-selector
2726
+ el.data( dataSpaceAnimated, true );
2727
+
2728
+ // Save effect mode for later use,
2729
+ // we can't just call $.effects.mode again later,
2730
+ // as the .show() below destroys the initial state
2731
+ modes.push( normalizedMode );
2732
+
2733
+ // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2734
+ if ( defaultMode && ( normalizedMode === "show" ||
2735
+ ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2736
+ el.show();
2737
+ }
2738
+
2739
+ if ( !defaultMode || normalizedMode !== "none" ) {
2740
+ $.effects.saveStyle( el );
2741
+ }
2742
+
2743
+ if ( typeof next === "function" ) {
2744
+ next();
2745
+ }
2746
+ };
2747
+
2748
+ if ( $.fx.off || !effectMethod ) {
2749
+
2750
+ // Delegate to the original method (e.g., .show()) if possible
2751
+ if ( mode ) {
2752
+ return this[ mode ]( args.duration, complete );
2753
+ } else {
2754
+ return this.each( function() {
2755
+ if ( complete ) {
2756
+ complete.call( this );
2757
+ }
2758
+ } );
2759
+ }
2760
+ }
2761
+
2762
+ function run( next ) {
2763
+ var elem = $( this );
2764
+
2765
+ function cleanup() {
2766
+ elem.removeData( dataSpaceAnimated );
2767
+
2768
+ $.effects.cleanUp( elem );
2769
+
2770
+ if ( args.mode === "hide" ) {
2771
+ elem.hide();
2772
+ }
2773
+
2774
+ done();
2775
+ }
2776
+
2777
+ function done() {
2778
+ if ( typeof complete === "function" ) {
2779
+ complete.call( elem[ 0 ] );
2780
+ }
2781
+
2782
+ if ( typeof next === "function" ) {
2783
+ next();
2784
+ }
2785
+ }
2786
+
2787
+ // Override mode option on a per element basis,
2788
+ // as toggle can be either show or hide depending on element state
2789
+ args.mode = modes.shift();
2790
+
2791
+ if ( $.uiBackCompat !== false && !defaultMode ) {
2792
+ if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2793
+
2794
+ // Call the core method to track "olddisplay" properly
2795
+ elem[ mode ]();
2796
+ done();
2797
+ } else {
2798
+ effectMethod.call( elem[ 0 ], args, done );
2799
+ }
2800
+ } else {
2801
+ if ( args.mode === "none" ) {
2802
+
2803
+ // Call the core method to track "olddisplay" properly
2804
+ elem[ mode ]();
2805
+ done();
2806
+ } else {
2807
+ effectMethod.call( elem[ 0 ], args, cleanup );
2808
+ }
2809
+ }
2810
+ }
2811
+
2812
+ // Run prefilter on all elements first to ensure that
2813
+ // any showing or hiding happens before placeholder creation,
2814
+ // which ensures that any layout changes are correctly captured.
2815
+ return queue === false ?
2816
+ this.each( prefilter ).each( run ) :
2817
+ this.queue( queueName, prefilter ).queue( queueName, run );
2818
+ },
2819
+
2820
+ show: ( function( orig ) {
2821
+ return function( option ) {
2822
+ if ( standardAnimationOption( option ) ) {
2823
+ return orig.apply( this, arguments );
2824
+ } else {
2825
+ var args = _normalizeArguments.apply( this, arguments );
2826
+ args.mode = "show";
2827
+ return this.effect.call( this, args );
2828
+ }
2829
+ };
2830
+ } )( $.fn.show ),
2831
+
2832
+ hide: ( function( orig ) {
2833
+ return function( option ) {
2834
+ if ( standardAnimationOption( option ) ) {
2835
+ return orig.apply( this, arguments );
2836
+ } else {
2837
+ var args = _normalizeArguments.apply( this, arguments );
2838
+ args.mode = "hide";
2839
+ return this.effect.call( this, args );
2840
+ }
2841
+ };
2842
+ } )( $.fn.hide ),
2843
+
2844
+ toggle: ( function( orig ) {
2845
+ return function( option ) {
2846
+ if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2847
+ return orig.apply( this, arguments );
2848
+ } else {
2849
+ var args = _normalizeArguments.apply( this, arguments );
2850
+ args.mode = "toggle";
2851
+ return this.effect.call( this, args );
2852
+ }
2853
+ };
2854
+ } )( $.fn.toggle ),
2855
+
2856
+ cssUnit: function( key ) {
2857
+ var style = this.css( key ),
2858
+ val = [];
2859
+
2860
+ $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2861
+ if ( style.indexOf( unit ) > 0 ) {
2862
+ val = [ parseFloat( style ), unit ];
2863
+ }
2864
+ } );
2865
+ return val;
2866
+ },
2867
+
2868
+ cssClip: function( clipObj ) {
2869
+ if ( clipObj ) {
2870
+ return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2871
+ clipObj.bottom + "px " + clipObj.left + "px)" );
2872
+ }
2873
+ return parseClip( this.css( "clip" ), this );
2874
+ },
2875
+
2876
+ transfer: function( options, done ) {
2877
+ var element = $( this ),
2878
+ target = $( options.to ),
2879
+ targetFixed = target.css( "position" ) === "fixed",
2880
+ body = $( "body" ),
2881
+ fixTop = targetFixed ? body.scrollTop() : 0,
2882
+ fixLeft = targetFixed ? body.scrollLeft() : 0,
2883
+ endPosition = target.offset(),
2884
+ animation = {
2885
+ top: endPosition.top - fixTop,
2886
+ left: endPosition.left - fixLeft,
2887
+ height: target.innerHeight(),
2888
+ width: target.innerWidth()
2889
+ },
2890
+ startPosition = element.offset(),
2891
+ transfer = $( "<div class='ui-effects-transfer'></div>" );
2892
+
2893
+ transfer
2894
+ .appendTo( "body" )
2895
+ .addClass( options.className )
2896
+ .css( {
2897
+ top: startPosition.top - fixTop,
2898
+ left: startPosition.left - fixLeft,
2899
+ height: element.innerHeight(),
2900
+ width: element.innerWidth(),
2901
+ position: targetFixed ? "fixed" : "absolute"
2902
+ } )
2903
+ .animate( animation, options.duration, options.easing, function() {
2904
+ transfer.remove();
2905
+ if ( typeof done === "function" ) {
2906
+ done();
2907
+ }
2908
+ } );
2909
+ }
2910
+ } );
2911
+
2912
+ function parseClip( str, element ) {
2913
+ var outerWidth = element.outerWidth(),
2914
+ outerHeight = element.outerHeight(),
2915
+ clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
2916
+ values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2917
+
2918
+ return {
2919
+ top: parseFloat( values[ 1 ] ) || 0,
2920
+ right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2921
+ bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2922
+ left: parseFloat( values[ 4 ] ) || 0
2923
+ };
2924
+ }
2925
+
2926
+ $.fx.step.clip = function( fx ) {
2927
+ if ( !fx.clipInit ) {
2928
+ fx.start = $( fx.elem ).cssClip();
2929
+ if ( typeof fx.end === "string" ) {
2930
+ fx.end = parseClip( fx.end, fx.elem );
2931
+ }
2932
+ fx.clipInit = true;
2933
+ }
2934
+
2935
+ $( fx.elem ).cssClip( {
2936
+ top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2937
+ right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2938
+ bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2939
+ left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2940
+ } );
2941
+ };
2942
+
2943
+ } )();
2944
+
2945
+ /******************************************************************************/
2946
+ /*********************************** EASING ***********************************/
2947
+ /******************************************************************************/
2948
+
2949
+ ( function() {
2950
+
2951
+ // Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
2952
+
2953
+ var baseEasings = {};
2954
+
2955
+ $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2956
+ baseEasings[ name ] = function( p ) {
2957
+ return Math.pow( p, i + 2 );
2958
+ };
2959
+ } );
2960
+
2961
+ $.extend( baseEasings, {
2962
+ Sine: function( p ) {
2963
+ return 1 - Math.cos( p * Math.PI / 2 );
2964
+ },
2965
+ Circ: function( p ) {
2966
+ return 1 - Math.sqrt( 1 - p * p );
2967
+ },
2968
+ Elastic: function( p ) {
2969
+ return p === 0 || p === 1 ? p :
2970
+ -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2971
+ },
2972
+ Back: function( p ) {
2973
+ return p * p * ( 3 * p - 2 );
2974
+ },
2975
+ Bounce: function( p ) {
2976
+ var pow2,
2977
+ bounce = 4;
2978
+
2979
+ while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2980
+ return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2981
+ }
2982
+ } );
2983
+
2984
+ $.each( baseEasings, function( name, easeIn ) {
2985
+ $.easing[ "easeIn" + name ] = easeIn;
2986
+ $.easing[ "easeOut" + name ] = function( p ) {
2987
+ return 1 - easeIn( 1 - p );
2988
+ };
2989
+ $.easing[ "easeInOut" + name ] = function( p ) {
2990
+ return p < 0.5 ?
2991
+ easeIn( p * 2 ) / 2 :
2992
+ 1 - easeIn( p * -2 + 2 ) / 2;
2993
+ };
2994
+ } );
2995
+
2996
+ } )();
2997
+
2998
+ var effect = $.effects;
2999
+
3000
+
3001
+ /*!
3002
+ * jQuery UI Effects Blind 1.13.1
3003
+ * http://jqueryui.com
3004
+ *
3005
+ * Copyright jQuery Foundation and other contributors
3006
+ * Released under the MIT license.
3007
+ * http://jquery.org/license
3008
+ */
3009
+
3010
+ //>>label: Blind Effect
3011
+ //>>group: Effects
3012
+ //>>description: Blinds the element.
3013
+ //>>docs: http://api.jqueryui.com/blind-effect/
3014
+ //>>demos: http://jqueryui.com/effect/
3015
+
3016
+
3017
+ var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
3018
+ var map = {
3019
+ up: [ "bottom", "top" ],
3020
+ vertical: [ "bottom", "top" ],
3021
+ down: [ "top", "bottom" ],
3022
+ left: [ "right", "left" ],
3023
+ horizontal: [ "right", "left" ],
3024
+ right: [ "left", "right" ]
3025
+ },
3026
+ element = $( this ),
3027
+ direction = options.direction || "up",
3028
+ start = element.cssClip(),
3029
+ animate = { clip: $.extend( {}, start ) },
3030
+ placeholder = $.effects.createPlaceholder( element );
3031
+
3032
+ animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
3033
+
3034
+ if ( options.mode === "show" ) {
3035
+ element.cssClip( animate.clip );
3036
+ if ( placeholder ) {
3037
+ placeholder.css( $.effects.clipToBox( animate ) );
3038
+ }
3039
+
3040
+ animate.clip = start;
3041
+ }
3042
+
3043
+ if ( placeholder ) {
3044
+ placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
3045
+ }
3046
+
3047
+ element.animate( animate, {
3048
+ queue: false,
3049
+ duration: options.duration,
3050
+ easing: options.easing,
3051
+ complete: done
3052
+ } );
3053
+ } );
3054
+
3055
+
3056
+ /*!
3057
+ * jQuery UI Effects Bounce 1.13.1
3058
+ * http://jqueryui.com
3059
+ *
3060
+ * Copyright jQuery Foundation and other contributors
3061
+ * Released under the MIT license.
3062
+ * http://jquery.org/license
3063
+ */
3064
+
3065
+ //>>label: Bounce Effect
3066
+ //>>group: Effects
3067
+ //>>description: Bounces an element horizontally or vertically n times.
3068
+ //>>docs: http://api.jqueryui.com/bounce-effect/
3069
+ //>>demos: http://jqueryui.com/effect/
3070
+
3071
+
3072
+ var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3073
+ var upAnim, downAnim, refValue,
3074
+ element = $( this ),
3075
+
3076
+ // Defaults:
3077
+ mode = options.mode,
3078
+ hide = mode === "hide",
3079
+ show = mode === "show",
3080
+ direction = options.direction || "up",
3081
+ distance = options.distance,
3082
+ times = options.times || 5,
3083
+
3084
+ // Number of internal animations
3085
+ anims = times * 2 + ( show || hide ? 1 : 0 ),
3086
+ speed = options.duration / anims,
3087
+ easing = options.easing,
3088
+
3089
+ // Utility:
3090
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3091
+ motion = ( direction === "up" || direction === "left" ),
3092
+ i = 0,
3093
+
3094
+ queuelen = element.queue().length;
3095
+
3096
+ $.effects.createPlaceholder( element );
3097
+
3098
+ refValue = element.css( ref );
3099
+
3100
+ // Default distance for the BIGGEST bounce is the outer Distance / 3
3101
+ if ( !distance ) {
3102
+ distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3103
+ }
3104
+
3105
+ if ( show ) {
3106
+ downAnim = { opacity: 1 };
3107
+ downAnim[ ref ] = refValue;
3108
+
3109
+ // If we are showing, force opacity 0 and set the initial position
3110
+ // then do the "first" animation
3111
+ element
3112
+ .css( "opacity", 0 )
3113
+ .css( ref, motion ? -distance * 2 : distance * 2 )
3114
+ .animate( downAnim, speed, easing );
3115
+ }
3116
+
3117
+ // Start at the smallest distance if we are hiding
3118
+ if ( hide ) {
3119
+ distance = distance / Math.pow( 2, times - 1 );
3120
+ }
3121
+
3122
+ downAnim = {};
3123
+ downAnim[ ref ] = refValue;
3124
+
3125
+ // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3126
+ for ( ; i < times; i++ ) {
3127
+ upAnim = {};
3128
+ upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3129
+
3130
+ element
3131
+ .animate( upAnim, speed, easing )
3132
+ .animate( downAnim, speed, easing );
3133
+
3134
+ distance = hide ? distance * 2 : distance / 2;
3135
+ }
3136
+
3137
+ // Last Bounce when Hiding
3138
+ if ( hide ) {
3139
+ upAnim = { opacity: 0 };
3140
+ upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3141
+
3142
+ element.animate( upAnim, speed, easing );
3143
+ }
3144
+
3145
+ element.queue( done );
3146
+
3147
+ $.effects.unshift( element, queuelen, anims + 1 );
3148
+ } );
3149
+
3150
+
3151
+ /*!
3152
+ * jQuery UI Effects Clip 1.13.1
3153
+ * http://jqueryui.com
3154
+ *
3155
+ * Copyright jQuery Foundation and other contributors
3156
+ * Released under the MIT license.
3157
+ * http://jquery.org/license
3158
+ */
3159
+
3160
+ //>>label: Clip Effect
3161
+ //>>group: Effects
3162
+ //>>description: Clips the element on and off like an old TV.
3163
+ //>>docs: http://api.jqueryui.com/clip-effect/
3164
+ //>>demos: http://jqueryui.com/effect/
3165
+
3166
+
3167
+ var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3168
+ var start,
3169
+ animate = {},
3170
+ element = $( this ),
3171
+ direction = options.direction || "vertical",
3172
+ both = direction === "both",
3173
+ horizontal = both || direction === "horizontal",
3174
+ vertical = both || direction === "vertical";
3175
+
3176
+ start = element.cssClip();
3177
+ animate.clip = {
3178
+ top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3179
+ right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3180
+ bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3181
+ left: horizontal ? ( start.right - start.left ) / 2 : start.left
3182
+ };
3183
+
3184
+ $.effects.createPlaceholder( element );
3185
+
3186
+ if ( options.mode === "show" ) {
3187
+ element.cssClip( animate.clip );
3188
+ animate.clip = start;
3189
+ }
3190
+
3191
+ element.animate( animate, {
3192
+ queue: false,
3193
+ duration: options.duration,
3194
+ easing: options.easing,
3195
+ complete: done
3196
+ } );
3197
+
3198
+ } );
3199
+
3200
+
3201
+ /*!
3202
+ * jQuery UI Effects Drop 1.13.1
3203
+ * http://jqueryui.com
3204
+ *
3205
+ * Copyright jQuery Foundation and other contributors
3206
+ * Released under the MIT license.
3207
+ * http://jquery.org/license
3208
+ */
3209
+
3210
+ //>>label: Drop Effect
3211
+ //>>group: Effects
3212
+ //>>description: Moves an element in one direction and hides it at the same time.
3213
+ //>>docs: http://api.jqueryui.com/drop-effect/
3214
+ //>>demos: http://jqueryui.com/effect/
3215
+
3216
+
3217
+ var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3218
+
3219
+ var distance,
3220
+ element = $( this ),
3221
+ mode = options.mode,
3222
+ show = mode === "show",
3223
+ direction = options.direction || "left",
3224
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3225
+ motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3226
+ oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3227
+ animation = {
3228
+ opacity: 0
3229
+ };
3230
+
3231
+ $.effects.createPlaceholder( element );
3232
+
3233
+ distance = options.distance ||
3234
+ element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3235
+
3236
+ animation[ ref ] = motion + distance;
3237
+
3238
+ if ( show ) {
3239
+ element.css( animation );
3240
+
3241
+ animation[ ref ] = oppositeMotion + distance;
3242
+ animation.opacity = 1;
3243
+ }
3244
+
3245
+ // Animate
3246
+ element.animate( animation, {
3247
+ queue: false,
3248
+ duration: options.duration,
3249
+ easing: options.easing,
3250
+ complete: done
3251
+ } );
3252
+ } );
3253
+
3254
+
3255
+ /*!
3256
+ * jQuery UI Effects Explode 1.13.1
3257
+ * http://jqueryui.com
3258
+ *
3259
+ * Copyright jQuery Foundation and other contributors
3260
+ * Released under the MIT license.
3261
+ * http://jquery.org/license
3262
+ */
3263
+
3264
+ //>>label: Explode Effect
3265
+ //>>group: Effects
3266
+ /* eslint-disable max-len */
3267
+ //>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3268
+ /* eslint-enable max-len */
3269
+ //>>docs: http://api.jqueryui.com/explode-effect/
3270
+ //>>demos: http://jqueryui.com/effect/
3271
+
3272
+
3273
+ var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3274
+
3275
+ var i, j, left, top, mx, my,
3276
+ rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3277
+ cells = rows,
3278
+ element = $( this ),
3279
+ mode = options.mode,
3280
+ show = mode === "show",
3281
+
3282
+ // Show and then visibility:hidden the element before calculating offset
3283
+ offset = element.show().css( "visibility", "hidden" ).offset(),
3284
+
3285
+ // Width and height of a piece
3286
+ width = Math.ceil( element.outerWidth() / cells ),
3287
+ height = Math.ceil( element.outerHeight() / rows ),
3288
+ pieces = [];
3289
+
3290
+ // Children animate complete:
3291
+ function childComplete() {
3292
+ pieces.push( this );
3293
+ if ( pieces.length === rows * cells ) {
3294
+ animComplete();
3295
+ }
3296
+ }
3297
+
3298
+ // Clone the element for each row and cell.
3299
+ for ( i = 0; i < rows; i++ ) { // ===>
3300
+ top = offset.top + i * height;
3301
+ my = i - ( rows - 1 ) / 2;
3302
+
3303
+ for ( j = 0; j < cells; j++ ) { // |||
3304
+ left = offset.left + j * width;
3305
+ mx = j - ( cells - 1 ) / 2;
3306
+
3307
+ // Create a clone of the now hidden main element that will be absolute positioned
3308
+ // within a wrapper div off the -left and -top equal to size of our pieces
3309
+ element
3310
+ .clone()
3311
+ .appendTo( "body" )
3312
+ .wrap( "<div></div>" )
3313
+ .css( {
3314
+ position: "absolute",
3315
+ visibility: "visible",
3316
+ left: -j * width,
3317
+ top: -i * height
3318
+ } )
3319
+
3320
+ // Select the wrapper - make it overflow: hidden and absolute positioned based on
3321
+ // where the original was located +left and +top equal to the size of pieces
3322
+ .parent()
3323
+ .addClass( "ui-effects-explode" )
3324
+ .css( {
3325
+ position: "absolute",
3326
+ overflow: "hidden",
3327
+ width: width,
3328
+ height: height,
3329
+ left: left + ( show ? mx * width : 0 ),
3330
+ top: top + ( show ? my * height : 0 ),
3331
+ opacity: show ? 0 : 1
3332
+ } )
3333
+ .animate( {
3334
+ left: left + ( show ? 0 : mx * width ),
3335
+ top: top + ( show ? 0 : my * height ),
3336
+ opacity: show ? 1 : 0
3337
+ }, options.duration || 500, options.easing, childComplete );
3338
+ }
3339
+ }
3340
+
3341
+ function animComplete() {
3342
+ element.css( {
3343
+ visibility: "visible"
3344
+ } );
3345
+ $( pieces ).remove();
3346
+ done();
3347
+ }
3348
+ } );
3349
+
3350
+
3351
+ /*!
3352
+ * jQuery UI Effects Fade 1.13.1
3353
+ * http://jqueryui.com
3354
+ *
3355
+ * Copyright jQuery Foundation and other contributors
3356
+ * Released under the MIT license.
3357
+ * http://jquery.org/license
3358
+ */
3359
+
3360
+ //>>label: Fade Effect
3361
+ //>>group: Effects
3362
+ //>>description: Fades the element.
3363
+ //>>docs: http://api.jqueryui.com/fade-effect/
3364
+ //>>demos: http://jqueryui.com/effect/
3365
+
3366
+
3367
+ var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3368
+ var show = options.mode === "show";
3369
+
3370
+ $( this )
3371
+ .css( "opacity", show ? 0 : 1 )
3372
+ .animate( {
3373
+ opacity: show ? 1 : 0
3374
+ }, {
3375
+ queue: false,
3376
+ duration: options.duration,
3377
+ easing: options.easing,
3378
+ complete: done
3379
+ } );
3380
+ } );
3381
+
3382
+
3383
+ /*!
3384
+ * jQuery UI Effects Fold 1.13.1
3385
+ * http://jqueryui.com
3386
+ *
3387
+ * Copyright jQuery Foundation and other contributors
3388
+ * Released under the MIT license.
3389
+ * http://jquery.org/license
3390
+ */
3391
+
3392
+ //>>label: Fold Effect
3393
+ //>>group: Effects
3394
+ //>>description: Folds an element first horizontally and then vertically.
3395
+ //>>docs: http://api.jqueryui.com/fold-effect/
3396
+ //>>demos: http://jqueryui.com/effect/
3397
+
3398
+
3399
+ var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3400
+
3401
+ // Create element
3402
+ var element = $( this ),
3403
+ mode = options.mode,
3404
+ show = mode === "show",
3405
+ hide = mode === "hide",
3406
+ size = options.size || 15,
3407
+ percent = /([0-9]+)%/.exec( size ),
3408
+ horizFirst = !!options.horizFirst,
3409
+ ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3410
+ duration = options.duration / 2,
3411
+
3412
+ placeholder = $.effects.createPlaceholder( element ),
3413
+
3414
+ start = element.cssClip(),
3415
+ animation1 = { clip: $.extend( {}, start ) },
3416
+ animation2 = { clip: $.extend( {}, start ) },
3417
+
3418
+ distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3419
+
3420
+ queuelen = element.queue().length;
3421
+
3422
+ if ( percent ) {
3423
+ size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3424
+ }
3425
+ animation1.clip[ ref[ 0 ] ] = size;
3426
+ animation2.clip[ ref[ 0 ] ] = size;
3427
+ animation2.clip[ ref[ 1 ] ] = 0;
3428
+
3429
+ if ( show ) {
3430
+ element.cssClip( animation2.clip );
3431
+ if ( placeholder ) {
3432
+ placeholder.css( $.effects.clipToBox( animation2 ) );
3433
+ }
3434
+
3435
+ animation2.clip = start;
3436
+ }
3437
+
3438
+ // Animate
3439
+ element
3440
+ .queue( function( next ) {
3441
+ if ( placeholder ) {
3442
+ placeholder
3443
+ .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3444
+ .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3445
+ }
3446
+
3447
+ next();
3448
+ } )
3449
+ .animate( animation1, duration, options.easing )
3450
+ .animate( animation2, duration, options.easing )
3451
+ .queue( done );
3452
+
3453
+ $.effects.unshift( element, queuelen, 4 );
3454
+ } );
3455
+
3456
+
3457
+ /*!
3458
+ * jQuery UI Effects Highlight 1.13.1
3459
+ * http://jqueryui.com
3460
+ *
3461
+ * Copyright jQuery Foundation and other contributors
3462
+ * Released under the MIT license.
3463
+ * http://jquery.org/license
3464
+ */
3465
+
3466
+ //>>label: Highlight Effect
3467
+ //>>group: Effects
3468
+ //>>description: Highlights the background of an element in a defined color for a custom duration.
3469
+ //>>docs: http://api.jqueryui.com/highlight-effect/
3470
+ //>>demos: http://jqueryui.com/effect/
3471
+
3472
+
3473
+ var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3474
+ var element = $( this ),
3475
+ animation = {
3476
+ backgroundColor: element.css( "backgroundColor" )
3477
+ };
3478
+
3479
+ if ( options.mode === "hide" ) {
3480
+ animation.opacity = 0;
3481
+ }
3482
+
3483
+ $.effects.saveStyle( element );
3484
+
3485
+ element
3486
+ .css( {
3487
+ backgroundImage: "none",
3488
+ backgroundColor: options.color || "#ffff99"
3489
+ } )
3490
+ .animate( animation, {
3491
+ queue: false,
3492
+ duration: options.duration,
3493
+ easing: options.easing,
3494
+ complete: done
3495
+ } );
3496
+ } );
3497
+
3498
+
3499
+ /*!
3500
+ * jQuery UI Effects Size 1.13.1
3501
+ * http://jqueryui.com
3502
+ *
3503
+ * Copyright jQuery Foundation and other contributors
3504
+ * Released under the MIT license.
3505
+ * http://jquery.org/license
3506
+ */
3507
+
3508
+ //>>label: Size Effect
3509
+ //>>group: Effects
3510
+ //>>description: Resize an element to a specified width and height.
3511
+ //>>docs: http://api.jqueryui.com/size-effect/
3512
+ //>>demos: http://jqueryui.com/effect/
3513
+
3514
+
3515
+ var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3516
+
3517
+ // Create element
3518
+ var baseline, factor, temp,
3519
+ element = $( this ),
3520
+
3521
+ // Copy for children
3522
+ cProps = [ "fontSize" ],
3523
+ vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3524
+ hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3525
+
3526
+ // Set options
3527
+ mode = options.mode,
3528
+ restore = mode !== "effect",
3529
+ scale = options.scale || "both",
3530
+ origin = options.origin || [ "middle", "center" ],
3531
+ position = element.css( "position" ),
3532
+ pos = element.position(),
3533
+ original = $.effects.scaledDimensions( element ),
3534
+ from = options.from || original,
3535
+ to = options.to || $.effects.scaledDimensions( element, 0 );
3536
+
3537
+ $.effects.createPlaceholder( element );
3538
+
3539
+ if ( mode === "show" ) {
3540
+ temp = from;
3541
+ from = to;
3542
+ to = temp;
3543
+ }
3544
+
3545
+ // Set scaling factor
3546
+ factor = {
3547
+ from: {
3548
+ y: from.height / original.height,
3549
+ x: from.width / original.width
3550
+ },
3551
+ to: {
3552
+ y: to.height / original.height,
3553
+ x: to.width / original.width
3554
+ }
3555
+ };
3556
+
3557
+ // Scale the css box
3558
+ if ( scale === "box" || scale === "both" ) {
3559
+
3560
+ // Vertical props scaling
3561
+ if ( factor.from.y !== factor.to.y ) {
3562
+ from = $.effects.setTransition( element, vProps, factor.from.y, from );
3563
+ to = $.effects.setTransition( element, vProps, factor.to.y, to );
3564
+ }
3565
+
3566
+ // Horizontal props scaling
3567
+ if ( factor.from.x !== factor.to.x ) {
3568
+ from = $.effects.setTransition( element, hProps, factor.from.x, from );
3569
+ to = $.effects.setTransition( element, hProps, factor.to.x, to );
3570
+ }
3571
+ }
3572
+
3573
+ // Scale the content
3574
+ if ( scale === "content" || scale === "both" ) {
3575
+
3576
+ // Vertical props scaling
3577
+ if ( factor.from.y !== factor.to.y ) {
3578
+ from = $.effects.setTransition( element, cProps, factor.from.y, from );
3579
+ to = $.effects.setTransition( element, cProps, factor.to.y, to );
3580
+ }
3581
+ }
3582
+
3583
+ // Adjust the position properties based on the provided origin points
3584
+ if ( origin ) {
3585
+ baseline = $.effects.getBaseline( origin, original );
3586
+ from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3587
+ from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3588
+ to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3589
+ to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3590
+ }
3591
+ delete from.outerHeight;
3592
+ delete from.outerWidth;
3593
+ element.css( from );
3594
+
3595
+ // Animate the children if desired
3596
+ if ( scale === "content" || scale === "both" ) {
3597
+
3598
+ vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3599
+ hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3600
+
3601
+ // Only animate children with width attributes specified
3602
+ // TODO: is this right? should we include anything with css width specified as well
3603
+ element.find( "*[width]" ).each( function() {
3604
+ var child = $( this ),
3605
+ childOriginal = $.effects.scaledDimensions( child ),
3606
+ childFrom = {
3607
+ height: childOriginal.height * factor.from.y,
3608
+ width: childOriginal.width * factor.from.x,
3609
+ outerHeight: childOriginal.outerHeight * factor.from.y,
3610
+ outerWidth: childOriginal.outerWidth * factor.from.x
3611
+ },
3612
+ childTo = {
3613
+ height: childOriginal.height * factor.to.y,
3614
+ width: childOriginal.width * factor.to.x,
3615
+ outerHeight: childOriginal.height * factor.to.y,
3616
+ outerWidth: childOriginal.width * factor.to.x
3617
+ };
3618
+
3619
+ // Vertical props scaling
3620
+ if ( factor.from.y !== factor.to.y ) {
3621
+ childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3622
+ childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3623
+ }
3624
+
3625
+ // Horizontal props scaling
3626
+ if ( factor.from.x !== factor.to.x ) {
3627
+ childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3628
+ childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3629
+ }
3630
+
3631
+ if ( restore ) {
3632
+ $.effects.saveStyle( child );
3633
+ }
3634
+
3635
+ // Animate children
3636
+ child.css( childFrom );
3637
+ child.animate( childTo, options.duration, options.easing, function() {
3638
+
3639
+ // Restore children
3640
+ if ( restore ) {
3641
+ $.effects.restoreStyle( child );
3642
+ }
3643
+ } );
3644
+ } );
3645
+ }
3646
+
3647
+ // Animate
3648
+ element.animate( to, {
3649
+ queue: false,
3650
+ duration: options.duration,
3651
+ easing: options.easing,
3652
+ complete: function() {
3653
+
3654
+ var offset = element.offset();
3655
+
3656
+ if ( to.opacity === 0 ) {
3657
+ element.css( "opacity", from.opacity );
3658
+ }
3659
+
3660
+ if ( !restore ) {
3661
+ element
3662
+ .css( "position", position === "static" ? "relative" : position )
3663
+ .offset( offset );
3664
+
3665
+ // Need to save style here so that automatic style restoration
3666
+ // doesn't restore to the original styles from before the animation.
3667
+ $.effects.saveStyle( element );
3668
+ }
3669
+
3670
+ done();
3671
+ }
3672
+ } );
3673
+
3674
+ } );
3675
+
3676
+
3677
+ /*!
3678
+ * jQuery UI Effects Scale 1.13.1
3679
+ * http://jqueryui.com
3680
+ *
3681
+ * Copyright jQuery Foundation and other contributors
3682
+ * Released under the MIT license.
3683
+ * http://jquery.org/license
3684
+ */
3685
+
3686
+ //>>label: Scale Effect
3687
+ //>>group: Effects
3688
+ //>>description: Grows or shrinks an element and its content.
3689
+ //>>docs: http://api.jqueryui.com/scale-effect/
3690
+ //>>demos: http://jqueryui.com/effect/
3691
+
3692
+
3693
+ var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3694
+
3695
+ // Create element
3696
+ var el = $( this ),
3697
+ mode = options.mode,
3698
+ percent = parseInt( options.percent, 10 ) ||
3699
+ ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3700
+
3701
+ newOptions = $.extend( true, {
3702
+ from: $.effects.scaledDimensions( el ),
3703
+ to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3704
+ origin: options.origin || [ "middle", "center" ]
3705
+ }, options );
3706
+
3707
+ // Fade option to support puff
3708
+ if ( options.fade ) {
3709
+ newOptions.from.opacity = 1;
3710
+ newOptions.to.opacity = 0;
3711
+ }
3712
+
3713
+ $.effects.effect.size.call( this, newOptions, done );
3714
+ } );
3715
+
3716
+
3717
+ /*!
3718
+ * jQuery UI Effects Puff 1.13.1
3719
+ * http://jqueryui.com
3720
+ *
3721
+ * Copyright jQuery Foundation and other contributors
3722
+ * Released under the MIT license.
3723
+ * http://jquery.org/license
3724
+ */
3725
+
3726
+ //>>label: Puff Effect
3727
+ //>>group: Effects
3728
+ //>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3729
+ //>>docs: http://api.jqueryui.com/puff-effect/
3730
+ //>>demos: http://jqueryui.com/effect/
3731
+
3732
+
3733
+ var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3734
+ var newOptions = $.extend( true, {}, options, {
3735
+ fade: true,
3736
+ percent: parseInt( options.percent, 10 ) || 150
3737
+ } );
3738
+
3739
+ $.effects.effect.scale.call( this, newOptions, done );
3740
+ } );
3741
+
3742
+
3743
+ /*!
3744
+ * jQuery UI Effects Pulsate 1.13.1
3745
+ * http://jqueryui.com
3746
+ *
3747
+ * Copyright jQuery Foundation and other contributors
3748
+ * Released under the MIT license.
3749
+ * http://jquery.org/license
3750
+ */
3751
+
3752
+ //>>label: Pulsate Effect
3753
+ //>>group: Effects
3754
+ //>>description: Pulsates an element n times by changing the opacity to zero and back.
3755
+ //>>docs: http://api.jqueryui.com/pulsate-effect/
3756
+ //>>demos: http://jqueryui.com/effect/
3757
+
3758
+
3759
+ var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3760
+ var element = $( this ),
3761
+ mode = options.mode,
3762
+ show = mode === "show",
3763
+ hide = mode === "hide",
3764
+ showhide = show || hide,
3765
+
3766
+ // Showing or hiding leaves off the "last" animation
3767
+ anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3768
+ duration = options.duration / anims,
3769
+ animateTo = 0,
3770
+ i = 1,
3771
+ queuelen = element.queue().length;
3772
+
3773
+ if ( show || !element.is( ":visible" ) ) {
3774
+ element.css( "opacity", 0 ).show();
3775
+ animateTo = 1;
3776
+ }
3777
+
3778
+ // Anims - 1 opacity "toggles"
3779
+ for ( ; i < anims; i++ ) {
3780
+ element.animate( { opacity: animateTo }, duration, options.easing );
3781
+ animateTo = 1 - animateTo;
3782
+ }
3783
+
3784
+ element.animate( { opacity: animateTo }, duration, options.easing );
3785
+
3786
+ element.queue( done );
3787
+
3788
+ $.effects.unshift( element, queuelen, anims + 1 );
3789
+ } );
3790
+
3791
+
3792
+ /*!
3793
+ * jQuery UI Effects Shake 1.13.1
3794
+ * http://jqueryui.com
3795
+ *
3796
+ * Copyright jQuery Foundation and other contributors
3797
+ * Released under the MIT license.
3798
+ * http://jquery.org/license
3799
+ */
3800
+
3801
+ //>>label: Shake Effect
3802
+ //>>group: Effects
3803
+ //>>description: Shakes an element horizontally or vertically n times.
3804
+ //>>docs: http://api.jqueryui.com/shake-effect/
3805
+ //>>demos: http://jqueryui.com/effect/
3806
+
3807
+
3808
+ var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3809
+
3810
+ var i = 1,
3811
+ element = $( this ),
3812
+ direction = options.direction || "left",
3813
+ distance = options.distance || 20,
3814
+ times = options.times || 3,
3815
+ anims = times * 2 + 1,
3816
+ speed = Math.round( options.duration / anims ),
3817
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3818
+ positiveMotion = ( direction === "up" || direction === "left" ),
3819
+ animation = {},
3820
+ animation1 = {},
3821
+ animation2 = {},
3822
+
3823
+ queuelen = element.queue().length;
3824
+
3825
+ $.effects.createPlaceholder( element );
3826
+
3827
+ // Animation
3828
+ animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3829
+ animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3830
+ animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3831
+
3832
+ // Animate
3833
+ element.animate( animation, speed, options.easing );
3834
+
3835
+ // Shakes
3836
+ for ( ; i < times; i++ ) {
3837
+ element
3838
+ .animate( animation1, speed, options.easing )
3839
+ .animate( animation2, speed, options.easing );
3840
+ }
3841
+
3842
+ element
3843
+ .animate( animation1, speed, options.easing )
3844
+ .animate( animation, speed / 2, options.easing )
3845
+ .queue( done );
3846
+
3847
+ $.effects.unshift( element, queuelen, anims + 1 );
3848
+ } );
3849
+
3850
+
3851
+ /*!
3852
+ * jQuery UI Effects Slide 1.13.1
3853
+ * http://jqueryui.com
3854
+ *
3855
+ * Copyright jQuery Foundation and other contributors
3856
+ * Released under the MIT license.
3857
+ * http://jquery.org/license
3858
+ */
3859
+
3860
+ //>>label: Slide Effect
3861
+ //>>group: Effects
3862
+ //>>description: Slides an element in and out of the viewport.
3863
+ //>>docs: http://api.jqueryui.com/slide-effect/
3864
+ //>>demos: http://jqueryui.com/effect/
3865
+
3866
+
3867
+ var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3868
+ var startClip, startRef,
3869
+ element = $( this ),
3870
+ map = {
3871
+ up: [ "bottom", "top" ],
3872
+ down: [ "top", "bottom" ],
3873
+ left: [ "right", "left" ],
3874
+ right: [ "left", "right" ]
3875
+ },
3876
+ mode = options.mode,
3877
+ direction = options.direction || "left",
3878
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3879
+ positiveMotion = ( direction === "up" || direction === "left" ),
3880
+ distance = options.distance ||
3881
+ element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3882
+ animation = {};
3883
+
3884
+ $.effects.createPlaceholder( element );
3885
+
3886
+ startClip = element.cssClip();
3887
+ startRef = element.position()[ ref ];
3888
+
3889
+ // Define hide animation
3890
+ animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3891
+ animation.clip = element.cssClip();
3892
+ animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3893
+
3894
+ // Reverse the animation if we're showing
3895
+ if ( mode === "show" ) {
3896
+ element.cssClip( animation.clip );
3897
+ element.css( ref, animation[ ref ] );
3898
+ animation.clip = startClip;
3899
+ animation[ ref ] = startRef;
3900
+ }
3901
+
3902
+ // Actually animate
3903
+ element.animate( animation, {
3904
+ queue: false,
3905
+ duration: options.duration,
3906
+ easing: options.easing,
3907
+ complete: done
3908
+ } );
3909
+ } );
3910
+
3911
+
3912
+ /*!
3913
+ * jQuery UI Effects Transfer 1.13.1
3914
+ * http://jqueryui.com
3915
+ *
3916
+ * Copyright jQuery Foundation and other contributors
3917
+ * Released under the MIT license.
3918
+ * http://jquery.org/license
3919
+ */
3920
+
3921
+ //>>label: Transfer Effect
3922
+ //>>group: Effects
3923
+ //>>description: Displays a transfer effect from one element to another.
3924
+ //>>docs: http://api.jqueryui.com/transfer-effect/
3925
+ //>>demos: http://jqueryui.com/effect/
3926
+
3927
+
3928
+ var effect;
3929
+ if ( $.uiBackCompat !== false ) {
3930
+ effect = $.effects.define( "transfer", function( options, done ) {
3931
+ $( this ).transfer( options, done );
3932
+ } );
3933
+ }
3934
+ var effectsEffectTransfer = effect;
3935
+
3936
+
3937
+ /*!
3938
+ * jQuery UI Focusable 1.13.1
3939
+ * http://jqueryui.com
3940
+ *
3941
+ * Copyright jQuery Foundation and other contributors
3942
+ * Released under the MIT license.
3943
+ * http://jquery.org/license
3944
+ */
3945
+
3946
+ //>>label: :focusable Selector
3947
+ //>>group: Core
3948
+ //>>description: Selects elements which can be focused.
3949
+ //>>docs: http://api.jqueryui.com/focusable-selector/
3950
+
3951
+
3952
+ // Selectors
3953
+ $.ui.focusable = function( element, hasTabindex ) {
3954
+ var map, mapName, img, focusableIfVisible, fieldset,
3955
+ nodeName = element.nodeName.toLowerCase();
3956
+
3957
+ if ( "area" === nodeName ) {
3958
+ map = element.parentNode;
3959
+ mapName = map.name;
3960
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3961
+ return false;
3962
+ }
3963
+ img = $( "img[usemap='#" + mapName + "']" );
3964
+ return img.length > 0 && img.is( ":visible" );
3965
+ }
3966
+
3967
+ if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3968
+ focusableIfVisible = !element.disabled;
3969
+
3970
+ if ( focusableIfVisible ) {
3971
+
3972
+ // Form controls within a disabled fieldset are disabled.
3973
+ // However, controls within the fieldset's legend do not get disabled.
3974
+ // Since controls generally aren't placed inside legends, we skip
3975
+ // this portion of the check.
3976
+ fieldset = $( element ).closest( "fieldset" )[ 0 ];
3977
+ if ( fieldset ) {
3978
+ focusableIfVisible = !fieldset.disabled;
3979
+ }
3980
+ }
3981
+ } else if ( "a" === nodeName ) {
3982
+ focusableIfVisible = element.href || hasTabindex;
3983
+ } else {
3984
+ focusableIfVisible = hasTabindex;
3985
+ }
3986
+
3987
+ return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
3988
+ };
3989
+
3990
+ // Support: IE 8 only
3991
+ // IE 8 doesn't resolve inherit to visible/hidden for computed values
3992
+ function visible( element ) {
3993
+ var visibility = element.css( "visibility" );
3994
+ while ( visibility === "inherit" ) {
3995
+ element = element.parent();
3996
+ visibility = element.css( "visibility" );
3997
+ }
3998
+ return visibility === "visible";
3999
+ }
4000
+
4001
+ $.extend( $.expr.pseudos, {
4002
+ focusable: function( element ) {
4003
+ return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
4004
+ }
4005
+ } );
4006
+
4007
+ var focusable = $.ui.focusable;
4008
+
4009
+
4010
+
4011
+ // Support: IE8 Only
4012
+ // IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
4013
+ // with a string, so we need to find the proper form.
4014
+ var form = $.fn._form = function() {
4015
+ return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
4016
+ };
4017
+
4018
+
4019
+ /*!
4020
+ * jQuery UI Form Reset Mixin 1.13.1
4021
+ * http://jqueryui.com
4022
+ *
4023
+ * Copyright jQuery Foundation and other contributors
4024
+ * Released under the MIT license.
4025
+ * http://jquery.org/license
4026
+ */
4027
+
4028
+ //>>label: Form Reset Mixin
4029
+ //>>group: Core
4030
+ //>>description: Refresh input widgets when their form is reset
4031
+ //>>docs: http://api.jqueryui.com/form-reset-mixin/
4032
+
4033
+
4034
+ var formResetMixin = $.ui.formResetMixin = {
4035
+ _formResetHandler: function() {
4036
+ var form = $( this );
4037
+
4038
+ // Wait for the form reset to actually happen before refreshing
4039
+ setTimeout( function() {
4040
+ var instances = form.data( "ui-form-reset-instances" );
4041
+ $.each( instances, function() {
4042
+ this.refresh();
4043
+ } );
4044
+ } );
4045
+ },
4046
+
4047
+ _bindFormResetHandler: function() {
4048
+ this.form = this.element._form();
4049
+ if ( !this.form.length ) {
4050
+ return;
4051
+ }
4052
+
4053
+ var instances = this.form.data( "ui-form-reset-instances" ) || [];
4054
+ if ( !instances.length ) {
4055
+
4056
+ // We don't use _on() here because we use a single event handler per form
4057
+ this.form.on( "reset.ui-form-reset", this._formResetHandler );
4058
+ }
4059
+ instances.push( this );
4060
+ this.form.data( "ui-form-reset-instances", instances );
4061
+ },
4062
+
4063
+ _unbindFormResetHandler: function() {
4064
+ if ( !this.form.length ) {
4065
+ return;
4066
+ }
4067
+
4068
+ var instances = this.form.data( "ui-form-reset-instances" );
4069
+ instances.splice( $.inArray( this, instances ), 1 );
4070
+ if ( instances.length ) {
4071
+ this.form.data( "ui-form-reset-instances", instances );
4072
+ } else {
4073
+ this.form
4074
+ .removeData( "ui-form-reset-instances" )
4075
+ .off( "reset.ui-form-reset" );
4076
+ }
4077
+ }
4078
+ };
4079
+
4080
+
4081
+ /*!
4082
+ * jQuery UI Support for jQuery core 1.8.x and newer 1.13.1
4083
+ * http://jqueryui.com
4084
+ *
4085
+ * Copyright jQuery Foundation and other contributors
4086
+ * Released under the MIT license.
4087
+ * http://jquery.org/license
4088
+ *
4089
+ */
4090
+
4091
+ //>>label: jQuery 1.8+ Support
4092
+ //>>group: Core
4093
+ //>>description: Support version 1.8.x and newer of jQuery core
4094
+
4095
+
4096
+ // Support: jQuery 1.9.x or older
4097
+ // $.expr[ ":" ] is deprecated.
4098
+ if ( !$.expr.pseudos ) {
4099
+ $.expr.pseudos = $.expr[ ":" ];
4100
+ }
4101
+
4102
+ // Support: jQuery 1.11.x or older
4103
+ // $.unique has been renamed to $.uniqueSort
4104
+ if ( !$.uniqueSort ) {
4105
+ $.uniqueSort = $.unique;
4106
+ }
4107
+
4108
+ // Support: jQuery 2.2.x or older.
4109
+ // This method has been defined in jQuery 3.0.0.
4110
+ // Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4111
+ if ( !$.escapeSelector ) {
4112
+
4113
+ // CSS string/identifier serialization
4114
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
4115
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
4116
+
4117
+ var fcssescape = function( ch, asCodePoint ) {
4118
+ if ( asCodePoint ) {
4119
+
4120
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
4121
+ if ( ch === "\0" ) {
4122
+ return "\uFFFD";
4123
+ }
4124
+
4125
+ // Control characters and (dependent upon position) numbers get escaped as code points
4126
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
4127
+ }
4128
+
4129
+ // Other potentially-special ASCII characters get backslash-escaped
4130
+ return "\\" + ch;
4131
+ };
4132
+
4133
+ $.escapeSelector = function( sel ) {
4134
+ return ( sel + "" ).replace( rcssescape, fcssescape );
4135
+ };
4136
+ }
4137
+
4138
+ // Support: jQuery 3.4.x or older
4139
+ // These methods have been defined in jQuery 3.5.0.
4140
+ if ( !$.fn.even || !$.fn.odd ) {
4141
+ $.fn.extend( {
4142
+ even: function() {
4143
+ return this.filter( function( i ) {
4144
+ return i % 2 === 0;
4145
+ } );
4146
+ },
4147
+ odd: function() {
4148
+ return this.filter( function( i ) {
4149
+ return i % 2 === 1;
4150
+ } );
4151
+ }
4152
+ } );
4153
+ }
4154
+
4155
+ ;
4156
+ /*!
4157
+ * jQuery UI Keycode 1.13.1
4158
+ * http://jqueryui.com
4159
+ *
4160
+ * Copyright jQuery Foundation and other contributors
4161
+ * Released under the MIT license.
4162
+ * http://jquery.org/license
4163
+ */
4164
+
4165
+ //>>label: Keycode
4166
+ //>>group: Core
4167
+ //>>description: Provide keycodes as keynames
4168
+ //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
4169
+
4170
+
4171
+ var keycode = $.ui.keyCode = {
4172
+ BACKSPACE: 8,
4173
+ COMMA: 188,
4174
+ DELETE: 46,
4175
+ DOWN: 40,
4176
+ END: 35,
4177
+ ENTER: 13,
4178
+ ESCAPE: 27,
4179
+ HOME: 36,
4180
+ LEFT: 37,
4181
+ PAGE_DOWN: 34,
4182
+ PAGE_UP: 33,
4183
+ PERIOD: 190,
4184
+ RIGHT: 39,
4185
+ SPACE: 32,
4186
+ TAB: 9,
4187
+ UP: 38
4188
+ };
4189
+
4190
+
4191
+ /*!
4192
+ * jQuery UI Labels 1.13.1
4193
+ * http://jqueryui.com
4194
+ *
4195
+ * Copyright jQuery Foundation and other contributors
4196
+ * Released under the MIT license.
4197
+ * http://jquery.org/license
4198
+ */
4199
+
4200
+ //>>label: labels
4201
+ //>>group: Core
4202
+ //>>description: Find all the labels associated with a given input
4203
+ //>>docs: http://api.jqueryui.com/labels/
4204
+
4205
+
4206
+ var labels = $.fn.labels = function() {
4207
+ var ancestor, selector, id, labels, ancestors;
4208
+
4209
+ if ( !this.length ) {
4210
+ return this.pushStack( [] );
4211
+ }
4212
+
4213
+ // Check control.labels first
4214
+ if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4215
+ return this.pushStack( this[ 0 ].labels );
4216
+ }
4217
+
4218
+ // Support: IE <= 11, FF <= 37, Android <= 2.3 only
4219
+ // Above browsers do not support control.labels. Everything below is to support them
4220
+ // as well as document fragments. control.labels does not work on document fragments
4221
+ labels = this.eq( 0 ).parents( "label" );
4222
+
4223
+ // Look for the label based on the id
4224
+ id = this.attr( "id" );
4225
+ if ( id ) {
4226
+
4227
+ // We don't search against the document in case the element
4228
+ // is disconnected from the DOM
4229
+ ancestor = this.eq( 0 ).parents().last();
4230
+
4231
+ // Get a full set of top level ancestors
4232
+ ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4233
+
4234
+ // Create a selector for the label based on the id
4235
+ selector = "label[for='" + $.escapeSelector( id ) + "']";
4236
+
4237
+ labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4238
+
4239
+ }
4240
+
4241
+ // Return whatever we have found for labels
4242
+ return this.pushStack( labels );
4243
+ };
4244
+
4245
+
4246
+ /*!
4247
+ * jQuery UI Scroll Parent 1.13.1
4248
+ * http://jqueryui.com
4249
+ *
4250
+ * Copyright jQuery Foundation and other contributors
4251
+ * Released under the MIT license.
4252
+ * http://jquery.org/license
4253
+ */
4254
+
4255
+ //>>label: scrollParent
4256
+ //>>group: Core
4257
+ //>>description: Get the closest ancestor element that is scrollable.
4258
+ //>>docs: http://api.jqueryui.com/scrollParent/
4259
+
4260
+
4261
+ var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4262
+ var position = this.css( "position" ),
4263
+ excludeStaticParent = position === "absolute",
4264
+ overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4265
+ scrollParent = this.parents().filter( function() {
4266
+ var parent = $( this );
4267
+ if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4268
+ return false;
4269
+ }
4270
+ return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4271
+ parent.css( "overflow-x" ) );
4272
+ } ).eq( 0 );
4273
+
4274
+ return position === "fixed" || !scrollParent.length ?
4275
+ $( this[ 0 ].ownerDocument || document ) :
4276
+ scrollParent;
4277
+ };
4278
+
4279
+
4280
+ /*!
4281
+ * jQuery UI Tabbable 1.13.1
4282
+ * http://jqueryui.com
4283
+ *
4284
+ * Copyright jQuery Foundation and other contributors
4285
+ * Released under the MIT license.
4286
+ * http://jquery.org/license
4287
+ */
4288
+
4289
+ //>>label: :tabbable Selector
4290
+ //>>group: Core
4291
+ //>>description: Selects elements which can be tabbed to.
4292
+ //>>docs: http://api.jqueryui.com/tabbable-selector/
4293
+
4294
+
4295
+ var tabbable = $.extend( $.expr.pseudos, {
4296
+ tabbable: function( element ) {
4297
+ var tabIndex = $.attr( element, "tabindex" ),
4298
+ hasTabindex = tabIndex != null;
4299
+ return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4300
+ }
4301
+ } );
4302
+
4303
+
4304
+ /*!
4305
+ * jQuery UI Unique ID 1.13.1
4306
+ * http://jqueryui.com
4307
+ *
4308
+ * Copyright jQuery Foundation and other contributors
4309
+ * Released under the MIT license.
4310
+ * http://jquery.org/license
4311
+ */
4312
+
4313
+ //>>label: uniqueId
4314
+ //>>group: Core
4315
+ //>>description: Functions to generate and remove uniqueId's
4316
+ //>>docs: http://api.jqueryui.com/uniqueId/
4317
+
4318
+
4319
+ var uniqueId = $.fn.extend( {
4320
+ uniqueId: ( function() {
4321
+ var uuid = 0;
4322
+
4323
+ return function() {
4324
+ return this.each( function() {
4325
+ if ( !this.id ) {
4326
+ this.id = "ui-id-" + ( ++uuid );
4327
+ }
4328
+ } );
4329
+ };
4330
+ } )(),
4331
+
4332
+ removeUniqueId: function() {
4333
+ return this.each( function() {
4334
+ if ( /^ui-id-\d+$/.test( this.id ) ) {
4335
+ $( this ).removeAttr( "id" );
4336
+ }
4337
+ } );
4338
+ }
4339
+ } );
4340
+
4341
+
4342
+ /*!
4343
+ * jQuery UI Accordion 1.13.1
4344
+ * http://jqueryui.com
4345
+ *
4346
+ * Copyright jQuery Foundation and other contributors
4347
+ * Released under the MIT license.
4348
+ * http://jquery.org/license
4349
+ */
4350
+
4351
+ //>>label: Accordion
4352
+ //>>group: Widgets
4353
+ /* eslint-disable max-len */
4354
+ //>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4355
+ /* eslint-enable max-len */
4356
+ //>>docs: http://api.jqueryui.com/accordion/
4357
+ //>>demos: http://jqueryui.com/accordion/
4358
+ //>>css.structure: ../../themes/base/core.css
4359
+ //>>css.structure: ../../themes/base/accordion.css
4360
+ //>>css.theme: ../../themes/base/theme.css
4361
+
4362
+
4363
+ var widgetsAccordion = $.widget( "ui.accordion", {
4364
+ version: "1.13.1",
4365
+ options: {
4366
+ active: 0,
4367
+ animate: {},
4368
+ classes: {
4369
+ "ui-accordion-header": "ui-corner-top",
4370
+ "ui-accordion-header-collapsed": "ui-corner-all",
4371
+ "ui-accordion-content": "ui-corner-bottom"
4372
+ },
4373
+ collapsible: false,
4374
+ event: "click",
4375
+ header: function( elem ) {
4376
+ return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
4377
+ },
4378
+ heightStyle: "auto",
4379
+ icons: {
4380
+ activeHeader: "ui-icon-triangle-1-s",
4381
+ header: "ui-icon-triangle-1-e"
4382
+ },
4383
+
4384
+ // Callbacks
4385
+ activate: null,
4386
+ beforeActivate: null
4387
+ },
4388
+
4389
+ hideProps: {
4390
+ borderTopWidth: "hide",
4391
+ borderBottomWidth: "hide",
4392
+ paddingTop: "hide",
4393
+ paddingBottom: "hide",
4394
+ height: "hide"
4395
+ },
4396
+
4397
+ showProps: {
4398
+ borderTopWidth: "show",
4399
+ borderBottomWidth: "show",
4400
+ paddingTop: "show",
4401
+ paddingBottom: "show",
4402
+ height: "show"
4403
+ },
4404
+
4405
+ _create: function() {
4406
+ var options = this.options;
4407
+
4408
+ this.prevShow = this.prevHide = $();
4409
+ this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4410
+ this.element.attr( "role", "tablist" );
4411
+
4412
+ // Don't allow collapsible: false and active: false / null
4413
+ if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4414
+ options.active = 0;
4415
+ }
4416
+
4417
+ this._processPanels();
4418
+
4419
+ // handle negative values
4420
+ if ( options.active < 0 ) {
4421
+ options.active += this.headers.length;
4422
+ }
4423
+ this._refresh();
4424
+ },
4425
+
4426
+ _getCreateEventData: function() {
4427
+ return {
4428
+ header: this.active,
4429
+ panel: !this.active.length ? $() : this.active.next()
4430
+ };
4431
+ },
4432
+
4433
+ _createIcons: function() {
4434
+ var icon, children,
4435
+ icons = this.options.icons;
4436
+
4437
+ if ( icons ) {
4438
+ icon = $( "<span>" );
4439
+ this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4440
+ icon.prependTo( this.headers );
4441
+ children = this.active.children( ".ui-accordion-header-icon" );
4442
+ this._removeClass( children, icons.header )
4443
+ ._addClass( children, null, icons.activeHeader )
4444
+ ._addClass( this.headers, "ui-accordion-icons" );
4445
+ }
4446
+ },
4447
+
4448
+ _destroyIcons: function() {
4449
+ this._removeClass( this.headers, "ui-accordion-icons" );
4450
+ this.headers.children( ".ui-accordion-header-icon" ).remove();
4451
+ },
4452
+
4453
+ _destroy: function() {
4454
+ var contents;
4455
+
4456
+ // Clean up main element
4457
+ this.element.removeAttr( "role" );
4458
+
4459
+ // Clean up headers
4460
+ this.headers
4461
+ .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4462
+ .removeUniqueId();
4463
+
4464
+ this._destroyIcons();
4465
+
4466
+ // Clean up content panels
4467
+ contents = this.headers.next()
4468
+ .css( "display", "" )
4469
+ .removeAttr( "role aria-hidden aria-labelledby" )
4470
+ .removeUniqueId();
4471
+
4472
+ if ( this.options.heightStyle !== "content" ) {
4473
+ contents.css( "height", "" );
4474
+ }
4475
+ },
4476
+
4477
+ _setOption: function( key, value ) {
4478
+ if ( key === "active" ) {
4479
+
4480
+ // _activate() will handle invalid values and update this.options
4481
+ this._activate( value );
4482
+ return;
4483
+ }
4484
+
4485
+ if ( key === "event" ) {
4486
+ if ( this.options.event ) {
4487
+ this._off( this.headers, this.options.event );
4488
+ }
4489
+ this._setupEvents( value );
4490
+ }
4491
+
4492
+ this._super( key, value );
4493
+
4494
+ // Setting collapsible: false while collapsed; open first panel
4495
+ if ( key === "collapsible" && !value && this.options.active === false ) {
4496
+ this._activate( 0 );
4497
+ }
4498
+
4499
+ if ( key === "icons" ) {
4500
+ this._destroyIcons();
4501
+ if ( value ) {
4502
+ this._createIcons();
4503
+ }
4504
+ }
4505
+ },
4506
+
4507
+ _setOptionDisabled: function( value ) {
4508
+ this._super( value );
4509
+
4510
+ this.element.attr( "aria-disabled", value );
4511
+
4512
+ // Support: IE8 Only
4513
+ // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
4514
+ // so we need to add the disabled class to the headers and panels
4515
+ this._toggleClass( null, "ui-state-disabled", !!value );
4516
+ this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
4517
+ !!value );
4518
+ },
4519
+
4520
+ _keydown: function( event ) {
4521
+ if ( event.altKey || event.ctrlKey ) {
4522
+ return;
4523
+ }
4524
+
4525
+ var keyCode = $.ui.keyCode,
4526
+ length = this.headers.length,
4527
+ currentIndex = this.headers.index( event.target ),
4528
+ toFocus = false;
4529
+
4530
+ switch ( event.keyCode ) {
4531
+ case keyCode.RIGHT:
4532
+ case keyCode.DOWN:
4533
+ toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4534
+ break;
4535
+ case keyCode.LEFT:
4536
+ case keyCode.UP:
4537
+ toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4538
+ break;
4539
+ case keyCode.SPACE:
4540
+ case keyCode.ENTER:
4541
+ this._eventHandler( event );
4542
+ break;
4543
+ case keyCode.HOME:
4544
+ toFocus = this.headers[ 0 ];
4545
+ break;
4546
+ case keyCode.END:
4547
+ toFocus = this.headers[ length - 1 ];
4548
+ break;
4549
+ }
4550
+
4551
+ if ( toFocus ) {
4552
+ $( event.target ).attr( "tabIndex", -1 );
4553
+ $( toFocus ).attr( "tabIndex", 0 );
4554
+ $( toFocus ).trigger( "focus" );
4555
+ event.preventDefault();
4556
+ }
4557
+ },
4558
+
4559
+ _panelKeyDown: function( event ) {
4560
+ if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4561
+ $( event.currentTarget ).prev().trigger( "focus" );
4562
+ }
4563
+ },
4564
+
4565
+ refresh: function() {
4566
+ var options = this.options;
4567
+ this._processPanels();
4568
+
4569
+ // Was collapsed or no panel
4570
+ if ( ( options.active === false && options.collapsible === true ) ||
4571
+ !this.headers.length ) {
4572
+ options.active = false;
4573
+ this.active = $();
4574
+
4575
+ // active false only when collapsible is true
4576
+ } else if ( options.active === false ) {
4577
+ this._activate( 0 );
4578
+
4579
+ // was active, but active panel is gone
4580
+ } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4581
+
4582
+ // all remaining panel are disabled
4583
+ if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4584
+ options.active = false;
4585
+ this.active = $();
4586
+
4587
+ // activate previous panel
4588
+ } else {
4589
+ this._activate( Math.max( 0, options.active - 1 ) );
4590
+ }
4591
+
4592
+ // was active, active panel still exists
4593
+ } else {
4594
+
4595
+ // make sure active index is correct
4596
+ options.active = this.headers.index( this.active );
4597
+ }
4598
+
4599
+ this._destroyIcons();
4600
+
4601
+ this._refresh();
4602
+ },
4603
+
4604
+ _processPanels: function() {
4605
+ var prevHeaders = this.headers,
4606
+ prevPanels = this.panels;
4607
+
4608
+ if ( typeof this.options.header === "function" ) {
4609
+ this.headers = this.options.header( this.element );
4610
+ } else {
4611
+ this.headers = this.element.find( this.options.header );
4612
+ }
4613
+ this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4614
+ "ui-state-default" );
4615
+
4616
+ this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4617
+ this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4618
+
4619
+ // Avoid memory leaks (#10056)
4620
+ if ( prevPanels ) {
4621
+ this._off( prevHeaders.not( this.headers ) );
4622
+ this._off( prevPanels.not( this.panels ) );
4623
+ }
4624
+ },
4625
+
4626
+ _refresh: function() {
4627
+ var maxHeight,
4628
+ options = this.options,
4629
+ heightStyle = options.heightStyle,
4630
+ parent = this.element.parent();
4631
+
4632
+ this.active = this._findActive( options.active );
4633
+ this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4634
+ ._removeClass( this.active, "ui-accordion-header-collapsed" );
4635
+ this._addClass( this.active.next(), "ui-accordion-content-active" );
4636
+ this.active.next().show();
4637
+
4638
+ this.headers
4639
+ .attr( "role", "tab" )
4640
+ .each( function() {
4641
+ var header = $( this ),
4642
+ headerId = header.uniqueId().attr( "id" ),
4643
+ panel = header.next(),
4644
+ panelId = panel.uniqueId().attr( "id" );
4645
+ header.attr( "aria-controls", panelId );
4646
+ panel.attr( "aria-labelledby", headerId );
4647
+ } )
4648
+ .next()
4649
+ .attr( "role", "tabpanel" );
4650
+
4651
+ this.headers
4652
+ .not( this.active )
4653
+ .attr( {
4654
+ "aria-selected": "false",
4655
+ "aria-expanded": "false",
4656
+ tabIndex: -1
4657
+ } )
4658
+ .next()
4659
+ .attr( {
4660
+ "aria-hidden": "true"
4661
+ } )
4662
+ .hide();
4663
+
4664
+ // Make sure at least one header is in the tab order
4665
+ if ( !this.active.length ) {
4666
+ this.headers.eq( 0 ).attr( "tabIndex", 0 );
4667
+ } else {
4668
+ this.active.attr( {
4669
+ "aria-selected": "true",
4670
+ "aria-expanded": "true",
4671
+ tabIndex: 0
4672
+ } )
4673
+ .next()
4674
+ .attr( {
4675
+ "aria-hidden": "false"
4676
+ } );
4677
+ }
4678
+
4679
+ this._createIcons();
4680
+
4681
+ this._setupEvents( options.event );
4682
+
4683
+ if ( heightStyle === "fill" ) {
4684
+ maxHeight = parent.height();
4685
+ this.element.siblings( ":visible" ).each( function() {
4686
+ var elem = $( this ),
4687
+ position = elem.css( "position" );
4688
+
4689
+ if ( position === "absolute" || position === "fixed" ) {
4690
+ return;
4691
+ }
4692
+ maxHeight -= elem.outerHeight( true );
4693
+ } );
4694
+
4695
+ this.headers.each( function() {
4696
+ maxHeight -= $( this ).outerHeight( true );
4697
+ } );
4698
+
4699
+ this.headers.next()
4700
+ .each( function() {
4701
+ $( this ).height( Math.max( 0, maxHeight -
4702
+ $( this ).innerHeight() + $( this ).height() ) );
4703
+ } )
4704
+ .css( "overflow", "auto" );
4705
+ } else if ( heightStyle === "auto" ) {
4706
+ maxHeight = 0;
4707
+ this.headers.next()
4708
+ .each( function() {
4709
+ var isVisible = $( this ).is( ":visible" );
4710
+ if ( !isVisible ) {
4711
+ $( this ).show();
4712
+ }
4713
+ maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4714
+ if ( !isVisible ) {
4715
+ $( this ).hide();
4716
+ }
4717
+ } )
4718
+ .height( maxHeight );
4719
+ }
4720
+ },
4721
+
4722
+ _activate: function( index ) {
4723
+ var active = this._findActive( index )[ 0 ];
4724
+
4725
+ // Trying to activate the already active panel
4726
+ if ( active === this.active[ 0 ] ) {
4727
+ return;
4728
+ }
4729
+
4730
+ // Trying to collapse, simulate a click on the currently active header
4731
+ active = active || this.active[ 0 ];
4732
+
4733
+ this._eventHandler( {
4734
+ target: active,
4735
+ currentTarget: active,
4736
+ preventDefault: $.noop
4737
+ } );
4738
+ },
4739
+
4740
+ _findActive: function( selector ) {
4741
+ return typeof selector === "number" ? this.headers.eq( selector ) : $();
4742
+ },
4743
+
4744
+ _setupEvents: function( event ) {
4745
+ var events = {
4746
+ keydown: "_keydown"
4747
+ };
4748
+ if ( event ) {
4749
+ $.each( event.split( " " ), function( index, eventName ) {
4750
+ events[ eventName ] = "_eventHandler";
4751
+ } );
4752
+ }
4753
+
4754
+ this._off( this.headers.add( this.headers.next() ) );
4755
+ this._on( this.headers, events );
4756
+ this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4757
+ this._hoverable( this.headers );
4758
+ this._focusable( this.headers );
4759
+ },
4760
+
4761
+ _eventHandler: function( event ) {
4762
+ var activeChildren, clickedChildren,
4763
+ options = this.options,
4764
+ active = this.active,
4765
+ clicked = $( event.currentTarget ),
4766
+ clickedIsActive = clicked[ 0 ] === active[ 0 ],
4767
+ collapsing = clickedIsActive && options.collapsible,
4768
+ toShow = collapsing ? $() : clicked.next(),
4769
+ toHide = active.next(),
4770
+ eventData = {
4771
+ oldHeader: active,
4772
+ oldPanel: toHide,
4773
+ newHeader: collapsing ? $() : clicked,
4774
+ newPanel: toShow
4775
+ };
4776
+
4777
+ event.preventDefault();
4778
+
4779
+ if (
4780
+
4781
+ // click on active header, but not collapsible
4782
+ ( clickedIsActive && !options.collapsible ) ||
4783
+
4784
+ // allow canceling activation
4785
+ ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4786
+ return;
4787
+ }
4788
+
4789
+ options.active = collapsing ? false : this.headers.index( clicked );
4790
+
4791
+ // When the call to ._toggle() comes after the class changes
4792
+ // it causes a very odd bug in IE 8 (see #6720)
4793
+ this.active = clickedIsActive ? $() : clicked;
4794
+ this._toggle( eventData );
4795
+
4796
+ // Switch classes
4797
+ // corner classes on the previously active header stay after the animation
4798
+ this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4799
+ if ( options.icons ) {
4800
+ activeChildren = active.children( ".ui-accordion-header-icon" );
4801
+ this._removeClass( activeChildren, null, options.icons.activeHeader )
4802
+ ._addClass( activeChildren, null, options.icons.header );
4803
+ }
4804
+
4805
+ if ( !clickedIsActive ) {
4806
+ this._removeClass( clicked, "ui-accordion-header-collapsed" )
4807
+ ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4808
+ if ( options.icons ) {
4809
+ clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4810
+ this._removeClass( clickedChildren, null, options.icons.header )
4811
+ ._addClass( clickedChildren, null, options.icons.activeHeader );
4812
+ }
4813
+
4814
+ this._addClass( clicked.next(), "ui-accordion-content-active" );
4815
+ }
4816
+ },
4817
+
4818
+ _toggle: function( data ) {
4819
+ var toShow = data.newPanel,
4820
+ toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4821
+
4822
+ // Handle activating a panel during the animation for another activation
4823
+ this.prevShow.add( this.prevHide ).stop( true, true );
4824
+ this.prevShow = toShow;
4825
+ this.prevHide = toHide;
4826
+
4827
+ if ( this.options.animate ) {
4828
+ this._animate( toShow, toHide, data );
4829
+ } else {
4830
+ toHide.hide();
4831
+ toShow.show();
4832
+ this._toggleComplete( data );
4833
+ }
4834
+
4835
+ toHide.attr( {
4836
+ "aria-hidden": "true"
4837
+ } );
4838
+ toHide.prev().attr( {
4839
+ "aria-selected": "false",
4840
+ "aria-expanded": "false"
4841
+ } );
4842
+
4843
+ // if we're switching panels, remove the old header from the tab order
4844
+ // if we're opening from collapsed state, remove the previous header from the tab order
4845
+ // if we're collapsing, then keep the collapsing header in the tab order
4846
+ if ( toShow.length && toHide.length ) {
4847
+ toHide.prev().attr( {
4848
+ "tabIndex": -1,
4849
+ "aria-expanded": "false"
4850
+ } );
4851
+ } else if ( toShow.length ) {
4852
+ this.headers.filter( function() {
4853
+ return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4854
+ } )
4855
+ .attr( "tabIndex", -1 );
4856
+ }
4857
+
4858
+ toShow
4859
+ .attr( "aria-hidden", "false" )
4860
+ .prev()
4861
+ .attr( {
4862
+ "aria-selected": "true",
4863
+ "aria-expanded": "true",
4864
+ tabIndex: 0
4865
+ } );
4866
+ },
4867
+
4868
+ _animate: function( toShow, toHide, data ) {
4869
+ var total, easing, duration,
4870
+ that = this,
4871
+ adjust = 0,
4872
+ boxSizing = toShow.css( "box-sizing" ),
4873
+ down = toShow.length &&
4874
+ ( !toHide.length || ( toShow.index() < toHide.index() ) ),
4875
+ animate = this.options.animate || {},
4876
+ options = down && animate.down || animate,
4877
+ complete = function() {
4878
+ that._toggleComplete( data );
4879
+ };
4880
+
4881
+ if ( typeof options === "number" ) {
4882
+ duration = options;
4883
+ }
4884
+ if ( typeof options === "string" ) {
4885
+ easing = options;
4886
+ }
4887
+
4888
+ // fall back from options to animation in case of partial down settings
4889
+ easing = easing || options.easing || animate.easing;
4890
+ duration = duration || options.duration || animate.duration;
4891
+
4892
+ if ( !toHide.length ) {
4893
+ return toShow.animate( this.showProps, duration, easing, complete );
4894
+ }
4895
+ if ( !toShow.length ) {
4896
+ return toHide.animate( this.hideProps, duration, easing, complete );
4897
+ }
4898
+
4899
+ total = toShow.show().outerHeight();
4900
+ toHide.animate( this.hideProps, {
4901
+ duration: duration,
4902
+ easing: easing,
4903
+ step: function( now, fx ) {
4904
+ fx.now = Math.round( now );
4905
+ }
4906
+ } );
4907
+ toShow
4908
+ .hide()
4909
+ .animate( this.showProps, {
4910
+ duration: duration,
4911
+ easing: easing,
4912
+ complete: complete,
4913
+ step: function( now, fx ) {
4914
+ fx.now = Math.round( now );
4915
+ if ( fx.prop !== "height" ) {
4916
+ if ( boxSizing === "content-box" ) {
4917
+ adjust += fx.now;
4918
+ }
4919
+ } else if ( that.options.heightStyle !== "content" ) {
4920
+ fx.now = Math.round( total - toHide.outerHeight() - adjust );
4921
+ adjust = 0;
4922
+ }
4923
+ }
4924
+ } );
4925
+ },
4926
+
4927
+ _toggleComplete: function( data ) {
4928
+ var toHide = data.oldPanel,
4929
+ prev = toHide.prev();
4930
+
4931
+ this._removeClass( toHide, "ui-accordion-content-active" );
4932
+ this._removeClass( prev, "ui-accordion-header-active" )
4933
+ ._addClass( prev, "ui-accordion-header-collapsed" );
4934
+
4935
+ // Work around for rendering bug in IE (#5421)
4936
+ if ( toHide.length ) {
4937
+ toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
4938
+ }
4939
+ this._trigger( "activate", null, data );
4940
+ }
4941
+ } );
4942
+
4943
+
4944
+
4945
+ var safeActiveElement = $.ui.safeActiveElement = function( document ) {
4946
+ var activeElement;
4947
+
4948
+ // Support: IE 9 only
4949
+ // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
4950
+ try {
4951
+ activeElement = document.activeElement;
4952
+ } catch ( error ) {
4953
+ activeElement = document.body;
4954
+ }
4955
+
4956
+ // Support: IE 9 - 11 only
4957
+ // IE may return null instead of an element
4958
+ // Interestingly, this only seems to occur when NOT in an iframe
4959
+ if ( !activeElement ) {
4960
+ activeElement = document.body;
4961
+ }
4962
+
4963
+ // Support: IE 11 only
4964
+ // IE11 returns a seemingly empty object in some cases when accessing
4965
+ // document.activeElement from an <iframe>
4966
+ if ( !activeElement.nodeName ) {
4967
+ activeElement = document.body;
4968
+ }
4969
+
4970
+ return activeElement;
4971
+ };
4972
+
4973
+
4974
+ /*!
4975
+ * jQuery UI Menu 1.13.1
4976
+ * http://jqueryui.com
4977
+ *
4978
+ * Copyright jQuery Foundation and other contributors
4979
+ * Released under the MIT license.
4980
+ * http://jquery.org/license
4981
+ */
4982
+
4983
+ //>>label: Menu
4984
+ //>>group: Widgets
4985
+ //>>description: Creates nestable menus.
4986
+ //>>docs: http://api.jqueryui.com/menu/
4987
+ //>>demos: http://jqueryui.com/menu/
4988
+ //>>css.structure: ../../themes/base/core.css
4989
+ //>>css.structure: ../../themes/base/menu.css
4990
+ //>>css.theme: ../../themes/base/theme.css
4991
+
4992
+
4993
+ var widgetsMenu = $.widget( "ui.menu", {
4994
+ version: "1.13.1",
4995
+ defaultElement: "<ul>",
4996
+ delay: 300,
4997
+ options: {
4998
+ icons: {
4999
+ submenu: "ui-icon-caret-1-e"
5000
+ },
5001
+ items: "> *",
5002
+ menus: "ul",
5003
+ position: {
5004
+ my: "left top",
5005
+ at: "right top"
5006
+ },
5007
+ role: "menu",
5008
+
5009
+ // Callbacks
5010
+ blur: null,
5011
+ focus: null,
5012
+ select: null
5013
+ },
5014
+
5015
+ _create: function() {
5016
+ this.activeMenu = this.element;
5017
+
5018
+ // Flag used to prevent firing of the click handler
5019
+ // as the event bubbles up through nested menus
5020
+ this.mouseHandled = false;
5021
+ this.lastMousePosition = { x: null, y: null };
5022
+ this.element
5023
+ .uniqueId()
5024
+ .attr( {
5025
+ role: this.options.role,
5026
+ tabIndex: 0
5027
+ } );
5028
+
5029
+ this._addClass( "ui-menu", "ui-widget ui-widget-content" );
5030
+ this._on( {
5031
+
5032
+ // Prevent focus from sticking to links inside menu after clicking
5033
+ // them (focus should always stay on UL during navigation).
5034
+ "mousedown .ui-menu-item": function( event ) {
5035
+ event.preventDefault();
5036
+
5037
+ this._activateItem( event );
5038
+ },
5039
+ "click .ui-menu-item": function( event ) {
5040
+ var target = $( event.target );
5041
+ var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
5042
+ if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
5043
+ this.select( event );
5044
+
5045
+ // Only set the mouseHandled flag if the event will bubble, see #9469.
5046
+ if ( !event.isPropagationStopped() ) {
5047
+ this.mouseHandled = true;
5048
+ }
5049
+
5050
+ // Open submenu on click
5051
+ if ( target.has( ".ui-menu" ).length ) {
5052
+ this.expand( event );
5053
+ } else if ( !this.element.is( ":focus" ) &&
5054
+ active.closest( ".ui-menu" ).length ) {
5055
+
5056
+ // Redirect focus to the menu
5057
+ this.element.trigger( "focus", [ true ] );
5058
+
5059
+ // If the active item is on the top level, let it stay active.
5060
+ // Otherwise, blur the active item since it is no longer visible.
5061
+ if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
5062
+ clearTimeout( this.timer );
5063
+ }
5064
+ }
5065
+ }
5066
+ },
5067
+ "mouseenter .ui-menu-item": "_activateItem",
5068
+ "mousemove .ui-menu-item": "_activateItem",
5069
+ mouseleave: "collapseAll",
5070
+ "mouseleave .ui-menu": "collapseAll",
5071
+ focus: function( event, keepActiveItem ) {
5072
+
5073
+ // If there's already an active item, keep it active
5074
+ // If not, activate the first item
5075
+ var item = this.active || this._menuItems().first();
5076
+
5077
+ if ( !keepActiveItem ) {
5078
+ this.focus( event, item );
5079
+ }
5080
+ },
5081
+ blur: function( event ) {
5082
+ this._delay( function() {
5083
+ var notContained = !$.contains(
5084
+ this.element[ 0 ],
5085
+ $.ui.safeActiveElement( this.document[ 0 ] )
5086
+ );
5087
+ if ( notContained ) {
5088
+ this.collapseAll( event );
5089
+ }
5090
+ } );
5091
+ },
5092
+ keydown: "_keydown"
5093
+ } );
5094
+
5095
+ this.refresh();
5096
+
5097
+ // Clicks outside of a menu collapse any open menus
5098
+ this._on( this.document, {
5099
+ click: function( event ) {
5100
+ if ( this._closeOnDocumentClick( event ) ) {
5101
+ this.collapseAll( event, true );
5102
+ }
5103
+
5104
+ // Reset the mouseHandled flag
5105
+ this.mouseHandled = false;
5106
+ }
5107
+ } );
5108
+ },
5109
+
5110
+ _activateItem: function( event ) {
5111
+
5112
+ // Ignore mouse events while typeahead is active, see #10458.
5113
+ // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
5114
+ // is over an item in the menu
5115
+ if ( this.previousFilter ) {
5116
+ return;
5117
+ }
5118
+
5119
+ // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
5120
+ if ( event.clientX === this.lastMousePosition.x &&
5121
+ event.clientY === this.lastMousePosition.y ) {
5122
+ return;
5123
+ }
5124
+
5125
+ this.lastMousePosition = {
5126
+ x: event.clientX,
5127
+ y: event.clientY
5128
+ };
5129
+
5130
+ var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
5131
+ target = $( event.currentTarget );
5132
+
5133
+ // Ignore bubbled events on parent items, see #11641
5134
+ if ( actualTarget[ 0 ] !== target[ 0 ] ) {
5135
+ return;
5136
+ }
5137
+
5138
+ // If the item is already active, there's nothing to do
5139
+ if ( target.is( ".ui-state-active" ) ) {
5140
+ return;
5141
+ }
5142
+
5143
+ // Remove ui-state-active class from siblings of the newly focused menu item
5144
+ // to avoid a jump caused by adjacent elements both having a class with a border
5145
+ this._removeClass( target.siblings().children( ".ui-state-active" ),
5146
+ null, "ui-state-active" );
5147
+ this.focus( event, target );
5148
+ },
5149
+
5150
+ _destroy: function() {
5151
+ var items = this.element.find( ".ui-menu-item" )
5152
+ .removeAttr( "role aria-disabled" ),
5153
+ submenus = items.children( ".ui-menu-item-wrapper" )
5154
+ .removeUniqueId()
5155
+ .removeAttr( "tabIndex role aria-haspopup" );
5156
+
5157
+ // Destroy (sub)menus
5158
+ this.element
5159
+ .removeAttr( "aria-activedescendant" )
5160
+ .find( ".ui-menu" ).addBack()
5161
+ .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5162
+ "tabIndex" )
5163
+ .removeUniqueId()
5164
+ .show();
5165
+
5166
+ submenus.children().each( function() {
5167
+ var elem = $( this );
5168
+ if ( elem.data( "ui-menu-submenu-caret" ) ) {
5169
+ elem.remove();
5170
+ }
5171
+ } );
5172
+ },
5173
+
5174
+ _keydown: function( event ) {
5175
+ var match, prev, character, skip,
5176
+ preventDefault = true;
5177
+
5178
+ switch ( event.keyCode ) {
5179
+ case $.ui.keyCode.PAGE_UP:
5180
+ this.previousPage( event );
5181
+ break;
5182
+ case $.ui.keyCode.PAGE_DOWN:
5183
+ this.nextPage( event );
5184
+ break;
5185
+ case $.ui.keyCode.HOME:
5186
+ this._move( "first", "first", event );
5187
+ break;
5188
+ case $.ui.keyCode.END:
5189
+ this._move( "last", "last", event );
5190
+ break;
5191
+ case $.ui.keyCode.UP:
5192
+ this.previous( event );
5193
+ break;
5194
+ case $.ui.keyCode.DOWN:
5195
+ this.next( event );
5196
+ break;
5197
+ case $.ui.keyCode.LEFT:
5198
+ this.collapse( event );
5199
+ break;
5200
+ case $.ui.keyCode.RIGHT:
5201
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5202
+ this.expand( event );
5203
+ }
5204
+ break;
5205
+ case $.ui.keyCode.ENTER:
5206
+ case $.ui.keyCode.SPACE:
5207
+ this._activate( event );
5208
+ break;
5209
+ case $.ui.keyCode.ESCAPE:
5210
+ this.collapse( event );
5211
+ break;
5212
+ default:
5213
+ preventDefault = false;
5214
+ prev = this.previousFilter || "";
5215
+ skip = false;
5216
+
5217
+ // Support number pad values
5218
+ character = event.keyCode >= 96 && event.keyCode <= 105 ?
5219
+ ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5220
+
5221
+ clearTimeout( this.filterTimer );
5222
+
5223
+ if ( character === prev ) {
5224
+ skip = true;
5225
+ } else {
5226
+ character = prev + character;
5227
+ }
5228
+
5229
+ match = this._filterMenuItems( character );
5230
+ match = skip && match.index( this.active.next() ) !== -1 ?
5231
+ this.active.nextAll( ".ui-menu-item" ) :
5232
+ match;
5233
+
5234
+ // If no matches on the current filter, reset to the last character pressed
5235
+ // to move down the menu to the first item that starts with that character
5236
+ if ( !match.length ) {
5237
+ character = String.fromCharCode( event.keyCode );
5238
+ match = this._filterMenuItems( character );
5239
+ }
5240
+
5241
+ if ( match.length ) {
5242
+ this.focus( event, match );
5243
+ this.previousFilter = character;
5244
+ this.filterTimer = this._delay( function() {
5245
+ delete this.previousFilter;
5246
+ }, 1000 );
5247
+ } else {
5248
+ delete this.previousFilter;
5249
+ }
5250
+ }
5251
+
5252
+ if ( preventDefault ) {
5253
+ event.preventDefault();
5254
+ }
5255
+ },
5256
+
5257
+ _activate: function( event ) {
5258
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5259
+ if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5260
+ this.expand( event );
5261
+ } else {
5262
+ this.select( event );
5263
+ }
5264
+ }
5265
+ },
5266
+
5267
+ refresh: function() {
5268
+ var menus, items, newSubmenus, newItems, newWrappers,
5269
+ that = this,
5270
+ icon = this.options.icons.submenu,
5271
+ submenus = this.element.find( this.options.menus );
5272
+
5273
+ this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5274
+
5275
+ // Initialize nested menus
5276
+ newSubmenus = submenus.filter( ":not(.ui-menu)" )
5277
+ .hide()
5278
+ .attr( {
5279
+ role: this.options.role,
5280
+ "aria-hidden": "true",
5281
+ "aria-expanded": "false"
5282
+ } )
5283
+ .each( function() {
5284
+ var menu = $( this ),
5285
+ item = menu.prev(),
5286
+ submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5287
+
5288
+ that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5289
+ item
5290
+ .attr( "aria-haspopup", "true" )
5291
+ .prepend( submenuCaret );
5292
+ menu.attr( "aria-labelledby", item.attr( "id" ) );
5293
+ } );
5294
+
5295
+ this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5296
+
5297
+ menus = submenus.add( this.element );
5298
+ items = menus.find( this.options.items );
5299
+
5300
+ // Initialize menu-items containing spaces and/or dashes only as dividers
5301
+ items.not( ".ui-menu-item" ).each( function() {
5302
+ var item = $( this );
5303
+ if ( that._isDivider( item ) ) {
5304
+ that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5305
+ }
5306
+ } );
5307
+
5308
+ // Don't refresh list items that are already adapted
5309
+ newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5310
+ newWrappers = newItems.children()
5311
+ .not( ".ui-menu" )
5312
+ .uniqueId()
5313
+ .attr( {
5314
+ tabIndex: -1,
5315
+ role: this._itemRole()
5316
+ } );
5317
+ this._addClass( newItems, "ui-menu-item" )
5318
+ ._addClass( newWrappers, "ui-menu-item-wrapper" );
5319
+
5320
+ // Add aria-disabled attribute to any disabled menu item
5321
+ items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5322
+
5323
+ // If the active item has been removed, blur the menu
5324
+ if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5325
+ this.blur();
5326
+ }
5327
+ },
5328
+
5329
+ _itemRole: function() {
5330
+ return {
5331
+ menu: "menuitem",
5332
+ listbox: "option"
5333
+ }[ this.options.role ];
5334
+ },
5335
+
5336
+ _setOption: function( key, value ) {
5337
+ if ( key === "icons" ) {
5338
+ var icons = this.element.find( ".ui-menu-icon" );
5339
+ this._removeClass( icons, null, this.options.icons.submenu )
5340
+ ._addClass( icons, null, value.submenu );
5341
+ }
5342
+ this._super( key, value );
5343
+ },
5344
+
5345
+ _setOptionDisabled: function( value ) {
5346
+ this._super( value );
5347
+
5348
+ this.element.attr( "aria-disabled", String( value ) );
5349
+ this._toggleClass( null, "ui-state-disabled", !!value );
5350
+ },
5351
+
5352
+ focus: function( event, item ) {
5353
+ var nested, focused, activeParent;
5354
+ this.blur( event, event && event.type === "focus" );
5355
+
5356
+ this._scrollIntoView( item );
5357
+
5358
+ this.active = item.first();
5359
+
5360
+ focused = this.active.children( ".ui-menu-item-wrapper" );
5361
+ this._addClass( focused, null, "ui-state-active" );
5362
+
5363
+ // Only update aria-activedescendant if there's a role
5364
+ // otherwise we assume focus is managed elsewhere
5365
+ if ( this.options.role ) {
5366
+ this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5367
+ }
5368
+
5369
+ // Highlight active parent menu item, if any
5370
+ activeParent = this.active
5371
+ .parent()
5372
+ .closest( ".ui-menu-item" )
5373
+ .children( ".ui-menu-item-wrapper" );
5374
+ this._addClass( activeParent, null, "ui-state-active" );
5375
+
5376
+ if ( event && event.type === "keydown" ) {
5377
+ this._close();
5378
+ } else {
5379
+ this.timer = this._delay( function() {
5380
+ this._close();
5381
+ }, this.delay );
5382
+ }
5383
+
5384
+ nested = item.children( ".ui-menu" );
5385
+ if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5386
+ this._startOpening( nested );
5387
+ }
5388
+ this.activeMenu = item.parent();
5389
+
5390
+ this._trigger( "focus", event, { item: item } );
5391
+ },
5392
+
5393
+ _scrollIntoView: function( item ) {
5394
+ var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5395
+ if ( this._hasScroll() ) {
5396
+ borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5397
+ paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5398
+ offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5399
+ scroll = this.activeMenu.scrollTop();
5400
+ elementHeight = this.activeMenu.height();
5401
+ itemHeight = item.outerHeight();
5402
+
5403
+ if ( offset < 0 ) {
5404
+ this.activeMenu.scrollTop( scroll + offset );
5405
+ } else if ( offset + itemHeight > elementHeight ) {
5406
+ this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5407
+ }
5408
+ }
5409
+ },
5410
+
5411
+ blur: function( event, fromFocus ) {
5412
+ if ( !fromFocus ) {
5413
+ clearTimeout( this.timer );
5414
+ }
5415
+
5416
+ if ( !this.active ) {
5417
+ return;
5418
+ }
5419
+
5420
+ this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5421
+ null, "ui-state-active" );
5422
+
5423
+ this._trigger( "blur", event, { item: this.active } );
5424
+ this.active = null;
5425
+ },
5426
+
5427
+ _startOpening: function( submenu ) {
5428
+ clearTimeout( this.timer );
5429
+
5430
+ // Don't open if already open fixes a Firefox bug that caused a .5 pixel
5431
+ // shift in the submenu position when mousing over the caret icon
5432
+ if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5433
+ return;
5434
+ }
5435
+
5436
+ this.timer = this._delay( function() {
5437
+ this._close();
5438
+ this._open( submenu );
5439
+ }, this.delay );
5440
+ },
5441
+
5442
+ _open: function( submenu ) {
5443
+ var position = $.extend( {
5444
+ of: this.active
5445
+ }, this.options.position );
5446
+
5447
+ clearTimeout( this.timer );
5448
+ this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5449
+ .hide()
5450
+ .attr( "aria-hidden", "true" );
5451
+
5452
+ submenu
5453
+ .show()
5454
+ .removeAttr( "aria-hidden" )
5455
+ .attr( "aria-expanded", "true" )
5456
+ .position( position );
5457
+ },
5458
+
5459
+ collapseAll: function( event, all ) {
5460
+ clearTimeout( this.timer );
5461
+ this.timer = this._delay( function() {
5462
+
5463
+ // If we were passed an event, look for the submenu that contains the event
5464
+ var currentMenu = all ? this.element :
5465
+ $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5466
+
5467
+ // If we found no valid submenu ancestor, use the main menu to close all
5468
+ // sub menus anyway
5469
+ if ( !currentMenu.length ) {
5470
+ currentMenu = this.element;
5471
+ }
5472
+
5473
+ this._close( currentMenu );
5474
+
5475
+ this.blur( event );
5476
+
5477
+ // Work around active item staying active after menu is blurred
5478
+ this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5479
+
5480
+ this.activeMenu = currentMenu;
5481
+ }, all ? 0 : this.delay );
5482
+ },
5483
+
5484
+ // With no arguments, closes the currently active menu - if nothing is active
5485
+ // it closes all menus. If passed an argument, it will search for menus BELOW
5486
+ _close: function( startMenu ) {
5487
+ if ( !startMenu ) {
5488
+ startMenu = this.active ? this.active.parent() : this.element;
5489
+ }
5490
+
5491
+ startMenu.find( ".ui-menu" )
5492
+ .hide()
5493
+ .attr( "aria-hidden", "true" )
5494
+ .attr( "aria-expanded", "false" );
5495
+ },
5496
+
5497
+ _closeOnDocumentClick: function( event ) {
5498
+ return !$( event.target ).closest( ".ui-menu" ).length;
5499
+ },
5500
+
5501
+ _isDivider: function( item ) {
5502
+
5503
+ // Match hyphen, em dash, en dash
5504
+ return !/[^\-\u2014\u2013\s]/.test( item.text() );
5505
+ },
5506
+
5507
+ collapse: function( event ) {
5508
+ var newItem = this.active &&
5509
+ this.active.parent().closest( ".ui-menu-item", this.element );
5510
+ if ( newItem && newItem.length ) {
5511
+ this._close();
5512
+ this.focus( event, newItem );
5513
+ }
5514
+ },
5515
+
5516
+ expand: function( event ) {
5517
+ var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5518
+
5519
+ if ( newItem && newItem.length ) {
5520
+ this._open( newItem.parent() );
5521
+
5522
+ // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5523
+ this._delay( function() {
5524
+ this.focus( event, newItem );
5525
+ } );
5526
+ }
5527
+ },
5528
+
5529
+ next: function( event ) {
5530
+ this._move( "next", "first", event );
5531
+ },
5532
+
5533
+ previous: function( event ) {
5534
+ this._move( "prev", "last", event );
5535
+ },
5536
+
5537
+ isFirstItem: function() {
5538
+ return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5539
+ },
5540
+
5541
+ isLastItem: function() {
5542
+ return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5543
+ },
5544
+
5545
+ _menuItems: function( menu ) {
5546
+ return ( menu || this.element )
5547
+ .find( this.options.items )
5548
+ .filter( ".ui-menu-item" );
5549
+ },
5550
+
5551
+ _move: function( direction, filter, event ) {
5552
+ var next;
5553
+ if ( this.active ) {
5554
+ if ( direction === "first" || direction === "last" ) {
5555
+ next = this.active
5556
+ [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5557
+ .last();
5558
+ } else {
5559
+ next = this.active
5560
+ [ direction + "All" ]( ".ui-menu-item" )
5561
+ .first();
5562
+ }
5563
+ }
5564
+ if ( !next || !next.length || !this.active ) {
5565
+ next = this._menuItems( this.activeMenu )[ filter ]();
5566
+ }
5567
+
5568
+ this.focus( event, next );
5569
+ },
5570
+
5571
+ nextPage: function( event ) {
5572
+ var item, base, height;
5573
+
5574
+ if ( !this.active ) {
5575
+ this.next( event );
5576
+ return;
5577
+ }
5578
+ if ( this.isLastItem() ) {
5579
+ return;
5580
+ }
5581
+ if ( this._hasScroll() ) {
5582
+ base = this.active.offset().top;
5583
+ height = this.element.innerHeight();
5584
+
5585
+ // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5586
+ if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5587
+ height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5588
+ }
5589
+
5590
+ this.active.nextAll( ".ui-menu-item" ).each( function() {
5591
+ item = $( this );
5592
+ return item.offset().top - base - height < 0;
5593
+ } );
5594
+
5595
+ this.focus( event, item );
5596
+ } else {
5597
+ this.focus( event, this._menuItems( this.activeMenu )
5598
+ [ !this.active ? "first" : "last" ]() );
5599
+ }
5600
+ },
5601
+
5602
+ previousPage: function( event ) {
5603
+ var item, base, height;
5604
+ if ( !this.active ) {
5605
+ this.next( event );
5606
+ return;
5607
+ }
5608
+ if ( this.isFirstItem() ) {
5609
+ return;
5610
+ }
5611
+ if ( this._hasScroll() ) {
5612
+ base = this.active.offset().top;
5613
+ height = this.element.innerHeight();
5614
+
5615
+ // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5616
+ if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5617
+ height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5618
+ }
5619
+
5620
+ this.active.prevAll( ".ui-menu-item" ).each( function() {
5621
+ item = $( this );
5622
+ return item.offset().top - base + height > 0;
5623
+ } );
5624
+
5625
+ this.focus( event, item );
5626
+ } else {
5627
+ this.focus( event, this._menuItems( this.activeMenu ).first() );
5628
+ }
5629
+ },
5630
+
5631
+ _hasScroll: function() {
5632
+ return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5633
+ },
5634
+
5635
+ select: function( event ) {
5636
+
5637
+ // TODO: It should never be possible to not have an active item at this
5638
+ // point, but the tests don't trigger mouseenter before click.
5639
+ this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5640
+ var ui = { item: this.active };
5641
+ if ( !this.active.has( ".ui-menu" ).length ) {
5642
+ this.collapseAll( event, true );
5643
+ }
5644
+ this._trigger( "select", event, ui );
5645
+ },
5646
+
5647
+ _filterMenuItems: function( character ) {
5648
+ var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5649
+ regex = new RegExp( "^" + escapedCharacter, "i" );
5650
+
5651
+ return this.activeMenu
5652
+ .find( this.options.items )
5653
+
5654
+ // Only match on items, not dividers or other content (#10571)
5655
+ .filter( ".ui-menu-item" )
5656
+ .filter( function() {
5657
+ return regex.test(
5658
+ String.prototype.trim.call(
5659
+ $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5660
+ } );
5661
+ }
5662
+ } );
5663
+
5664
+
5665
+ /*!
5666
+ * jQuery UI Autocomplete 1.13.1
5667
+ * http://jqueryui.com
5668
+ *
5669
+ * Copyright jQuery Foundation and other contributors
5670
+ * Released under the MIT license.
5671
+ * http://jquery.org/license
5672
+ */
5673
+
5674
+ //>>label: Autocomplete
5675
+ //>>group: Widgets
5676
+ //>>description: Lists suggested words as the user is typing.
5677
+ //>>docs: http://api.jqueryui.com/autocomplete/
5678
+ //>>demos: http://jqueryui.com/autocomplete/
5679
+ //>>css.structure: ../../themes/base/core.css
5680
+ //>>css.structure: ../../themes/base/autocomplete.css
5681
+ //>>css.theme: ../../themes/base/theme.css
5682
+
5683
+
5684
+ $.widget( "ui.autocomplete", {
5685
+ version: "1.13.1",
5686
+ defaultElement: "<input>",
5687
+ options: {
5688
+ appendTo: null,
5689
+ autoFocus: false,
5690
+ delay: 300,
5691
+ minLength: 1,
5692
+ position: {
5693
+ my: "left top",
5694
+ at: "left bottom",
5695
+ collision: "none"
5696
+ },
5697
+ source: null,
5698
+
5699
+ // Callbacks
5700
+ change: null,
5701
+ close: null,
5702
+ focus: null,
5703
+ open: null,
5704
+ response: null,
5705
+ search: null,
5706
+ select: null
5707
+ },
5708
+
5709
+ requestIndex: 0,
5710
+ pending: 0,
5711
+ liveRegionTimer: null,
5712
+
5713
+ _create: function() {
5714
+
5715
+ // Some browsers only repeat keydown events, not keypress events,
5716
+ // so we use the suppressKeyPress flag to determine if we've already
5717
+ // handled the keydown event. #7269
5718
+ // Unfortunately the code for & in keypress is the same as the up arrow,
5719
+ // so we use the suppressKeyPressRepeat flag to avoid handling keypress
5720
+ // events when we know the keydown event was used to modify the
5721
+ // search term. #7799
5722
+ var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5723
+ nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5724
+ isTextarea = nodeName === "textarea",
5725
+ isInput = nodeName === "input";
5726
+
5727
+ // Textareas are always multi-line
5728
+ // Inputs are always single-line, even if inside a contentEditable element
5729
+ // IE also treats inputs as contentEditable
5730
+ // All other element types are determined by whether or not they're contentEditable
5731
+ this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
5732
+
5733
+ this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5734
+ this.isNewMenu = true;
5735
+
5736
+ this._addClass( "ui-autocomplete-input" );
5737
+ this.element.attr( "autocomplete", "off" );
5738
+
5739
+ this._on( this.element, {
5740
+ keydown: function( event ) {
5741
+ if ( this.element.prop( "readOnly" ) ) {
5742
+ suppressKeyPress = true;
5743
+ suppressInput = true;
5744
+ suppressKeyPressRepeat = true;
5745
+ return;
5746
+ }
5747
+
5748
+ suppressKeyPress = false;
5749
+ suppressInput = false;
5750
+ suppressKeyPressRepeat = false;
5751
+ var keyCode = $.ui.keyCode;
5752
+ switch ( event.keyCode ) {
5753
+ case keyCode.PAGE_UP:
5754
+ suppressKeyPress = true;
5755
+ this._move( "previousPage", event );
5756
+ break;
5757
+ case keyCode.PAGE_DOWN:
5758
+ suppressKeyPress = true;
5759
+ this._move( "nextPage", event );
5760
+ break;
5761
+ case keyCode.UP:
5762
+ suppressKeyPress = true;
5763
+ this._keyEvent( "previous", event );
5764
+ break;
5765
+ case keyCode.DOWN:
5766
+ suppressKeyPress = true;
5767
+ this._keyEvent( "next", event );
5768
+ break;
5769
+ case keyCode.ENTER:
5770
+
5771
+ // when menu is open and has focus
5772
+ if ( this.menu.active ) {
5773
+
5774
+ // #6055 - Opera still allows the keypress to occur
5775
+ // which causes forms to submit
5776
+ suppressKeyPress = true;
5777
+ event.preventDefault();
5778
+ this.menu.select( event );
5779
+ }
5780
+ break;
5781
+ case keyCode.TAB:
5782
+ if ( this.menu.active ) {
5783
+ this.menu.select( event );
5784
+ }
5785
+ break;
5786
+ case keyCode.ESCAPE:
5787
+ if ( this.menu.element.is( ":visible" ) ) {
5788
+ if ( !this.isMultiLine ) {
5789
+ this._value( this.term );
5790
+ }
5791
+ this.close( event );
5792
+
5793
+ // Different browsers have different default behavior for escape
5794
+ // Single press can mean undo or clear
5795
+ // Double press in IE means clear the whole form
5796
+ event.preventDefault();
5797
+ }
5798
+ break;
5799
+ default:
5800
+ suppressKeyPressRepeat = true;
5801
+
5802
+ // search timeout should be triggered before the input value is changed
5803
+ this._searchTimeout( event );
5804
+ break;
5805
+ }
5806
+ },
5807
+ keypress: function( event ) {
5808
+ if ( suppressKeyPress ) {
5809
+ suppressKeyPress = false;
5810
+ if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5811
+ event.preventDefault();
5812
+ }
5813
+ return;
5814
+ }
5815
+ if ( suppressKeyPressRepeat ) {
5816
+ return;
5817
+ }
5818
+
5819
+ // Replicate some key handlers to allow them to repeat in Firefox and Opera
5820
+ var keyCode = $.ui.keyCode;
5821
+ switch ( event.keyCode ) {
5822
+ case keyCode.PAGE_UP:
5823
+ this._move( "previousPage", event );
5824
+ break;
5825
+ case keyCode.PAGE_DOWN:
5826
+ this._move( "nextPage", event );
5827
+ break;
5828
+ case keyCode.UP:
5829
+ this._keyEvent( "previous", event );
5830
+ break;
5831
+ case keyCode.DOWN:
5832
+ this._keyEvent( "next", event );
5833
+ break;
5834
+ }
5835
+ },
5836
+ input: function( event ) {
5837
+ if ( suppressInput ) {
5838
+ suppressInput = false;
5839
+ event.preventDefault();
5840
+ return;
5841
+ }
5842
+ this._searchTimeout( event );
5843
+ },
5844
+ focus: function() {
5845
+ this.selectedItem = null;
5846
+ this.previous = this._value();
5847
+ },
5848
+ blur: function( event ) {
5849
+ clearTimeout( this.searching );
5850
+ this.close( event );
5851
+ this._change( event );
5852
+ }
5853
+ } );
5854
+
5855
+ this._initSource();
5856
+ this.menu = $( "<ul>" )
5857
+ .appendTo( this._appendTo() )
5858
+ .menu( {
5859
+
5860
+ // disable ARIA support, the live region takes care of that
5861
+ role: null
5862
+ } )
5863
+ .hide()
5864
+
5865
+ // Support: IE 11 only, Edge <= 14
5866
+ // For other browsers, we preventDefault() on the mousedown event
5867
+ // to keep the dropdown from taking focus from the input. This doesn't
5868
+ // work for IE/Edge, causing problems with selection and scrolling (#9638)
5869
+ // Happily, IE and Edge support an "unselectable" attribute that
5870
+ // prevents an element from receiving focus, exactly what we want here.
5871
+ .attr( {
5872
+ "unselectable": "on"
5873
+ } )
5874
+ .menu( "instance" );
5875
+
5876
+ this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5877
+ this._on( this.menu.element, {
5878
+ mousedown: function( event ) {
5879
+
5880
+ // Prevent moving focus out of the text field
5881
+ event.preventDefault();
5882
+ },
5883
+ menufocus: function( event, ui ) {
5884
+ var label, item;
5885
+
5886
+ // support: Firefox
5887
+ // Prevent accidental activation of menu items in Firefox (#7024 #9118)
5888
+ if ( this.isNewMenu ) {
5889
+ this.isNewMenu = false;
5890
+ if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5891
+ this.menu.blur();
5892
+
5893
+ this.document.one( "mousemove", function() {
5894
+ $( event.target ).trigger( event.originalEvent );
5895
+ } );
5896
+
5897
+ return;
5898
+ }
5899
+ }
5900
+
5901
+ item = ui.item.data( "ui-autocomplete-item" );
5902
+ if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5903
+
5904
+ // use value to match what will end up in the input, if it was a key event
5905
+ if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5906
+ this._value( item.value );
5907
+ }
5908
+ }
5909
+
5910
+ // Announce the value in the liveRegion
5911
+ label = ui.item.attr( "aria-label" ) || item.value;
5912
+ if ( label && String.prototype.trim.call( label ).length ) {
5913
+ clearTimeout( this.liveRegionTimer );
5914
+ this.liveRegionTimer = this._delay( function() {
5915
+ this.liveRegion.html( $( "<div>" ).text( label ) );
5916
+ }, 100 );
5917
+ }
5918
+ },
5919
+ menuselect: function( event, ui ) {
5920
+ var item = ui.item.data( "ui-autocomplete-item" ),
5921
+ previous = this.previous;
5922
+
5923
+ // Only trigger when focus was lost (click on menu)
5924
+ if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5925
+ this.element.trigger( "focus" );
5926
+ this.previous = previous;
5927
+
5928
+ // #6109 - IE triggers two focus events and the second
5929
+ // is asynchronous, so we need to reset the previous
5930
+ // term synchronously and asynchronously :-(
5931
+ this._delay( function() {
5932
+ this.previous = previous;
5933
+ this.selectedItem = item;
5934
+ } );
5935
+ }
5936
+
5937
+ if ( false !== this._trigger( "select", event, { item: item } ) ) {
5938
+ this._value( item.value );
5939
+ }
5940
+
5941
+ // reset the term after the select event
5942
+ // this allows custom select handling to work properly
5943
+ this.term = this._value();
5944
+
5945
+ this.close( event );
5946
+ this.selectedItem = item;
5947
+ }
5948
+ } );
5949
+
5950
+ this.liveRegion = $( "<div>", {
5951
+ role: "status",
5952
+ "aria-live": "assertive",
5953
+ "aria-relevant": "additions"
5954
+ } )
5955
+ .appendTo( this.document[ 0 ].body );
5956
+
5957
+ this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5958
+
5959
+ // Turning off autocomplete prevents the browser from remembering the
5960
+ // value when navigating through history, so we re-enable autocomplete
5961
+ // if the page is unloaded before the widget is destroyed. #7790
5962
+ this._on( this.window, {
5963
+ beforeunload: function() {
5964
+ this.element.removeAttr( "autocomplete" );
5965
+ }
5966
+ } );
5967
+ },
5968
+
5969
+ _destroy: function() {
5970
+ clearTimeout( this.searching );
5971
+ this.element.removeAttr( "autocomplete" );
5972
+ this.menu.element.remove();
5973
+ this.liveRegion.remove();
5974
+ },
5975
+
5976
+ _setOption: function( key, value ) {
5977
+ this._super( key, value );
5978
+ if ( key === "source" ) {
5979
+ this._initSource();
5980
+ }
5981
+ if ( key === "appendTo" ) {
5982
+ this.menu.element.appendTo( this._appendTo() );
5983
+ }
5984
+ if ( key === "disabled" && value && this.xhr ) {
5985
+ this.xhr.abort();
5986
+ }
5987
+ },
5988
+
5989
+ _isEventTargetInWidget: function( event ) {
5990
+ var menuElement = this.menu.element[ 0 ];
5991
+
5992
+ return event.target === this.element[ 0 ] ||
5993
+ event.target === menuElement ||
5994
+ $.contains( menuElement, event.target );
5995
+ },
5996
+
5997
+ _closeOnClickOutside: function( event ) {
5998
+ if ( !this._isEventTargetInWidget( event ) ) {
5999
+ this.close();
6000
+ }
6001
+ },
6002
+
6003
+ _appendTo: function() {
6004
+ var element = this.options.appendTo;
6005
+
6006
+ if ( element ) {
6007
+ element = element.jquery || element.nodeType ?
6008
+ $( element ) :
6009
+ this.document.find( element ).eq( 0 );
6010
+ }
6011
+
6012
+ if ( !element || !element[ 0 ] ) {
6013
+ element = this.element.closest( ".ui-front, dialog" );
6014
+ }
6015
+
6016
+ if ( !element.length ) {
6017
+ element = this.document[ 0 ].body;
6018
+ }
6019
+
6020
+ return element;
6021
+ },
6022
+
6023
+ _initSource: function() {
6024
+ var array, url,
6025
+ that = this;
6026
+ if ( Array.isArray( this.options.source ) ) {
6027
+ array = this.options.source;
6028
+ this.source = function( request, response ) {
6029
+ response( $.ui.autocomplete.filter( array, request.term ) );
6030
+ };
6031
+ } else if ( typeof this.options.source === "string" ) {
6032
+ url = this.options.source;
6033
+ this.source = function( request, response ) {
6034
+ if ( that.xhr ) {
6035
+ that.xhr.abort();
6036
+ }
6037
+ that.xhr = $.ajax( {
6038
+ url: url,
6039
+ data: request,
6040
+ dataType: "json",
6041
+ success: function( data ) {
6042
+ response( data );
6043
+ },
6044
+ error: function() {
6045
+ response( [] );
6046
+ }
6047
+ } );
6048
+ };
6049
+ } else {
6050
+ this.source = this.options.source;
6051
+ }
6052
+ },
6053
+
6054
+ _searchTimeout: function( event ) {
6055
+ clearTimeout( this.searching );
6056
+ this.searching = this._delay( function() {
6057
+
6058
+ // Search if the value has changed, or if the user retypes the same value (see #7434)
6059
+ var equalValues = this.term === this._value(),
6060
+ menuVisible = this.menu.element.is( ":visible" ),
6061
+ modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
6062
+
6063
+ if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
6064
+ this.selectedItem = null;
6065
+ this.search( null, event );
6066
+ }
6067
+ }, this.options.delay );
6068
+ },
6069
+
6070
+ search: function( value, event ) {
6071
+ value = value != null ? value : this._value();
6072
+
6073
+ // Always save the actual value, not the one passed as an argument
6074
+ this.term = this._value();
6075
+
6076
+ if ( value.length < this.options.minLength ) {
6077
+ return this.close( event );
6078
+ }
6079
+
6080
+ if ( this._trigger( "search", event ) === false ) {
6081
+ return;
6082
+ }
6083
+
6084
+ return this._search( value );
6085
+ },
6086
+
6087
+ _search: function( value ) {
6088
+ this.pending++;
6089
+ this._addClass( "ui-autocomplete-loading" );
6090
+ this.cancelSearch = false;
6091
+
6092
+ this.source( { term: value }, this._response() );
6093
+ },
6094
+
6095
+ _response: function() {
6096
+ var index = ++this.requestIndex;
6097
+
6098
+ return function( content ) {
6099
+ if ( index === this.requestIndex ) {
6100
+ this.__response( content );
6101
+ }
6102
+
6103
+ this.pending--;
6104
+ if ( !this.pending ) {
6105
+ this._removeClass( "ui-autocomplete-loading" );
6106
+ }
6107
+ }.bind( this );
6108
+ },
6109
+
6110
+ __response: function( content ) {
6111
+ if ( content ) {
6112
+ content = this._normalize( content );
6113
+ }
6114
+ this._trigger( "response", null, { content: content } );
6115
+ if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6116
+ this._suggest( content );
6117
+ this._trigger( "open" );
6118
+ } else {
6119
+
6120
+ // use ._close() instead of .close() so we don't cancel future searches
6121
+ this._close();
6122
+ }
6123
+ },
6124
+
6125
+ close: function( event ) {
6126
+ this.cancelSearch = true;
6127
+ this._close( event );
6128
+ },
6129
+
6130
+ _close: function( event ) {
6131
+
6132
+ // Remove the handler that closes the menu on outside clicks
6133
+ this._off( this.document, "mousedown" );
6134
+
6135
+ if ( this.menu.element.is( ":visible" ) ) {
6136
+ this.menu.element.hide();
6137
+ this.menu.blur();
6138
+ this.isNewMenu = true;
6139
+ this._trigger( "close", event );
6140
+ }
6141
+ },
6142
+
6143
+ _change: function( event ) {
6144
+ if ( this.previous !== this._value() ) {
6145
+ this._trigger( "change", event, { item: this.selectedItem } );
6146
+ }
6147
+ },
6148
+
6149
+ _normalize: function( items ) {
6150
+
6151
+ // assume all items have the right format when the first item is complete
6152
+ if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
6153
+ return items;
6154
+ }
6155
+ return $.map( items, function( item ) {
6156
+ if ( typeof item === "string" ) {
6157
+ return {
6158
+ label: item,
6159
+ value: item
6160
+ };
6161
+ }
6162
+ return $.extend( {}, item, {
6163
+ label: item.label || item.value,
6164
+ value: item.value || item.label
6165
+ } );
6166
+ } );
6167
+ },
6168
+
6169
+ _suggest: function( items ) {
6170
+ var ul = this.menu.element.empty();
6171
+ this._renderMenu( ul, items );
6172
+ this.isNewMenu = true;
6173
+ this.menu.refresh();
6174
+
6175
+ // Size and position menu
6176
+ ul.show();
6177
+ this._resizeMenu();
6178
+ ul.position( $.extend( {
6179
+ of: this.element
6180
+ }, this.options.position ) );
6181
+
6182
+ if ( this.options.autoFocus ) {
6183
+ this.menu.next();
6184
+ }
6185
+
6186
+ // Listen for interactions outside of the widget (#6642)
6187
+ this._on( this.document, {
6188
+ mousedown: "_closeOnClickOutside"
6189
+ } );
6190
+ },
6191
+
6192
+ _resizeMenu: function() {
6193
+ var ul = this.menu.element;
6194
+ ul.outerWidth( Math.max(
6195
+
6196
+ // Firefox wraps long text (possibly a rounding bug)
6197
+ // so we add 1px to avoid the wrapping (#7513)
6198
+ ul.width( "" ).outerWidth() + 1,
6199
+ this.element.outerWidth()
6200
+ ) );
6201
+ },
6202
+
6203
+ _renderMenu: function( ul, items ) {
6204
+ var that = this;
6205
+ $.each( items, function( index, item ) {
6206
+ that._renderItemData( ul, item );
6207
+ } );
6208
+ },
6209
+
6210
+ _renderItemData: function( ul, item ) {
6211
+ return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6212
+ },
6213
+
6214
+ _renderItem: function( ul, item ) {
6215
+ return $( "<li>" )
6216
+ .append( $( "<div>" ).text( item.label ) )
6217
+ .appendTo( ul );
6218
+ },
6219
+
6220
+ _move: function( direction, event ) {
6221
+ if ( !this.menu.element.is( ":visible" ) ) {
6222
+ this.search( null, event );
6223
+ return;
6224
+ }
6225
+ if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6226
+ this.menu.isLastItem() && /^next/.test( direction ) ) {
6227
+
6228
+ if ( !this.isMultiLine ) {
6229
+ this._value( this.term );
6230
+ }
6231
+
6232
+ this.menu.blur();
6233
+ return;
6234
+ }
6235
+ this.menu[ direction ]( event );
6236
+ },
6237
+
6238
+ widget: function() {
6239
+ return this.menu.element;
6240
+ },
6241
+
6242
+ _value: function() {
6243
+ return this.valueMethod.apply( this.element, arguments );
6244
+ },
6245
+
6246
+ _keyEvent: function( keyEvent, event ) {
6247
+ if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6248
+ this._move( keyEvent, event );
6249
+
6250
+ // Prevents moving cursor to beginning/end of the text field in some browsers
6251
+ event.preventDefault();
6252
+ }
6253
+ },
6254
+
6255
+ // Support: Chrome <=50
6256
+ // We should be able to just use this.element.prop( "isContentEditable" )
6257
+ // but hidden elements always report false in Chrome.
6258
+ // https://code.google.com/p/chromium/issues/detail?id=313082
6259
+ _isContentEditable: function( element ) {
6260
+ if ( !element.length ) {
6261
+ return false;
6262
+ }
6263
+
6264
+ var editable = element.prop( "contentEditable" );
6265
+
6266
+ if ( editable === "inherit" ) {
6267
+ return this._isContentEditable( element.parent() );
6268
+ }
6269
+
6270
+ return editable === "true";
6271
+ }
6272
+ } );
6273
+
6274
+ $.extend( $.ui.autocomplete, {
6275
+ escapeRegex: function( value ) {
6276
+ return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6277
+ },
6278
+ filter: function( array, term ) {
6279
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6280
+ return $.grep( array, function( value ) {
6281
+ return matcher.test( value.label || value.value || value );
6282
+ } );
6283
+ }
6284
+ } );
6285
+
6286
+ // Live region extension, adding a `messages` option
6287
+ // NOTE: This is an experimental API. We are still investigating
6288
+ // a full solution for string manipulation and internationalization.
6289
+ $.widget( "ui.autocomplete", $.ui.autocomplete, {
6290
+ options: {
6291
+ messages: {
6292
+ noResults: "No search results.",
6293
+ results: function( amount ) {
6294
+ return amount + ( amount > 1 ? " results are" : " result is" ) +
6295
+ " available, use up and down arrow keys to navigate.";
6296
+ }
6297
+ }
6298
+ },
6299
+
6300
+ __response: function( content ) {
6301
+ var message;
6302
+ this._superApply( arguments );
6303
+ if ( this.options.disabled || this.cancelSearch ) {
6304
+ return;
6305
+ }
6306
+ if ( content && content.length ) {
6307
+ message = this.options.messages.results( content.length );
6308
+ } else {
6309
+ message = this.options.messages.noResults;
6310
+ }
6311
+ clearTimeout( this.liveRegionTimer );
6312
+ this.liveRegionTimer = this._delay( function() {
6313
+ this.liveRegion.html( $( "<div>" ).text( message ) );
6314
+ }, 100 );
6315
+ }
6316
+ } );
6317
+
6318
+ var widgetsAutocomplete = $.ui.autocomplete;
6319
+
6320
+
6321
+ /*!
6322
+ * jQuery UI Controlgroup 1.13.1
6323
+ * http://jqueryui.com
6324
+ *
6325
+ * Copyright jQuery Foundation and other contributors
6326
+ * Released under the MIT license.
6327
+ * http://jquery.org/license
6328
+ */
6329
+
6330
+ //>>label: Controlgroup
6331
+ //>>group: Widgets
6332
+ //>>description: Visually groups form control widgets
6333
+ //>>docs: http://api.jqueryui.com/controlgroup/
6334
+ //>>demos: http://jqueryui.com/controlgroup/
6335
+ //>>css.structure: ../../themes/base/core.css
6336
+ //>>css.structure: ../../themes/base/controlgroup.css
6337
+ //>>css.theme: ../../themes/base/theme.css
6338
+
6339
+
6340
+ var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6341
+
6342
+ var widgetsControlgroup = $.widget( "ui.controlgroup", {
6343
+ version: "1.13.1",
6344
+ defaultElement: "<div>",
6345
+ options: {
6346
+ direction: "horizontal",
6347
+ disabled: null,
6348
+ onlyVisible: true,
6349
+ items: {
6350
+ "button": "input[type=button], input[type=submit], input[type=reset], button, a",
6351
+ "controlgroupLabel": ".ui-controlgroup-label",
6352
+ "checkboxradio": "input[type='checkbox'], input[type='radio']",
6353
+ "selectmenu": "select",
6354
+ "spinner": ".ui-spinner-input"
6355
+ }
6356
+ },
6357
+
6358
+ _create: function() {
6359
+ this._enhance();
6360
+ },
6361
+
6362
+ // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6363
+ _enhance: function() {
6364
+ this.element.attr( "role", "toolbar" );
6365
+ this.refresh();
6366
+ },
6367
+
6368
+ _destroy: function() {
6369
+ this._callChildMethod( "destroy" );
6370
+ this.childWidgets.removeData( "ui-controlgroup-data" );
6371
+ this.element.removeAttr( "role" );
6372
+ if ( this.options.items.controlgroupLabel ) {
6373
+ this.element
6374
+ .find( this.options.items.controlgroupLabel )
6375
+ .find( ".ui-controlgroup-label-contents" )
6376
+ .contents().unwrap();
6377
+ }
6378
+ },
6379
+
6380
+ _initWidgets: function() {
6381
+ var that = this,
6382
+ childWidgets = [];
6383
+
6384
+ // First we iterate over each of the items options
6385
+ $.each( this.options.items, function( widget, selector ) {
6386
+ var labels;
6387
+ var options = {};
6388
+
6389
+ // Make sure the widget has a selector set
6390
+ if ( !selector ) {
6391
+ return;
6392
+ }
6393
+
6394
+ if ( widget === "controlgroupLabel" ) {
6395
+ labels = that.element.find( selector );
6396
+ labels.each( function() {
6397
+ var element = $( this );
6398
+
6399
+ if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6400
+ return;
6401
+ }
6402
+ element.contents()
6403
+ .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6404
+ } );
6405
+ that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6406
+ childWidgets = childWidgets.concat( labels.get() );
6407
+ return;
6408
+ }
6409
+
6410
+ // Make sure the widget actually exists
6411
+ if ( !$.fn[ widget ] ) {
6412
+ return;
6413
+ }
6414
+
6415
+ // We assume everything is in the middle to start because we can't determine
6416
+ // first / last elements until all enhancments are done.
6417
+ if ( that[ "_" + widget + "Options" ] ) {
6418
+ options = that[ "_" + widget + "Options" ]( "middle" );
6419
+ } else {
6420
+ options = { classes: {} };
6421
+ }
6422
+
6423
+ // Find instances of this widget inside controlgroup and init them
6424
+ that.element
6425
+ .find( selector )
6426
+ .each( function() {
6427
+ var element = $( this );
6428
+ var instance = element[ widget ]( "instance" );
6429
+
6430
+ // We need to clone the default options for this type of widget to avoid
6431
+ // polluting the variable options which has a wider scope than a single widget.
6432
+ var instanceOptions = $.widget.extend( {}, options );
6433
+
6434
+ // If the button is the child of a spinner ignore it
6435
+ // TODO: Find a more generic solution
6436
+ if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6437
+ return;
6438
+ }
6439
+
6440
+ // Create the widget if it doesn't exist
6441
+ if ( !instance ) {
6442
+ instance = element[ widget ]()[ widget ]( "instance" );
6443
+ }
6444
+ if ( instance ) {
6445
+ instanceOptions.classes =
6446
+ that._resolveClassesValues( instanceOptions.classes, instance );
6447
+ }
6448
+ element[ widget ]( instanceOptions );
6449
+
6450
+ // Store an instance of the controlgroup to be able to reference
6451
+ // from the outermost element for changing options and refresh
6452
+ var widgetElement = element[ widget ]( "widget" );
6453
+ $.data( widgetElement[ 0 ], "ui-controlgroup-data",
6454
+ instance ? instance : element[ widget ]( "instance" ) );
6455
+
6456
+ childWidgets.push( widgetElement[ 0 ] );
6457
+ } );
6458
+ } );
6459
+
6460
+ this.childWidgets = $( $.uniqueSort( childWidgets ) );
6461
+ this._addClass( this.childWidgets, "ui-controlgroup-item" );
6462
+ },
6463
+
6464
+ _callChildMethod: function( method ) {
6465
+ this.childWidgets.each( function() {
6466
+ var element = $( this ),
6467
+ data = element.data( "ui-controlgroup-data" );
6468
+ if ( data && data[ method ] ) {
6469
+ data[ method ]();
6470
+ }
6471
+ } );
6472
+ },
6473
+
6474
+ _updateCornerClass: function( element, position ) {
6475
+ var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6476
+ var add = this._buildSimpleOptions( position, "label" ).classes.label;
6477
+
6478
+ this._removeClass( element, null, remove );
6479
+ this._addClass( element, null, add );
6480
+ },
6481
+
6482
+ _buildSimpleOptions: function( position, key ) {
6483
+ var direction = this.options.direction === "vertical";
6484
+ var result = {
6485
+ classes: {}
6486
+ };
6487
+ result.classes[ key ] = {
6488
+ "middle": "",
6489
+ "first": "ui-corner-" + ( direction ? "top" : "left" ),
6490
+ "last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6491
+ "only": "ui-corner-all"
6492
+ }[ position ];
6493
+
6494
+ return result;
6495
+ },
6496
+
6497
+ _spinnerOptions: function( position ) {
6498
+ var options = this._buildSimpleOptions( position, "ui-spinner" );
6499
+
6500
+ options.classes[ "ui-spinner-up" ] = "";
6501
+ options.classes[ "ui-spinner-down" ] = "";
6502
+
6503
+ return options;
6504
+ },
6505
+
6506
+ _buttonOptions: function( position ) {
6507
+ return this._buildSimpleOptions( position, "ui-button" );
6508
+ },
6509
+
6510
+ _checkboxradioOptions: function( position ) {
6511
+ return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6512
+ },
6513
+
6514
+ _selectmenuOptions: function( position ) {
6515
+ var direction = this.options.direction === "vertical";
6516
+ return {
6517
+ width: direction ? "auto" : false,
6518
+ classes: {
6519
+ middle: {
6520
+ "ui-selectmenu-button-open": "",
6521
+ "ui-selectmenu-button-closed": ""
6522
+ },
6523
+ first: {
6524
+ "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6525
+ "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6526
+ },
6527
+ last: {
6528
+ "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6529
+ "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6530
+ },
6531
+ only: {
6532
+ "ui-selectmenu-button-open": "ui-corner-top",
6533
+ "ui-selectmenu-button-closed": "ui-corner-all"
6534
+ }
6535
+
6536
+ }[ position ]
6537
+ };
6538
+ },
6539
+
6540
+ _resolveClassesValues: function( classes, instance ) {
6541
+ var result = {};
6542
+ $.each( classes, function( key ) {
6543
+ var current = instance.options.classes[ key ] || "";
6544
+ current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6545
+ result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6546
+ } );
6547
+ return result;
6548
+ },
6549
+
6550
+ _setOption: function( key, value ) {
6551
+ if ( key === "direction" ) {
6552
+ this._removeClass( "ui-controlgroup-" + this.options.direction );
6553
+ }
6554
+
6555
+ this._super( key, value );
6556
+ if ( key === "disabled" ) {
6557
+ this._callChildMethod( value ? "disable" : "enable" );
6558
+ return;
6559
+ }
6560
+
6561
+ this.refresh();
6562
+ },
6563
+
6564
+ refresh: function() {
6565
+ var children,
6566
+ that = this;
6567
+
6568
+ this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6569
+
6570
+ if ( this.options.direction === "horizontal" ) {
6571
+ this._addClass( null, "ui-helper-clearfix" );
6572
+ }
6573
+ this._initWidgets();
6574
+
6575
+ children = this.childWidgets;
6576
+
6577
+ // We filter here because we need to track all childWidgets not just the visible ones
6578
+ if ( this.options.onlyVisible ) {
6579
+ children = children.filter( ":visible" );
6580
+ }
6581
+
6582
+ if ( children.length ) {
6583
+
6584
+ // We do this last because we need to make sure all enhancment is done
6585
+ // before determining first and last
6586
+ $.each( [ "first", "last" ], function( index, value ) {
6587
+ var instance = children[ value ]().data( "ui-controlgroup-data" );
6588
+
6589
+ if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6590
+ var options = that[ "_" + instance.widgetName + "Options" ](
6591
+ children.length === 1 ? "only" : value
6592
+ );
6593
+ options.classes = that._resolveClassesValues( options.classes, instance );
6594
+ instance.element[ instance.widgetName ]( options );
6595
+ } else {
6596
+ that._updateCornerClass( children[ value ](), value );
6597
+ }
6598
+ } );
6599
+
6600
+ // Finally call the refresh method on each of the child widgets.
6601
+ this._callChildMethod( "refresh" );
6602
+ }
6603
+ }
6604
+ } );
6605
+
6606
+ /*!
6607
+ * jQuery UI Checkboxradio 1.13.1
6608
+ * http://jqueryui.com
6609
+ *
6610
+ * Copyright jQuery Foundation and other contributors
6611
+ * Released under the MIT license.
6612
+ * http://jquery.org/license
6613
+ */
6614
+
6615
+ //>>label: Checkboxradio
6616
+ //>>group: Widgets
6617
+ //>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6618
+ //>>docs: http://api.jqueryui.com/checkboxradio/
6619
+ //>>demos: http://jqueryui.com/checkboxradio/
6620
+ //>>css.structure: ../../themes/base/core.css
6621
+ //>>css.structure: ../../themes/base/button.css
6622
+ //>>css.structure: ../../themes/base/checkboxradio.css
6623
+ //>>css.theme: ../../themes/base/theme.css
6624
+
6625
+
6626
+ $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6627
+ version: "1.13.1",
6628
+ options: {
6629
+ disabled: null,
6630
+ label: null,
6631
+ icon: true,
6632
+ classes: {
6633
+ "ui-checkboxradio-label": "ui-corner-all",
6634
+ "ui-checkboxradio-icon": "ui-corner-all"
6635
+ }
6636
+ },
6637
+
6638
+ _getCreateOptions: function() {
6639
+ var disabled, labels;
6640
+ var that = this;
6641
+ var options = this._super() || {};
6642
+
6643
+ // We read the type here, because it makes more sense to throw a element type error first,
6644
+ // rather then the error for lack of a label. Often if its the wrong type, it
6645
+ // won't have a label (e.g. calling on a div, btn, etc)
6646
+ this._readType();
6647
+
6648
+ labels = this.element.labels();
6649
+
6650
+ // If there are multiple labels, use the last one
6651
+ this.label = $( labels[ labels.length - 1 ] );
6652
+ if ( !this.label.length ) {
6653
+ $.error( "No label found for checkboxradio widget" );
6654
+ }
6655
+
6656
+ this.originalLabel = "";
6657
+
6658
+ // We need to get the label text but this may also need to make sure it does not contain the
6659
+ // input itself.
6660
+ this.label.contents().not( this.element[ 0 ] ).each( function() {
6661
+
6662
+ // The label contents could be text, html, or a mix. We concat each element to get a
6663
+ // string representation of the label, without the input as part of it.
6664
+ that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
6665
+ } );
6666
+
6667
+ // Set the label option if we found label text
6668
+ if ( this.originalLabel ) {
6669
+ options.label = this.originalLabel;
6670
+ }
6671
+
6672
+ disabled = this.element[ 0 ].disabled;
6673
+ if ( disabled != null ) {
6674
+ options.disabled = disabled;
6675
+ }
6676
+ return options;
6677
+ },
6678
+
6679
+ _create: function() {
6680
+ var checked = this.element[ 0 ].checked;
6681
+
6682
+ this._bindFormResetHandler();
6683
+
6684
+ if ( this.options.disabled == null ) {
6685
+ this.options.disabled = this.element[ 0 ].disabled;
6686
+ }
6687
+
6688
+ this._setOption( "disabled", this.options.disabled );
6689
+ this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6690
+ this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6691
+
6692
+ if ( this.type === "radio" ) {
6693
+ this._addClass( this.label, "ui-checkboxradio-radio-label" );
6694
+ }
6695
+
6696
+ if ( this.options.label && this.options.label !== this.originalLabel ) {
6697
+ this._updateLabel();
6698
+ } else if ( this.originalLabel ) {
6699
+ this.options.label = this.originalLabel;
6700
+ }
6701
+
6702
+ this._enhance();
6703
+
6704
+ if ( checked ) {
6705
+ this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6706
+ }
6707
+
6708
+ this._on( {
6709
+ change: "_toggleClasses",
6710
+ focus: function() {
6711
+ this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6712
+ },
6713
+ blur: function() {
6714
+ this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6715
+ }
6716
+ } );
6717
+ },
6718
+
6719
+ _readType: function() {
6720
+ var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6721
+ this.type = this.element[ 0 ].type;
6722
+ if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6723
+ $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6724
+ " and element.type=" + this.type );
6725
+ }
6726
+ },
6727
+
6728
+ // Support jQuery Mobile enhanced option
6729
+ _enhance: function() {
6730
+ this._updateIcon( this.element[ 0 ].checked );
6731
+ },
6732
+
6733
+ widget: function() {
6734
+ return this.label;
6735
+ },
6736
+
6737
+ _getRadioGroup: function() {
6738
+ var group;
6739
+ var name = this.element[ 0 ].name;
6740
+ var nameSelector = "input[name='" + $.escapeSelector( name ) + "']";
6741
+
6742
+ if ( !name ) {
6743
+ return $( [] );
6744
+ }
6745
+
6746
+ if ( this.form.length ) {
6747
+ group = $( this.form[ 0 ].elements ).filter( nameSelector );
6748
+ } else {
6749
+
6750
+ // Not inside a form, check all inputs that also are not inside a form
6751
+ group = $( nameSelector ).filter( function() {
6752
+ return $( this )._form().length === 0;
6753
+ } );
6754
+ }
6755
+
6756
+ return group.not( this.element );
6757
+ },
6758
+
6759
+ _toggleClasses: function() {
6760
+ var checked = this.element[ 0 ].checked;
6761
+ this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6762
+
6763
+ if ( this.options.icon && this.type === "checkbox" ) {
6764
+ this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6765
+ ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6766
+ }
6767
+
6768
+ if ( this.type === "radio" ) {
6769
+ this._getRadioGroup()
6770
+ .each( function() {
6771
+ var instance = $( this ).checkboxradio( "instance" );
6772
+
6773
+ if ( instance ) {
6774
+ instance._removeClass( instance.label,
6775
+ "ui-checkboxradio-checked", "ui-state-active" );
6776
+ }
6777
+ } );
6778
+ }
6779
+ },
6780
+
6781
+ _destroy: function() {
6782
+ this._unbindFormResetHandler();
6783
+
6784
+ if ( this.icon ) {
6785
+ this.icon.remove();
6786
+ this.iconSpace.remove();
6787
+ }
6788
+ },
6789
+
6790
+ _setOption: function( key, value ) {
6791
+
6792
+ // We don't allow the value to be set to nothing
6793
+ if ( key === "label" && !value ) {
6794
+ return;
6795
+ }
6796
+
6797
+ this._super( key, value );
6798
+
6799
+ if ( key === "disabled" ) {
6800
+ this._toggleClass( this.label, null, "ui-state-disabled", value );
6801
+ this.element[ 0 ].disabled = value;
6802
+
6803
+ // Don't refresh when setting disabled
6804
+ return;
6805
+ }
6806
+ this.refresh();
6807
+ },
6808
+
6809
+ _updateIcon: function( checked ) {
6810
+ var toAdd = "ui-icon ui-icon-background ";
6811
+
6812
+ if ( this.options.icon ) {
6813
+ if ( !this.icon ) {
6814
+ this.icon = $( "<span>" );
6815
+ this.iconSpace = $( "<span> </span>" );
6816
+ this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6817
+ }
6818
+
6819
+ if ( this.type === "checkbox" ) {
6820
+ toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6821
+ this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6822
+ } else {
6823
+ toAdd += "ui-icon-blank";
6824
+ }
6825
+ this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6826
+ if ( !checked ) {
6827
+ this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6828
+ }
6829
+ this.icon.prependTo( this.label ).after( this.iconSpace );
6830
+ } else if ( this.icon !== undefined ) {
6831
+ this.icon.remove();
6832
+ this.iconSpace.remove();
6833
+ delete this.icon;
6834
+ }
6835
+ },
6836
+
6837
+ _updateLabel: function() {
6838
+
6839
+ // Remove the contents of the label ( minus the icon, icon space, and input )
6840
+ var contents = this.label.contents().not( this.element[ 0 ] );
6841
+ if ( this.icon ) {
6842
+ contents = contents.not( this.icon[ 0 ] );
6843
+ }
6844
+ if ( this.iconSpace ) {
6845
+ contents = contents.not( this.iconSpace[ 0 ] );
6846
+ }
6847
+ contents.remove();
6848
+
6849
+ this.label.append( this.options.label );
6850
+ },
6851
+
6852
+ refresh: function() {
6853
+ var checked = this.element[ 0 ].checked,
6854
+ isDisabled = this.element[ 0 ].disabled;
6855
+
6856
+ this._updateIcon( checked );
6857
+ this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6858
+ if ( this.options.label !== null ) {
6859
+ this._updateLabel();
6860
+ }
6861
+
6862
+ if ( isDisabled !== this.options.disabled ) {
6863
+ this._setOptions( { "disabled": isDisabled } );
6864
+ }
6865
+ }
6866
+
6867
+ } ] );
6868
+
6869
+ var widgetsCheckboxradio = $.ui.checkboxradio;
6870
+
6871
+
6872
+ /*!
6873
+ * jQuery UI Button 1.13.1
6874
+ * http://jqueryui.com
6875
+ *
6876
+ * Copyright jQuery Foundation and other contributors
6877
+ * Released under the MIT license.
6878
+ * http://jquery.org/license
6879
+ */
6880
+
6881
+ //>>label: Button
6882
+ //>>group: Widgets
6883
+ //>>description: Enhances a form with themeable buttons.
6884
+ //>>docs: http://api.jqueryui.com/button/
6885
+ //>>demos: http://jqueryui.com/button/
6886
+ //>>css.structure: ../../themes/base/core.css
6887
+ //>>css.structure: ../../themes/base/button.css
6888
+ //>>css.theme: ../../themes/base/theme.css
6889
+
6890
+
6891
+ $.widget( "ui.button", {
6892
+ version: "1.13.1",
6893
+ defaultElement: "<button>",
6894
+ options: {
6895
+ classes: {
6896
+ "ui-button": "ui-corner-all"
6897
+ },
6898
+ disabled: null,
6899
+ icon: null,
6900
+ iconPosition: "beginning",
6901
+ label: null,
6902
+ showLabel: true
6903
+ },
6904
+
6905
+ _getCreateOptions: function() {
6906
+ var disabled,
6907
+
6908
+ // This is to support cases like in jQuery Mobile where the base widget does have
6909
+ // an implementation of _getCreateOptions
6910
+ options = this._super() || {};
6911
+
6912
+ this.isInput = this.element.is( "input" );
6913
+
6914
+ disabled = this.element[ 0 ].disabled;
6915
+ if ( disabled != null ) {
6916
+ options.disabled = disabled;
6917
+ }
6918
+
6919
+ this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6920
+ if ( this.originalLabel ) {
6921
+ options.label = this.originalLabel;
6922
+ }
6923
+
6924
+ return options;
6925
+ },
6926
+
6927
+ _create: function() {
6928
+ if ( !this.option.showLabel & !this.options.icon ) {
6929
+ this.options.showLabel = true;
6930
+ }
6931
+
6932
+ // We have to check the option again here even though we did in _getCreateOptions,
6933
+ // because null may have been passed on init which would override what was set in
6934
+ // _getCreateOptions
6935
+ if ( this.options.disabled == null ) {
6936
+ this.options.disabled = this.element[ 0 ].disabled || false;
6937
+ }
6938
+
6939
+ this.hasTitle = !!this.element.attr( "title" );
6940
+
6941
+ // Check to see if the label needs to be set or if its already correct
6942
+ if ( this.options.label && this.options.label !== this.originalLabel ) {
6943
+ if ( this.isInput ) {
6944
+ this.element.val( this.options.label );
6945
+ } else {
6946
+ this.element.html( this.options.label );
6947
+ }
6948
+ }
6949
+ this._addClass( "ui-button", "ui-widget" );
6950
+ this._setOption( "disabled", this.options.disabled );
6951
+ this._enhance();
6952
+
6953
+ if ( this.element.is( "a" ) ) {
6954
+ this._on( {
6955
+ "keyup": function( event ) {
6956
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
6957
+ event.preventDefault();
6958
+
6959
+ // Support: PhantomJS <= 1.9, IE 8 Only
6960
+ // If a native click is available use it so we actually cause navigation
6961
+ // otherwise just trigger a click event
6962
+ if ( this.element[ 0 ].click ) {
6963
+ this.element[ 0 ].click();
6964
+ } else {
6965
+ this.element.trigger( "click" );
6966
+ }
6967
+ }
6968
+ }
6969
+ } );
6970
+ }
6971
+ },
6972
+
6973
+ _enhance: function() {
6974
+ if ( !this.element.is( "button" ) ) {
6975
+ this.element.attr( "role", "button" );
6976
+ }
6977
+
6978
+ if ( this.options.icon ) {
6979
+ this._updateIcon( "icon", this.options.icon );
6980
+ this._updateTooltip();
6981
+ }
6982
+ },
6983
+
6984
+ _updateTooltip: function() {
6985
+ this.title = this.element.attr( "title" );
6986
+
6987
+ if ( !this.options.showLabel && !this.title ) {
6988
+ this.element.attr( "title", this.options.label );
6989
+ }
6990
+ },
6991
+
6992
+ _updateIcon: function( option, value ) {
6993
+ var icon = option !== "iconPosition",
6994
+ position = icon ? this.options.iconPosition : value,
6995
+ displayBlock = position === "top" || position === "bottom";
6996
+
6997
+ // Create icon
6998
+ if ( !this.icon ) {
6999
+ this.icon = $( "<span>" );
7000
+
7001
+ this._addClass( this.icon, "ui-button-icon", "ui-icon" );
7002
+
7003
+ if ( !this.options.showLabel ) {
7004
+ this._addClass( "ui-button-icon-only" );
7005
+ }
7006
+ } else if ( icon ) {
7007
+
7008
+ // If we are updating the icon remove the old icon class
7009
+ this._removeClass( this.icon, null, this.options.icon );
7010
+ }
7011
+
7012
+ // If we are updating the icon add the new icon class
7013
+ if ( icon ) {
7014
+ this._addClass( this.icon, null, value );
7015
+ }
7016
+
7017
+ this._attachIcon( position );
7018
+
7019
+ // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
7020
+ // the iconSpace if there is one.
7021
+ if ( displayBlock ) {
7022
+ this._addClass( this.icon, null, "ui-widget-icon-block" );
7023
+ if ( this.iconSpace ) {
7024
+ this.iconSpace.remove();
7025
+ }
7026
+ } else {
7027
+
7028
+ // Position is beginning or end so remove the ui-widget-icon-block class and add the
7029
+ // space if it does not exist
7030
+ if ( !this.iconSpace ) {
7031
+ this.iconSpace = $( "<span> </span>" );
7032
+ this._addClass( this.iconSpace, "ui-button-icon-space" );
7033
+ }
7034
+ this._removeClass( this.icon, null, "ui-wiget-icon-block" );
7035
+ this._attachIconSpace( position );
7036
+ }
7037
+ },
7038
+
7039
+ _destroy: function() {
7040
+ this.element.removeAttr( "role" );
7041
+
7042
+ if ( this.icon ) {
7043
+ this.icon.remove();
7044
+ }
7045
+ if ( this.iconSpace ) {
7046
+ this.iconSpace.remove();
7047
+ }
7048
+ if ( !this.hasTitle ) {
7049
+ this.element.removeAttr( "title" );
7050
+ }
7051
+ },
7052
+
7053
+ _attachIconSpace: function( iconPosition ) {
7054
+ this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
7055
+ },
7056
+
7057
+ _attachIcon: function( iconPosition ) {
7058
+ this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
7059
+ },
7060
+
7061
+ _setOptions: function( options ) {
7062
+ var newShowLabel = options.showLabel === undefined ?
7063
+ this.options.showLabel :
7064
+ options.showLabel,
7065
+ newIcon = options.icon === undefined ? this.options.icon : options.icon;
7066
+
7067
+ if ( !newShowLabel && !newIcon ) {
7068
+ options.showLabel = true;
7069
+ }
7070
+ this._super( options );
7071
+ },
7072
+
7073
+ _setOption: function( key, value ) {
7074
+ if ( key === "icon" ) {
7075
+ if ( value ) {
7076
+ this._updateIcon( key, value );
7077
+ } else if ( this.icon ) {
7078
+ this.icon.remove();
7079
+ if ( this.iconSpace ) {
7080
+ this.iconSpace.remove();
7081
+ }
7082
+ }
7083
+ }
7084
+
7085
+ if ( key === "iconPosition" ) {
7086
+ this._updateIcon( key, value );
7087
+ }
7088
+
7089
+ // Make sure we can't end up with a button that has neither text nor icon
7090
+ if ( key === "showLabel" ) {
7091
+ this._toggleClass( "ui-button-icon-only", null, !value );
7092
+ this._updateTooltip();
7093
+ }
7094
+
7095
+ if ( key === "label" ) {
7096
+ if ( this.isInput ) {
7097
+ this.element.val( value );
7098
+ } else {
7099
+
7100
+ // If there is an icon, append it, else nothing then append the value
7101
+ // this avoids removal of the icon when setting label text
7102
+ this.element.html( value );
7103
+ if ( this.icon ) {
7104
+ this._attachIcon( this.options.iconPosition );
7105
+ this._attachIconSpace( this.options.iconPosition );
7106
+ }
7107
+ }
7108
+ }
7109
+
7110
+ this._super( key, value );
7111
+
7112
+ if ( key === "disabled" ) {
7113
+ this._toggleClass( null, "ui-state-disabled", value );
7114
+ this.element[ 0 ].disabled = value;
7115
+ if ( value ) {
7116
+ this.element.trigger( "blur" );
7117
+ }
7118
+ }
7119
+ },
7120
+
7121
+ refresh: function() {
7122
+
7123
+ // Make sure to only check disabled if its an element that supports this otherwise
7124
+ // check for the disabled class to determine state
7125
+ var isDisabled = this.element.is( "input, button" ) ?
7126
+ this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
7127
+
7128
+ if ( isDisabled !== this.options.disabled ) {
7129
+ this._setOptions( { disabled: isDisabled } );
7130
+ }
7131
+
7132
+ this._updateTooltip();
7133
+ }
7134
+ } );
7135
+
7136
+ // DEPRECATED
7137
+ if ( $.uiBackCompat !== false ) {
7138
+
7139
+ // Text and Icons options
7140
+ $.widget( "ui.button", $.ui.button, {
7141
+ options: {
7142
+ text: true,
7143
+ icons: {
7144
+ primary: null,
7145
+ secondary: null
7146
+ }
7147
+ },
7148
+
7149
+ _create: function() {
7150
+ if ( this.options.showLabel && !this.options.text ) {
7151
+ this.options.showLabel = this.options.text;
7152
+ }
7153
+ if ( !this.options.showLabel && this.options.text ) {
7154
+ this.options.text = this.options.showLabel;
7155
+ }
7156
+ if ( !this.options.icon && ( this.options.icons.primary ||
7157
+ this.options.icons.secondary ) ) {
7158
+ if ( this.options.icons.primary ) {
7159
+ this.options.icon = this.options.icons.primary;
7160
+ } else {
7161
+ this.options.icon = this.options.icons.secondary;
7162
+ this.options.iconPosition = "end";
7163
+ }
7164
+ } else if ( this.options.icon ) {
7165
+ this.options.icons.primary = this.options.icon;
7166
+ }
7167
+ this._super();
7168
+ },
7169
+
7170
+ _setOption: function( key, value ) {
7171
+ if ( key === "text" ) {
7172
+ this._super( "showLabel", value );
7173
+ return;
7174
+ }
7175
+ if ( key === "showLabel" ) {
7176
+ this.options.text = value;
7177
+ }
7178
+ if ( key === "icon" ) {
7179
+ this.options.icons.primary = value;
7180
+ }
7181
+ if ( key === "icons" ) {
7182
+ if ( value.primary ) {
7183
+ this._super( "icon", value.primary );
7184
+ this._super( "iconPosition", "beginning" );
7185
+ } else if ( value.secondary ) {
7186
+ this._super( "icon", value.secondary );
7187
+ this._super( "iconPosition", "end" );
7188
+ }
7189
+ }
7190
+ this._superApply( arguments );
7191
+ }
7192
+ } );
7193
+
7194
+ $.fn.button = ( function( orig ) {
7195
+ return function( options ) {
7196
+ var isMethodCall = typeof options === "string";
7197
+ var args = Array.prototype.slice.call( arguments, 1 );
7198
+ var returnValue = this;
7199
+
7200
+ if ( isMethodCall ) {
7201
+
7202
+ // If this is an empty collection, we need to have the instance method
7203
+ // return undefined instead of the jQuery instance
7204
+ if ( !this.length && options === "instance" ) {
7205
+ returnValue = undefined;
7206
+ } else {
7207
+ this.each( function() {
7208
+ var methodValue;
7209
+ var type = $( this ).attr( "type" );
7210
+ var name = type !== "checkbox" && type !== "radio" ?
7211
+ "button" :
7212
+ "checkboxradio";
7213
+ var instance = $.data( this, "ui-" + name );
7214
+
7215
+ if ( options === "instance" ) {
7216
+ returnValue = instance;
7217
+ return false;
7218
+ }
7219
+
7220
+ if ( !instance ) {
7221
+ return $.error( "cannot call methods on button" +
7222
+ " prior to initialization; " +
7223
+ "attempted to call method '" + options + "'" );
7224
+ }
7225
+
7226
+ if ( typeof instance[ options ] !== "function" ||
7227
+ options.charAt( 0 ) === "_" ) {
7228
+ return $.error( "no such method '" + options + "' for button" +
7229
+ " widget instance" );
7230
+ }
7231
+
7232
+ methodValue = instance[ options ].apply( instance, args );
7233
+
7234
+ if ( methodValue !== instance && methodValue !== undefined ) {
7235
+ returnValue = methodValue && methodValue.jquery ?
7236
+ returnValue.pushStack( methodValue.get() ) :
7237
+ methodValue;
7238
+ return false;
7239
+ }
7240
+ } );
7241
+ }
7242
+ } else {
7243
+
7244
+ // Allow multiple hashes to be passed on init
7245
+ if ( args.length ) {
7246
+ options = $.widget.extend.apply( null, [ options ].concat( args ) );
7247
+ }
7248
+
7249
+ this.each( function() {
7250
+ var type = $( this ).attr( "type" );
7251
+ var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7252
+ var instance = $.data( this, "ui-" + name );
7253
+
7254
+ if ( instance ) {
7255
+ instance.option( options || {} );
7256
+ if ( instance._init ) {
7257
+ instance._init();
7258
+ }
7259
+ } else {
7260
+ if ( name === "button" ) {
7261
+ orig.call( $( this ), options );
7262
+ return;
7263
+ }
7264
+
7265
+ $( this ).checkboxradio( $.extend( { icon: false }, options ) );
7266
+ }
7267
+ } );
7268
+ }
7269
+
7270
+ return returnValue;
7271
+ };
7272
+ } )( $.fn.button );
7273
+
7274
+ $.fn.buttonset = function() {
7275
+ if ( !$.ui.controlgroup ) {
7276
+ $.error( "Controlgroup widget missing" );
7277
+ }
7278
+ if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7279
+ return this.controlgroup.apply( this,
7280
+ [ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7281
+ }
7282
+ if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7283
+ return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7284
+ }
7285
+ if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7286
+ arguments[ 0 ].items = {
7287
+ button: arguments[ 0 ].items
7288
+ };
7289
+ }
7290
+ return this.controlgroup.apply( this, arguments );
7291
+ };
7292
+ }
7293
+
7294
+ var widgetsButton = $.ui.button;
7295
+
7296
+
7297
+ /* eslint-disable max-len, camelcase */
7298
+ /*!
7299
+ * jQuery UI Datepicker 1.13.1
7300
+ * http://jqueryui.com
7301
+ *
7302
+ * Copyright jQuery Foundation and other contributors
7303
+ * Released under the MIT license.
7304
+ * http://jquery.org/license
7305
+ */
7306
+
7307
+ //>>label: Datepicker
7308
+ //>>group: Widgets
7309
+ //>>description: Displays a calendar from an input or inline for selecting dates.
7310
+ //>>docs: http://api.jqueryui.com/datepicker/
7311
+ //>>demos: http://jqueryui.com/datepicker/
7312
+ //>>css.structure: ../../themes/base/core.css
7313
+ //>>css.structure: ../../themes/base/datepicker.css
7314
+ //>>css.theme: ../../themes/base/theme.css
7315
+
7316
+
7317
+ $.extend( $.ui, { datepicker: { version: "1.13.1" } } );
7318
+
7319
+ var datepicker_instActive;
7320
+
7321
+ function datepicker_getZindex( elem ) {
7322
+ var position, value;
7323
+ while ( elem.length && elem[ 0 ] !== document ) {
7324
+
7325
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
7326
+ // This makes behavior of this function consistent across browsers
7327
+ // WebKit always returns auto if the element is positioned
7328
+ position = elem.css( "position" );
7329
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7330
+
7331
+ // IE returns 0 when zIndex is not specified
7332
+ // other browsers return a string
7333
+ // we ignore the case of nested elements with an explicit value of 0
7334
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7335
+ value = parseInt( elem.css( "zIndex" ), 10 );
7336
+ if ( !isNaN( value ) && value !== 0 ) {
7337
+ return value;
7338
+ }
7339
+ }
7340
+ elem = elem.parent();
7341
+ }
7342
+
7343
+ return 0;
7344
+ }
7345
+
7346
+ /* Date picker manager.
7347
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7348
+ Settings for (groups of) date pickers are maintained in an instance object,
7349
+ allowing multiple different settings on the same page. */
7350
+
7351
+ function Datepicker() {
7352
+ this._curInst = null; // The current instance in use
7353
+ this._keyEvent = false; // If the last event was a key event
7354
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
7355
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
7356
+ this._inDialog = false; // True if showing within a "dialog", false if not
7357
+ this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7358
+ this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7359
+ this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7360
+ this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7361
+ this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7362
+ this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7363
+ this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7364
+ this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7365
+ this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7366
+ this.regional = []; // Available regional settings, indexed by language code
7367
+ this.regional[ "" ] = { // Default regional settings
7368
+ closeText: "Done", // Display text for close link
7369
+ prevText: "Prev", // Display text for previous month link
7370
+ nextText: "Next", // Display text for next month link
7371
+ currentText: "Today", // Display text for current month link
7372
+ monthNames: [ "January", "February", "March", "April", "May", "June",
7373
+ "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7374
+ monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7375
+ dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7376
+ dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7377
+ dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7378
+ weekHeader: "Wk", // Column header for week of the year
7379
+ dateFormat: "mm/dd/yy", // See format options on parseDate
7380
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7381
+ isRTL: false, // True if right-to-left language, false if left-to-right
7382
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7383
+ yearSuffix: "", // Additional text to append to the year in the month headers,
7384
+ selectMonthLabel: "Select month", // Invisible label for month selector
7385
+ selectYearLabel: "Select year" // Invisible label for year selector
7386
+ };
7387
+ this._defaults = { // Global defaults for all the date picker instances
7388
+ showOn: "focus", // "focus" for popup on focus,
7389
+ // "button" for trigger button, or "both" for either
7390
+ showAnim: "fadeIn", // Name of jQuery animation for popup
7391
+ showOptions: {}, // Options for enhanced animations
7392
+ defaultDate: null, // Used when field is blank: actual date,
7393
+ // +/-number for offset from today, null for today
7394
+ appendText: "", // Display text following the input box, e.g. showing the format
7395
+ buttonText: "...", // Text for trigger button
7396
+ buttonImage: "", // URL for trigger button image
7397
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7398
+ hideIfNoPrevNext: false, // True to hide next/previous month links
7399
+ // if not applicable, false to just disable them
7400
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7401
+ gotoCurrent: false, // True if today link goes back to current selection instead
7402
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
7403
+ changeYear: false, // True if year can be selected directly, false if only prev/next
7404
+ yearRange: "c-10:c+10", // Range of years to display in drop-down,
7405
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
7406
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7407
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
7408
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7409
+ showWeek: false, // True to show week of the year, false to not show it
7410
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7411
+ // takes a Date and returns the number of the week for it
7412
+ shortYearCutoff: "+10", // Short year values < this are in the current century,
7413
+ // > this are in the previous century,
7414
+ // string value starting with "+" for current year + value
7415
+ minDate: null, // The earliest selectable date, or null for no limit
7416
+ maxDate: null, // The latest selectable date, or null for no limit
7417
+ duration: "fast", // Duration of display/closure
7418
+ beforeShowDay: null, // Function that takes a date and returns an array with
7419
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7420
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7421
+ beforeShow: null, // Function that takes an input field and
7422
+ // returns a set of custom settings for the date picker
7423
+ onSelect: null, // Define a callback function when a date is selected
7424
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
7425
+ onClose: null, // Define a callback function when the datepicker is closed
7426
+ onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7427
+ numberOfMonths: 1, // Number of months to show at a time
7428
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7429
+ stepMonths: 1, // Number of months to step back/forward
7430
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
7431
+ altField: "", // Selector for an alternate field to store selected dates into
7432
+ altFormat: "", // The date format to use for the alternate field
7433
+ constrainInput: true, // The input is constrained by the current date format
7434
+ showButtonPanel: false, // True to show button panel, false to not show it
7435
+ autoSize: false, // True to size the input for the date format, false to leave as is
7436
+ disabled: false // The initial disabled state
7437
+ };
7438
+ $.extend( this._defaults, this.regional[ "" ] );
7439
+ this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7440
+ this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7441
+ this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7442
+ }
7443
+
7444
+ $.extend( Datepicker.prototype, {
7445
+
7446
+ /* Class name added to elements to indicate already configured with a date picker. */
7447
+ markerClassName: "hasDatepicker",
7448
+
7449
+ //Keep track of the maximum number of rows displayed (see #7043)
7450
+ maxRows: 4,
7451
+
7452
+ // TODO rename to "widget" when switching to widget factory
7453
+ _widgetDatepicker: function() {
7454
+ return this.dpDiv;
7455
+ },
7456
+
7457
+ /* Override the default settings for all instances of the date picker.
7458
+ * @param settings object - the new settings to use as defaults (anonymous object)
7459
+ * @return the manager object
7460
+ */
7461
+ setDefaults: function( settings ) {
7462
+ datepicker_extendRemove( this._defaults, settings || {} );
7463
+ return this;
7464
+ },
7465
+
7466
+ /* Attach the date picker to a jQuery selection.
7467
+ * @param target element - the target input field or division or span
7468
+ * @param settings object - the new settings to use for this date picker instance (anonymous)
7469
+ */
7470
+ _attachDatepicker: function( target, settings ) {
7471
+ var nodeName, inline, inst;
7472
+ nodeName = target.nodeName.toLowerCase();
7473
+ inline = ( nodeName === "div" || nodeName === "span" );
7474
+ if ( !target.id ) {
7475
+ this.uuid += 1;
7476
+ target.id = "dp" + this.uuid;
7477
+ }
7478
+ inst = this._newInst( $( target ), inline );
7479
+ inst.settings = $.extend( {}, settings || {} );
7480
+ if ( nodeName === "input" ) {
7481
+ this._connectDatepicker( target, inst );
7482
+ } else if ( inline ) {
7483
+ this._inlineDatepicker( target, inst );
7484
+ }
7485
+ },
7486
+
7487
+ /* Create a new instance object. */
7488
+ _newInst: function( target, inline ) {
7489
+ var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7490
+ return { id: id, input: target, // associated target
7491
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7492
+ drawMonth: 0, drawYear: 0, // month being drawn
7493
+ inline: inline, // is datepicker inline or not
7494
+ dpDiv: ( !inline ? this.dpDiv : // presentation div
7495
+ datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7496
+ },
7497
+
7498
+ /* Attach the date picker to an input field. */
7499
+ _connectDatepicker: function( target, inst ) {
7500
+ var input = $( target );
7501
+ inst.append = $( [] );
7502
+ inst.trigger = $( [] );
7503
+ if ( input.hasClass( this.markerClassName ) ) {
7504
+ return;
7505
+ }
7506
+ this._attachments( input, inst );
7507
+ input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7508
+ on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7509
+ this._autoSize( inst );
7510
+ $.data( target, "datepicker", inst );
7511
+
7512
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7513
+ if ( inst.settings.disabled ) {
7514
+ this._disableDatepicker( target );
7515
+ }
7516
+ },
7517
+
7518
+ /* Make attachments based on settings. */
7519
+ _attachments: function( input, inst ) {
7520
+ var showOn, buttonText, buttonImage,
7521
+ appendText = this._get( inst, "appendText" ),
7522
+ isRTL = this._get( inst, "isRTL" );
7523
+
7524
+ if ( inst.append ) {
7525
+ inst.append.remove();
7526
+ }
7527
+ if ( appendText ) {
7528
+ inst.append = $( "<span>" )
7529
+ .addClass( this._appendClass )
7530
+ .text( appendText );
7531
+ input[ isRTL ? "before" : "after" ]( inst.append );
7532
+ }
7533
+
7534
+ input.off( "focus", this._showDatepicker );
7535
+
7536
+ if ( inst.trigger ) {
7537
+ inst.trigger.remove();
7538
+ }
7539
+
7540
+ showOn = this._get( inst, "showOn" );
7541
+ if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7542
+ input.on( "focus", this._showDatepicker );
7543
+ }
7544
+ if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7545
+ buttonText = this._get( inst, "buttonText" );
7546
+ buttonImage = this._get( inst, "buttonImage" );
7547
+
7548
+ if ( this._get( inst, "buttonImageOnly" ) ) {
7549
+ inst.trigger = $( "<img>" )
7550
+ .addClass( this._triggerClass )
7551
+ .attr( {
7552
+ src: buttonImage,
7553
+ alt: buttonText,
7554
+ title: buttonText
7555
+ } );
7556
+ } else {
7557
+ inst.trigger = $( "<button type='button'>" )
7558
+ .addClass( this._triggerClass );
7559
+ if ( buttonImage ) {
7560
+ inst.trigger.html(
7561
+ $( "<img>" )
7562
+ .attr( {
7563
+ src: buttonImage,
7564
+ alt: buttonText,
7565
+ title: buttonText
7566
+ } )
7567
+ );
7568
+ } else {
7569
+ inst.trigger.text( buttonText );
7570
+ }
7571
+ }
7572
+
7573
+ input[ isRTL ? "before" : "after" ]( inst.trigger );
7574
+ inst.trigger.on( "click", function() {
7575
+ if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7576
+ $.datepicker._hideDatepicker();
7577
+ } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7578
+ $.datepicker._hideDatepicker();
7579
+ $.datepicker._showDatepicker( input[ 0 ] );
7580
+ } else {
7581
+ $.datepicker._showDatepicker( input[ 0 ] );
7582
+ }
7583
+ return false;
7584
+ } );
7585
+ }
7586
+ },
7587
+
7588
+ /* Apply the maximum length for the date format. */
7589
+ _autoSize: function( inst ) {
7590
+ if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7591
+ var findMax, max, maxI, i,
7592
+ date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7593
+ dateFormat = this._get( inst, "dateFormat" );
7594
+
7595
+ if ( dateFormat.match( /[DM]/ ) ) {
7596
+ findMax = function( names ) {
7597
+ max = 0;
7598
+ maxI = 0;
7599
+ for ( i = 0; i < names.length; i++ ) {
7600
+ if ( names[ i ].length > max ) {
7601
+ max = names[ i ].length;
7602
+ maxI = i;
7603
+ }
7604
+ }
7605
+ return maxI;
7606
+ };
7607
+ date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7608
+ "monthNames" : "monthNamesShort" ) ) ) );
7609
+ date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7610
+ "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7611
+ }
7612
+ inst.input.attr( "size", this._formatDate( inst, date ).length );
7613
+ }
7614
+ },
7615
+
7616
+ /* Attach an inline date picker to a div. */
7617
+ _inlineDatepicker: function( target, inst ) {
7618
+ var divSpan = $( target );
7619
+ if ( divSpan.hasClass( this.markerClassName ) ) {
7620
+ return;
7621
+ }
7622
+ divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7623
+ $.data( target, "datepicker", inst );
7624
+ this._setDate( inst, this._getDefaultDate( inst ), true );
7625
+ this._updateDatepicker( inst );
7626
+ this._updateAlternate( inst );
7627
+
7628
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7629
+ if ( inst.settings.disabled ) {
7630
+ this._disableDatepicker( target );
7631
+ }
7632
+
7633
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7634
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7635
+ inst.dpDiv.css( "display", "block" );
7636
+ },
7637
+
7638
+ /* Pop-up the date picker in a "dialog" box.
7639
+ * @param input element - ignored
7640
+ * @param date string or Date - the initial date to display
7641
+ * @param onSelect function - the function to call when a date is selected
7642
+ * @param settings object - update the dialog date picker instance's settings (anonymous object)
7643
+ * @param pos int[2] - coordinates for the dialog's position within the screen or
7644
+ * event - with x/y coordinates or
7645
+ * leave empty for default (screen centre)
7646
+ * @return the manager object
7647
+ */
7648
+ _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7649
+ var id, browserWidth, browserHeight, scrollX, scrollY,
7650
+ inst = this._dialogInst; // internal instance
7651
+
7652
+ if ( !inst ) {
7653
+ this.uuid += 1;
7654
+ id = "dp" + this.uuid;
7655
+ this._dialogInput = $( "<input type='text' id='" + id +
7656
+ "' style='position: absolute; top: -100px; width: 0px;'/>" );
7657
+ this._dialogInput.on( "keydown", this._doKeyDown );
7658
+ $( "body" ).append( this._dialogInput );
7659
+ inst = this._dialogInst = this._newInst( this._dialogInput, false );
7660
+ inst.settings = {};
7661
+ $.data( this._dialogInput[ 0 ], "datepicker", inst );
7662
+ }
7663
+ datepicker_extendRemove( inst.settings, settings || {} );
7664
+ date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7665
+ this._dialogInput.val( date );
7666
+
7667
+ this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7668
+ if ( !this._pos ) {
7669
+ browserWidth = document.documentElement.clientWidth;
7670
+ browserHeight = document.documentElement.clientHeight;
7671
+ scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7672
+ scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7673
+ this._pos = // should use actual width/height below
7674
+ [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7675
+ }
7676
+
7677
+ // Move input on screen for focus, but hidden behind dialog
7678
+ this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7679
+ inst.settings.onSelect = onSelect;
7680
+ this._inDialog = true;
7681
+ this.dpDiv.addClass( this._dialogClass );
7682
+ this._showDatepicker( this._dialogInput[ 0 ] );
7683
+ if ( $.blockUI ) {
7684
+ $.blockUI( this.dpDiv );
7685
+ }
7686
+ $.data( this._dialogInput[ 0 ], "datepicker", inst );
7687
+ return this;
7688
+ },
7689
+
7690
+ /* Detach a datepicker from its control.
7691
+ * @param target element - the target input field or division or span
7692
+ */
7693
+ _destroyDatepicker: function( target ) {
7694
+ var nodeName,
7695
+ $target = $( target ),
7696
+ inst = $.data( target, "datepicker" );
7697
+
7698
+ if ( !$target.hasClass( this.markerClassName ) ) {
7699
+ return;
7700
+ }
7701
+
7702
+ nodeName = target.nodeName.toLowerCase();
7703
+ $.removeData( target, "datepicker" );
7704
+ if ( nodeName === "input" ) {
7705
+ inst.append.remove();
7706
+ inst.trigger.remove();
7707
+ $target.removeClass( this.markerClassName ).
7708
+ off( "focus", this._showDatepicker ).
7709
+ off( "keydown", this._doKeyDown ).
7710
+ off( "keypress", this._doKeyPress ).
7711
+ off( "keyup", this._doKeyUp );
7712
+ } else if ( nodeName === "div" || nodeName === "span" ) {
7713
+ $target.removeClass( this.markerClassName ).empty();
7714
+ }
7715
+
7716
+ if ( datepicker_instActive === inst ) {
7717
+ datepicker_instActive = null;
7718
+ this._curInst = null;
7719
+ }
7720
+ },
7721
+
7722
+ /* Enable the date picker to a jQuery selection.
7723
+ * @param target element - the target input field or division or span
7724
+ */
7725
+ _enableDatepicker: function( target ) {
7726
+ var nodeName, inline,
7727
+ $target = $( target ),
7728
+ inst = $.data( target, "datepicker" );
7729
+
7730
+ if ( !$target.hasClass( this.markerClassName ) ) {
7731
+ return;
7732
+ }
7733
+
7734
+ nodeName = target.nodeName.toLowerCase();
7735
+ if ( nodeName === "input" ) {
7736
+ target.disabled = false;
7737
+ inst.trigger.filter( "button" ).
7738
+ each( function() {
7739
+ this.disabled = false;
7740
+ } ).end().
7741
+ filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7742
+ } else if ( nodeName === "div" || nodeName === "span" ) {
7743
+ inline = $target.children( "." + this._inlineClass );
7744
+ inline.children().removeClass( "ui-state-disabled" );
7745
+ inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7746
+ prop( "disabled", false );
7747
+ }
7748
+ this._disabledInputs = $.map( this._disabledInputs,
7749
+
7750
+ // Delete entry
7751
+ function( value ) {
7752
+ return ( value === target ? null : value );
7753
+ } );
7754
+ },
7755
+
7756
+ /* Disable the date picker to a jQuery selection.
7757
+ * @param target element - the target input field or division or span
7758
+ */
7759
+ _disableDatepicker: function( target ) {
7760
+ var nodeName, inline,
7761
+ $target = $( target ),
7762
+ inst = $.data( target, "datepicker" );
7763
+
7764
+ if ( !$target.hasClass( this.markerClassName ) ) {
7765
+ return;
7766
+ }
7767
+
7768
+ nodeName = target.nodeName.toLowerCase();
7769
+ if ( nodeName === "input" ) {
7770
+ target.disabled = true;
7771
+ inst.trigger.filter( "button" ).
7772
+ each( function() {
7773
+ this.disabled = true;
7774
+ } ).end().
7775
+ filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7776
+ } else if ( nodeName === "div" || nodeName === "span" ) {
7777
+ inline = $target.children( "." + this._inlineClass );
7778
+ inline.children().addClass( "ui-state-disabled" );
7779
+ inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7780
+ prop( "disabled", true );
7781
+ }
7782
+ this._disabledInputs = $.map( this._disabledInputs,
7783
+
7784
+ // Delete entry
7785
+ function( value ) {
7786
+ return ( value === target ? null : value );
7787
+ } );
7788
+ this._disabledInputs[ this._disabledInputs.length ] = target;
7789
+ },
7790
+
7791
+ /* Is the first field in a jQuery collection disabled as a datepicker?
7792
+ * @param target element - the target input field or division or span
7793
+ * @return boolean - true if disabled, false if enabled
7794
+ */
7795
+ _isDisabledDatepicker: function( target ) {
7796
+ if ( !target ) {
7797
+ return false;
7798
+ }
7799
+ for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7800
+ if ( this._disabledInputs[ i ] === target ) {
7801
+ return true;
7802
+ }
7803
+ }
7804
+ return false;
7805
+ },
7806
+
7807
+ /* Retrieve the instance data for the target control.
7808
+ * @param target element - the target input field or division or span
7809
+ * @return object - the associated instance data
7810
+ * @throws error if a jQuery problem getting data
7811
+ */
7812
+ _getInst: function( target ) {
7813
+ try {
7814
+ return $.data( target, "datepicker" );
7815
+ } catch ( err ) {
7816
+ throw "Missing instance data for this datepicker";
7817
+ }
7818
+ },
7819
+
7820
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
7821
+ * @param target element - the target input field or division or span
7822
+ * @param name object - the new settings to update or
7823
+ * string - the name of the setting to change or retrieve,
7824
+ * when retrieving also "all" for all instance settings or
7825
+ * "defaults" for all global defaults
7826
+ * @param value any - the new value for the setting
7827
+ * (omit if above is an object or to retrieve a value)
7828
+ */
7829
+ _optionDatepicker: function( target, name, value ) {
7830
+ var settings, date, minDate, maxDate,
7831
+ inst = this._getInst( target );
7832
+
7833
+ if ( arguments.length === 2 && typeof name === "string" ) {
7834
+ return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7835
+ ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7836
+ this._get( inst, name ) ) : null ) );
7837
+ }
7838
+
7839
+ settings = name || {};
7840
+ if ( typeof name === "string" ) {
7841
+ settings = {};
7842
+ settings[ name ] = value;
7843
+ }
7844
+
7845
+ if ( inst ) {
7846
+ if ( this._curInst === inst ) {
7847
+ this._hideDatepicker();
7848
+ }
7849
+
7850
+ date = this._getDateDatepicker( target, true );
7851
+ minDate = this._getMinMaxDate( inst, "min" );
7852
+ maxDate = this._getMinMaxDate( inst, "max" );
7853
+ datepicker_extendRemove( inst.settings, settings );
7854
+
7855
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7856
+ if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7857
+ inst.settings.minDate = this._formatDate( inst, minDate );
7858
+ }
7859
+ if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7860
+ inst.settings.maxDate = this._formatDate( inst, maxDate );
7861
+ }
7862
+ if ( "disabled" in settings ) {
7863
+ if ( settings.disabled ) {
7864
+ this._disableDatepicker( target );
7865
+ } else {
7866
+ this._enableDatepicker( target );
7867
+ }
7868
+ }
7869
+ this._attachments( $( target ), inst );
7870
+ this._autoSize( inst );
7871
+ this._setDate( inst, date );
7872
+ this._updateAlternate( inst );
7873
+ this._updateDatepicker( inst );
7874
+ }
7875
+ },
7876
+
7877
+ // Change method deprecated
7878
+ _changeDatepicker: function( target, name, value ) {
7879
+ this._optionDatepicker( target, name, value );
7880
+ },
7881
+
7882
+ /* Redraw the date picker attached to an input field or division.
7883
+ * @param target element - the target input field or division or span
7884
+ */
7885
+ _refreshDatepicker: function( target ) {
7886
+ var inst = this._getInst( target );
7887
+ if ( inst ) {
7888
+ this._updateDatepicker( inst );
7889
+ }
7890
+ },
7891
+
7892
+ /* Set the dates for a jQuery selection.
7893
+ * @param target element - the target input field or division or span
7894
+ * @param date Date - the new date
7895
+ */
7896
+ _setDateDatepicker: function( target, date ) {
7897
+ var inst = this._getInst( target );
7898
+ if ( inst ) {
7899
+ this._setDate( inst, date );
7900
+ this._updateDatepicker( inst );
7901
+ this._updateAlternate( inst );
7902
+ }
7903
+ },
7904
+
7905
+ /* Get the date(s) for the first entry in a jQuery selection.
7906
+ * @param target element - the target input field or division or span
7907
+ * @param noDefault boolean - true if no default date is to be used
7908
+ * @return Date - the current date
7909
+ */
7910
+ _getDateDatepicker: function( target, noDefault ) {
7911
+ var inst = this._getInst( target );
7912
+ if ( inst && !inst.inline ) {
7913
+ this._setDateFromField( inst, noDefault );
7914
+ }
7915
+ return ( inst ? this._getDate( inst ) : null );
7916
+ },
7917
+
7918
+ /* Handle keystrokes. */
7919
+ _doKeyDown: function( event ) {
7920
+ var onSelect, dateStr, sel,
7921
+ inst = $.datepicker._getInst( event.target ),
7922
+ handled = true,
7923
+ isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7924
+
7925
+ inst._keyEvent = true;
7926
+ if ( $.datepicker._datepickerShowing ) {
7927
+ switch ( event.keyCode ) {
7928
+ case 9: $.datepicker._hideDatepicker();
7929
+ handled = false;
7930
+ break; // hide on tab out
7931
+ case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7932
+ $.datepicker._currentClass + ")", inst.dpDiv );
7933
+ if ( sel[ 0 ] ) {
7934
+ $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7935
+ }
7936
+
7937
+ onSelect = $.datepicker._get( inst, "onSelect" );
7938
+ if ( onSelect ) {
7939
+ dateStr = $.datepicker._formatDate( inst );
7940
+
7941
+ // Trigger custom callback
7942
+ onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7943
+ } else {
7944
+ $.datepicker._hideDatepicker();
7945
+ }
7946
+
7947
+ return false; // don't submit the form
7948
+ case 27: $.datepicker._hideDatepicker();
7949
+ break; // hide on escape
7950
+ case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7951
+ -$.datepicker._get( inst, "stepBigMonths" ) :
7952
+ -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7953
+ break; // previous month/year on page up/+ ctrl
7954
+ case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7955
+ +$.datepicker._get( inst, "stepBigMonths" ) :
7956
+ +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7957
+ break; // next month/year on page down/+ ctrl
7958
+ case 35: if ( event.ctrlKey || event.metaKey ) {
7959
+ $.datepicker._clearDate( event.target );
7960
+ }
7961
+ handled = event.ctrlKey || event.metaKey;
7962
+ break; // clear on ctrl or command +end
7963
+ case 36: if ( event.ctrlKey || event.metaKey ) {
7964
+ $.datepicker._gotoToday( event.target );
7965
+ }
7966
+ handled = event.ctrlKey || event.metaKey;
7967
+ break; // current on ctrl or command +home
7968
+ case 37: if ( event.ctrlKey || event.metaKey ) {
7969
+ $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7970
+ }
7971
+ handled = event.ctrlKey || event.metaKey;
7972
+
7973
+ // -1 day on ctrl or command +left
7974
+ if ( event.originalEvent.altKey ) {
7975
+ $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7976
+ -$.datepicker._get( inst, "stepBigMonths" ) :
7977
+ -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7978
+ }
7979
+
7980
+ // next month/year on alt +left on Mac
7981
+ break;
7982
+ case 38: if ( event.ctrlKey || event.metaKey ) {
7983
+ $.datepicker._adjustDate( event.target, -7, "D" );
7984
+ }
7985
+ handled = event.ctrlKey || event.metaKey;
7986
+ break; // -1 week on ctrl or command +up
7987
+ case 39: if ( event.ctrlKey || event.metaKey ) {
7988
+ $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7989
+ }
7990
+ handled = event.ctrlKey || event.metaKey;
7991
+
7992
+ // +1 day on ctrl or command +right
7993
+ if ( event.originalEvent.altKey ) {
7994
+ $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7995
+ +$.datepicker._get( inst, "stepBigMonths" ) :
7996
+ +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7997
+ }
7998
+
7999
+ // next month/year on alt +right
8000
+ break;
8001
+ case 40: if ( event.ctrlKey || event.metaKey ) {
8002
+ $.datepicker._adjustDate( event.target, +7, "D" );
8003
+ }
8004
+ handled = event.ctrlKey || event.metaKey;
8005
+ break; // +1 week on ctrl or command +down
8006
+ default: handled = false;
8007
+ }
8008
+ } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
8009
+ $.datepicker._showDatepicker( this );
8010
+ } else {
8011
+ handled = false;
8012
+ }
8013
+
8014
+ if ( handled ) {
8015
+ event.preventDefault();
8016
+ event.stopPropagation();
8017
+ }
8018
+ },
8019
+
8020
+ /* Filter entered characters - based on date format. */
8021
+ _doKeyPress: function( event ) {
8022
+ var chars, chr,
8023
+ inst = $.datepicker._getInst( event.target );
8024
+
8025
+ if ( $.datepicker._get( inst, "constrainInput" ) ) {
8026
+ chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
8027
+ chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
8028
+ return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
8029
+ }
8030
+ },
8031
+
8032
+ /* Synchronise manual entry and field/alternate field. */
8033
+ _doKeyUp: function( event ) {
8034
+ var date,
8035
+ inst = $.datepicker._getInst( event.target );
8036
+
8037
+ if ( inst.input.val() !== inst.lastVal ) {
8038
+ try {
8039
+ date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8040
+ ( inst.input ? inst.input.val() : null ),
8041
+ $.datepicker._getFormatConfig( inst ) );
8042
+
8043
+ if ( date ) { // only if valid
8044
+ $.datepicker._setDateFromField( inst );
8045
+ $.datepicker._updateAlternate( inst );
8046
+ $.datepicker._updateDatepicker( inst );
8047
+ }
8048
+ } catch ( err ) {
8049
+ }
8050
+ }
8051
+ return true;
8052
+ },
8053
+
8054
+ /* Pop-up the date picker for a given input field.
8055
+ * If false returned from beforeShow event handler do not show.
8056
+ * @param input element - the input field attached to the date picker or
8057
+ * event - if triggered by focus
8058
+ */
8059
+ _showDatepicker: function( input ) {
8060
+ input = input.target || input;
8061
+ if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
8062
+ input = $( "input", input.parentNode )[ 0 ];
8063
+ }
8064
+
8065
+ if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
8066
+ return;
8067
+ }
8068
+
8069
+ var inst, beforeShow, beforeShowSettings, isFixed,
8070
+ offset, showAnim, duration;
8071
+
8072
+ inst = $.datepicker._getInst( input );
8073
+ if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
8074
+ $.datepicker._curInst.dpDiv.stop( true, true );
8075
+ if ( inst && $.datepicker._datepickerShowing ) {
8076
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
8077
+ }
8078
+ }
8079
+
8080
+ beforeShow = $.datepicker._get( inst, "beforeShow" );
8081
+ beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
8082
+ if ( beforeShowSettings === false ) {
8083
+ return;
8084
+ }
8085
+ datepicker_extendRemove( inst.settings, beforeShowSettings );
8086
+
8087
+ inst.lastVal = null;
8088
+ $.datepicker._lastInput = input;
8089
+ $.datepicker._setDateFromField( inst );
8090
+
8091
+ if ( $.datepicker._inDialog ) { // hide cursor
8092
+ input.value = "";
8093
+ }
8094
+ if ( !$.datepicker._pos ) { // position below input
8095
+ $.datepicker._pos = $.datepicker._findPos( input );
8096
+ $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
8097
+ }
8098
+
8099
+ isFixed = false;
8100
+ $( input ).parents().each( function() {
8101
+ isFixed |= $( this ).css( "position" ) === "fixed";
8102
+ return !isFixed;
8103
+ } );
8104
+
8105
+ offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
8106
+ $.datepicker._pos = null;
8107
+
8108
+ //to avoid flashes on Firefox
8109
+ inst.dpDiv.empty();
8110
+
8111
+ // determine sizing offscreen
8112
+ inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
8113
+ $.datepicker._updateDatepicker( inst );
8114
+
8115
+ // fix width for dynamic number of date pickers
8116
+ // and adjust position before showing
8117
+ offset = $.datepicker._checkOffset( inst, offset, isFixed );
8118
+ inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
8119
+ "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
8120
+ left: offset.left + "px", top: offset.top + "px" } );
8121
+
8122
+ if ( !inst.inline ) {
8123
+ showAnim = $.datepicker._get( inst, "showAnim" );
8124
+ duration = $.datepicker._get( inst, "duration" );
8125
+ inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
8126
+ $.datepicker._datepickerShowing = true;
8127
+
8128
+ if ( $.effects && $.effects.effect[ showAnim ] ) {
8129
+ inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
8130
+ } else {
8131
+ inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
8132
+ }
8133
+
8134
+ if ( $.datepicker._shouldFocusInput( inst ) ) {
8135
+ inst.input.trigger( "focus" );
8136
+ }
8137
+
8138
+ $.datepicker._curInst = inst;
8139
+ }
8140
+ },
8141
+
8142
+ /* Generate the date picker content. */
8143
+ _updateDatepicker: function( inst ) {
8144
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8145
+ datepicker_instActive = inst; // for delegate hover events
8146
+ inst.dpDiv.empty().append( this._generateHTML( inst ) );
8147
+ this._attachHandlers( inst );
8148
+
8149
+ var origyearshtml,
8150
+ numMonths = this._getNumberOfMonths( inst ),
8151
+ cols = numMonths[ 1 ],
8152
+ width = 17,
8153
+ activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
8154
+ onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
8155
+
8156
+ if ( activeCell.length > 0 ) {
8157
+ datepicker_handleMouseover.apply( activeCell.get( 0 ) );
8158
+ }
8159
+
8160
+ inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
8161
+ if ( cols > 1 ) {
8162
+ inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
8163
+ }
8164
+ inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
8165
+ "Class" ]( "ui-datepicker-multi" );
8166
+ inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
8167
+ "Class" ]( "ui-datepicker-rtl" );
8168
+
8169
+ if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8170
+ inst.input.trigger( "focus" );
8171
+ }
8172
+
8173
+ // Deffered render of the years select (to avoid flashes on Firefox)
8174
+ if ( inst.yearshtml ) {
8175
+ origyearshtml = inst.yearshtml;
8176
+ setTimeout( function() {
8177
+
8178
+ //assure that inst.yearshtml didn't change.
8179
+ if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8180
+ inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8181
+ }
8182
+ origyearshtml = inst.yearshtml = null;
8183
+ }, 0 );
8184
+ }
8185
+
8186
+ if ( onUpdateDatepicker ) {
8187
+ onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8188
+ }
8189
+ },
8190
+
8191
+ // #6694 - don't focus the input if it's already focused
8192
+ // this breaks the change event in IE
8193
+ // Support: IE and jQuery <1.9
8194
+ _shouldFocusInput: function( inst ) {
8195
+ return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8196
+ },
8197
+
8198
+ /* Check positioning to remain on screen. */
8199
+ _checkOffset: function( inst, offset, isFixed ) {
8200
+ var dpWidth = inst.dpDiv.outerWidth(),
8201
+ dpHeight = inst.dpDiv.outerHeight(),
8202
+ inputWidth = inst.input ? inst.input.outerWidth() : 0,
8203
+ inputHeight = inst.input ? inst.input.outerHeight() : 0,
8204
+ viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8205
+ viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8206
+
8207
+ offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8208
+ offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8209
+ offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8210
+
8211
+ // Now check if datepicker is showing outside window viewport - move to a better place if so.
8212
+ offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8213
+ Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8214
+ offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8215
+ Math.abs( dpHeight + inputHeight ) : 0 );
8216
+
8217
+ return offset;
8218
+ },
8219
+
8220
+ /* Find an object's position on the screen. */
8221
+ _findPos: function( obj ) {
8222
+ var position,
8223
+ inst = this._getInst( obj ),
8224
+ isRTL = this._get( inst, "isRTL" );
8225
+
8226
+ while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8227
+ obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8228
+ }
8229
+
8230
+ position = $( obj ).offset();
8231
+ return [ position.left, position.top ];
8232
+ },
8233
+
8234
+ /* Hide the date picker from view.
8235
+ * @param input element - the input field attached to the date picker
8236
+ */
8237
+ _hideDatepicker: function( input ) {
8238
+ var showAnim, duration, postProcess, onClose,
8239
+ inst = this._curInst;
8240
+
8241
+ if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8242
+ return;
8243
+ }
8244
+
8245
+ if ( this._datepickerShowing ) {
8246
+ showAnim = this._get( inst, "showAnim" );
8247
+ duration = this._get( inst, "duration" );
8248
+ postProcess = function() {
8249
+ $.datepicker._tidyDialog( inst );
8250
+ };
8251
+
8252
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8253
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8254
+ inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8255
+ } else {
8256
+ inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8257
+ ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8258
+ }
8259
+
8260
+ if ( !showAnim ) {
8261
+ postProcess();
8262
+ }
8263
+ this._datepickerShowing = false;
8264
+
8265
+ onClose = this._get( inst, "onClose" );
8266
+ if ( onClose ) {
8267
+ onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8268
+ }
8269
+
8270
+ this._lastInput = null;
8271
+ if ( this._inDialog ) {
8272
+ this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8273
+ if ( $.blockUI ) {
8274
+ $.unblockUI();
8275
+ $( "body" ).append( this.dpDiv );
8276
+ }
8277
+ }
8278
+ this._inDialog = false;
8279
+ }
8280
+ },
8281
+
8282
+ /* Tidy up after a dialog display. */
8283
+ _tidyDialog: function( inst ) {
8284
+ inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8285
+ },
8286
+
8287
+ /* Close date picker if clicked elsewhere. */
8288
+ _checkExternalClick: function( event ) {
8289
+ if ( !$.datepicker._curInst ) {
8290
+ return;
8291
+ }
8292
+
8293
+ var $target = $( event.target ),
8294
+ inst = $.datepicker._getInst( $target[ 0 ] );
8295
+
8296
+ if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8297
+ $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8298
+ !$target.hasClass( $.datepicker.markerClassName ) &&
8299
+ !$target.closest( "." + $.datepicker._triggerClass ).length &&
8300
+ $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8301
+ ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8302
+ $.datepicker._hideDatepicker();
8303
+ }
8304
+ },
8305
+
8306
+ /* Adjust one of the date sub-fields. */
8307
+ _adjustDate: function( id, offset, period ) {
8308
+ var target = $( id ),
8309
+ inst = this._getInst( target[ 0 ] );
8310
+
8311
+ if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8312
+ return;
8313
+ }
8314
+ this._adjustInstDate( inst, offset, period );
8315
+ this._updateDatepicker( inst );
8316
+ },
8317
+
8318
+ /* Action for current link. */
8319
+ _gotoToday: function( id ) {
8320
+ var date,
8321
+ target = $( id ),
8322
+ inst = this._getInst( target[ 0 ] );
8323
+
8324
+ if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8325
+ inst.selectedDay = inst.currentDay;
8326
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8327
+ inst.drawYear = inst.selectedYear = inst.currentYear;
8328
+ } else {
8329
+ date = new Date();
8330
+ inst.selectedDay = date.getDate();
8331
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
8332
+ inst.drawYear = inst.selectedYear = date.getFullYear();
8333
+ }
8334
+ this._notifyChange( inst );
8335
+ this._adjustDate( target );
8336
+ },
8337
+
8338
+ /* Action for selecting a new month/year. */
8339
+ _selectMonthYear: function( id, select, period ) {
8340
+ var target = $( id ),
8341
+ inst = this._getInst( target[ 0 ] );
8342
+
8343
+ inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8344
+ inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8345
+ parseInt( select.options[ select.selectedIndex ].value, 10 );
8346
+
8347
+ this._notifyChange( inst );
8348
+ this._adjustDate( target );
8349
+ },
8350
+
8351
+ /* Action for selecting a day. */
8352
+ _selectDay: function( id, month, year, td ) {
8353
+ var inst,
8354
+ target = $( id );
8355
+
8356
+ if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8357
+ return;
8358
+ }
8359
+
8360
+ inst = this._getInst( target[ 0 ] );
8361
+ inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8362
+ inst.selectedMonth = inst.currentMonth = month;
8363
+ inst.selectedYear = inst.currentYear = year;
8364
+ this._selectDate( id, this._formatDate( inst,
8365
+ inst.currentDay, inst.currentMonth, inst.currentYear ) );
8366
+ },
8367
+
8368
+ /* Erase the input field and hide the date picker. */
8369
+ _clearDate: function( id ) {
8370
+ var target = $( id );
8371
+ this._selectDate( target, "" );
8372
+ },
8373
+
8374
+ /* Update the input field with the selected date. */
8375
+ _selectDate: function( id, dateStr ) {
8376
+ var onSelect,
8377
+ target = $( id ),
8378
+ inst = this._getInst( target[ 0 ] );
8379
+
8380
+ dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8381
+ if ( inst.input ) {
8382
+ inst.input.val( dateStr );
8383
+ }
8384
+ this._updateAlternate( inst );
8385
+
8386
+ onSelect = this._get( inst, "onSelect" );
8387
+ if ( onSelect ) {
8388
+ onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback
8389
+ } else if ( inst.input ) {
8390
+ inst.input.trigger( "change" ); // fire the change event
8391
+ }
8392
+
8393
+ if ( inst.inline ) {
8394
+ this._updateDatepicker( inst );
8395
+ } else {
8396
+ this._hideDatepicker();
8397
+ this._lastInput = inst.input[ 0 ];
8398
+ if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8399
+ inst.input.trigger( "focus" ); // restore focus
8400
+ }
8401
+ this._lastInput = null;
8402
+ }
8403
+ },
8404
+
8405
+ /* Update any alternate field to synchronise with the main field. */
8406
+ _updateAlternate: function( inst ) {
8407
+ var altFormat, date, dateStr,
8408
+ altField = this._get( inst, "altField" );
8409
+
8410
+ if ( altField ) { // update alternate field too
8411
+ altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8412
+ date = this._getDate( inst );
8413
+ dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8414
+ $( document ).find( altField ).val( dateStr );
8415
+ }
8416
+ },
8417
+
8418
+ /* Set as beforeShowDay function to prevent selection of weekends.
8419
+ * @param date Date - the date to customise
8420
+ * @return [boolean, string] - is this date selectable?, what is its CSS class?
8421
+ */
8422
+ noWeekends: function( date ) {
8423
+ var day = date.getDay();
8424
+ return [ ( day > 0 && day < 6 ), "" ];
8425
+ },
8426
+
8427
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8428
+ * @param date Date - the date to get the week for
8429
+ * @return number - the number of the week within the year that contains this date
8430
+ */
8431
+ iso8601Week: function( date ) {
8432
+ var time,
8433
+ checkDate = new Date( date.getTime() );
8434
+
8435
+ // Find Thursday of this week starting on Monday
8436
+ checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8437
+
8438
+ time = checkDate.getTime();
8439
+ checkDate.setMonth( 0 ); // Compare with Jan 1
8440
+ checkDate.setDate( 1 );
8441
+ return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8442
+ },
8443
+
8444
+ /* Parse a string value into a date object.
8445
+ * See formatDate below for the possible formats.
8446
+ *
8447
+ * @param format string - the expected format of the date
8448
+ * @param value string - the date in the above format
8449
+ * @param settings Object - attributes include:
8450
+ * shortYearCutoff number - the cutoff year for determining the century (optional)
8451
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8452
+ * dayNames string[7] - names of the days from Sunday (optional)
8453
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
8454
+ * monthNames string[12] - names of the months (optional)
8455
+ * @return Date - the extracted date value or null if value is blank
8456
+ */
8457
+ parseDate: function( format, value, settings ) {
8458
+ if ( format == null || value == null ) {
8459
+ throw "Invalid arguments";
8460
+ }
8461
+
8462
+ value = ( typeof value === "object" ? value.toString() : value + "" );
8463
+ if ( value === "" ) {
8464
+ return null;
8465
+ }
8466
+
8467
+ var iFormat, dim, extra,
8468
+ iValue = 0,
8469
+ shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8470
+ shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8471
+ new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8472
+ dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8473
+ dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8474
+ monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8475
+ monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8476
+ year = -1,
8477
+ month = -1,
8478
+ day = -1,
8479
+ doy = -1,
8480
+ literal = false,
8481
+ date,
8482
+
8483
+ // Check whether a format character is doubled
8484
+ lookAhead = function( match ) {
8485
+ var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8486
+ if ( matches ) {
8487
+ iFormat++;
8488
+ }
8489
+ return matches;
8490
+ },
8491
+
8492
+ // Extract a number from the string value
8493
+ getNumber = function( match ) {
8494
+ var isDoubled = lookAhead( match ),
8495
+ size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8496
+ ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8497
+ minSize = ( match === "y" ? size : 1 ),
8498
+ digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8499
+ num = value.substring( iValue ).match( digits );
8500
+ if ( !num ) {
8501
+ throw "Missing number at position " + iValue;
8502
+ }
8503
+ iValue += num[ 0 ].length;
8504
+ return parseInt( num[ 0 ], 10 );
8505
+ },
8506
+
8507
+ // Extract a name from the string value and convert to an index
8508
+ getName = function( match, shortNames, longNames ) {
8509
+ var index = -1,
8510
+ names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8511
+ return [ [ k, v ] ];
8512
+ } ).sort( function( a, b ) {
8513
+ return -( a[ 1 ].length - b[ 1 ].length );
8514
+ } );
8515
+
8516
+ $.each( names, function( i, pair ) {
8517
+ var name = pair[ 1 ];
8518
+ if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8519
+ index = pair[ 0 ];
8520
+ iValue += name.length;
8521
+ return false;
8522
+ }
8523
+ } );
8524
+ if ( index !== -1 ) {
8525
+ return index + 1;
8526
+ } else {
8527
+ throw "Unknown name at position " + iValue;
8528
+ }
8529
+ },
8530
+
8531
+ // Confirm that a literal character matches the string value
8532
+ checkLiteral = function() {
8533
+ if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8534
+ throw "Unexpected literal at position " + iValue;
8535
+ }
8536
+ iValue++;
8537
+ };
8538
+
8539
+ for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8540
+ if ( literal ) {
8541
+ if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8542
+ literal = false;
8543
+ } else {
8544
+ checkLiteral();
8545
+ }
8546
+ } else {
8547
+ switch ( format.charAt( iFormat ) ) {
8548
+ case "d":
8549
+ day = getNumber( "d" );
8550
+ break;
8551
+ case "D":
8552
+ getName( "D", dayNamesShort, dayNames );
8553
+ break;
8554
+ case "o":
8555
+ doy = getNumber( "o" );
8556
+ break;
8557
+ case "m":
8558
+ month = getNumber( "m" );
8559
+ break;
8560
+ case "M":
8561
+ month = getName( "M", monthNamesShort, monthNames );
8562
+ break;
8563
+ case "y":
8564
+ year = getNumber( "y" );
8565
+ break;
8566
+ case "@":
8567
+ date = new Date( getNumber( "@" ) );
8568
+ year = date.getFullYear();
8569
+ month = date.getMonth() + 1;
8570
+ day = date.getDate();
8571
+ break;
8572
+ case "!":
8573
+ date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8574
+ year = date.getFullYear();
8575
+ month = date.getMonth() + 1;
8576
+ day = date.getDate();
8577
+ break;
8578
+ case "'":
8579
+ if ( lookAhead( "'" ) ) {
8580
+ checkLiteral();
8581
+ } else {
8582
+ literal = true;
8583
+ }
8584
+ break;
8585
+ default:
8586
+ checkLiteral();
8587
+ }
8588
+ }
8589
+ }
8590
+
8591
+ if ( iValue < value.length ) {
8592
+ extra = value.substr( iValue );
8593
+ if ( !/^\s+/.test( extra ) ) {
8594
+ throw "Extra/unparsed characters found in date: " + extra;
8595
+ }
8596
+ }
8597
+
8598
+ if ( year === -1 ) {
8599
+ year = new Date().getFullYear();
8600
+ } else if ( year < 100 ) {
8601
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8602
+ ( year <= shortYearCutoff ? 0 : -100 );
8603
+ }
8604
+
8605
+ if ( doy > -1 ) {
8606
+ month = 1;
8607
+ day = doy;
8608
+ do {
8609
+ dim = this._getDaysInMonth( year, month - 1 );
8610
+ if ( day <= dim ) {
8611
+ break;
8612
+ }
8613
+ month++;
8614
+ day -= dim;
8615
+ } while ( true );
8616
+ }
8617
+
8618
+ date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8619
+ if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8620
+ throw "Invalid date"; // E.g. 31/02/00
8621
+ }
8622
+ return date;
8623
+ },
8624
+
8625
+ /* Standard date formats. */
8626
+ ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8627
+ COOKIE: "D, dd M yy",
8628
+ ISO_8601: "yy-mm-dd",
8629
+ RFC_822: "D, d M y",
8630
+ RFC_850: "DD, dd-M-y",
8631
+ RFC_1036: "D, d M y",
8632
+ RFC_1123: "D, d M yy",
8633
+ RFC_2822: "D, d M yy",
8634
+ RSS: "D, d M y", // RFC 822
8635
+ TICKS: "!",
8636
+ TIMESTAMP: "@",
8637
+ W3C: "yy-mm-dd", // ISO 8601
8638
+
8639
+ _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8640
+ Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8641
+
8642
+ /* Format a date object into a string value.
8643
+ * The format can be combinations of the following:
8644
+ * d - day of month (no leading zero)
8645
+ * dd - day of month (two digit)
8646
+ * o - day of year (no leading zeros)
8647
+ * oo - day of year (three digit)
8648
+ * D - day name short
8649
+ * DD - day name long
8650
+ * m - month of year (no leading zero)
8651
+ * mm - month of year (two digit)
8652
+ * M - month name short
8653
+ * MM - month name long
8654
+ * y - year (two digit)
8655
+ * yy - year (four digit)
8656
+ * @ - Unix timestamp (ms since 01/01/1970)
8657
+ * ! - Windows ticks (100ns since 01/01/0001)
8658
+ * "..." - literal text
8659
+ * '' - single quote
8660
+ *
8661
+ * @param format string - the desired format of the date
8662
+ * @param date Date - the date value to format
8663
+ * @param settings Object - attributes include:
8664
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8665
+ * dayNames string[7] - names of the days from Sunday (optional)
8666
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
8667
+ * monthNames string[12] - names of the months (optional)
8668
+ * @return string - the date in the above format
8669
+ */
8670
+ formatDate: function( format, date, settings ) {
8671
+ if ( !date ) {
8672
+ return "";
8673
+ }
8674
+
8675
+ var iFormat,
8676
+ dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8677
+ dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8678
+ monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8679
+ monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8680
+
8681
+ // Check whether a format character is doubled
8682
+ lookAhead = function( match ) {
8683
+ var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8684
+ if ( matches ) {
8685
+ iFormat++;
8686
+ }
8687
+ return matches;
8688
+ },
8689
+
8690
+ // Format a number, with leading zero if necessary
8691
+ formatNumber = function( match, value, len ) {
8692
+ var num = "" + value;
8693
+ if ( lookAhead( match ) ) {
8694
+ while ( num.length < len ) {
8695
+ num = "0" + num;
8696
+ }
8697
+ }
8698
+ return num;
8699
+ },
8700
+
8701
+ // Format a name, short or long as requested
8702
+ formatName = function( match, value, shortNames, longNames ) {
8703
+ return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8704
+ },
8705
+ output = "",
8706
+ literal = false;
8707
+
8708
+ if ( date ) {
8709
+ for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8710
+ if ( literal ) {
8711
+ if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8712
+ literal = false;
8713
+ } else {
8714
+ output += format.charAt( iFormat );
8715
+ }
8716
+ } else {
8717
+ switch ( format.charAt( iFormat ) ) {
8718
+ case "d":
8719
+ output += formatNumber( "d", date.getDate(), 2 );
8720
+ break;
8721
+ case "D":
8722
+ output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8723
+ break;
8724
+ case "o":
8725
+ output += formatNumber( "o",
8726
+ Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8727
+ break;
8728
+ case "m":
8729
+ output += formatNumber( "m", date.getMonth() + 1, 2 );
8730
+ break;
8731
+ case "M":
8732
+ output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8733
+ break;
8734
+ case "y":
8735
+ output += ( lookAhead( "y" ) ? date.getFullYear() :
8736
+ ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8737
+ break;
8738
+ case "@":
8739
+ output += date.getTime();
8740
+ break;
8741
+ case "!":
8742
+ output += date.getTime() * 10000 + this._ticksTo1970;
8743
+ break;
8744
+ case "'":
8745
+ if ( lookAhead( "'" ) ) {
8746
+ output += "'";
8747
+ } else {
8748
+ literal = true;
8749
+ }
8750
+ break;
8751
+ default:
8752
+ output += format.charAt( iFormat );
8753
+ }
8754
+ }
8755
+ }
8756
+ }
8757
+ return output;
8758
+ },
8759
+
8760
+ /* Extract all possible characters from the date format. */
8761
+ _possibleChars: function( format ) {
8762
+ var iFormat,
8763
+ chars = "",
8764
+ literal = false,
8765
+
8766
+ // Check whether a format character is doubled
8767
+ lookAhead = function( match ) {
8768
+ var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8769
+ if ( matches ) {
8770
+ iFormat++;
8771
+ }
8772
+ return matches;
8773
+ };
8774
+
8775
+ for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8776
+ if ( literal ) {
8777
+ if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8778
+ literal = false;
8779
+ } else {
8780
+ chars += format.charAt( iFormat );
8781
+ }
8782
+ } else {
8783
+ switch ( format.charAt( iFormat ) ) {
8784
+ case "d": case "m": case "y": case "@":
8785
+ chars += "0123456789";
8786
+ break;
8787
+ case "D": case "M":
8788
+ return null; // Accept anything
8789
+ case "'":
8790
+ if ( lookAhead( "'" ) ) {
8791
+ chars += "'";
8792
+ } else {
8793
+ literal = true;
8794
+ }
8795
+ break;
8796
+ default:
8797
+ chars += format.charAt( iFormat );
8798
+ }
8799
+ }
8800
+ }
8801
+ return chars;
8802
+ },
8803
+
8804
+ /* Get a setting value, defaulting if necessary. */
8805
+ _get: function( inst, name ) {
8806
+ return inst.settings[ name ] !== undefined ?
8807
+ inst.settings[ name ] : this._defaults[ name ];
8808
+ },
8809
+
8810
+ /* Parse existing date and initialise date picker. */
8811
+ _setDateFromField: function( inst, noDefault ) {
8812
+ if ( inst.input.val() === inst.lastVal ) {
8813
+ return;
8814
+ }
8815
+
8816
+ var dateFormat = this._get( inst, "dateFormat" ),
8817
+ dates = inst.lastVal = inst.input ? inst.input.val() : null,
8818
+ defaultDate = this._getDefaultDate( inst ),
8819
+ date = defaultDate,
8820
+ settings = this._getFormatConfig( inst );
8821
+
8822
+ try {
8823
+ date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8824
+ } catch ( event ) {
8825
+ dates = ( noDefault ? "" : dates );
8826
+ }
8827
+ inst.selectedDay = date.getDate();
8828
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
8829
+ inst.drawYear = inst.selectedYear = date.getFullYear();
8830
+ inst.currentDay = ( dates ? date.getDate() : 0 );
8831
+ inst.currentMonth = ( dates ? date.getMonth() : 0 );
8832
+ inst.currentYear = ( dates ? date.getFullYear() : 0 );
8833
+ this._adjustInstDate( inst );
8834
+ },
8835
+
8836
+ /* Retrieve the default date shown on opening. */
8837
+ _getDefaultDate: function( inst ) {
8838
+ return this._restrictMinMax( inst,
8839
+ this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8840
+ },
8841
+
8842
+ /* A date may be specified as an exact value or a relative one. */
8843
+ _determineDate: function( inst, date, defaultDate ) {
8844
+ var offsetNumeric = function( offset ) {
8845
+ var date = new Date();
8846
+ date.setDate( date.getDate() + offset );
8847
+ return date;
8848
+ },
8849
+ offsetString = function( offset ) {
8850
+ try {
8851
+ return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8852
+ offset, $.datepicker._getFormatConfig( inst ) );
8853
+ } catch ( e ) {
8854
+
8855
+ // Ignore
8856
+ }
8857
+
8858
+ var date = ( offset.toLowerCase().match( /^c/ ) ?
8859
+ $.datepicker._getDate( inst ) : null ) || new Date(),
8860
+ year = date.getFullYear(),
8861
+ month = date.getMonth(),
8862
+ day = date.getDate(),
8863
+ pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8864
+ matches = pattern.exec( offset );
8865
+
8866
+ while ( matches ) {
8867
+ switch ( matches[ 2 ] || "d" ) {
8868
+ case "d" : case "D" :
8869
+ day += parseInt( matches[ 1 ], 10 ); break;
8870
+ case "w" : case "W" :
8871
+ day += parseInt( matches[ 1 ], 10 ) * 7; break;
8872
+ case "m" : case "M" :
8873
+ month += parseInt( matches[ 1 ], 10 );
8874
+ day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8875
+ break;
8876
+ case "y": case "Y" :
8877
+ year += parseInt( matches[ 1 ], 10 );
8878
+ day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8879
+ break;
8880
+ }
8881
+ matches = pattern.exec( offset );
8882
+ }
8883
+ return new Date( year, month, day );
8884
+ },
8885
+ newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8886
+ ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8887
+
8888
+ newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8889
+ if ( newDate ) {
8890
+ newDate.setHours( 0 );
8891
+ newDate.setMinutes( 0 );
8892
+ newDate.setSeconds( 0 );
8893
+ newDate.setMilliseconds( 0 );
8894
+ }
8895
+ return this._daylightSavingAdjust( newDate );
8896
+ },
8897
+
8898
+ /* Handle switch to/from daylight saving.
8899
+ * Hours may be non-zero on daylight saving cut-over:
8900
+ * > 12 when midnight changeover, but then cannot generate
8901
+ * midnight datetime, so jump to 1AM, otherwise reset.
8902
+ * @param date (Date) the date to check
8903
+ * @return (Date) the corrected date
8904
+ */
8905
+ _daylightSavingAdjust: function( date ) {
8906
+ if ( !date ) {
8907
+ return null;
8908
+ }
8909
+ date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8910
+ return date;
8911
+ },
8912
+
8913
+ /* Set the date(s) directly. */
8914
+ _setDate: function( inst, date, noChange ) {
8915
+ var clear = !date,
8916
+ origMonth = inst.selectedMonth,
8917
+ origYear = inst.selectedYear,
8918
+ newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8919
+
8920
+ inst.selectedDay = inst.currentDay = newDate.getDate();
8921
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8922
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8923
+ if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8924
+ this._notifyChange( inst );
8925
+ }
8926
+ this._adjustInstDate( inst );
8927
+ if ( inst.input ) {
8928
+ inst.input.val( clear ? "" : this._formatDate( inst ) );
8929
+ }
8930
+ },
8931
+
8932
+ /* Retrieve the date(s) directly. */
8933
+ _getDate: function( inst ) {
8934
+ var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8935
+ this._daylightSavingAdjust( new Date(
8936
+ inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8937
+ return startDate;
8938
+ },
8939
+
8940
+ /* Attach the onxxx handlers. These are declared statically so
8941
+ * they work with static code transformers like Caja.
8942
+ */
8943
+ _attachHandlers: function( inst ) {
8944
+ var stepMonths = this._get( inst, "stepMonths" ),
8945
+ id = "#" + inst.id.replace( /\\\\/g, "\\" );
8946
+ inst.dpDiv.find( "[data-handler]" ).map( function() {
8947
+ var handler = {
8948
+ prev: function() {
8949
+ $.datepicker._adjustDate( id, -stepMonths, "M" );
8950
+ },
8951
+ next: function() {
8952
+ $.datepicker._adjustDate( id, +stepMonths, "M" );
8953
+ },
8954
+ hide: function() {
8955
+ $.datepicker._hideDatepicker();
8956
+ },
8957
+ today: function() {
8958
+ $.datepicker._gotoToday( id );
8959
+ },
8960
+ selectDay: function() {
8961
+ $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8962
+ return false;
8963
+ },
8964
+ selectMonth: function() {
8965
+ $.datepicker._selectMonthYear( id, this, "M" );
8966
+ return false;
8967
+ },
8968
+ selectYear: function() {
8969
+ $.datepicker._selectMonthYear( id, this, "Y" );
8970
+ return false;
8971
+ }
8972
+ };
8973
+ $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8974
+ } );
8975
+ },
8976
+
8977
+ /* Generate the HTML for the current state of the date picker. */
8978
+ _generateHTML: function( inst ) {
8979
+ var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8980
+ controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8981
+ monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8982
+ selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8983
+ cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8984
+ printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8985
+ tempDate = new Date(),
8986
+ today = this._daylightSavingAdjust(
8987
+ new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8988
+ isRTL = this._get( inst, "isRTL" ),
8989
+ showButtonPanel = this._get( inst, "showButtonPanel" ),
8990
+ hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8991
+ navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8992
+ numMonths = this._getNumberOfMonths( inst ),
8993
+ showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8994
+ stepMonths = this._get( inst, "stepMonths" ),
8995
+ isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8996
+ currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8997
+ new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8998
+ minDate = this._getMinMaxDate( inst, "min" ),
8999
+ maxDate = this._getMinMaxDate( inst, "max" ),
9000
+ drawMonth = inst.drawMonth - showCurrentAtPos,
9001
+ drawYear = inst.drawYear;
9002
+
9003
+ if ( drawMonth < 0 ) {
9004
+ drawMonth += 12;
9005
+ drawYear--;
9006
+ }
9007
+ if ( maxDate ) {
9008
+ maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
9009
+ maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
9010
+ maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
9011
+ while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
9012
+ drawMonth--;
9013
+ if ( drawMonth < 0 ) {
9014
+ drawMonth = 11;
9015
+ drawYear--;
9016
+ }
9017
+ }
9018
+ }
9019
+ inst.drawMonth = drawMonth;
9020
+ inst.drawYear = drawYear;
9021
+
9022
+ prevText = this._get( inst, "prevText" );
9023
+ prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
9024
+ this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
9025
+ this._getFormatConfig( inst ) ) );
9026
+
9027
+ if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
9028
+ prev = $( "<a>" )
9029
+ .attr( {
9030
+ "class": "ui-datepicker-prev ui-corner-all",
9031
+ "data-handler": "prev",
9032
+ "data-event": "click",
9033
+ title: prevText
9034
+ } )
9035
+ .append(
9036
+ $( "<span>" )
9037
+ .addClass( "ui-icon ui-icon-circle-triangle-" +
9038
+ ( isRTL ? "e" : "w" ) )
9039
+ .text( prevText )
9040
+ )[ 0 ].outerHTML;
9041
+ } else if ( hideIfNoPrevNext ) {
9042
+ prev = "";
9043
+ } else {
9044
+ prev = $( "<a>" )
9045
+ .attr( {
9046
+ "class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
9047
+ title: prevText
9048
+ } )
9049
+ .append(
9050
+ $( "<span>" )
9051
+ .addClass( "ui-icon ui-icon-circle-triangle-" +
9052
+ ( isRTL ? "e" : "w" ) )
9053
+ .text( prevText )
9054
+ )[ 0 ].outerHTML;
9055
+ }
9056
+
9057
+ nextText = this._get( inst, "nextText" );
9058
+ nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
9059
+ this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
9060
+ this._getFormatConfig( inst ) ) );
9061
+
9062
+ if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
9063
+ next = $( "<a>" )
9064
+ .attr( {
9065
+ "class": "ui-datepicker-next ui-corner-all",
9066
+ "data-handler": "next",
9067
+ "data-event": "click",
9068
+ title: nextText
9069
+ } )
9070
+ .append(
9071
+ $( "<span>" )
9072
+ .addClass( "ui-icon ui-icon-circle-triangle-" +
9073
+ ( isRTL ? "w" : "e" ) )
9074
+ .text( nextText )
9075
+ )[ 0 ].outerHTML;
9076
+ } else if ( hideIfNoPrevNext ) {
9077
+ next = "";
9078
+ } else {
9079
+ next = $( "<a>" )
9080
+ .attr( {
9081
+ "class": "ui-datepicker-next ui-corner-all ui-state-disabled",
9082
+ title: nextText
9083
+ } )
9084
+ .append(
9085
+ $( "<span>" )
9086
+ .attr( "class", "ui-icon ui-icon-circle-triangle-" +
9087
+ ( isRTL ? "w" : "e" ) )
9088
+ .text( nextText )
9089
+ )[ 0 ].outerHTML;
9090
+ }
9091
+
9092
+ currentText = this._get( inst, "currentText" );
9093
+ gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
9094
+ currentText = ( !navigationAsDateFormat ? currentText :
9095
+ this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
9096
+
9097
+ controls = "";
9098
+ if ( !inst.inline ) {
9099
+ controls = $( "<button>" )
9100
+ .attr( {
9101
+ type: "button",
9102
+ "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
9103
+ "data-handler": "hide",
9104
+ "data-event": "click"
9105
+ } )
9106
+ .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
9107
+ }
9108
+
9109
+ buttonPanel = "";
9110
+ if ( showButtonPanel ) {
9111
+ buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
9112
+ .append( isRTL ? controls : "" )
9113
+ .append( this._isInRange( inst, gotoDate ) ?
9114
+ $( "<button>" )
9115
+ .attr( {
9116
+ type: "button",
9117
+ "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
9118
+ "data-handler": "today",
9119
+ "data-event": "click"
9120
+ } )
9121
+ .text( currentText ) :
9122
+ "" )
9123
+ .append( isRTL ? "" : controls )[ 0 ].outerHTML;
9124
+ }
9125
+
9126
+ firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
9127
+ firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
9128
+
9129
+ showWeek = this._get( inst, "showWeek" );
9130
+ dayNames = this._get( inst, "dayNames" );
9131
+ dayNamesMin = this._get( inst, "dayNamesMin" );
9132
+ monthNames = this._get( inst, "monthNames" );
9133
+ monthNamesShort = this._get( inst, "monthNamesShort" );
9134
+ beforeShowDay = this._get( inst, "beforeShowDay" );
9135
+ showOtherMonths = this._get( inst, "showOtherMonths" );
9136
+ selectOtherMonths = this._get( inst, "selectOtherMonths" );
9137
+ defaultDate = this._getDefaultDate( inst );
9138
+ html = "";
9139
+
9140
+ for ( row = 0; row < numMonths[ 0 ]; row++ ) {
9141
+ group = "";
9142
+ this.maxRows = 4;
9143
+ for ( col = 0; col < numMonths[ 1 ]; col++ ) {
9144
+ selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
9145
+ cornerClass = " ui-corner-all";
9146
+ calender = "";
9147
+ if ( isMultiMonth ) {
9148
+ calender += "<div class='ui-datepicker-group";
9149
+ if ( numMonths[ 1 ] > 1 ) {
9150
+ switch ( col ) {
9151
+ case 0: calender += " ui-datepicker-group-first";
9152
+ cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
9153
+ case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
9154
+ cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
9155
+ default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9156
+ }
9157
+ }
9158
+ calender += "'>";
9159
+ }
9160
+ calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9161
+ ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
9162
+ ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
9163
+ this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
9164
+ row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
9165
+ "</div><table class='ui-datepicker-calendar'><thead>" +
9166
+ "<tr>";
9167
+ thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
9168
+ for ( dow = 0; dow < 7; dow++ ) { // days of the week
9169
+ day = ( dow + firstDay ) % 7;
9170
+ thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
9171
+ "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
9172
+ }
9173
+ calender += thead + "</tr></thead><tbody>";
9174
+ daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
9175
+ if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
9176
+ inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9177
+ }
9178
+ leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9179
+ curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9180
+ numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9181
+ this.maxRows = numRows;
9182
+ printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9183
+ for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9184
+ calender += "<tr>";
9185
+ tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9186
+ this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9187
+ for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9188
+ daySettings = ( beforeShowDay ?
9189
+ beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9190
+ otherMonth = ( printDate.getMonth() !== drawMonth );
9191
+ unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9192
+ ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9193
+ tbody += "<td class='" +
9194
+ ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9195
+ ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9196
+ ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9197
+ ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9198
+
9199
+ // or defaultDate is current printedDate and defaultDate is selectedDate
9200
+ " " + this._dayOverClass : "" ) + // highlight selected day
9201
+ ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days
9202
+ ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9203
+ ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9204
+ ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9205
+ ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9206
+ ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9207
+ ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9208
+ ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9209
+ ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9210
+ ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9211
+ ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9212
+ "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9213
+ "' data-date='" + printDate.getDate() + // store date as data
9214
+ "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9215
+ printDate.setDate( printDate.getDate() + 1 );
9216
+ printDate = this._daylightSavingAdjust( printDate );
9217
+ }
9218
+ calender += tbody + "</tr>";
9219
+ }
9220
+ drawMonth++;
9221
+ if ( drawMonth > 11 ) {
9222
+ drawMonth = 0;
9223
+ drawYear++;
9224
+ }
9225
+ calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9226
+ ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9227
+ group += calender;
9228
+ }
9229
+ html += group;
9230
+ }
9231
+ html += buttonPanel;
9232
+ inst._keyEvent = false;
9233
+ return html;
9234
+ },
9235
+
9236
+ /* Generate the month and year header. */
9237
+ _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9238
+ secondary, monthNames, monthNamesShort ) {
9239
+
9240
+ var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9241
+ changeMonth = this._get( inst, "changeMonth" ),
9242
+ changeYear = this._get( inst, "changeYear" ),
9243
+ showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9244
+ selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9245
+ selectYearLabel = this._get( inst, "selectYearLabel" ),
9246
+ html = "<div class='ui-datepicker-title'>",
9247
+ monthHtml = "";
9248
+
9249
+ // Month selection
9250
+ if ( secondary || !changeMonth ) {
9251
+ monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9252
+ } else {
9253
+ inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9254
+ inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9255
+ monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9256
+ for ( month = 0; month < 12; month++ ) {
9257
+ if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9258
+ monthHtml += "<option value='" + month + "'" +
9259
+ ( month === drawMonth ? " selected='selected'" : "" ) +
9260
+ ">" + monthNamesShort[ month ] + "</option>";
9261
+ }
9262
+ }
9263
+ monthHtml += "</select>";
9264
+ }
9265
+
9266
+ if ( !showMonthAfterYear ) {
9267
+ html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9268
+ }
9269
+
9270
+ // Year selection
9271
+ if ( !inst.yearshtml ) {
9272
+ inst.yearshtml = "";
9273
+ if ( secondary || !changeYear ) {
9274
+ html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9275
+ } else {
9276
+
9277
+ // determine range of years to display
9278
+ years = this._get( inst, "yearRange" ).split( ":" );
9279
+ thisYear = new Date().getFullYear();
9280
+ determineYear = function( value ) {
9281
+ var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9282
+ ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9283
+ parseInt( value, 10 ) ) );
9284
+ return ( isNaN( year ) ? thisYear : year );
9285
+ };
9286
+ year = determineYear( years[ 0 ] );
9287
+ endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9288
+ year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9289
+ endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9290
+ inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9291
+ for ( ; year <= endYear; year++ ) {
9292
+ inst.yearshtml += "<option value='" + year + "'" +
9293
+ ( year === drawYear ? " selected='selected'" : "" ) +
9294
+ ">" + year + "</option>";
9295
+ }
9296
+ inst.yearshtml += "</select>";
9297
+
9298
+ html += inst.yearshtml;
9299
+ inst.yearshtml = null;
9300
+ }
9301
+ }
9302
+
9303
+ html += this._get( inst, "yearSuffix" );
9304
+ if ( showMonthAfterYear ) {
9305
+ html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9306
+ }
9307
+ html += "</div>"; // Close datepicker_header
9308
+ return html;
9309
+ },
9310
+
9311
+ /* Adjust one of the date sub-fields. */
9312
+ _adjustInstDate: function( inst, offset, period ) {
9313
+ var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9314
+ month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9315
+ day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9316
+ date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9317
+
9318
+ inst.selectedDay = date.getDate();
9319
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
9320
+ inst.drawYear = inst.selectedYear = date.getFullYear();
9321
+ if ( period === "M" || period === "Y" ) {
9322
+ this._notifyChange( inst );
9323
+ }
9324
+ },
9325
+
9326
+ /* Ensure a date is within any min/max bounds. */
9327
+ _restrictMinMax: function( inst, date ) {
9328
+ var minDate = this._getMinMaxDate( inst, "min" ),
9329
+ maxDate = this._getMinMaxDate( inst, "max" ),
9330
+ newDate = ( minDate && date < minDate ? minDate : date );
9331
+ return ( maxDate && newDate > maxDate ? maxDate : newDate );
9332
+ },
9333
+
9334
+ /* Notify change of month/year. */
9335
+ _notifyChange: function( inst ) {
9336
+ var onChange = this._get( inst, "onChangeMonthYear" );
9337
+ if ( onChange ) {
9338
+ onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9339
+ [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9340
+ }
9341
+ },
9342
+
9343
+ /* Determine the number of months to show. */
9344
+ _getNumberOfMonths: function( inst ) {
9345
+ var numMonths = this._get( inst, "numberOfMonths" );
9346
+ return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9347
+ },
9348
+
9349
+ /* Determine the current maximum date - ensure no time components are set. */
9350
+ _getMinMaxDate: function( inst, minMax ) {
9351
+ return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9352
+ },
9353
+
9354
+ /* Find the number of days in a given month. */
9355
+ _getDaysInMonth: function( year, month ) {
9356
+ return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9357
+ },
9358
+
9359
+ /* Find the day of the week of the first of a month. */
9360
+ _getFirstDayOfMonth: function( year, month ) {
9361
+ return new Date( year, month, 1 ).getDay();
9362
+ },
9363
+
9364
+ /* Determines if we should allow a "next/prev" month display change. */
9365
+ _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9366
+ var numMonths = this._getNumberOfMonths( inst ),
9367
+ date = this._daylightSavingAdjust( new Date( curYear,
9368
+ curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9369
+
9370
+ if ( offset < 0 ) {
9371
+ date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9372
+ }
9373
+ return this._isInRange( inst, date );
9374
+ },
9375
+
9376
+ /* Is the given date in the accepted range? */
9377
+ _isInRange: function( inst, date ) {
9378
+ var yearSplit, currentYear,
9379
+ minDate = this._getMinMaxDate( inst, "min" ),
9380
+ maxDate = this._getMinMaxDate( inst, "max" ),
9381
+ minYear = null,
9382
+ maxYear = null,
9383
+ years = this._get( inst, "yearRange" );
9384
+ if ( years ) {
9385
+ yearSplit = years.split( ":" );
9386
+ currentYear = new Date().getFullYear();
9387
+ minYear = parseInt( yearSplit[ 0 ], 10 );
9388
+ maxYear = parseInt( yearSplit[ 1 ], 10 );
9389
+ if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9390
+ minYear += currentYear;
9391
+ }
9392
+ if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9393
+ maxYear += currentYear;
9394
+ }
9395
+ }
9396
+
9397
+ return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9398
+ ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9399
+ ( !minYear || date.getFullYear() >= minYear ) &&
9400
+ ( !maxYear || date.getFullYear() <= maxYear ) );
9401
+ },
9402
+
9403
+ /* Provide the configuration settings for formatting/parsing. */
9404
+ _getFormatConfig: function( inst ) {
9405
+ var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9406
+ shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9407
+ new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9408
+ return { shortYearCutoff: shortYearCutoff,
9409
+ dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9410
+ monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9411
+ },
9412
+
9413
+ /* Format the given date for display. */
9414
+ _formatDate: function( inst, day, month, year ) {
9415
+ if ( !day ) {
9416
+ inst.currentDay = inst.selectedDay;
9417
+ inst.currentMonth = inst.selectedMonth;
9418
+ inst.currentYear = inst.selectedYear;
9419
+ }
9420
+ var date = ( day ? ( typeof day === "object" ? day :
9421
+ this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9422
+ this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9423
+ return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9424
+ }
9425
+ } );
9426
+
9427
+ /*
9428
+ * Bind hover events for datepicker elements.
9429
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9430
+ * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9431
+ */
9432
+ function datepicker_bindHover( dpDiv ) {
9433
+ var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9434
+ return dpDiv.on( "mouseout", selector, function() {
9435
+ $( this ).removeClass( "ui-state-hover" );
9436
+ if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9437
+ $( this ).removeClass( "ui-datepicker-prev-hover" );
9438
+ }
9439
+ if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9440
+ $( this ).removeClass( "ui-datepicker-next-hover" );
9441
+ }
9442
+ } )
9443
+ .on( "mouseover", selector, datepicker_handleMouseover );
9444
+ }
9445
+
9446
+ function datepicker_handleMouseover() {
9447
+ if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9448
+ $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9449
+ $( this ).addClass( "ui-state-hover" );
9450
+ if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9451
+ $( this ).addClass( "ui-datepicker-prev-hover" );
9452
+ }
9453
+ if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9454
+ $( this ).addClass( "ui-datepicker-next-hover" );
9455
+ }
9456
+ }
9457
+ }
9458
+
9459
+ /* jQuery extend now ignores nulls! */
9460
+ function datepicker_extendRemove( target, props ) {
9461
+ $.extend( target, props );
9462
+ for ( var name in props ) {
9463
+ if ( props[ name ] == null ) {
9464
+ target[ name ] = props[ name ];
9465
+ }
9466
+ }
9467
+ return target;
9468
+ }
9469
+
9470
+ /* Invoke the datepicker functionality.
9471
+ @param options string - a command, optionally followed by additional parameters or
9472
+ Object - settings for attaching new datepicker functionality
9473
+ @return jQuery object */
9474
+ $.fn.datepicker = function( options ) {
9475
+
9476
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
9477
+ if ( !this.length ) {
9478
+ return this;
9479
+ }
9480
+
9481
+ /* Initialise the date picker. */
9482
+ if ( !$.datepicker.initialized ) {
9483
+ $( document ).on( "mousedown", $.datepicker._checkExternalClick );
9484
+ $.datepicker.initialized = true;
9485
+ }
9486
+
9487
+ /* Append datepicker main container to body if not exist. */
9488
+ if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9489
+ $( "body" ).append( $.datepicker.dpDiv );
9490
+ }
9491
+
9492
+ var otherArgs = Array.prototype.slice.call( arguments, 1 );
9493
+ if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9494
+ return $.datepicker[ "_" + options + "Datepicker" ].
9495
+ apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9496
+ }
9497
+ if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9498
+ return $.datepicker[ "_" + options + "Datepicker" ].
9499
+ apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9500
+ }
9501
+ return this.each( function() {
9502
+ if ( typeof options === "string" ) {
9503
+ $.datepicker[ "_" + options + "Datepicker" ]
9504
+ .apply( $.datepicker, [ this ].concat( otherArgs ) );
9505
+ } else {
9506
+ $.datepicker._attachDatepicker( this, options );
9507
+ }
9508
+ } );
9509
+ };
9510
+
9511
+ $.datepicker = new Datepicker(); // singleton instance
9512
+ $.datepicker.initialized = false;
9513
+ $.datepicker.uuid = new Date().getTime();
9514
+ $.datepicker.version = "1.13.1";
9515
+
9516
+ var widgetsDatepicker = $.datepicker;
9517
+
9518
+
9519
+
9520
+ // This file is deprecated
9521
+ var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
9522
+
9523
+ /*!
9524
+ * jQuery UI Mouse 1.13.1
9525
+ * http://jqueryui.com
9526
+ *
9527
+ * Copyright jQuery Foundation and other contributors
9528
+ * Released under the MIT license.
9529
+ * http://jquery.org/license
9530
+ */
9531
+
9532
+ //>>label: Mouse
9533
+ //>>group: Widgets
9534
+ //>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9535
+ //>>docs: http://api.jqueryui.com/mouse/
9536
+
9537
+
9538
+ var mouseHandled = false;
9539
+ $( document ).on( "mouseup", function() {
9540
+ mouseHandled = false;
9541
+ } );
9542
+
9543
+ var widgetsMouse = $.widget( "ui.mouse", {
9544
+ version: "1.13.1",
9545
+ options: {
9546
+ cancel: "input, textarea, button, select, option",
9547
+ distance: 1,
9548
+ delay: 0
9549
+ },
9550
+ _mouseInit: function() {
9551
+ var that = this;
9552
+
9553
+ this.element
9554
+ .on( "mousedown." + this.widgetName, function( event ) {
9555
+ return that._mouseDown( event );
9556
+ } )
9557
+ .on( "click." + this.widgetName, function( event ) {
9558
+ if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9559
+ $.removeData( event.target, that.widgetName + ".preventClickEvent" );
9560
+ event.stopImmediatePropagation();
9561
+ return false;
9562
+ }
9563
+ } );
9564
+
9565
+ this.started = false;
9566
+ },
9567
+
9568
+ // TODO: make sure destroying one instance of mouse doesn't mess with
9569
+ // other instances of mouse
9570
+ _mouseDestroy: function() {
9571
+ this.element.off( "." + this.widgetName );
9572
+ if ( this._mouseMoveDelegate ) {
9573
+ this.document
9574
+ .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9575
+ .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9576
+ }
9577
+ },
9578
+
9579
+ _mouseDown: function( event ) {
9580
+
9581
+ // don't let more than one widget handle mouseStart
9582
+ if ( mouseHandled ) {
9583
+ return;
9584
+ }
9585
+
9586
+ this._mouseMoved = false;
9587
+
9588
+ // We may have missed mouseup (out of window)
9589
+ if ( this._mouseStarted ) {
9590
+ this._mouseUp( event );
9591
+ }
9592
+
9593
+ this._mouseDownEvent = event;
9594
+
9595
+ var that = this,
9596
+ btnIsLeft = ( event.which === 1 ),
9597
+
9598
+ // event.target.nodeName works around a bug in IE 8 with
9599
+ // disabled inputs (#7620)
9600
+ elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
9601
+ $( event.target ).closest( this.options.cancel ).length : false );
9602
+ if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9603
+ return true;
9604
+ }
9605
+
9606
+ this.mouseDelayMet = !this.options.delay;
9607
+ if ( !this.mouseDelayMet ) {
9608
+ this._mouseDelayTimer = setTimeout( function() {
9609
+ that.mouseDelayMet = true;
9610
+ }, this.options.delay );
9611
+ }
9612
+
9613
+ if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9614
+ this._mouseStarted = ( this._mouseStart( event ) !== false );
9615
+ if ( !this._mouseStarted ) {
9616
+ event.preventDefault();
9617
+ return true;
9618
+ }
9619
+ }
9620
+
9621
+ // Click event may never have fired (Gecko & Opera)
9622
+ if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9623
+ $.removeData( event.target, this.widgetName + ".preventClickEvent" );
9624
+ }
9625
+
9626
+ // These delegates are required to keep context
9627
+ this._mouseMoveDelegate = function( event ) {
9628
+ return that._mouseMove( event );
9629
+ };
9630
+ this._mouseUpDelegate = function( event ) {
9631
+ return that._mouseUp( event );
9632
+ };
9633
+
9634
+ this.document
9635
+ .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9636
+ .on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9637
+
9638
+ event.preventDefault();
9639
+
9640
+ mouseHandled = true;
9641
+ return true;
9642
+ },
9643
+
9644
+ _mouseMove: function( event ) {
9645
+
9646
+ // Only check for mouseups outside the document if you've moved inside the document
9647
+ // at least once. This prevents the firing of mouseup in the case of IE<9, which will
9648
+ // fire a mousemove event if content is placed under the cursor. See #7778
9649
+ // Support: IE <9
9650
+ if ( this._mouseMoved ) {
9651
+
9652
+ // IE mouseup check - mouseup happened when mouse was out of window
9653
+ if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
9654
+ !event.button ) {
9655
+ return this._mouseUp( event );
9656
+
9657
+ // Iframe mouseup check - mouseup occurred in another document
9658
+ } else if ( !event.which ) {
9659
+
9660
+ // Support: Safari <=8 - 9
9661
+ // Safari sets which to 0 if you press any of the following keys
9662
+ // during a drag (#14461)
9663
+ if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9664
+ event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9665
+ this.ignoreMissingWhich = true;
9666
+ } else if ( !this.ignoreMissingWhich ) {
9667
+ return this._mouseUp( event );
9668
+ }
9669
+ }
9670
+ }
9671
+
9672
+ if ( event.which || event.button ) {
9673
+ this._mouseMoved = true;
9674
+ }
9675
+
9676
+ if ( this._mouseStarted ) {
9677
+ this._mouseDrag( event );
9678
+ return event.preventDefault();
9679
+ }
9680
+
9681
+ if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9682
+ this._mouseStarted =
9683
+ ( this._mouseStart( this._mouseDownEvent, event ) !== false );
9684
+ if ( this._mouseStarted ) {
9685
+ this._mouseDrag( event );
9686
+ } else {
9687
+ this._mouseUp( event );
9688
+ }
9689
+ }
9690
+
9691
+ return !this._mouseStarted;
9692
+ },
9693
+
9694
+ _mouseUp: function( event ) {
9695
+ this.document
9696
+ .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9697
+ .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9698
+
9699
+ if ( this._mouseStarted ) {
9700
+ this._mouseStarted = false;
9701
+
9702
+ if ( event.target === this._mouseDownEvent.target ) {
9703
+ $.data( event.target, this.widgetName + ".preventClickEvent", true );
9704
+ }
9705
+
9706
+ this._mouseStop( event );
9707
+ }
9708
+
9709
+ if ( this._mouseDelayTimer ) {
9710
+ clearTimeout( this._mouseDelayTimer );
9711
+ delete this._mouseDelayTimer;
9712
+ }
9713
+
9714
+ this.ignoreMissingWhich = false;
9715
+ mouseHandled = false;
9716
+ event.preventDefault();
9717
+ },
9718
+
9719
+ _mouseDistanceMet: function( event ) {
9720
+ return ( Math.max(
9721
+ Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9722
+ Math.abs( this._mouseDownEvent.pageY - event.pageY )
9723
+ ) >= this.options.distance
9724
+ );
9725
+ },
9726
+
9727
+ _mouseDelayMet: function( /* event */ ) {
9728
+ return this.mouseDelayMet;
9729
+ },
9730
+
9731
+ // These are placeholder methods, to be overriden by extending plugin
9732
+ _mouseStart: function( /* event */ ) {},
9733
+ _mouseDrag: function( /* event */ ) {},
9734
+ _mouseStop: function( /* event */ ) {},
9735
+ _mouseCapture: function( /* event */ ) {
9736
+ return true;
9737
+ }
9738
+ } );
9739
+
9740
+
9741
+
9742
+ // $.ui.plugin is deprecated. Use $.widget() extensions instead.
9743
+ var plugin = $.ui.plugin = {
9744
+ add: function( module, option, set ) {
9745
+ var i,
9746
+ proto = $.ui[ module ].prototype;
9747
+ for ( i in set ) {
9748
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
9749
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
9750
+ }
9751
+ },
9752
+ call: function( instance, name, args, allowDisconnected ) {
9753
+ var i,
9754
+ set = instance.plugins[ name ];
9755
+
9756
+ if ( !set ) {
9757
+ return;
9758
+ }
9759
+
9760
+ if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9761
+ instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9762
+ return;
9763
+ }
9764
+
9765
+ for ( i = 0; i < set.length; i++ ) {
9766
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
9767
+ set[ i ][ 1 ].apply( instance.element, args );
9768
+ }
9769
+ }
9770
+ }
9771
+ };
9772
+
9773
+
9774
+
9775
+ var safeBlur = $.ui.safeBlur = function( element ) {
9776
+
9777
+ // Support: IE9 - 10 only
9778
+ // If the <body> is blurred, IE will switch windows, see #9420
9779
+ if ( element && element.nodeName.toLowerCase() !== "body" ) {
9780
+ $( element ).trigger( "blur" );
9781
+ }
9782
+ };
9783
+
9784
+
9785
+ /*!
9786
+ * jQuery UI Draggable 1.13.1
9787
+ * http://jqueryui.com
9788
+ *
9789
+ * Copyright jQuery Foundation and other contributors
9790
+ * Released under the MIT license.
9791
+ * http://jquery.org/license
9792
+ */
9793
+
9794
+ //>>label: Draggable
9795
+ //>>group: Interactions
9796
+ //>>description: Enables dragging functionality for any element.
9797
+ //>>docs: http://api.jqueryui.com/draggable/
9798
+ //>>demos: http://jqueryui.com/draggable/
9799
+ //>>css.structure: ../../themes/base/draggable.css
9800
+
9801
+
9802
+ $.widget( "ui.draggable", $.ui.mouse, {
9803
+ version: "1.13.1",
9804
+ widgetEventPrefix: "drag",
9805
+ options: {
9806
+ addClasses: true,
9807
+ appendTo: "parent",
9808
+ axis: false,
9809
+ connectToSortable: false,
9810
+ containment: false,
9811
+ cursor: "auto",
9812
+ cursorAt: false,
9813
+ grid: false,
9814
+ handle: false,
9815
+ helper: "original",
9816
+ iframeFix: false,
9817
+ opacity: false,
9818
+ refreshPositions: false,
9819
+ revert: false,
9820
+ revertDuration: 500,
9821
+ scope: "default",
9822
+ scroll: true,
9823
+ scrollSensitivity: 20,
9824
+ scrollSpeed: 20,
9825
+ snap: false,
9826
+ snapMode: "both",
9827
+ snapTolerance: 20,
9828
+ stack: false,
9829
+ zIndex: false,
9830
+
9831
+ // Callbacks
9832
+ drag: null,
9833
+ start: null,
9834
+ stop: null
9835
+ },
9836
+ _create: function() {
9837
+
9838
+ if ( this.options.helper === "original" ) {
9839
+ this._setPositionRelative();
9840
+ }
9841
+ if ( this.options.addClasses ) {
9842
+ this._addClass( "ui-draggable" );
9843
+ }
9844
+ this._setHandleClassName();
9845
+
9846
+ this._mouseInit();
9847
+ },
9848
+
9849
+ _setOption: function( key, value ) {
9850
+ this._super( key, value );
9851
+ if ( key === "handle" ) {
9852
+ this._removeHandleClassName();
9853
+ this._setHandleClassName();
9854
+ }
9855
+ },
9856
+
9857
+ _destroy: function() {
9858
+ if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9859
+ this.destroyOnClear = true;
9860
+ return;
9861
+ }
9862
+ this._removeHandleClassName();
9863
+ this._mouseDestroy();
9864
+ },
9865
+
9866
+ _mouseCapture: function( event ) {
9867
+ var o = this.options;
9868
+
9869
+ // Among others, prevent a drag on a resizable-handle
9870
+ if ( this.helper || o.disabled ||
9871
+ $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9872
+ return false;
9873
+ }
9874
+
9875
+ //Quit if we're not on a valid handle
9876
+ this.handle = this._getHandle( event );
9877
+ if ( !this.handle ) {
9878
+ return false;
9879
+ }
9880
+
9881
+ this._blurActiveElement( event );
9882
+
9883
+ this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9884
+
9885
+ return true;
9886
+
9887
+ },
9888
+
9889
+ _blockFrames: function( selector ) {
9890
+ this.iframeBlocks = this.document.find( selector ).map( function() {
9891
+ var iframe = $( this );
9892
+
9893
+ return $( "<div>" )
9894
+ .css( "position", "absolute" )
9895
+ .appendTo( iframe.parent() )
9896
+ .outerWidth( iframe.outerWidth() )
9897
+ .outerHeight( iframe.outerHeight() )
9898
+ .offset( iframe.offset() )[ 0 ];
9899
+ } );
9900
+ },
9901
+
9902
+ _unblockFrames: function() {
9903
+ if ( this.iframeBlocks ) {
9904
+ this.iframeBlocks.remove();
9905
+ delete this.iframeBlocks;
9906
+ }
9907
+ },
9908
+
9909
+ _blurActiveElement: function( event ) {
9910
+ var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
9911
+ target = $( event.target );
9912
+
9913
+ // Don't blur if the event occurred on an element that is within
9914
+ // the currently focused element
9915
+ // See #10527, #12472
9916
+ if ( target.closest( activeElement ).length ) {
9917
+ return;
9918
+ }
9919
+
9920
+ // Blur any element that currently has focus, see #4261
9921
+ $.ui.safeBlur( activeElement );
9922
+ },
9923
+
9924
+ _mouseStart: function( event ) {
9925
+
9926
+ var o = this.options;
9927
+
9928
+ //Create and append the visible helper
9929
+ this.helper = this._createHelper( event );
9930
+
9931
+ this._addClass( this.helper, "ui-draggable-dragging" );
9932
+
9933
+ //Cache the helper size
9934
+ this._cacheHelperProportions();
9935
+
9936
+ //If ddmanager is used for droppables, set the global draggable
9937
+ if ( $.ui.ddmanager ) {
9938
+ $.ui.ddmanager.current = this;
9939
+ }
9940
+
9941
+ /*
9942
+ * - Position generation -
9943
+ * This block generates everything position related - it's the core of draggables.
9944
+ */
9945
+
9946
+ //Cache the margins of the original element
9947
+ this._cacheMargins();
9948
+
9949
+ //Store the helper's css position
9950
+ this.cssPosition = this.helper.css( "position" );
9951
+ this.scrollParent = this.helper.scrollParent( true );
9952
+ this.offsetParent = this.helper.offsetParent();
9953
+ this.hasFixedAncestor = this.helper.parents().filter( function() {
9954
+ return $( this ).css( "position" ) === "fixed";
9955
+ } ).length > 0;
9956
+
9957
+ //The element's absolute position on the page minus margins
9958
+ this.positionAbs = this.element.offset();
9959
+ this._refreshOffsets( event );
9960
+
9961
+ //Generate the original position
9962
+ this.originalPosition = this.position = this._generatePosition( event, false );
9963
+ this.originalPageX = event.pageX;
9964
+ this.originalPageY = event.pageY;
9965
+
9966
+ //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9967
+ if ( o.cursorAt ) {
9968
+ this._adjustOffsetFromHelper( o.cursorAt );
9969
+ }
9970
+
9971
+ //Set a containment if given in the options
9972
+ this._setContainment();
9973
+
9974
+ //Trigger event + callbacks
9975
+ if ( this._trigger( "start", event ) === false ) {
9976
+ this._clear();
9977
+ return false;
9978
+ }
9979
+
9980
+ //Recache the helper size
9981
+ this._cacheHelperProportions();
9982
+
9983
+ //Prepare the droppable offsets
9984
+ if ( $.ui.ddmanager && !o.dropBehaviour ) {
9985
+ $.ui.ddmanager.prepareOffsets( this, event );
9986
+ }
9987
+
9988
+ // Execute the drag once - this causes the helper not to be visible before getting its
9989
+ // correct position
9990
+ this._mouseDrag( event, true );
9991
+
9992
+ // If the ddmanager is used for droppables, inform the manager that dragging has started
9993
+ // (see #5003)
9994
+ if ( $.ui.ddmanager ) {
9995
+ $.ui.ddmanager.dragStart( this, event );
9996
+ }
9997
+
9998
+ return true;
9999
+ },
10000
+
10001
+ _refreshOffsets: function( event ) {
10002
+ this.offset = {
10003
+ top: this.positionAbs.top - this.margins.top,
10004
+ left: this.positionAbs.left - this.margins.left,
10005
+ scroll: false,
10006
+ parent: this._getParentOffset(),
10007
+ relative: this._getRelativeOffset()
10008
+ };
10009
+
10010
+ this.offset.click = {
10011
+ left: event.pageX - this.offset.left,
10012
+ top: event.pageY - this.offset.top
10013
+ };
10014
+ },
10015
+
10016
+ _mouseDrag: function( event, noPropagation ) {
10017
+
10018
+ // reset any necessary cached properties (see #5009)
10019
+ if ( this.hasFixedAncestor ) {
10020
+ this.offset.parent = this._getParentOffset();
10021
+ }
10022
+
10023
+ //Compute the helpers position
10024
+ this.position = this._generatePosition( event, true );
10025
+ this.positionAbs = this._convertPositionTo( "absolute" );
10026
+
10027
+ //Call plugins and callbacks and use the resulting position if something is returned
10028
+ if ( !noPropagation ) {
10029
+ var ui = this._uiHash();
10030
+ if ( this._trigger( "drag", event, ui ) === false ) {
10031
+ this._mouseUp( new $.Event( "mouseup", event ) );
10032
+ return false;
10033
+ }
10034
+ this.position = ui.position;
10035
+ }
10036
+
10037
+ this.helper[ 0 ].style.left = this.position.left + "px";
10038
+ this.helper[ 0 ].style.top = this.position.top + "px";
10039
+
10040
+ if ( $.ui.ddmanager ) {
10041
+ $.ui.ddmanager.drag( this, event );
10042
+ }
10043
+
10044
+ return false;
10045
+ },
10046
+
10047
+ _mouseStop: function( event ) {
10048
+
10049
+ //If we are using droppables, inform the manager about the drop
10050
+ var that = this,
10051
+ dropped = false;
10052
+ if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
10053
+ dropped = $.ui.ddmanager.drop( this, event );
10054
+ }
10055
+
10056
+ //if a drop comes from outside (a sortable)
10057
+ if ( this.dropped ) {
10058
+ dropped = this.dropped;
10059
+ this.dropped = false;
10060
+ }
10061
+
10062
+ if ( ( this.options.revert === "invalid" && !dropped ) ||
10063
+ ( this.options.revert === "valid" && dropped ) ||
10064
+ this.options.revert === true || ( typeof this.options.revert === "function" &&
10065
+ this.options.revert.call( this.element, dropped ) )
10066
+ ) {
10067
+ $( this.helper ).animate(
10068
+ this.originalPosition,
10069
+ parseInt( this.options.revertDuration, 10 ),
10070
+ function() {
10071
+ if ( that._trigger( "stop", event ) !== false ) {
10072
+ that._clear();
10073
+ }
10074
+ }
10075
+ );
10076
+ } else {
10077
+ if ( this._trigger( "stop", event ) !== false ) {
10078
+ this._clear();
10079
+ }
10080
+ }
10081
+
10082
+ return false;
10083
+ },
10084
+
10085
+ _mouseUp: function( event ) {
10086
+ this._unblockFrames();
10087
+
10088
+ // If the ddmanager is used for droppables, inform the manager that dragging has stopped
10089
+ // (see #5003)
10090
+ if ( $.ui.ddmanager ) {
10091
+ $.ui.ddmanager.dragStop( this, event );
10092
+ }
10093
+
10094
+ // Only need to focus if the event occurred on the draggable itself, see #10527
10095
+ if ( this.handleElement.is( event.target ) ) {
10096
+
10097
+ // The interaction is over; whether or not the click resulted in a drag,
10098
+ // focus the element
10099
+ this.element.trigger( "focus" );
10100
+ }
10101
+
10102
+ return $.ui.mouse.prototype._mouseUp.call( this, event );
10103
+ },
10104
+
10105
+ cancel: function() {
10106
+
10107
+ if ( this.helper.is( ".ui-draggable-dragging" ) ) {
10108
+ this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
10109
+ } else {
10110
+ this._clear();
10111
+ }
10112
+
10113
+ return this;
10114
+
10115
+ },
10116
+
10117
+ _getHandle: function( event ) {
10118
+ return this.options.handle ?
10119
+ !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
10120
+ true;
10121
+ },
10122
+
10123
+ _setHandleClassName: function() {
10124
+ this.handleElement = this.options.handle ?
10125
+ this.element.find( this.options.handle ) : this.element;
10126
+ this._addClass( this.handleElement, "ui-draggable-handle" );
10127
+ },
10128
+
10129
+ _removeHandleClassName: function() {
10130
+ this._removeClass( this.handleElement, "ui-draggable-handle" );
10131
+ },
10132
+
10133
+ _createHelper: function( event ) {
10134
+
10135
+ var o = this.options,
10136
+ helperIsFunction = typeof o.helper === "function",
10137
+ helper = helperIsFunction ?
10138
+ $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
10139
+ ( o.helper === "clone" ?
10140
+ this.element.clone().removeAttr( "id" ) :
10141
+ this.element );
10142
+
10143
+ if ( !helper.parents( "body" ).length ) {
10144
+ helper.appendTo( ( o.appendTo === "parent" ?
10145
+ this.element[ 0 ].parentNode :
10146
+ o.appendTo ) );
10147
+ }
10148
+
10149
+ // Http://bugs.jqueryui.com/ticket/9446
10150
+ // a helper function can return the original element
10151
+ // which wouldn't have been set to relative in _create
10152
+ if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
10153
+ this._setPositionRelative();
10154
+ }
10155
+
10156
+ if ( helper[ 0 ] !== this.element[ 0 ] &&
10157
+ !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
10158
+ helper.css( "position", "absolute" );
10159
+ }
10160
+
10161
+ return helper;
10162
+
10163
+ },
10164
+
10165
+ _setPositionRelative: function() {
10166
+ if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
10167
+ this.element[ 0 ].style.position = "relative";
10168
+ }
10169
+ },
10170
+
10171
+ _adjustOffsetFromHelper: function( obj ) {
10172
+ if ( typeof obj === "string" ) {
10173
+ obj = obj.split( " " );
10174
+ }
10175
+ if ( Array.isArray( obj ) ) {
10176
+ obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
10177
+ }
10178
+ if ( "left" in obj ) {
10179
+ this.offset.click.left = obj.left + this.margins.left;
10180
+ }
10181
+ if ( "right" in obj ) {
10182
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
10183
+ }
10184
+ if ( "top" in obj ) {
10185
+ this.offset.click.top = obj.top + this.margins.top;
10186
+ }
10187
+ if ( "bottom" in obj ) {
10188
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
10189
+ }
10190
+ },
10191
+
10192
+ _isRootNode: function( element ) {
10193
+ return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
10194
+ },
10195
+
10196
+ _getParentOffset: function() {
10197
+
10198
+ //Get the offsetParent and cache its position
10199
+ var po = this.offsetParent.offset(),
10200
+ document = this.document[ 0 ];
10201
+
10202
+ // This is a special case where we need to modify a offset calculated on start, since the
10203
+ // following happened:
10204
+ // 1. The position of the helper is absolute, so it's position is calculated based on the
10205
+ // next positioned parent
10206
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10207
+ // the document, which means that the scroll is included in the initial calculation of the
10208
+ // offset of the parent, and never recalculated upon drag
10209
+ if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10210
+ $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10211
+ po.left += this.scrollParent.scrollLeft();
10212
+ po.top += this.scrollParent.scrollTop();
10213
+ }
10214
+
10215
+ if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10216
+ po = { top: 0, left: 0 };
10217
+ }
10218
+
10219
+ return {
10220
+ top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10221
+ left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10222
+ };
10223
+
10224
+ },
10225
+
10226
+ _getRelativeOffset: function() {
10227
+ if ( this.cssPosition !== "relative" ) {
10228
+ return { top: 0, left: 0 };
10229
+ }
10230
+
10231
+ var p = this.element.position(),
10232
+ scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10233
+
10234
+ return {
10235
+ top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10236
+ ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10237
+ left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10238
+ ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10239
+ };
10240
+
10241
+ },
10242
+
10243
+ _cacheMargins: function() {
10244
+ this.margins = {
10245
+ left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10246
+ top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10247
+ right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10248
+ bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10249
+ };
10250
+ },
10251
+
10252
+ _cacheHelperProportions: function() {
10253
+ this.helperProportions = {
10254
+ width: this.helper.outerWidth(),
10255
+ height: this.helper.outerHeight()
10256
+ };
10257
+ },
10258
+
10259
+ _setContainment: function() {
10260
+
10261
+ var isUserScrollable, c, ce,
10262
+ o = this.options,
10263
+ document = this.document[ 0 ];
10264
+
10265
+ this.relativeContainer = null;
10266
+
10267
+ if ( !o.containment ) {
10268
+ this.containment = null;
10269
+ return;
10270
+ }
10271
+
10272
+ if ( o.containment === "window" ) {
10273
+ this.containment = [
10274
+ $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10275
+ $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10276
+ $( window ).scrollLeft() + $( window ).width() -
10277
+ this.helperProportions.width - this.margins.left,
10278
+ $( window ).scrollTop() +
10279
+ ( $( window ).height() || document.body.parentNode.scrollHeight ) -
10280
+ this.helperProportions.height - this.margins.top
10281
+ ];
10282
+ return;
10283
+ }
10284
+
10285
+ if ( o.containment === "document" ) {
10286
+ this.containment = [
10287
+ 0,
10288
+ 0,
10289
+ $( document ).width() - this.helperProportions.width - this.margins.left,
10290
+ ( $( document ).height() || document.body.parentNode.scrollHeight ) -
10291
+ this.helperProportions.height - this.margins.top
10292
+ ];
10293
+ return;
10294
+ }
10295
+
10296
+ if ( o.containment.constructor === Array ) {
10297
+ this.containment = o.containment;
10298
+ return;
10299
+ }
10300
+
10301
+ if ( o.containment === "parent" ) {
10302
+ o.containment = this.helper[ 0 ].parentNode;
10303
+ }
10304
+
10305
+ c = $( o.containment );
10306
+ ce = c[ 0 ];
10307
+
10308
+ if ( !ce ) {
10309
+ return;
10310
+ }
10311
+
10312
+ isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10313
+
10314
+ this.containment = [
10315
+ ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10316
+ ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10317
+ ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10318
+ ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10319
+ ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10320
+ ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10321
+ ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10322
+ this.helperProportions.width -
10323
+ this.margins.left -
10324
+ this.margins.right,
10325
+ ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10326
+ ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10327
+ ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10328
+ this.helperProportions.height -
10329
+ this.margins.top -
10330
+ this.margins.bottom
10331
+ ];
10332
+ this.relativeContainer = c;
10333
+ },
10334
+
10335
+ _convertPositionTo: function( d, pos ) {
10336
+
10337
+ if ( !pos ) {
10338
+ pos = this.position;
10339
+ }
10340
+
10341
+ var mod = d === "absolute" ? 1 : -1,
10342
+ scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10343
+
10344
+ return {
10345
+ top: (
10346
+
10347
+ // The absolute mouse position
10348
+ pos.top +
10349
+
10350
+ // Only for relative positioned nodes: Relative offset from element to offset parent
10351
+ this.offset.relative.top * mod +
10352
+
10353
+ // The offsetParent's offset without borders (offset + border)
10354
+ this.offset.parent.top * mod -
10355
+ ( ( this.cssPosition === "fixed" ?
10356
+ -this.offset.scroll.top :
10357
+ ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10358
+ ),
10359
+ left: (
10360
+
10361
+ // The absolute mouse position
10362
+ pos.left +
10363
+
10364
+ // Only for relative positioned nodes: Relative offset from element to offset parent
10365
+ this.offset.relative.left * mod +
10366
+
10367
+ // The offsetParent's offset without borders (offset + border)
10368
+ this.offset.parent.left * mod -
10369
+ ( ( this.cssPosition === "fixed" ?
10370
+ -this.offset.scroll.left :
10371
+ ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10372
+ )
10373
+ };
10374
+
10375
+ },
10376
+
10377
+ _generatePosition: function( event, constrainPosition ) {
10378
+
10379
+ var containment, co, top, left,
10380
+ o = this.options,
10381
+ scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10382
+ pageX = event.pageX,
10383
+ pageY = event.pageY;
10384
+
10385
+ // Cache the scroll
10386
+ if ( !scrollIsRootNode || !this.offset.scroll ) {
10387
+ this.offset.scroll = {
10388
+ top: this.scrollParent.scrollTop(),
10389
+ left: this.scrollParent.scrollLeft()
10390
+ };
10391
+ }
10392
+
10393
+ /*
10394
+ * - Position constraining -
10395
+ * Constrain the position to a mix of grid, containment.
10396
+ */
10397
+
10398
+ // If we are not dragging yet, we won't check for options
10399
+ if ( constrainPosition ) {
10400
+ if ( this.containment ) {
10401
+ if ( this.relativeContainer ) {
10402
+ co = this.relativeContainer.offset();
10403
+ containment = [
10404
+ this.containment[ 0 ] + co.left,
10405
+ this.containment[ 1 ] + co.top,
10406
+ this.containment[ 2 ] + co.left,
10407
+ this.containment[ 3 ] + co.top
10408
+ ];
10409
+ } else {
10410
+ containment = this.containment;
10411
+ }
10412
+
10413
+ if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10414
+ pageX = containment[ 0 ] + this.offset.click.left;
10415
+ }
10416
+ if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10417
+ pageY = containment[ 1 ] + this.offset.click.top;
10418
+ }
10419
+ if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10420
+ pageX = containment[ 2 ] + this.offset.click.left;
10421
+ }
10422
+ if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10423
+ pageY = containment[ 3 ] + this.offset.click.top;
10424
+ }
10425
+ }
10426
+
10427
+ if ( o.grid ) {
10428
+
10429
+ //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10430
+ // argument errors in IE (see ticket #6950)
10431
+ top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10432
+ this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10433
+ pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10434
+ top - this.offset.click.top > containment[ 3 ] ) ?
10435
+ top :
10436
+ ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10437
+ top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10438
+
10439
+ left = o.grid[ 0 ] ? this.originalPageX +
10440
+ Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10441
+ this.originalPageX;
10442
+ pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10443
+ left - this.offset.click.left > containment[ 2 ] ) ?
10444
+ left :
10445
+ ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10446
+ left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10447
+ }
10448
+
10449
+ if ( o.axis === "y" ) {
10450
+ pageX = this.originalPageX;
10451
+ }
10452
+
10453
+ if ( o.axis === "x" ) {
10454
+ pageY = this.originalPageY;
10455
+ }
10456
+ }
10457
+
10458
+ return {
10459
+ top: (
10460
+
10461
+ // The absolute mouse position
10462
+ pageY -
10463
+
10464
+ // Click offset (relative to the element)
10465
+ this.offset.click.top -
10466
+
10467
+ // Only for relative positioned nodes: Relative offset from element to offset parent
10468
+ this.offset.relative.top -
10469
+
10470
+ // The offsetParent's offset without borders (offset + border)
10471
+ this.offset.parent.top +
10472
+ ( this.cssPosition === "fixed" ?
10473
+ -this.offset.scroll.top :
10474
+ ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10475
+ ),
10476
+ left: (
10477
+
10478
+ // The absolute mouse position
10479
+ pageX -
10480
+
10481
+ // Click offset (relative to the element)
10482
+ this.offset.click.left -
10483
+
10484
+ // Only for relative positioned nodes: Relative offset from element to offset parent
10485
+ this.offset.relative.left -
10486
+
10487
+ // The offsetParent's offset without borders (offset + border)
10488
+ this.offset.parent.left +
10489
+ ( this.cssPosition === "fixed" ?
10490
+ -this.offset.scroll.left :
10491
+ ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10492
+ )
10493
+ };
10494
+
10495
+ },
10496
+
10497
+ _clear: function() {
10498
+ this._removeClass( this.helper, "ui-draggable-dragging" );
10499
+ if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10500
+ this.helper.remove();
10501
+ }
10502
+ this.helper = null;
10503
+ this.cancelHelperRemoval = false;
10504
+ if ( this.destroyOnClear ) {
10505
+ this.destroy();
10506
+ }
10507
+ },
10508
+
10509
+ // From now on bulk stuff - mainly helpers
10510
+
10511
+ _trigger: function( type, event, ui ) {
10512
+ ui = ui || this._uiHash();
10513
+ $.ui.plugin.call( this, type, [ event, ui, this ], true );
10514
+
10515
+ // Absolute position and offset (see #6884 ) have to be recalculated after plugins
10516
+ if ( /^(drag|start|stop)/.test( type ) ) {
10517
+ this.positionAbs = this._convertPositionTo( "absolute" );
10518
+ ui.offset = this.positionAbs;
10519
+ }
10520
+ return $.Widget.prototype._trigger.call( this, type, event, ui );
10521
+ },
10522
+
10523
+ plugins: {},
10524
+
10525
+ _uiHash: function() {
10526
+ return {
10527
+ helper: this.helper,
10528
+ position: this.position,
10529
+ originalPosition: this.originalPosition,
10530
+ offset: this.positionAbs
10531
+ };
10532
+ }
10533
+
10534
+ } );
10535
+
10536
+ $.ui.plugin.add( "draggable", "connectToSortable", {
10537
+ start: function( event, ui, draggable ) {
10538
+ var uiSortable = $.extend( {}, ui, {
10539
+ item: draggable.element
10540
+ } );
10541
+
10542
+ draggable.sortables = [];
10543
+ $( draggable.options.connectToSortable ).each( function() {
10544
+ var sortable = $( this ).sortable( "instance" );
10545
+
10546
+ if ( sortable && !sortable.options.disabled ) {
10547
+ draggable.sortables.push( sortable );
10548
+
10549
+ // RefreshPositions is called at drag start to refresh the containerCache
10550
+ // which is used in drag. This ensures it's initialized and synchronized
10551
+ // with any changes that might have happened on the page since initialization.
10552
+ sortable.refreshPositions();
10553
+ sortable._trigger( "activate", event, uiSortable );
10554
+ }
10555
+ } );
10556
+ },
10557
+ stop: function( event, ui, draggable ) {
10558
+ var uiSortable = $.extend( {}, ui, {
10559
+ item: draggable.element
10560
+ } );
10561
+
10562
+ draggable.cancelHelperRemoval = false;
10563
+
10564
+ $.each( draggable.sortables, function() {
10565
+ var sortable = this;
10566
+
10567
+ if ( sortable.isOver ) {
10568
+ sortable.isOver = 0;
10569
+
10570
+ // Allow this sortable to handle removing the helper
10571
+ draggable.cancelHelperRemoval = true;
10572
+ sortable.cancelHelperRemoval = false;
10573
+
10574
+ // Use _storedCSS To restore properties in the sortable,
10575
+ // as this also handles revert (#9675) since the draggable
10576
+ // may have modified them in unexpected ways (#8809)
10577
+ sortable._storedCSS = {
10578
+ position: sortable.placeholder.css( "position" ),
10579
+ top: sortable.placeholder.css( "top" ),
10580
+ left: sortable.placeholder.css( "left" )
10581
+ };
10582
+
10583
+ sortable._mouseStop( event );
10584
+
10585
+ // Once drag has ended, the sortable should return to using
10586
+ // its original helper, not the shared helper from draggable
10587
+ sortable.options.helper = sortable.options._helper;
10588
+ } else {
10589
+
10590
+ // Prevent this Sortable from removing the helper.
10591
+ // However, don't set the draggable to remove the helper
10592
+ // either as another connected Sortable may yet handle the removal.
10593
+ sortable.cancelHelperRemoval = true;
10594
+
10595
+ sortable._trigger( "deactivate", event, uiSortable );
10596
+ }
10597
+ } );
10598
+ },
10599
+ drag: function( event, ui, draggable ) {
10600
+ $.each( draggable.sortables, function() {
10601
+ var innermostIntersecting = false,
10602
+ sortable = this;
10603
+
10604
+ // Copy over variables that sortable's _intersectsWith uses
10605
+ sortable.positionAbs = draggable.positionAbs;
10606
+ sortable.helperProportions = draggable.helperProportions;
10607
+ sortable.offset.click = draggable.offset.click;
10608
+
10609
+ if ( sortable._intersectsWith( sortable.containerCache ) ) {
10610
+ innermostIntersecting = true;
10611
+
10612
+ $.each( draggable.sortables, function() {
10613
+
10614
+ // Copy over variables that sortable's _intersectsWith uses
10615
+ this.positionAbs = draggable.positionAbs;
10616
+ this.helperProportions = draggable.helperProportions;
10617
+ this.offset.click = draggable.offset.click;
10618
+
10619
+ if ( this !== sortable &&
10620
+ this._intersectsWith( this.containerCache ) &&
10621
+ $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10622
+ innermostIntersecting = false;
10623
+ }
10624
+
10625
+ return innermostIntersecting;
10626
+ } );
10627
+ }
10628
+
10629
+ if ( innermostIntersecting ) {
10630
+
10631
+ // If it intersects, we use a little isOver variable and set it once,
10632
+ // so that the move-in stuff gets fired only once.
10633
+ if ( !sortable.isOver ) {
10634
+ sortable.isOver = 1;
10635
+
10636
+ // Store draggable's parent in case we need to reappend to it later.
10637
+ draggable._parent = ui.helper.parent();
10638
+
10639
+ sortable.currentItem = ui.helper
10640
+ .appendTo( sortable.element )
10641
+ .data( "ui-sortable-item", true );
10642
+
10643
+ // Store helper option to later restore it
10644
+ sortable.options._helper = sortable.options.helper;
10645
+
10646
+ sortable.options.helper = function() {
10647
+ return ui.helper[ 0 ];
10648
+ };
10649
+
10650
+ // Fire the start events of the sortable with our passed browser event,
10651
+ // and our own helper (so it doesn't create a new one)
10652
+ event.target = sortable.currentItem[ 0 ];
10653
+ sortable._mouseCapture( event, true );
10654
+ sortable._mouseStart( event, true, true );
10655
+
10656
+ // Because the browser event is way off the new appended portlet,
10657
+ // modify necessary variables to reflect the changes
10658
+ sortable.offset.click.top = draggable.offset.click.top;
10659
+ sortable.offset.click.left = draggable.offset.click.left;
10660
+ sortable.offset.parent.left -= draggable.offset.parent.left -
10661
+ sortable.offset.parent.left;
10662
+ sortable.offset.parent.top -= draggable.offset.parent.top -
10663
+ sortable.offset.parent.top;
10664
+
10665
+ draggable._trigger( "toSortable", event );
10666
+
10667
+ // Inform draggable that the helper is in a valid drop zone,
10668
+ // used solely in the revert option to handle "valid/invalid".
10669
+ draggable.dropped = sortable.element;
10670
+
10671
+ // Need to refreshPositions of all sortables in the case that
10672
+ // adding to one sortable changes the location of the other sortables (#9675)
10673
+ $.each( draggable.sortables, function() {
10674
+ this.refreshPositions();
10675
+ } );
10676
+
10677
+ // Hack so receive/update callbacks work (mostly)
10678
+ draggable.currentItem = draggable.element;
10679
+ sortable.fromOutside = draggable;
10680
+ }
10681
+
10682
+ if ( sortable.currentItem ) {
10683
+ sortable._mouseDrag( event );
10684
+
10685
+ // Copy the sortable's position because the draggable's can potentially reflect
10686
+ // a relative position, while sortable is always absolute, which the dragged
10687
+ // element has now become. (#8809)
10688
+ ui.position = sortable.position;
10689
+ }
10690
+ } else {
10691
+
10692
+ // If it doesn't intersect with the sortable, and it intersected before,
10693
+ // we fake the drag stop of the sortable, but make sure it doesn't remove
10694
+ // the helper by using cancelHelperRemoval.
10695
+ if ( sortable.isOver ) {
10696
+
10697
+ sortable.isOver = 0;
10698
+ sortable.cancelHelperRemoval = true;
10699
+
10700
+ // Calling sortable's mouseStop would trigger a revert,
10701
+ // so revert must be temporarily false until after mouseStop is called.
10702
+ sortable.options._revert = sortable.options.revert;
10703
+ sortable.options.revert = false;
10704
+
10705
+ sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10706
+ sortable._mouseStop( event, true );
10707
+
10708
+ // Restore sortable behaviors that were modfied
10709
+ // when the draggable entered the sortable area (#9481)
10710
+ sortable.options.revert = sortable.options._revert;
10711
+ sortable.options.helper = sortable.options._helper;
10712
+
10713
+ if ( sortable.placeholder ) {
10714
+ sortable.placeholder.remove();
10715
+ }
10716
+
10717
+ // Restore and recalculate the draggable's offset considering the sortable
10718
+ // may have modified them in unexpected ways. (#8809, #10669)
10719
+ ui.helper.appendTo( draggable._parent );
10720
+ draggable._refreshOffsets( event );
10721
+ ui.position = draggable._generatePosition( event, true );
10722
+
10723
+ draggable._trigger( "fromSortable", event );
10724
+
10725
+ // Inform draggable that the helper is no longer in a valid drop zone
10726
+ draggable.dropped = false;
10727
+
10728
+ // Need to refreshPositions of all sortables just in case removing
10729
+ // from one sortable changes the location of other sortables (#9675)
10730
+ $.each( draggable.sortables, function() {
10731
+ this.refreshPositions();
10732
+ } );
10733
+ }
10734
+ }
10735
+ } );
10736
+ }
10737
+ } );
10738
+
10739
+ $.ui.plugin.add( "draggable", "cursor", {
10740
+ start: function( event, ui, instance ) {
10741
+ var t = $( "body" ),
10742
+ o = instance.options;
10743
+
10744
+ if ( t.css( "cursor" ) ) {
10745
+ o._cursor = t.css( "cursor" );
10746
+ }
10747
+ t.css( "cursor", o.cursor );
10748
+ },
10749
+ stop: function( event, ui, instance ) {
10750
+ var o = instance.options;
10751
+ if ( o._cursor ) {
10752
+ $( "body" ).css( "cursor", o._cursor );
10753
+ }
10754
+ }
10755
+ } );
10756
+
10757
+ $.ui.plugin.add( "draggable", "opacity", {
10758
+ start: function( event, ui, instance ) {
10759
+ var t = $( ui.helper ),
10760
+ o = instance.options;
10761
+ if ( t.css( "opacity" ) ) {
10762
+ o._opacity = t.css( "opacity" );
10763
+ }
10764
+ t.css( "opacity", o.opacity );
10765
+ },
10766
+ stop: function( event, ui, instance ) {
10767
+ var o = instance.options;
10768
+ if ( o._opacity ) {
10769
+ $( ui.helper ).css( "opacity", o._opacity );
10770
+ }
10771
+ }
10772
+ } );
10773
+
10774
+ $.ui.plugin.add( "draggable", "scroll", {
10775
+ start: function( event, ui, i ) {
10776
+ if ( !i.scrollParentNotHidden ) {
10777
+ i.scrollParentNotHidden = i.helper.scrollParent( false );
10778
+ }
10779
+
10780
+ if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10781
+ i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10782
+ i.overflowOffset = i.scrollParentNotHidden.offset();
10783
+ }
10784
+ },
10785
+ drag: function( event, ui, i ) {
10786
+
10787
+ var o = i.options,
10788
+ scrolled = false,
10789
+ scrollParent = i.scrollParentNotHidden[ 0 ],
10790
+ document = i.document[ 0 ];
10791
+
10792
+ if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10793
+ if ( !o.axis || o.axis !== "x" ) {
10794
+ if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10795
+ o.scrollSensitivity ) {
10796
+ scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10797
+ } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10798
+ scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10799
+ }
10800
+ }
10801
+
10802
+ if ( !o.axis || o.axis !== "y" ) {
10803
+ if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10804
+ o.scrollSensitivity ) {
10805
+ scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10806
+ } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10807
+ scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10808
+ }
10809
+ }
10810
+
10811
+ } else {
10812
+
10813
+ if ( !o.axis || o.axis !== "x" ) {
10814
+ if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10815
+ scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10816
+ } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10817
+ o.scrollSensitivity ) {
10818
+ scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10819
+ }
10820
+ }
10821
+
10822
+ if ( !o.axis || o.axis !== "y" ) {
10823
+ if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10824
+ scrolled = $( document ).scrollLeft(
10825
+ $( document ).scrollLeft() - o.scrollSpeed
10826
+ );
10827
+ } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10828
+ o.scrollSensitivity ) {
10829
+ scrolled = $( document ).scrollLeft(
10830
+ $( document ).scrollLeft() + o.scrollSpeed
10831
+ );
10832
+ }
10833
+ }
10834
+
10835
+ }
10836
+
10837
+ if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10838
+ $.ui.ddmanager.prepareOffsets( i, event );
10839
+ }
10840
+
10841
+ }
10842
+ } );
10843
+
10844
+ $.ui.plugin.add( "draggable", "snap", {
10845
+ start: function( event, ui, i ) {
10846
+
10847
+ var o = i.options;
10848
+
10849
+ i.snapElements = [];
10850
+
10851
+ $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10852
+ .each( function() {
10853
+ var $t = $( this ),
10854
+ $o = $t.offset();
10855
+ if ( this !== i.element[ 0 ] ) {
10856
+ i.snapElements.push( {
10857
+ item: this,
10858
+ width: $t.outerWidth(), height: $t.outerHeight(),
10859
+ top: $o.top, left: $o.left
10860
+ } );
10861
+ }
10862
+ } );
10863
+
10864
+ },
10865
+ drag: function( event, ui, inst ) {
10866
+
10867
+ var ts, bs, ls, rs, l, r, t, b, i, first,
10868
+ o = inst.options,
10869
+ d = o.snapTolerance,
10870
+ x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10871
+ y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10872
+
10873
+ for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10874
+
10875
+ l = inst.snapElements[ i ].left - inst.margins.left;
10876
+ r = l + inst.snapElements[ i ].width;
10877
+ t = inst.snapElements[ i ].top - inst.margins.top;
10878
+ b = t + inst.snapElements[ i ].height;
10879
+
10880
+ if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10881
+ !$.contains( inst.snapElements[ i ].item.ownerDocument,
10882
+ inst.snapElements[ i ].item ) ) {
10883
+ if ( inst.snapElements[ i ].snapping ) {
10884
+ if ( inst.options.snap.release ) {
10885
+ inst.options.snap.release.call(
10886
+ inst.element,
10887
+ event,
10888
+ $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10889
+ );
10890
+ }
10891
+ }
10892
+ inst.snapElements[ i ].snapping = false;
10893
+ continue;
10894
+ }
10895
+
10896
+ if ( o.snapMode !== "inner" ) {
10897
+ ts = Math.abs( t - y2 ) <= d;
10898
+ bs = Math.abs( b - y1 ) <= d;
10899
+ ls = Math.abs( l - x2 ) <= d;
10900
+ rs = Math.abs( r - x1 ) <= d;
10901
+ if ( ts ) {
10902
+ ui.position.top = inst._convertPositionTo( "relative", {
10903
+ top: t - inst.helperProportions.height,
10904
+ left: 0
10905
+ } ).top;
10906
+ }
10907
+ if ( bs ) {
10908
+ ui.position.top = inst._convertPositionTo( "relative", {
10909
+ top: b,
10910
+ left: 0
10911
+ } ).top;
10912
+ }
10913
+ if ( ls ) {
10914
+ ui.position.left = inst._convertPositionTo( "relative", {
10915
+ top: 0,
10916
+ left: l - inst.helperProportions.width
10917
+ } ).left;
10918
+ }
10919
+ if ( rs ) {
10920
+ ui.position.left = inst._convertPositionTo( "relative", {
10921
+ top: 0,
10922
+ left: r
10923
+ } ).left;
10924
+ }
10925
+ }
10926
+
10927
+ first = ( ts || bs || ls || rs );
10928
+
10929
+ if ( o.snapMode !== "outer" ) {
10930
+ ts = Math.abs( t - y1 ) <= d;
10931
+ bs = Math.abs( b - y2 ) <= d;
10932
+ ls = Math.abs( l - x1 ) <= d;
10933
+ rs = Math.abs( r - x2 ) <= d;
10934
+ if ( ts ) {
10935
+ ui.position.top = inst._convertPositionTo( "relative", {
10936
+ top: t,
10937
+ left: 0
10938
+ } ).top;
10939
+ }
10940
+ if ( bs ) {
10941
+ ui.position.top = inst._convertPositionTo( "relative", {
10942
+ top: b - inst.helperProportions.height,
10943
+ left: 0
10944
+ } ).top;
10945
+ }
10946
+ if ( ls ) {
10947
+ ui.position.left = inst._convertPositionTo( "relative", {
10948
+ top: 0,
10949
+ left: l
10950
+ } ).left;
10951
+ }
10952
+ if ( rs ) {
10953
+ ui.position.left = inst._convertPositionTo( "relative", {
10954
+ top: 0,
10955
+ left: r - inst.helperProportions.width
10956
+ } ).left;
10957
+ }
10958
+ }
10959
+
10960
+ if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10961
+ if ( inst.options.snap.snap ) {
10962
+ inst.options.snap.snap.call(
10963
+ inst.element,
10964
+ event,
10965
+ $.extend( inst._uiHash(), {
10966
+ snapItem: inst.snapElements[ i ].item
10967
+ } ) );
10968
+ }
10969
+ }
10970
+ inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10971
+
10972
+ }
10973
+
10974
+ }
10975
+ } );
10976
+
10977
+ $.ui.plugin.add( "draggable", "stack", {
10978
+ start: function( event, ui, instance ) {
10979
+ var min,
10980
+ o = instance.options,
10981
+ group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10982
+ return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10983
+ ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10984
+ } );
10985
+
10986
+ if ( !group.length ) {
10987
+ return;
10988
+ }
10989
+
10990
+ min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10991
+ $( group ).each( function( i ) {
10992
+ $( this ).css( "zIndex", min + i );
10993
+ } );
10994
+ this.css( "zIndex", ( min + group.length ) );
10995
+ }
10996
+ } );
10997
+
10998
+ $.ui.plugin.add( "draggable", "zIndex", {
10999
+ start: function( event, ui, instance ) {
11000
+ var t = $( ui.helper ),
11001
+ o = instance.options;
11002
+
11003
+ if ( t.css( "zIndex" ) ) {
11004
+ o._zIndex = t.css( "zIndex" );
11005
+ }
11006
+ t.css( "zIndex", o.zIndex );
11007
+ },
11008
+ stop: function( event, ui, instance ) {
11009
+ var o = instance.options;
11010
+
11011
+ if ( o._zIndex ) {
11012
+ $( ui.helper ).css( "zIndex", o._zIndex );
11013
+ }
11014
+ }
11015
+ } );
11016
+
11017
+ var widgetsDraggable = $.ui.draggable;
11018
+
11019
+
11020
+ /*!
11021
+ * jQuery UI Resizable 1.13.1
11022
+ * http://jqueryui.com
11023
+ *
11024
+ * Copyright jQuery Foundation and other contributors
11025
+ * Released under the MIT license.
11026
+ * http://jquery.org/license
11027
+ */
11028
+
11029
+ //>>label: Resizable
11030
+ //>>group: Interactions
11031
+ //>>description: Enables resize functionality for any element.
11032
+ //>>docs: http://api.jqueryui.com/resizable/
11033
+ //>>demos: http://jqueryui.com/resizable/
11034
+ //>>css.structure: ../../themes/base/core.css
11035
+ //>>css.structure: ../../themes/base/resizable.css
11036
+ //>>css.theme: ../../themes/base/theme.css
11037
+
11038
+
11039
+ $.widget( "ui.resizable", $.ui.mouse, {
11040
+ version: "1.13.1",
11041
+ widgetEventPrefix: "resize",
11042
+ options: {
11043
+ alsoResize: false,
11044
+ animate: false,
11045
+ animateDuration: "slow",
11046
+ animateEasing: "swing",
11047
+ aspectRatio: false,
11048
+ autoHide: false,
11049
+ classes: {
11050
+ "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
11051
+ },
11052
+ containment: false,
11053
+ ghost: false,
11054
+ grid: false,
11055
+ handles: "e,s,se",
11056
+ helper: false,
11057
+ maxHeight: null,
11058
+ maxWidth: null,
11059
+ minHeight: 10,
11060
+ minWidth: 10,
11061
+
11062
+ // See #7960
11063
+ zIndex: 90,
11064
+
11065
+ // Callbacks
11066
+ resize: null,
11067
+ start: null,
11068
+ stop: null
11069
+ },
11070
+
11071
+ _num: function( value ) {
11072
+ return parseFloat( value ) || 0;
11073
+ },
11074
+
11075
+ _isNumber: function( value ) {
11076
+ return !isNaN( parseFloat( value ) );
11077
+ },
11078
+
11079
+ _hasScroll: function( el, a ) {
11080
+
11081
+ if ( $( el ).css( "overflow" ) === "hidden" ) {
11082
+ return false;
11083
+ }
11084
+
11085
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
11086
+ has = false;
11087
+
11088
+ if ( el[ scroll ] > 0 ) {
11089
+ return true;
11090
+ }
11091
+
11092
+ // TODO: determine which cases actually cause this to happen
11093
+ // if the element doesn't have the scroll set, see if it's possible to
11094
+ // set the scroll
11095
+ try {
11096
+ el[ scroll ] = 1;
11097
+ has = ( el[ scroll ] > 0 );
11098
+ el[ scroll ] = 0;
11099
+ } catch ( e ) {
11100
+
11101
+ // `el` might be a string, then setting `scroll` will throw
11102
+ // an error in strict mode; ignore it.
11103
+ }
11104
+ return has;
11105
+ },
11106
+
11107
+ _create: function() {
11108
+
11109
+ var margins,
11110
+ o = this.options,
11111
+ that = this;
11112
+ this._addClass( "ui-resizable" );
11113
+
11114
+ $.extend( this, {
11115
+ _aspectRatio: !!( o.aspectRatio ),
11116
+ aspectRatio: o.aspectRatio,
11117
+ originalElement: this.element,
11118
+ _proportionallyResizeElements: [],
11119
+ _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
11120
+ } );
11121
+
11122
+ // Wrap the element if it cannot hold child nodes
11123
+ if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
11124
+
11125
+ this.element.wrap(
11126
+ $( "<div class='ui-wrapper'></div>" ).css( {
11127
+ overflow: "hidden",
11128
+ position: this.element.css( "position" ),
11129
+ width: this.element.outerWidth(),
11130
+ height: this.element.outerHeight(),
11131
+ top: this.element.css( "top" ),
11132
+ left: this.element.css( "left" )
11133
+ } )
11134
+ );
11135
+
11136
+ this.element = this.element.parent().data(
11137
+ "ui-resizable", this.element.resizable( "instance" )
11138
+ );
11139
+
11140
+ this.elementIsWrapper = true;
11141
+
11142
+ margins = {
11143
+ marginTop: this.originalElement.css( "marginTop" ),
11144
+ marginRight: this.originalElement.css( "marginRight" ),
11145
+ marginBottom: this.originalElement.css( "marginBottom" ),
11146
+ marginLeft: this.originalElement.css( "marginLeft" )
11147
+ };
11148
+
11149
+ this.element.css( margins );
11150
+ this.originalElement.css( "margin", 0 );
11151
+
11152
+ // support: Safari
11153
+ // Prevent Safari textarea resize
11154
+ this.originalResizeStyle = this.originalElement.css( "resize" );
11155
+ this.originalElement.css( "resize", "none" );
11156
+
11157
+ this._proportionallyResizeElements.push( this.originalElement.css( {
11158
+ position: "static",
11159
+ zoom: 1,
11160
+ display: "block"
11161
+ } ) );
11162
+
11163
+ // Support: IE9
11164
+ // avoid IE jump (hard set the margin)
11165
+ this.originalElement.css( margins );
11166
+
11167
+ this._proportionallyResize();
11168
+ }
11169
+
11170
+ this._setupHandles();
11171
+
11172
+ if ( o.autoHide ) {
11173
+ $( this.element )
11174
+ .on( "mouseenter", function() {
11175
+ if ( o.disabled ) {
11176
+ return;
11177
+ }
11178
+ that._removeClass( "ui-resizable-autohide" );
11179
+ that._handles.show();
11180
+ } )
11181
+ .on( "mouseleave", function() {
11182
+ if ( o.disabled ) {
11183
+ return;
11184
+ }
11185
+ if ( !that.resizing ) {
11186
+ that._addClass( "ui-resizable-autohide" );
11187
+ that._handles.hide();
11188
+ }
11189
+ } );
11190
+ }
11191
+
11192
+ this._mouseInit();
11193
+ },
11194
+
11195
+ _destroy: function() {
11196
+
11197
+ this._mouseDestroy();
11198
+ this._addedHandles.remove();
11199
+
11200
+ var wrapper,
11201
+ _destroy = function( exp ) {
11202
+ $( exp )
11203
+ .removeData( "resizable" )
11204
+ .removeData( "ui-resizable" )
11205
+ .off( ".resizable" );
11206
+ };
11207
+
11208
+ // TODO: Unwrap at same DOM position
11209
+ if ( this.elementIsWrapper ) {
11210
+ _destroy( this.element );
11211
+ wrapper = this.element;
11212
+ this.originalElement.css( {
11213
+ position: wrapper.css( "position" ),
11214
+ width: wrapper.outerWidth(),
11215
+ height: wrapper.outerHeight(),
11216
+ top: wrapper.css( "top" ),
11217
+ left: wrapper.css( "left" )
11218
+ } ).insertAfter( wrapper );
11219
+ wrapper.remove();
11220
+ }
11221
+
11222
+ this.originalElement.css( "resize", this.originalResizeStyle );
11223
+ _destroy( this.originalElement );
11224
+
11225
+ return this;
11226
+ },
11227
+
11228
+ _setOption: function( key, value ) {
11229
+ this._super( key, value );
11230
+
11231
+ switch ( key ) {
11232
+ case "handles":
11233
+ this._removeHandles();
11234
+ this._setupHandles();
11235
+ break;
11236
+ case "aspectRatio":
11237
+ this._aspectRatio = !!value;
11238
+ break;
11239
+ default:
11240
+ break;
11241
+ }
11242
+ },
11243
+
11244
+ _setupHandles: function() {
11245
+ var o = this.options, handle, i, n, hname, axis, that = this;
11246
+ this.handles = o.handles ||
11247
+ ( !$( ".ui-resizable-handle", this.element ).length ?
11248
+ "e,s,se" : {
11249
+ n: ".ui-resizable-n",
11250
+ e: ".ui-resizable-e",
11251
+ s: ".ui-resizable-s",
11252
+ w: ".ui-resizable-w",
11253
+ se: ".ui-resizable-se",
11254
+ sw: ".ui-resizable-sw",
11255
+ ne: ".ui-resizable-ne",
11256
+ nw: ".ui-resizable-nw"
11257
+ } );
11258
+
11259
+ this._handles = $();
11260
+ this._addedHandles = $();
11261
+ if ( this.handles.constructor === String ) {
11262
+
11263
+ if ( this.handles === "all" ) {
11264
+ this.handles = "n,e,s,w,se,sw,ne,nw";
11265
+ }
11266
+
11267
+ n = this.handles.split( "," );
11268
+ this.handles = {};
11269
+
11270
+ for ( i = 0; i < n.length; i++ ) {
11271
+
11272
+ handle = String.prototype.trim.call( n[ i ] );
11273
+ hname = "ui-resizable-" + handle;
11274
+ axis = $( "<div>" );
11275
+ this._addClass( axis, "ui-resizable-handle " + hname );
11276
+
11277
+ axis.css( { zIndex: o.zIndex } );
11278
+
11279
+ this.handles[ handle ] = ".ui-resizable-" + handle;
11280
+ if ( !this.element.children( this.handles[ handle ] ).length ) {
11281
+ this.element.append( axis );
11282
+ this._addedHandles = this._addedHandles.add( axis );
11283
+ }
11284
+ }
11285
+
11286
+ }
11287
+
11288
+ this._renderAxis = function( target ) {
11289
+
11290
+ var i, axis, padPos, padWrapper;
11291
+
11292
+ target = target || this.element;
11293
+
11294
+ for ( i in this.handles ) {
11295
+
11296
+ if ( this.handles[ i ].constructor === String ) {
11297
+ this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11298
+ } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11299
+ this.handles[ i ] = $( this.handles[ i ] );
11300
+ this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11301
+ }
11302
+
11303
+ if ( this.elementIsWrapper &&
11304
+ this.originalElement[ 0 ]
11305
+ .nodeName
11306
+ .match( /^(textarea|input|select|button)$/i ) ) {
11307
+ axis = $( this.handles[ i ], this.element );
11308
+
11309
+ padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11310
+ axis.outerHeight() :
11311
+ axis.outerWidth();
11312
+
11313
+ padPos = [ "padding",
11314
+ /ne|nw|n/.test( i ) ? "Top" :
11315
+ /se|sw|s/.test( i ) ? "Bottom" :
11316
+ /^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11317
+
11318
+ target.css( padPos, padWrapper );
11319
+
11320
+ this._proportionallyResize();
11321
+ }
11322
+
11323
+ this._handles = this._handles.add( this.handles[ i ] );
11324
+ }
11325
+ };
11326
+
11327
+ // TODO: make renderAxis a prototype function
11328
+ this._renderAxis( this.element );
11329
+
11330
+ this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11331
+ this._handles.disableSelection();
11332
+
11333
+ this._handles.on( "mouseover", function() {
11334
+ if ( !that.resizing ) {
11335
+ if ( this.className ) {
11336
+ axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11337
+ }
11338
+ that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11339
+ }
11340
+ } );
11341
+
11342
+ if ( o.autoHide ) {
11343
+ this._handles.hide();
11344
+ this._addClass( "ui-resizable-autohide" );
11345
+ }
11346
+ },
11347
+
11348
+ _removeHandles: function() {
11349
+ this._addedHandles.remove();
11350
+ },
11351
+
11352
+ _mouseCapture: function( event ) {
11353
+ var i, handle,
11354
+ capture = false;
11355
+
11356
+ for ( i in this.handles ) {
11357
+ handle = $( this.handles[ i ] )[ 0 ];
11358
+ if ( handle === event.target || $.contains( handle, event.target ) ) {
11359
+ capture = true;
11360
+ }
11361
+ }
11362
+
11363
+ return !this.options.disabled && capture;
11364
+ },
11365
+
11366
+ _mouseStart: function( event ) {
11367
+
11368
+ var curleft, curtop, cursor,
11369
+ o = this.options,
11370
+ el = this.element;
11371
+
11372
+ this.resizing = true;
11373
+
11374
+ this._renderProxy();
11375
+
11376
+ curleft = this._num( this.helper.css( "left" ) );
11377
+ curtop = this._num( this.helper.css( "top" ) );
11378
+
11379
+ if ( o.containment ) {
11380
+ curleft += $( o.containment ).scrollLeft() || 0;
11381
+ curtop += $( o.containment ).scrollTop() || 0;
11382
+ }
11383
+
11384
+ this.offset = this.helper.offset();
11385
+ this.position = { left: curleft, top: curtop };
11386
+
11387
+ this.size = this._helper ? {
11388
+ width: this.helper.width(),
11389
+ height: this.helper.height()
11390
+ } : {
11391
+ width: el.width(),
11392
+ height: el.height()
11393
+ };
11394
+
11395
+ this.originalSize = this._helper ? {
11396
+ width: el.outerWidth(),
11397
+ height: el.outerHeight()
11398
+ } : {
11399
+ width: el.width(),
11400
+ height: el.height()
11401
+ };
11402
+
11403
+ this.sizeDiff = {
11404
+ width: el.outerWidth() - el.width(),
11405
+ height: el.outerHeight() - el.height()
11406
+ };
11407
+
11408
+ this.originalPosition = { left: curleft, top: curtop };
11409
+ this.originalMousePosition = { left: event.pageX, top: event.pageY };
11410
+
11411
+ this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11412
+ o.aspectRatio :
11413
+ ( ( this.originalSize.width / this.originalSize.height ) || 1 );
11414
+
11415
+ cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11416
+ $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11417
+
11418
+ this._addClass( "ui-resizable-resizing" );
11419
+ this._propagate( "start", event );
11420
+ return true;
11421
+ },
11422
+
11423
+ _mouseDrag: function( event ) {
11424
+
11425
+ var data, props,
11426
+ smp = this.originalMousePosition,
11427
+ a = this.axis,
11428
+ dx = ( event.pageX - smp.left ) || 0,
11429
+ dy = ( event.pageY - smp.top ) || 0,
11430
+ trigger = this._change[ a ];
11431
+
11432
+ this._updatePrevProperties();
11433
+
11434
+ if ( !trigger ) {
11435
+ return false;
11436
+ }
11437
+
11438
+ data = trigger.apply( this, [ event, dx, dy ] );
11439
+
11440
+ this._updateVirtualBoundaries( event.shiftKey );
11441
+ if ( this._aspectRatio || event.shiftKey ) {
11442
+ data = this._updateRatio( data, event );
11443
+ }
11444
+
11445
+ data = this._respectSize( data, event );
11446
+
11447
+ this._updateCache( data );
11448
+
11449
+ this._propagate( "resize", event );
11450
+
11451
+ props = this._applyChanges();
11452
+
11453
+ if ( !this._helper && this._proportionallyResizeElements.length ) {
11454
+ this._proportionallyResize();
11455
+ }
11456
+
11457
+ if ( !$.isEmptyObject( props ) ) {
11458
+ this._updatePrevProperties();
11459
+ this._trigger( "resize", event, this.ui() );
11460
+ this._applyChanges();
11461
+ }
11462
+
11463
+ return false;
11464
+ },
11465
+
11466
+ _mouseStop: function( event ) {
11467
+
11468
+ this.resizing = false;
11469
+ var pr, ista, soffseth, soffsetw, s, left, top,
11470
+ o = this.options, that = this;
11471
+
11472
+ if ( this._helper ) {
11473
+
11474
+ pr = this._proportionallyResizeElements;
11475
+ ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11476
+ soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11477
+ soffsetw = ista ? 0 : that.sizeDiff.width;
11478
+
11479
+ s = {
11480
+ width: ( that.helper.width() - soffsetw ),
11481
+ height: ( that.helper.height() - soffseth )
11482
+ };
11483
+ left = ( parseFloat( that.element.css( "left" ) ) +
11484
+ ( that.position.left - that.originalPosition.left ) ) || null;
11485
+ top = ( parseFloat( that.element.css( "top" ) ) +
11486
+ ( that.position.top - that.originalPosition.top ) ) || null;
11487
+
11488
+ if ( !o.animate ) {
11489
+ this.element.css( $.extend( s, { top: top, left: left } ) );
11490
+ }
11491
+
11492
+ that.helper.height( that.size.height );
11493
+ that.helper.width( that.size.width );
11494
+
11495
+ if ( this._helper && !o.animate ) {
11496
+ this._proportionallyResize();
11497
+ }
11498
+ }
11499
+
11500
+ $( "body" ).css( "cursor", "auto" );
11501
+
11502
+ this._removeClass( "ui-resizable-resizing" );
11503
+
11504
+ this._propagate( "stop", event );
11505
+
11506
+ if ( this._helper ) {
11507
+ this.helper.remove();
11508
+ }
11509
+
11510
+ return false;
11511
+
11512
+ },
11513
+
11514
+ _updatePrevProperties: function() {
11515
+ this.prevPosition = {
11516
+ top: this.position.top,
11517
+ left: this.position.left
11518
+ };
11519
+ this.prevSize = {
11520
+ width: this.size.width,
11521
+ height: this.size.height
11522
+ };
11523
+ },
11524
+
11525
+ _applyChanges: function() {
11526
+ var props = {};
11527
+
11528
+ if ( this.position.top !== this.prevPosition.top ) {
11529
+ props.top = this.position.top + "px";
11530
+ }
11531
+ if ( this.position.left !== this.prevPosition.left ) {
11532
+ props.left = this.position.left + "px";
11533
+ }
11534
+ if ( this.size.width !== this.prevSize.width ) {
11535
+ props.width = this.size.width + "px";
11536
+ }
11537
+ if ( this.size.height !== this.prevSize.height ) {
11538
+ props.height = this.size.height + "px";
11539
+ }
11540
+
11541
+ this.helper.css( props );
11542
+
11543
+ return props;
11544
+ },
11545
+
11546
+ _updateVirtualBoundaries: function( forceAspectRatio ) {
11547
+ var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11548
+ o = this.options;
11549
+
11550
+ b = {
11551
+ minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11552
+ maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11553
+ minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11554
+ maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11555
+ };
11556
+
11557
+ if ( this._aspectRatio || forceAspectRatio ) {
11558
+ pMinWidth = b.minHeight * this.aspectRatio;
11559
+ pMinHeight = b.minWidth / this.aspectRatio;
11560
+ pMaxWidth = b.maxHeight * this.aspectRatio;
11561
+ pMaxHeight = b.maxWidth / this.aspectRatio;
11562
+
11563
+ if ( pMinWidth > b.minWidth ) {
11564
+ b.minWidth = pMinWidth;
11565
+ }
11566
+ if ( pMinHeight > b.minHeight ) {
11567
+ b.minHeight = pMinHeight;
11568
+ }
11569
+ if ( pMaxWidth < b.maxWidth ) {
11570
+ b.maxWidth = pMaxWidth;
11571
+ }
11572
+ if ( pMaxHeight < b.maxHeight ) {
11573
+ b.maxHeight = pMaxHeight;
11574
+ }
11575
+ }
11576
+ this._vBoundaries = b;
11577
+ },
11578
+
11579
+ _updateCache: function( data ) {
11580
+ this.offset = this.helper.offset();
11581
+ if ( this._isNumber( data.left ) ) {
11582
+ this.position.left = data.left;
11583
+ }
11584
+ if ( this._isNumber( data.top ) ) {
11585
+ this.position.top = data.top;
11586
+ }
11587
+ if ( this._isNumber( data.height ) ) {
11588
+ this.size.height = data.height;
11589
+ }
11590
+ if ( this._isNumber( data.width ) ) {
11591
+ this.size.width = data.width;
11592
+ }
11593
+ },
11594
+
11595
+ _updateRatio: function( data ) {
11596
+
11597
+ var cpos = this.position,
11598
+ csize = this.size,
11599
+ a = this.axis;
11600
+
11601
+ if ( this._isNumber( data.height ) ) {
11602
+ data.width = ( data.height * this.aspectRatio );
11603
+ } else if ( this._isNumber( data.width ) ) {
11604
+ data.height = ( data.width / this.aspectRatio );
11605
+ }
11606
+
11607
+ if ( a === "sw" ) {
11608
+ data.left = cpos.left + ( csize.width - data.width );
11609
+ data.top = null;
11610
+ }
11611
+ if ( a === "nw" ) {
11612
+ data.top = cpos.top + ( csize.height - data.height );
11613
+ data.left = cpos.left + ( csize.width - data.width );
11614
+ }
11615
+
11616
+ return data;
11617
+ },
11618
+
11619
+ _respectSize: function( data ) {
11620
+
11621
+ var o = this._vBoundaries,
11622
+ a = this.axis,
11623
+ ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11624
+ ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11625
+ isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11626
+ isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11627
+ dw = this.originalPosition.left + this.originalSize.width,
11628
+ dh = this.originalPosition.top + this.originalSize.height,
11629
+ cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11630
+ if ( isminw ) {
11631
+ data.width = o.minWidth;
11632
+ }
11633
+ if ( isminh ) {
11634
+ data.height = o.minHeight;
11635
+ }
11636
+ if ( ismaxw ) {
11637
+ data.width = o.maxWidth;
11638
+ }
11639
+ if ( ismaxh ) {
11640
+ data.height = o.maxHeight;
11641
+ }
11642
+
11643
+ if ( isminw && cw ) {
11644
+ data.left = dw - o.minWidth;
11645
+ }
11646
+ if ( ismaxw && cw ) {
11647
+ data.left = dw - o.maxWidth;
11648
+ }
11649
+ if ( isminh && ch ) {
11650
+ data.top = dh - o.minHeight;
11651
+ }
11652
+ if ( ismaxh && ch ) {
11653
+ data.top = dh - o.maxHeight;
11654
+ }
11655
+
11656
+ // Fixing jump error on top/left - bug #2330
11657
+ if ( !data.width && !data.height && !data.left && data.top ) {
11658
+ data.top = null;
11659
+ } else if ( !data.width && !data.height && !data.top && data.left ) {
11660
+ data.left = null;
11661
+ }
11662
+
11663
+ return data;
11664
+ },
11665
+
11666
+ _getPaddingPlusBorderDimensions: function( element ) {
11667
+ var i = 0,
11668
+ widths = [],
11669
+ borders = [
11670
+ element.css( "borderTopWidth" ),
11671
+ element.css( "borderRightWidth" ),
11672
+ element.css( "borderBottomWidth" ),
11673
+ element.css( "borderLeftWidth" )
11674
+ ],
11675
+ paddings = [
11676
+ element.css( "paddingTop" ),
11677
+ element.css( "paddingRight" ),
11678
+ element.css( "paddingBottom" ),
11679
+ element.css( "paddingLeft" )
11680
+ ];
11681
+
11682
+ for ( ; i < 4; i++ ) {
11683
+ widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11684
+ widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11685
+ }
11686
+
11687
+ return {
11688
+ height: widths[ 0 ] + widths[ 2 ],
11689
+ width: widths[ 1 ] + widths[ 3 ]
11690
+ };
11691
+ },
11692
+
11693
+ _proportionallyResize: function() {
11694
+
11695
+ if ( !this._proportionallyResizeElements.length ) {
11696
+ return;
11697
+ }
11698
+
11699
+ var prel,
11700
+ i = 0,
11701
+ element = this.helper || this.element;
11702
+
11703
+ for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11704
+
11705
+ prel = this._proportionallyResizeElements[ i ];
11706
+
11707
+ // TODO: Seems like a bug to cache this.outerDimensions
11708
+ // considering that we are in a loop.
11709
+ if ( !this.outerDimensions ) {
11710
+ this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11711
+ }
11712
+
11713
+ prel.css( {
11714
+ height: ( element.height() - this.outerDimensions.height ) || 0,
11715
+ width: ( element.width() - this.outerDimensions.width ) || 0
11716
+ } );
11717
+
11718
+ }
11719
+
11720
+ },
11721
+
11722
+ _renderProxy: function() {
11723
+
11724
+ var el = this.element, o = this.options;
11725
+ this.elementOffset = el.offset();
11726
+
11727
+ if ( this._helper ) {
11728
+
11729
+ this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11730
+
11731
+ this._addClass( this.helper, this._helper );
11732
+ this.helper.css( {
11733
+ width: this.element.outerWidth(),
11734
+ height: this.element.outerHeight(),
11735
+ position: "absolute",
11736
+ left: this.elementOffset.left + "px",
11737
+ top: this.elementOffset.top + "px",
11738
+ zIndex: ++o.zIndex //TODO: Don't modify option
11739
+ } );
11740
+
11741
+ this.helper
11742
+ .appendTo( "body" )
11743
+ .disableSelection();
11744
+
11745
+ } else {
11746
+ this.helper = this.element;
11747
+ }
11748
+
11749
+ },
11750
+
11751
+ _change: {
11752
+ e: function( event, dx ) {
11753
+ return { width: this.originalSize.width + dx };
11754
+ },
11755
+ w: function( event, dx ) {
11756
+ var cs = this.originalSize, sp = this.originalPosition;
11757
+ return { left: sp.left + dx, width: cs.width - dx };
11758
+ },
11759
+ n: function( event, dx, dy ) {
11760
+ var cs = this.originalSize, sp = this.originalPosition;
11761
+ return { top: sp.top + dy, height: cs.height - dy };
11762
+ },
11763
+ s: function( event, dx, dy ) {
11764
+ return { height: this.originalSize.height + dy };
11765
+ },
11766
+ se: function( event, dx, dy ) {
11767
+ return $.extend( this._change.s.apply( this, arguments ),
11768
+ this._change.e.apply( this, [ event, dx, dy ] ) );
11769
+ },
11770
+ sw: function( event, dx, dy ) {
11771
+ return $.extend( this._change.s.apply( this, arguments ),
11772
+ this._change.w.apply( this, [ event, dx, dy ] ) );
11773
+ },
11774
+ ne: function( event, dx, dy ) {
11775
+ return $.extend( this._change.n.apply( this, arguments ),
11776
+ this._change.e.apply( this, [ event, dx, dy ] ) );
11777
+ },
11778
+ nw: function( event, dx, dy ) {
11779
+ return $.extend( this._change.n.apply( this, arguments ),
11780
+ this._change.w.apply( this, [ event, dx, dy ] ) );
11781
+ }
11782
+ },
11783
+
11784
+ _propagate: function( n, event ) {
11785
+ $.ui.plugin.call( this, n, [ event, this.ui() ] );
11786
+ if ( n !== "resize" ) {
11787
+ this._trigger( n, event, this.ui() );
11788
+ }
11789
+ },
11790
+
11791
+ plugins: {},
11792
+
11793
+ ui: function() {
11794
+ return {
11795
+ originalElement: this.originalElement,
11796
+ element: this.element,
11797
+ helper: this.helper,
11798
+ position: this.position,
11799
+ size: this.size,
11800
+ originalSize: this.originalSize,
11801
+ originalPosition: this.originalPosition
11802
+ };
11803
+ }
11804
+
11805
+ } );
11806
+
11807
+ /*
11808
+ * Resizable Extensions
11809
+ */
11810
+
11811
+ $.ui.plugin.add( "resizable", "animate", {
11812
+
11813
+ stop: function( event ) {
11814
+ var that = $( this ).resizable( "instance" ),
11815
+ o = that.options,
11816
+ pr = that._proportionallyResizeElements,
11817
+ ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11818
+ soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11819
+ soffsetw = ista ? 0 : that.sizeDiff.width,
11820
+ style = {
11821
+ width: ( that.size.width - soffsetw ),
11822
+ height: ( that.size.height - soffseth )
11823
+ },
11824
+ left = ( parseFloat( that.element.css( "left" ) ) +
11825
+ ( that.position.left - that.originalPosition.left ) ) || null,
11826
+ top = ( parseFloat( that.element.css( "top" ) ) +
11827
+ ( that.position.top - that.originalPosition.top ) ) || null;
11828
+
11829
+ that.element.animate(
11830
+ $.extend( style, top && left ? { top: top, left: left } : {} ), {
11831
+ duration: o.animateDuration,
11832
+ easing: o.animateEasing,
11833
+ step: function() {
11834
+
11835
+ var data = {
11836
+ width: parseFloat( that.element.css( "width" ) ),
11837
+ height: parseFloat( that.element.css( "height" ) ),
11838
+ top: parseFloat( that.element.css( "top" ) ),
11839
+ left: parseFloat( that.element.css( "left" ) )
11840
+ };
11841
+
11842
+ if ( pr && pr.length ) {
11843
+ $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11844
+ }
11845
+
11846
+ // Propagating resize, and updating values for each animation step
11847
+ that._updateCache( data );
11848
+ that._propagate( "resize", event );
11849
+
11850
+ }
11851
+ }
11852
+ );
11853
+ }
11854
+
11855
+ } );
11856
+
11857
+ $.ui.plugin.add( "resizable", "containment", {
11858
+
11859
+ start: function() {
11860
+ var element, p, co, ch, cw, width, height,
11861
+ that = $( this ).resizable( "instance" ),
11862
+ o = that.options,
11863
+ el = that.element,
11864
+ oc = o.containment,
11865
+ ce = ( oc instanceof $ ) ?
11866
+ oc.get( 0 ) :
11867
+ ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11868
+
11869
+ if ( !ce ) {
11870
+ return;
11871
+ }
11872
+
11873
+ that.containerElement = $( ce );
11874
+
11875
+ if ( /document/.test( oc ) || oc === document ) {
11876
+ that.containerOffset = {
11877
+ left: 0,
11878
+ top: 0
11879
+ };
11880
+ that.containerPosition = {
11881
+ left: 0,
11882
+ top: 0
11883
+ };
11884
+
11885
+ that.parentData = {
11886
+ element: $( document ),
11887
+ left: 0,
11888
+ top: 0,
11889
+ width: $( document ).width(),
11890
+ height: $( document ).height() || document.body.parentNode.scrollHeight
11891
+ };
11892
+ } else {
11893
+ element = $( ce );
11894
+ p = [];
11895
+ $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11896
+ p[ i ] = that._num( element.css( "padding" + name ) );
11897
+ } );
11898
+
11899
+ that.containerOffset = element.offset();
11900
+ that.containerPosition = element.position();
11901
+ that.containerSize = {
11902
+ height: ( element.innerHeight() - p[ 3 ] ),
11903
+ width: ( element.innerWidth() - p[ 1 ] )
11904
+ };
11905
+
11906
+ co = that.containerOffset;
11907
+ ch = that.containerSize.height;
11908
+ cw = that.containerSize.width;
11909
+ width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11910
+ height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11911
+
11912
+ that.parentData = {
11913
+ element: ce,
11914
+ left: co.left,
11915
+ top: co.top,
11916
+ width: width,
11917
+ height: height
11918
+ };
11919
+ }
11920
+ },
11921
+
11922
+ resize: function( event ) {
11923
+ var woset, hoset, isParent, isOffsetRelative,
11924
+ that = $( this ).resizable( "instance" ),
11925
+ o = that.options,
11926
+ co = that.containerOffset,
11927
+ cp = that.position,
11928
+ pRatio = that._aspectRatio || event.shiftKey,
11929
+ cop = {
11930
+ top: 0,
11931
+ left: 0
11932
+ },
11933
+ ce = that.containerElement,
11934
+ continueResize = true;
11935
+
11936
+ if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11937
+ cop = co;
11938
+ }
11939
+
11940
+ if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11941
+ that.size.width = that.size.width +
11942
+ ( that._helper ?
11943
+ ( that.position.left - co.left ) :
11944
+ ( that.position.left - cop.left ) );
11945
+
11946
+ if ( pRatio ) {
11947
+ that.size.height = that.size.width / that.aspectRatio;
11948
+ continueResize = false;
11949
+ }
11950
+ that.position.left = o.helper ? co.left : 0;
11951
+ }
11952
+
11953
+ if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11954
+ that.size.height = that.size.height +
11955
+ ( that._helper ?
11956
+ ( that.position.top - co.top ) :
11957
+ that.position.top );
11958
+
11959
+ if ( pRatio ) {
11960
+ that.size.width = that.size.height * that.aspectRatio;
11961
+ continueResize = false;
11962
+ }
11963
+ that.position.top = that._helper ? co.top : 0;
11964
+ }
11965
+
11966
+ isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11967
+ isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11968
+
11969
+ if ( isParent && isOffsetRelative ) {
11970
+ that.offset.left = that.parentData.left + that.position.left;
11971
+ that.offset.top = that.parentData.top + that.position.top;
11972
+ } else {
11973
+ that.offset.left = that.element.offset().left;
11974
+ that.offset.top = that.element.offset().top;
11975
+ }
11976
+
11977
+ woset = Math.abs( that.sizeDiff.width +
11978
+ ( that._helper ?
11979
+ that.offset.left - cop.left :
11980
+ ( that.offset.left - co.left ) ) );
11981
+
11982
+ hoset = Math.abs( that.sizeDiff.height +
11983
+ ( that._helper ?
11984
+ that.offset.top - cop.top :
11985
+ ( that.offset.top - co.top ) ) );
11986
+
11987
+ if ( woset + that.size.width >= that.parentData.width ) {
11988
+ that.size.width = that.parentData.width - woset;
11989
+ if ( pRatio ) {
11990
+ that.size.height = that.size.width / that.aspectRatio;
11991
+ continueResize = false;
11992
+ }
11993
+ }
11994
+
11995
+ if ( hoset + that.size.height >= that.parentData.height ) {
11996
+ that.size.height = that.parentData.height - hoset;
11997
+ if ( pRatio ) {
11998
+ that.size.width = that.size.height * that.aspectRatio;
11999
+ continueResize = false;
12000
+ }
12001
+ }
12002
+
12003
+ if ( !continueResize ) {
12004
+ that.position.left = that.prevPosition.left;
12005
+ that.position.top = that.prevPosition.top;
12006
+ that.size.width = that.prevSize.width;
12007
+ that.size.height = that.prevSize.height;
12008
+ }
12009
+ },
12010
+
12011
+ stop: function() {
12012
+ var that = $( this ).resizable( "instance" ),
12013
+ o = that.options,
12014
+ co = that.containerOffset,
12015
+ cop = that.containerPosition,
12016
+ ce = that.containerElement,
12017
+ helper = $( that.helper ),
12018
+ ho = helper.offset(),
12019
+ w = helper.outerWidth() - that.sizeDiff.width,
12020
+ h = helper.outerHeight() - that.sizeDiff.height;
12021
+
12022
+ if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
12023
+ $( this ).css( {
12024
+ left: ho.left - cop.left - co.left,
12025
+ width: w,
12026
+ height: h
12027
+ } );
12028
+ }
12029
+
12030
+ if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
12031
+ $( this ).css( {
12032
+ left: ho.left - cop.left - co.left,
12033
+ width: w,
12034
+ height: h
12035
+ } );
12036
+ }
12037
+ }
12038
+ } );
12039
+
12040
+ $.ui.plugin.add( "resizable", "alsoResize", {
12041
+
12042
+ start: function() {
12043
+ var that = $( this ).resizable( "instance" ),
12044
+ o = that.options;
12045
+
12046
+ $( o.alsoResize ).each( function() {
12047
+ var el = $( this );
12048
+ el.data( "ui-resizable-alsoresize", {
12049
+ width: parseFloat( el.width() ), height: parseFloat( el.height() ),
12050
+ left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
12051
+ } );
12052
+ } );
12053
+ },
12054
+
12055
+ resize: function( event, ui ) {
12056
+ var that = $( this ).resizable( "instance" ),
12057
+ o = that.options,
12058
+ os = that.originalSize,
12059
+ op = that.originalPosition,
12060
+ delta = {
12061
+ height: ( that.size.height - os.height ) || 0,
12062
+ width: ( that.size.width - os.width ) || 0,
12063
+ top: ( that.position.top - op.top ) || 0,
12064
+ left: ( that.position.left - op.left ) || 0
12065
+ };
12066
+
12067
+ $( o.alsoResize ).each( function() {
12068
+ var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
12069
+ css = el.parents( ui.originalElement[ 0 ] ).length ?
12070
+ [ "width", "height" ] :
12071
+ [ "width", "height", "top", "left" ];
12072
+
12073
+ $.each( css, function( i, prop ) {
12074
+ var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
12075
+ if ( sum && sum >= 0 ) {
12076
+ style[ prop ] = sum || null;
12077
+ }
12078
+ } );
12079
+
12080
+ el.css( style );
12081
+ } );
12082
+ },
12083
+
12084
+ stop: function() {
12085
+ $( this ).removeData( "ui-resizable-alsoresize" );
12086
+ }
12087
+ } );
12088
+
12089
+ $.ui.plugin.add( "resizable", "ghost", {
12090
+
12091
+ start: function() {
12092
+
12093
+ var that = $( this ).resizable( "instance" ), cs = that.size;
12094
+
12095
+ that.ghost = that.originalElement.clone();
12096
+ that.ghost.css( {
12097
+ opacity: 0.25,
12098
+ display: "block",
12099
+ position: "relative",
12100
+ height: cs.height,
12101
+ width: cs.width,
12102
+ margin: 0,
12103
+ left: 0,
12104
+ top: 0
12105
+ } );
12106
+
12107
+ that._addClass( that.ghost, "ui-resizable-ghost" );
12108
+
12109
+ // DEPRECATED
12110
+ // TODO: remove after 1.12
12111
+ if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
12112
+
12113
+ // Ghost option
12114
+ that.ghost.addClass( this.options.ghost );
12115
+ }
12116
+
12117
+ that.ghost.appendTo( that.helper );
12118
+
12119
+ },
12120
+
12121
+ resize: function() {
12122
+ var that = $( this ).resizable( "instance" );
12123
+ if ( that.ghost ) {
12124
+ that.ghost.css( {
12125
+ position: "relative",
12126
+ height: that.size.height,
12127
+ width: that.size.width
12128
+ } );
12129
+ }
12130
+ },
12131
+
12132
+ stop: function() {
12133
+ var that = $( this ).resizable( "instance" );
12134
+ if ( that.ghost && that.helper ) {
12135
+ that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
12136
+ }
12137
+ }
12138
+
12139
+ } );
12140
+
12141
+ $.ui.plugin.add( "resizable", "grid", {
12142
+
12143
+ resize: function() {
12144
+ var outerDimensions,
12145
+ that = $( this ).resizable( "instance" ),
12146
+ o = that.options,
12147
+ cs = that.size,
12148
+ os = that.originalSize,
12149
+ op = that.originalPosition,
12150
+ a = that.axis,
12151
+ grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12152
+ gridX = ( grid[ 0 ] || 1 ),
12153
+ gridY = ( grid[ 1 ] || 1 ),
12154
+ ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12155
+ oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12156
+ newWidth = os.width + ox,
12157
+ newHeight = os.height + oy,
12158
+ isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12159
+ isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12160
+ isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12161
+ isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12162
+
12163
+ o.grid = grid;
12164
+
12165
+ if ( isMinWidth ) {
12166
+ newWidth += gridX;
12167
+ }
12168
+ if ( isMinHeight ) {
12169
+ newHeight += gridY;
12170
+ }
12171
+ if ( isMaxWidth ) {
12172
+ newWidth -= gridX;
12173
+ }
12174
+ if ( isMaxHeight ) {
12175
+ newHeight -= gridY;
12176
+ }
12177
+
12178
+ if ( /^(se|s|e)$/.test( a ) ) {
12179
+ that.size.width = newWidth;
12180
+ that.size.height = newHeight;
12181
+ } else if ( /^(ne)$/.test( a ) ) {
12182
+ that.size.width = newWidth;
12183
+ that.size.height = newHeight;
12184
+ that.position.top = op.top - oy;
12185
+ } else if ( /^(sw)$/.test( a ) ) {
12186
+ that.size.width = newWidth;
12187
+ that.size.height = newHeight;
12188
+ that.position.left = op.left - ox;
12189
+ } else {
12190
+ if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12191
+ outerDimensions = that._getPaddingPlusBorderDimensions( this );
12192
+ }
12193
+
12194
+ if ( newHeight - gridY > 0 ) {
12195
+ that.size.height = newHeight;
12196
+ that.position.top = op.top - oy;
12197
+ } else {
12198
+ newHeight = gridY - outerDimensions.height;
12199
+ that.size.height = newHeight;
12200
+ that.position.top = op.top + os.height - newHeight;
12201
+ }
12202
+ if ( newWidth - gridX > 0 ) {
12203
+ that.size.width = newWidth;
12204
+ that.position.left = op.left - ox;
12205
+ } else {
12206
+ newWidth = gridX - outerDimensions.width;
12207
+ that.size.width = newWidth;
12208
+ that.position.left = op.left + os.width - newWidth;
12209
+ }
12210
+ }
12211
+ }
12212
+
12213
+ } );
12214
+
12215
+ var widgetsResizable = $.ui.resizable;
12216
+
12217
+
12218
+ /*!
12219
+ * jQuery UI Dialog 1.13.1
12220
+ * http://jqueryui.com
12221
+ *
12222
+ * Copyright jQuery Foundation and other contributors
12223
+ * Released under the MIT license.
12224
+ * http://jquery.org/license
12225
+ */
12226
+
12227
+ //>>label: Dialog
12228
+ //>>group: Widgets
12229
+ //>>description: Displays customizable dialog windows.
12230
+ //>>docs: http://api.jqueryui.com/dialog/
12231
+ //>>demos: http://jqueryui.com/dialog/
12232
+ //>>css.structure: ../../themes/base/core.css
12233
+ //>>css.structure: ../../themes/base/dialog.css
12234
+ //>>css.theme: ../../themes/base/theme.css
12235
+
12236
+
12237
+ $.widget( "ui.dialog", {
12238
+ version: "1.13.1",
12239
+ options: {
12240
+ appendTo: "body",
12241
+ autoOpen: true,
12242
+ buttons: [],
12243
+ classes: {
12244
+ "ui-dialog": "ui-corner-all",
12245
+ "ui-dialog-titlebar": "ui-corner-all"
12246
+ },
12247
+ closeOnEscape: true,
12248
+ closeText: "Close",
12249
+ draggable: true,
12250
+ hide: null,
12251
+ height: "auto",
12252
+ maxHeight: null,
12253
+ maxWidth: null,
12254
+ minHeight: 150,
12255
+ minWidth: 150,
12256
+ modal: false,
12257
+ position: {
12258
+ my: "center",
12259
+ at: "center",
12260
+ of: window,
12261
+ collision: "fit",
12262
+
12263
+ // Ensure the titlebar is always visible
12264
+ using: function( pos ) {
12265
+ var topOffset = $( this ).css( pos ).offset().top;
12266
+ if ( topOffset < 0 ) {
12267
+ $( this ).css( "top", pos.top - topOffset );
12268
+ }
12269
+ }
12270
+ },
12271
+ resizable: true,
12272
+ show: null,
12273
+ title: null,
12274
+ width: 300,
12275
+
12276
+ // Callbacks
12277
+ beforeClose: null,
12278
+ close: null,
12279
+ drag: null,
12280
+ dragStart: null,
12281
+ dragStop: null,
12282
+ focus: null,
12283
+ open: null,
12284
+ resize: null,
12285
+ resizeStart: null,
12286
+ resizeStop: null
12287
+ },
12288
+
12289
+ sizeRelatedOptions: {
12290
+ buttons: true,
12291
+ height: true,
12292
+ maxHeight: true,
12293
+ maxWidth: true,
12294
+ minHeight: true,
12295
+ minWidth: true,
12296
+ width: true
12297
+ },
12298
+
12299
+ resizableRelatedOptions: {
12300
+ maxHeight: true,
12301
+ maxWidth: true,
12302
+ minHeight: true,
12303
+ minWidth: true
12304
+ },
12305
+
12306
+ _create: function() {
12307
+ this.originalCss = {
12308
+ display: this.element[ 0 ].style.display,
12309
+ width: this.element[ 0 ].style.width,
12310
+ minHeight: this.element[ 0 ].style.minHeight,
12311
+ maxHeight: this.element[ 0 ].style.maxHeight,
12312
+ height: this.element[ 0 ].style.height
12313
+ };
12314
+ this.originalPosition = {
12315
+ parent: this.element.parent(),
12316
+ index: this.element.parent().children().index( this.element )
12317
+ };
12318
+ this.originalTitle = this.element.attr( "title" );
12319
+ if ( this.options.title == null && this.originalTitle != null ) {
12320
+ this.options.title = this.originalTitle;
12321
+ }
12322
+
12323
+ // Dialogs can't be disabled
12324
+ if ( this.options.disabled ) {
12325
+ this.options.disabled = false;
12326
+ }
12327
+
12328
+ this._createWrapper();
12329
+
12330
+ this.element
12331
+ .show()
12332
+ .removeAttr( "title" )
12333
+ .appendTo( this.uiDialog );
12334
+
12335
+ this._addClass( "ui-dialog-content", "ui-widget-content" );
12336
+
12337
+ this._createTitlebar();
12338
+ this._createButtonPane();
12339
+
12340
+ if ( this.options.draggable && $.fn.draggable ) {
12341
+ this._makeDraggable();
12342
+ }
12343
+ if ( this.options.resizable && $.fn.resizable ) {
12344
+ this._makeResizable();
12345
+ }
12346
+
12347
+ this._isOpen = false;
12348
+
12349
+ this._trackFocus();
12350
+ },
12351
+
12352
+ _init: function() {
12353
+ if ( this.options.autoOpen ) {
12354
+ this.open();
12355
+ }
12356
+ },
12357
+
12358
+ _appendTo: function() {
12359
+ var element = this.options.appendTo;
12360
+ if ( element && ( element.jquery || element.nodeType ) ) {
12361
+ return $( element );
12362
+ }
12363
+ return this.document.find( element || "body" ).eq( 0 );
12364
+ },
12365
+
12366
+ _destroy: function() {
12367
+ var next,
12368
+ originalPosition = this.originalPosition;
12369
+
12370
+ this._untrackInstance();
12371
+ this._destroyOverlay();
12372
+
12373
+ this.element
12374
+ .removeUniqueId()
12375
+ .css( this.originalCss )
12376
+
12377
+ // Without detaching first, the following becomes really slow
12378
+ .detach();
12379
+
12380
+ this.uiDialog.remove();
12381
+
12382
+ if ( this.originalTitle ) {
12383
+ this.element.attr( "title", this.originalTitle );
12384
+ }
12385
+
12386
+ next = originalPosition.parent.children().eq( originalPosition.index );
12387
+
12388
+ // Don't try to place the dialog next to itself (#8613)
12389
+ if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12390
+ next.before( this.element );
12391
+ } else {
12392
+ originalPosition.parent.append( this.element );
12393
+ }
12394
+ },
12395
+
12396
+ widget: function() {
12397
+ return this.uiDialog;
12398
+ },
12399
+
12400
+ disable: $.noop,
12401
+ enable: $.noop,
12402
+
12403
+ close: function( event ) {
12404
+ var that = this;
12405
+
12406
+ if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12407
+ return;
12408
+ }
12409
+
12410
+ this._isOpen = false;
12411
+ this._focusedElement = null;
12412
+ this._destroyOverlay();
12413
+ this._untrackInstance();
12414
+
12415
+ if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12416
+
12417
+ // Hiding a focused element doesn't trigger blur in WebKit
12418
+ // so in case we have nothing to focus on, explicitly blur the active element
12419
+ // https://bugs.webkit.org/show_bug.cgi?id=47182
12420
+ $.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
12421
+ }
12422
+
12423
+ this._hide( this.uiDialog, this.options.hide, function() {
12424
+ that._trigger( "close", event );
12425
+ } );
12426
+ },
12427
+
12428
+ isOpen: function() {
12429
+ return this._isOpen;
12430
+ },
12431
+
12432
+ moveToTop: function() {
12433
+ this._moveToTop();
12434
+ },
12435
+
12436
+ _moveToTop: function( event, silent ) {
12437
+ var moved = false,
12438
+ zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12439
+ return +$( this ).css( "z-index" );
12440
+ } ).get(),
12441
+ zIndexMax = Math.max.apply( null, zIndices );
12442
+
12443
+ if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12444
+ this.uiDialog.css( "z-index", zIndexMax + 1 );
12445
+ moved = true;
12446
+ }
12447
+
12448
+ if ( moved && !silent ) {
12449
+ this._trigger( "focus", event );
12450
+ }
12451
+ return moved;
12452
+ },
12453
+
12454
+ open: function() {
12455
+ var that = this;
12456
+ if ( this._isOpen ) {
12457
+ if ( this._moveToTop() ) {
12458
+ this._focusTabbable();
12459
+ }
12460
+ return;
12461
+ }
12462
+
12463
+ this._isOpen = true;
12464
+ this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
12465
+
12466
+ this._size();
12467
+ this._position();
12468
+ this._createOverlay();
12469
+ this._moveToTop( null, true );
12470
+
12471
+ // Ensure the overlay is moved to the top with the dialog, but only when
12472
+ // opening. The overlay shouldn't move after the dialog is open so that
12473
+ // modeless dialogs opened after the modal dialog stack properly.
12474
+ if ( this.overlay ) {
12475
+ this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12476
+ }
12477
+
12478
+ this._show( this.uiDialog, this.options.show, function() {
12479
+ that._focusTabbable();
12480
+ that._trigger( "focus" );
12481
+ } );
12482
+
12483
+ // Track the dialog immediately upon opening in case a focus event
12484
+ // somehow occurs outside of the dialog before an element inside the
12485
+ // dialog is focused (#10152)
12486
+ this._makeFocusTarget();
12487
+
12488
+ this._trigger( "open" );
12489
+ },
12490
+
12491
+ _focusTabbable: function() {
12492
+
12493
+ // Set focus to the first match:
12494
+ // 1. An element that was focused previously
12495
+ // 2. First element inside the dialog matching [autofocus]
12496
+ // 3. Tabbable element inside the content element
12497
+ // 4. Tabbable element inside the buttonpane
12498
+ // 5. The close button
12499
+ // 6. The dialog itself
12500
+ var hasFocus = this._focusedElement;
12501
+ if ( !hasFocus ) {
12502
+ hasFocus = this.element.find( "[autofocus]" );
12503
+ }
12504
+ if ( !hasFocus.length ) {
12505
+ hasFocus = this.element.find( ":tabbable" );
12506
+ }
12507
+ if ( !hasFocus.length ) {
12508
+ hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12509
+ }
12510
+ if ( !hasFocus.length ) {
12511
+ hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12512
+ }
12513
+ if ( !hasFocus.length ) {
12514
+ hasFocus = this.uiDialog;
12515
+ }
12516
+ hasFocus.eq( 0 ).trigger( "focus" );
12517
+ },
12518
+
12519
+ _restoreTabbableFocus: function() {
12520
+ var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
12521
+ isActive = this.uiDialog[ 0 ] === activeElement ||
12522
+ $.contains( this.uiDialog[ 0 ], activeElement );
12523
+ if ( !isActive ) {
12524
+ this._focusTabbable();
12525
+ }
12526
+ },
12527
+
12528
+ _keepFocus: function( event ) {
12529
+ event.preventDefault();
12530
+ this._restoreTabbableFocus();
12531
+
12532
+ // support: IE
12533
+ // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
12534
+ // so we check again later
12535
+ this._delay( this._restoreTabbableFocus );
12536
+ },
12537
+
12538
+ _createWrapper: function() {
12539
+ this.uiDialog = $( "<div>" )
12540
+ .hide()
12541
+ .attr( {
12542
+
12543
+ // Setting tabIndex makes the div focusable
12544
+ tabIndex: -1,
12545
+ role: "dialog"
12546
+ } )
12547
+ .appendTo( this._appendTo() );
12548
+
12549
+ this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12550
+ this._on( this.uiDialog, {
12551
+ keydown: function( event ) {
12552
+ if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12553
+ event.keyCode === $.ui.keyCode.ESCAPE ) {
12554
+ event.preventDefault();
12555
+ this.close( event );
12556
+ return;
12557
+ }
12558
+
12559
+ // Prevent tabbing out of dialogs
12560
+ if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12561
+ return;
12562
+ }
12563
+ var tabbables = this.uiDialog.find( ":tabbable" ),
12564
+ first = tabbables.first(),
12565
+ last = tabbables.last();
12566
+
12567
+ if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12568
+ !event.shiftKey ) {
12569
+ this._delay( function() {
12570
+ first.trigger( "focus" );
12571
+ } );
12572
+ event.preventDefault();
12573
+ } else if ( ( event.target === first[ 0 ] ||
12574
+ event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12575
+ this._delay( function() {
12576
+ last.trigger( "focus" );
12577
+ } );
12578
+ event.preventDefault();
12579
+ }
12580
+ },
12581
+ mousedown: function( event ) {
12582
+ if ( this._moveToTop( event ) ) {
12583
+ this._focusTabbable();
12584
+ }
12585
+ }
12586
+ } );
12587
+
12588
+ // We assume that any existing aria-describedby attribute means
12589
+ // that the dialog content is marked up properly
12590
+ // otherwise we brute force the content as the description
12591
+ if ( !this.element.find( "[aria-describedby]" ).length ) {
12592
+ this.uiDialog.attr( {
12593
+ "aria-describedby": this.element.uniqueId().attr( "id" )
12594
+ } );
12595
+ }
12596
+ },
12597
+
12598
+ _createTitlebar: function() {
12599
+ var uiDialogTitle;
12600
+
12601
+ this.uiDialogTitlebar = $( "<div>" );
12602
+ this._addClass( this.uiDialogTitlebar,
12603
+ "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12604
+ this._on( this.uiDialogTitlebar, {
12605
+ mousedown: function( event ) {
12606
+
12607
+ // Don't prevent click on close button (#8838)
12608
+ // Focusing a dialog that is partially scrolled out of view
12609
+ // causes the browser to scroll it into view, preventing the click event
12610
+ if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12611
+
12612
+ // Dialog isn't getting focus when dragging (#8063)
12613
+ this.uiDialog.trigger( "focus" );
12614
+ }
12615
+ }
12616
+ } );
12617
+
12618
+ // Support: IE
12619
+ // Use type="button" to prevent enter keypresses in textboxes from closing the
12620
+ // dialog in IE (#9312)
12621
+ this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12622
+ .button( {
12623
+ label: $( "<a>" ).text( this.options.closeText ).html(),
12624
+ icon: "ui-icon-closethick",
12625
+ showLabel: false
12626
+ } )
12627
+ .appendTo( this.uiDialogTitlebar );
12628
+
12629
+ this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12630
+ this._on( this.uiDialogTitlebarClose, {
12631
+ click: function( event ) {
12632
+ event.preventDefault();
12633
+ this.close( event );
12634
+ }
12635
+ } );
12636
+
12637
+ uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
12638
+ this._addClass( uiDialogTitle, "ui-dialog-title" );
12639
+ this._title( uiDialogTitle );
12640
+
12641
+ this.uiDialogTitlebar.prependTo( this.uiDialog );
12642
+
12643
+ this.uiDialog.attr( {
12644
+ "aria-labelledby": uiDialogTitle.attr( "id" )
12645
+ } );
12646
+ },
12647
+
12648
+ _title: function( title ) {
12649
+ if ( this.options.title ) {
12650
+ title.text( this.options.title );
12651
+ } else {
12652
+ title.html( "&#160;" );
12653
+ }
12654
+ },
12655
+
12656
+ _createButtonPane: function() {
12657
+ this.uiDialogButtonPane = $( "<div>" );
12658
+ this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12659
+ "ui-widget-content ui-helper-clearfix" );
12660
+
12661
+ this.uiButtonSet = $( "<div>" )
12662
+ .appendTo( this.uiDialogButtonPane );
12663
+ this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12664
+
12665
+ this._createButtons();
12666
+ },
12667
+
12668
+ _createButtons: function() {
12669
+ var that = this,
12670
+ buttons = this.options.buttons;
12671
+
12672
+ // If we already have a button pane, remove it
12673
+ this.uiDialogButtonPane.remove();
12674
+ this.uiButtonSet.empty();
12675
+
12676
+ if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12677
+ this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12678
+ return;
12679
+ }
12680
+
12681
+ $.each( buttons, function( name, props ) {
12682
+ var click, buttonOptions;
12683
+ props = typeof props === "function" ?
12684
+ { click: props, text: name } :
12685
+ props;
12686
+
12687
+ // Default to a non-submitting button
12688
+ props = $.extend( { type: "button" }, props );
12689
+
12690
+ // Change the context for the click callback to be the main element
12691
+ click = props.click;
12692
+ buttonOptions = {
12693
+ icon: props.icon,
12694
+ iconPosition: props.iconPosition,
12695
+ showLabel: props.showLabel,
12696
+
12697
+ // Deprecated options
12698
+ icons: props.icons,
12699
+ text: props.text
12700
+ };
12701
+
12702
+ delete props.click;
12703
+ delete props.icon;
12704
+ delete props.iconPosition;
12705
+ delete props.showLabel;
12706
+
12707
+ // Deprecated options
12708
+ delete props.icons;
12709
+ if ( typeof props.text === "boolean" ) {
12710
+ delete props.text;
12711
+ }
12712
+
12713
+ $( "<button></button>", props )
12714
+ .button( buttonOptions )
12715
+ .appendTo( that.uiButtonSet )
12716
+ .on( "click", function() {
12717
+ click.apply( that.element[ 0 ], arguments );
12718
+ } );
12719
+ } );
12720
+ this._addClass( this.uiDialog, "ui-dialog-buttons" );
12721
+ this.uiDialogButtonPane.appendTo( this.uiDialog );
12722
+ },
12723
+
12724
+ _makeDraggable: function() {
12725
+ var that = this,
12726
+ options = this.options;
12727
+
12728
+ function filteredUi( ui ) {
12729
+ return {
12730
+ position: ui.position,
12731
+ offset: ui.offset
12732
+ };
12733
+ }
12734
+
12735
+ this.uiDialog.draggable( {
12736
+ cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12737
+ handle: ".ui-dialog-titlebar",
12738
+ containment: "document",
12739
+ start: function( event, ui ) {
12740
+ that._addClass( $( this ), "ui-dialog-dragging" );
12741
+ that._blockFrames();
12742
+ that._trigger( "dragStart", event, filteredUi( ui ) );
12743
+ },
12744
+ drag: function( event, ui ) {
12745
+ that._trigger( "drag", event, filteredUi( ui ) );
12746
+ },
12747
+ stop: function( event, ui ) {
12748
+ var left = ui.offset.left - that.document.scrollLeft(),
12749
+ top = ui.offset.top - that.document.scrollTop();
12750
+
12751
+ options.position = {
12752
+ my: "left top",
12753
+ at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12754
+ "top" + ( top >= 0 ? "+" : "" ) + top,
12755
+ of: that.window
12756
+ };
12757
+ that._removeClass( $( this ), "ui-dialog-dragging" );
12758
+ that._unblockFrames();
12759
+ that._trigger( "dragStop", event, filteredUi( ui ) );
12760
+ }
12761
+ } );
12762
+ },
12763
+
12764
+ _makeResizable: function() {
12765
+ var that = this,
12766
+ options = this.options,
12767
+ handles = options.resizable,
12768
+
12769
+ // .ui-resizable has position: relative defined in the stylesheet
12770
+ // but dialogs have to use absolute or fixed positioning
12771
+ position = this.uiDialog.css( "position" ),
12772
+ resizeHandles = typeof handles === "string" ?
12773
+ handles :
12774
+ "n,e,s,w,se,sw,ne,nw";
12775
+
12776
+ function filteredUi( ui ) {
12777
+ return {
12778
+ originalPosition: ui.originalPosition,
12779
+ originalSize: ui.originalSize,
12780
+ position: ui.position,
12781
+ size: ui.size
12782
+ };
12783
+ }
12784
+
12785
+ this.uiDialog.resizable( {
12786
+ cancel: ".ui-dialog-content",
12787
+ containment: "document",
12788
+ alsoResize: this.element,
12789
+ maxWidth: options.maxWidth,
12790
+ maxHeight: options.maxHeight,
12791
+ minWidth: options.minWidth,
12792
+ minHeight: this._minHeight(),
12793
+ handles: resizeHandles,
12794
+ start: function( event, ui ) {
12795
+ that._addClass( $( this ), "ui-dialog-resizing" );
12796
+ that._blockFrames();
12797
+ that._trigger( "resizeStart", event, filteredUi( ui ) );
12798
+ },
12799
+ resize: function( event, ui ) {
12800
+ that._trigger( "resize", event, filteredUi( ui ) );
12801
+ },
12802
+ stop: function( event, ui ) {
12803
+ var offset = that.uiDialog.offset(),
12804
+ left = offset.left - that.document.scrollLeft(),
12805
+ top = offset.top - that.document.scrollTop();
12806
+
12807
+ options.height = that.uiDialog.height();
12808
+ options.width = that.uiDialog.width();
12809
+ options.position = {
12810
+ my: "left top",
12811
+ at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12812
+ "top" + ( top >= 0 ? "+" : "" ) + top,
12813
+ of: that.window
12814
+ };
12815
+ that._removeClass( $( this ), "ui-dialog-resizing" );
12816
+ that._unblockFrames();
12817
+ that._trigger( "resizeStop", event, filteredUi( ui ) );
12818
+ }
12819
+ } )
12820
+ .css( "position", position );
12821
+ },
12822
+
12823
+ _trackFocus: function() {
12824
+ this._on( this.widget(), {
12825
+ focusin: function( event ) {
12826
+ this._makeFocusTarget();
12827
+ this._focusedElement = $( event.target );
12828
+ }
12829
+ } );
12830
+ },
12831
+
12832
+ _makeFocusTarget: function() {
12833
+ this._untrackInstance();
12834
+ this._trackingInstances().unshift( this );
12835
+ },
12836
+
12837
+ _untrackInstance: function() {
12838
+ var instances = this._trackingInstances(),
12839
+ exists = $.inArray( this, instances );
12840
+ if ( exists !== -1 ) {
12841
+ instances.splice( exists, 1 );
12842
+ }
12843
+ },
12844
+
12845
+ _trackingInstances: function() {
12846
+ var instances = this.document.data( "ui-dialog-instances" );
12847
+ if ( !instances ) {
12848
+ instances = [];
12849
+ this.document.data( "ui-dialog-instances", instances );
12850
+ }
12851
+ return instances;
12852
+ },
12853
+
12854
+ _minHeight: function() {
12855
+ var options = this.options;
12856
+
12857
+ return options.height === "auto" ?
12858
+ options.minHeight :
12859
+ Math.min( options.minHeight, options.height );
12860
+ },
12861
+
12862
+ _position: function() {
12863
+
12864
+ // Need to show the dialog to get the actual offset in the position plugin
12865
+ var isVisible = this.uiDialog.is( ":visible" );
12866
+ if ( !isVisible ) {
12867
+ this.uiDialog.show();
12868
+ }
12869
+ this.uiDialog.position( this.options.position );
12870
+ if ( !isVisible ) {
12871
+ this.uiDialog.hide();
12872
+ }
12873
+ },
12874
+
12875
+ _setOptions: function( options ) {
12876
+ var that = this,
12877
+ resize = false,
12878
+ resizableOptions = {};
12879
+
12880
+ $.each( options, function( key, value ) {
12881
+ that._setOption( key, value );
12882
+
12883
+ if ( key in that.sizeRelatedOptions ) {
12884
+ resize = true;
12885
+ }
12886
+ if ( key in that.resizableRelatedOptions ) {
12887
+ resizableOptions[ key ] = value;
12888
+ }
12889
+ } );
12890
+
12891
+ if ( resize ) {
12892
+ this._size();
12893
+ this._position();
12894
+ }
12895
+ if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12896
+ this.uiDialog.resizable( "option", resizableOptions );
12897
+ }
12898
+ },
12899
+
12900
+ _setOption: function( key, value ) {
12901
+ var isDraggable, isResizable,
12902
+ uiDialog = this.uiDialog;
12903
+
12904
+ if ( key === "disabled" ) {
12905
+ return;
12906
+ }
12907
+
12908
+ this._super( key, value );
12909
+
12910
+ if ( key === "appendTo" ) {
12911
+ this.uiDialog.appendTo( this._appendTo() );
12912
+ }
12913
+
12914
+ if ( key === "buttons" ) {
12915
+ this._createButtons();
12916
+ }
12917
+
12918
+ if ( key === "closeText" ) {
12919
+ this.uiDialogTitlebarClose.button( {
12920
+
12921
+ // Ensure that we always pass a string
12922
+ label: $( "<a>" ).text( "" + this.options.closeText ).html()
12923
+ } );
12924
+ }
12925
+
12926
+ if ( key === "draggable" ) {
12927
+ isDraggable = uiDialog.is( ":data(ui-draggable)" );
12928
+ if ( isDraggable && !value ) {
12929
+ uiDialog.draggable( "destroy" );
12930
+ }
12931
+
12932
+ if ( !isDraggable && value ) {
12933
+ this._makeDraggable();
12934
+ }
12935
+ }
12936
+
12937
+ if ( key === "position" ) {
12938
+ this._position();
12939
+ }
12940
+
12941
+ if ( key === "resizable" ) {
12942
+
12943
+ // currently resizable, becoming non-resizable
12944
+ isResizable = uiDialog.is( ":data(ui-resizable)" );
12945
+ if ( isResizable && !value ) {
12946
+ uiDialog.resizable( "destroy" );
12947
+ }
12948
+
12949
+ // Currently resizable, changing handles
12950
+ if ( isResizable && typeof value === "string" ) {
12951
+ uiDialog.resizable( "option", "handles", value );
12952
+ }
12953
+
12954
+ // Currently non-resizable, becoming resizable
12955
+ if ( !isResizable && value !== false ) {
12956
+ this._makeResizable();
12957
+ }
12958
+ }
12959
+
12960
+ if ( key === "title" ) {
12961
+ this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12962
+ }
12963
+ },
12964
+
12965
+ _size: function() {
12966
+
12967
+ // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12968
+ // divs will both have width and height set, so we need to reset them
12969
+ var nonContentHeight, minContentHeight, maxContentHeight,
12970
+ options = this.options;
12971
+
12972
+ // Reset content sizing
12973
+ this.element.show().css( {
12974
+ width: "auto",
12975
+ minHeight: 0,
12976
+ maxHeight: "none",
12977
+ height: 0
12978
+ } );
12979
+
12980
+ if ( options.minWidth > options.width ) {
12981
+ options.width = options.minWidth;
12982
+ }
12983
+
12984
+ // Reset wrapper sizing
12985
+ // determine the height of all the non-content elements
12986
+ nonContentHeight = this.uiDialog.css( {
12987
+ height: "auto",
12988
+ width: options.width
12989
+ } )
12990
+ .outerHeight();
12991
+ minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12992
+ maxContentHeight = typeof options.maxHeight === "number" ?
12993
+ Math.max( 0, options.maxHeight - nonContentHeight ) :
12994
+ "none";
12995
+
12996
+ if ( options.height === "auto" ) {
12997
+ this.element.css( {
12998
+ minHeight: minContentHeight,
12999
+ maxHeight: maxContentHeight,
13000
+ height: "auto"
13001
+ } );
13002
+ } else {
13003
+ this.element.height( Math.max( 0, options.height - nonContentHeight ) );
13004
+ }
13005
+
13006
+ if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
13007
+ this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
13008
+ }
13009
+ },
13010
+
13011
+ _blockFrames: function() {
13012
+ this.iframeBlocks = this.document.find( "iframe" ).map( function() {
13013
+ var iframe = $( this );
13014
+
13015
+ return $( "<div>" )
13016
+ .css( {
13017
+ position: "absolute",
13018
+ width: iframe.outerWidth(),
13019
+ height: iframe.outerHeight()
13020
+ } )
13021
+ .appendTo( iframe.parent() )
13022
+ .offset( iframe.offset() )[ 0 ];
13023
+ } );
13024
+ },
13025
+
13026
+ _unblockFrames: function() {
13027
+ if ( this.iframeBlocks ) {
13028
+ this.iframeBlocks.remove();
13029
+ delete this.iframeBlocks;
13030
+ }
13031
+ },
13032
+
13033
+ _allowInteraction: function( event ) {
13034
+ if ( $( event.target ).closest( ".ui-dialog" ).length ) {
13035
+ return true;
13036
+ }
13037
+
13038
+ // TODO: Remove hack when datepicker implements
13039
+ // the .ui-front logic (#8989)
13040
+ return !!$( event.target ).closest( ".ui-datepicker" ).length;
13041
+ },
13042
+
13043
+ _createOverlay: function() {
13044
+ if ( !this.options.modal ) {
13045
+ return;
13046
+ }
13047
+
13048
+ var jqMinor = $.fn.jquery.substring( 0, 4 );
13049
+
13050
+ // We use a delay in case the overlay is created from an
13051
+ // event that we're going to be cancelling (#2804)
13052
+ var isOpening = true;
13053
+ this._delay( function() {
13054
+ isOpening = false;
13055
+ } );
13056
+
13057
+ if ( !this.document.data( "ui-dialog-overlays" ) ) {
13058
+
13059
+ // Prevent use of anchors and inputs
13060
+ // This doesn't use `_on()` because it is a shared event handler
13061
+ // across all open modal dialogs.
13062
+ this.document.on( "focusin.ui-dialog", function( event ) {
13063
+ if ( isOpening ) {
13064
+ return;
13065
+ }
13066
+
13067
+ var instance = this._trackingInstances()[ 0 ];
13068
+ if ( !instance._allowInteraction( event ) ) {
13069
+ event.preventDefault();
13070
+ instance._focusTabbable();
13071
+
13072
+ // Support: jQuery >=3.4 <3.6 only
13073
+ // Focus re-triggering in jQuery 3.4/3.5 makes the original element
13074
+ // have its focus event propagated last, breaking the re-targeting.
13075
+ // Trigger focus in a delay in addition if needed to avoid the issue
13076
+ // See https://github.com/jquery/jquery/issues/4382
13077
+ if ( jqMinor === "3.4." || jqMinor === "3.5." ) {
13078
+ instance._delay( instance._restoreTabbableFocus );
13079
+ }
13080
+ }
13081
+ }.bind( this ) );
13082
+ }
13083
+
13084
+ this.overlay = $( "<div>" )
13085
+ .appendTo( this._appendTo() );
13086
+
13087
+ this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
13088
+ this._on( this.overlay, {
13089
+ mousedown: "_keepFocus"
13090
+ } );
13091
+ this.document.data( "ui-dialog-overlays",
13092
+ ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
13093
+ },
13094
+
13095
+ _destroyOverlay: function() {
13096
+ if ( !this.options.modal ) {
13097
+ return;
13098
+ }
13099
+
13100
+ if ( this.overlay ) {
13101
+ var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
13102
+
13103
+ if ( !overlays ) {
13104
+ this.document.off( "focusin.ui-dialog" );
13105
+ this.document.removeData( "ui-dialog-overlays" );
13106
+ } else {
13107
+ this.document.data( "ui-dialog-overlays", overlays );
13108
+ }
13109
+
13110
+ this.overlay.remove();
13111
+ this.overlay = null;
13112
+ }
13113
+ }
13114
+ } );
13115
+
13116
+ // DEPRECATED
13117
+ // TODO: switch return back to widget declaration at top of file when this is removed
13118
+ if ( $.uiBackCompat !== false ) {
13119
+
13120
+ // Backcompat for dialogClass option
13121
+ $.widget( "ui.dialog", $.ui.dialog, {
13122
+ options: {
13123
+ dialogClass: ""
13124
+ },
13125
+ _createWrapper: function() {
13126
+ this._super();
13127
+ this.uiDialog.addClass( this.options.dialogClass );
13128
+ },
13129
+ _setOption: function( key, value ) {
13130
+ if ( key === "dialogClass" ) {
13131
+ this.uiDialog
13132
+ .removeClass( this.options.dialogClass )
13133
+ .addClass( value );
13134
+ }
13135
+ this._superApply( arguments );
13136
+ }
13137
+ } );
13138
+ }
13139
+
13140
+ var widgetsDialog = $.ui.dialog;
13141
+
13142
+
13143
+ /*!
13144
+ * jQuery UI Droppable 1.13.1
13145
+ * http://jqueryui.com
13146
+ *
13147
+ * Copyright jQuery Foundation and other contributors
13148
+ * Released under the MIT license.
13149
+ * http://jquery.org/license
13150
+ */
13151
+
13152
+ //>>label: Droppable
13153
+ //>>group: Interactions
13154
+ //>>description: Enables drop targets for draggable elements.
13155
+ //>>docs: http://api.jqueryui.com/droppable/
13156
+ //>>demos: http://jqueryui.com/droppable/
13157
+
13158
+
13159
+ $.widget( "ui.droppable", {
13160
+ version: "1.13.1",
13161
+ widgetEventPrefix: "drop",
13162
+ options: {
13163
+ accept: "*",
13164
+ addClasses: true,
13165
+ greedy: false,
13166
+ scope: "default",
13167
+ tolerance: "intersect",
13168
+
13169
+ // Callbacks
13170
+ activate: null,
13171
+ deactivate: null,
13172
+ drop: null,
13173
+ out: null,
13174
+ over: null
13175
+ },
13176
+ _create: function() {
13177
+
13178
+ var proportions,
13179
+ o = this.options,
13180
+ accept = o.accept;
13181
+
13182
+ this.isover = false;
13183
+ this.isout = true;
13184
+
13185
+ this.accept = typeof accept === "function" ? accept : function( d ) {
13186
+ return d.is( accept );
13187
+ };
13188
+
13189
+ this.proportions = function( /* valueToWrite */ ) {
13190
+ if ( arguments.length ) {
13191
+
13192
+ // Store the droppable's proportions
13193
+ proportions = arguments[ 0 ];
13194
+ } else {
13195
+
13196
+ // Retrieve or derive the droppable's proportions
13197
+ return proportions ?
13198
+ proportions :
13199
+ proportions = {
13200
+ width: this.element[ 0 ].offsetWidth,
13201
+ height: this.element[ 0 ].offsetHeight
13202
+ };
13203
+ }
13204
+ };
13205
+
13206
+ this._addToManager( o.scope );
13207
+
13208
+ if ( o.addClasses ) {
13209
+ this._addClass( "ui-droppable" );
13210
+ }
13211
+
13212
+ },
13213
+
13214
+ _addToManager: function( scope ) {
13215
+
13216
+ // Add the reference and positions to the manager
13217
+ $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13218
+ $.ui.ddmanager.droppables[ scope ].push( this );
13219
+ },
13220
+
13221
+ _splice: function( drop ) {
13222
+ var i = 0;
13223
+ for ( ; i < drop.length; i++ ) {
13224
+ if ( drop[ i ] === this ) {
13225
+ drop.splice( i, 1 );
13226
+ }
13227
+ }
13228
+ },
13229
+
13230
+ _destroy: function() {
13231
+ var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13232
+
13233
+ this._splice( drop );
13234
+ },
13235
+
13236
+ _setOption: function( key, value ) {
13237
+
13238
+ if ( key === "accept" ) {
13239
+ this.accept = typeof value === "function" ? value : function( d ) {
13240
+ return d.is( value );
13241
+ };
13242
+ } else if ( key === "scope" ) {
13243
+ var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13244
+
13245
+ this._splice( drop );
13246
+ this._addToManager( value );
13247
+ }
13248
+
13249
+ this._super( key, value );
13250
+ },
13251
+
13252
+ _activate: function( event ) {
13253
+ var draggable = $.ui.ddmanager.current;
13254
+
13255
+ this._addActiveClass();
13256
+ if ( draggable ) {
13257
+ this._trigger( "activate", event, this.ui( draggable ) );
13258
+ }
13259
+ },
13260
+
13261
+ _deactivate: function( event ) {
13262
+ var draggable = $.ui.ddmanager.current;
13263
+
13264
+ this._removeActiveClass();
13265
+ if ( draggable ) {
13266
+ this._trigger( "deactivate", event, this.ui( draggable ) );
13267
+ }
13268
+ },
13269
+
13270
+ _over: function( event ) {
13271
+
13272
+ var draggable = $.ui.ddmanager.current;
13273
+
13274
+ // Bail if draggable and droppable are same element
13275
+ if ( !draggable || ( draggable.currentItem ||
13276
+ draggable.element )[ 0 ] === this.element[ 0 ] ) {
13277
+ return;
13278
+ }
13279
+
13280
+ if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13281
+ draggable.element ) ) ) {
13282
+ this._addHoverClass();
13283
+ this._trigger( "over", event, this.ui( draggable ) );
13284
+ }
13285
+
13286
+ },
13287
+
13288
+ _out: function( event ) {
13289
+
13290
+ var draggable = $.ui.ddmanager.current;
13291
+
13292
+ // Bail if draggable and droppable are same element
13293
+ if ( !draggable || ( draggable.currentItem ||
13294
+ draggable.element )[ 0 ] === this.element[ 0 ] ) {
13295
+ return;
13296
+ }
13297
+
13298
+ if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13299
+ draggable.element ) ) ) {
13300
+ this._removeHoverClass();
13301
+ this._trigger( "out", event, this.ui( draggable ) );
13302
+ }
13303
+
13304
+ },
13305
+
13306
+ _drop: function( event, custom ) {
13307
+
13308
+ var draggable = custom || $.ui.ddmanager.current,
13309
+ childrenIntersection = false;
13310
+
13311
+ // Bail if draggable and droppable are same element
13312
+ if ( !draggable || ( draggable.currentItem ||
13313
+ draggable.element )[ 0 ] === this.element[ 0 ] ) {
13314
+ return false;
13315
+ }
13316
+
13317
+ this.element
13318
+ .find( ":data(ui-droppable)" )
13319
+ .not( ".ui-draggable-dragging" )
13320
+ .each( function() {
13321
+ var inst = $( this ).droppable( "instance" );
13322
+ if (
13323
+ inst.options.greedy &&
13324
+ !inst.options.disabled &&
13325
+ inst.options.scope === draggable.options.scope &&
13326
+ inst.accept.call(
13327
+ inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13328
+ ) &&
13329
+ $.ui.intersect(
13330
+ draggable,
13331
+ $.extend( inst, { offset: inst.element.offset() } ),
13332
+ inst.options.tolerance, event
13333
+ )
13334
+ ) {
13335
+ childrenIntersection = true;
13336
+ return false;
13337
+ }
13338
+ } );
13339
+ if ( childrenIntersection ) {
13340
+ return false;
13341
+ }
13342
+
13343
+ if ( this.accept.call( this.element[ 0 ],
13344
+ ( draggable.currentItem || draggable.element ) ) ) {
13345
+ this._removeActiveClass();
13346
+ this._removeHoverClass();
13347
+
13348
+ this._trigger( "drop", event, this.ui( draggable ) );
13349
+ return this.element;
13350
+ }
13351
+
13352
+ return false;
13353
+
13354
+ },
13355
+
13356
+ ui: function( c ) {
13357
+ return {
13358
+ draggable: ( c.currentItem || c.element ),
13359
+ helper: c.helper,
13360
+ position: c.position,
13361
+ offset: c.positionAbs
13362
+ };
13363
+ },
13364
+
13365
+ // Extension points just to make backcompat sane and avoid duplicating logic
13366
+ // TODO: Remove in 1.14 along with call to it below
13367
+ _addHoverClass: function() {
13368
+ this._addClass( "ui-droppable-hover" );
13369
+ },
13370
+
13371
+ _removeHoverClass: function() {
13372
+ this._removeClass( "ui-droppable-hover" );
13373
+ },
13374
+
13375
+ _addActiveClass: function() {
13376
+ this._addClass( "ui-droppable-active" );
13377
+ },
13378
+
13379
+ _removeActiveClass: function() {
13380
+ this._removeClass( "ui-droppable-active" );
13381
+ }
13382
+ } );
13383
+
13384
+ $.ui.intersect = ( function() {
13385
+ function isOverAxis( x, reference, size ) {
13386
+ return ( x >= reference ) && ( x < ( reference + size ) );
13387
+ }
13388
+
13389
+ return function( draggable, droppable, toleranceMode, event ) {
13390
+
13391
+ if ( !droppable.offset ) {
13392
+ return false;
13393
+ }
13394
+
13395
+ var x1 = ( draggable.positionAbs ||
13396
+ draggable.position.absolute ).left + draggable.margins.left,
13397
+ y1 = ( draggable.positionAbs ||
13398
+ draggable.position.absolute ).top + draggable.margins.top,
13399
+ x2 = x1 + draggable.helperProportions.width,
13400
+ y2 = y1 + draggable.helperProportions.height,
13401
+ l = droppable.offset.left,
13402
+ t = droppable.offset.top,
13403
+ r = l + droppable.proportions().width,
13404
+ b = t + droppable.proportions().height;
13405
+
13406
+ switch ( toleranceMode ) {
13407
+ case "fit":
13408
+ return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13409
+ case "intersect":
13410
+ return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13411
+ x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13412
+ t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13413
+ y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13414
+ case "pointer":
13415
+ return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13416
+ isOverAxis( event.pageX, l, droppable.proportions().width );
13417
+ case "touch":
13418
+ return (
13419
+ ( y1 >= t && y1 <= b ) || // Top edge touching
13420
+ ( y2 >= t && y2 <= b ) || // Bottom edge touching
13421
+ ( y1 < t && y2 > b ) // Surrounded vertically
13422
+ ) && (
13423
+ ( x1 >= l && x1 <= r ) || // Left edge touching
13424
+ ( x2 >= l && x2 <= r ) || // Right edge touching
13425
+ ( x1 < l && x2 > r ) // Surrounded horizontally
13426
+ );
13427
+ default:
13428
+ return false;
13429
+ }
13430
+ };
13431
+ } )();
13432
+
13433
+ /*
13434
+ This manager tracks offsets of draggables and droppables
13435
+ */
13436
+ $.ui.ddmanager = {
13437
+ current: null,
13438
+ droppables: { "default": [] },
13439
+ prepareOffsets: function( t, event ) {
13440
+
13441
+ var i, j,
13442
+ m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13443
+ type = event ? event.type : null, // workaround for #2317
13444
+ list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13445
+
13446
+ droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13447
+
13448
+ // No disabled and non-accepted
13449
+ if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13450
+ ( t.currentItem || t.element ) ) ) ) {
13451
+ continue;
13452
+ }
13453
+
13454
+ // Filter out elements in the current dragged item
13455
+ for ( j = 0; j < list.length; j++ ) {
13456
+ if ( list[ j ] === m[ i ].element[ 0 ] ) {
13457
+ m[ i ].proportions().height = 0;
13458
+ continue droppablesLoop;
13459
+ }
13460
+ }
13461
+
13462
+ m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13463
+ if ( !m[ i ].visible ) {
13464
+ continue;
13465
+ }
13466
+
13467
+ // Activate the droppable if used directly from draggables
13468
+ if ( type === "mousedown" ) {
13469
+ m[ i ]._activate.call( m[ i ], event );
13470
+ }
13471
+
13472
+ m[ i ].offset = m[ i ].element.offset();
13473
+ m[ i ].proportions( {
13474
+ width: m[ i ].element[ 0 ].offsetWidth,
13475
+ height: m[ i ].element[ 0 ].offsetHeight
13476
+ } );
13477
+
13478
+ }
13479
+
13480
+ },
13481
+ drop: function( draggable, event ) {
13482
+
13483
+ var dropped = false;
13484
+
13485
+ // Create a copy of the droppables in case the list changes during the drop (#9116)
13486
+ $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13487
+
13488
+ if ( !this.options ) {
13489
+ return;
13490
+ }
13491
+ if ( !this.options.disabled && this.visible &&
13492
+ $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13493
+ dropped = this._drop.call( this, event ) || dropped;
13494
+ }
13495
+
13496
+ if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13497
+ ( draggable.currentItem || draggable.element ) ) ) {
13498
+ this.isout = true;
13499
+ this.isover = false;
13500
+ this._deactivate.call( this, event );
13501
+ }
13502
+
13503
+ } );
13504
+ return dropped;
13505
+
13506
+ },
13507
+ dragStart: function( draggable, event ) {
13508
+
13509
+ // Listen for scrolling so that if the dragging causes scrolling the position of the
13510
+ // droppables can be recalculated (see #5003)
13511
+ draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13512
+ if ( !draggable.options.refreshPositions ) {
13513
+ $.ui.ddmanager.prepareOffsets( draggable, event );
13514
+ }
13515
+ } );
13516
+ },
13517
+ drag: function( draggable, event ) {
13518
+
13519
+ // If you have a highly dynamic page, you might try this option. It renders positions
13520
+ // every time you move the mouse.
13521
+ if ( draggable.options.refreshPositions ) {
13522
+ $.ui.ddmanager.prepareOffsets( draggable, event );
13523
+ }
13524
+
13525
+ // Run through all droppables and check their positions based on specific tolerance options
13526
+ $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13527
+
13528
+ if ( this.options.disabled || this.greedyChild || !this.visible ) {
13529
+ return;
13530
+ }
13531
+
13532
+ var parentInstance, scope, parent,
13533
+ intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13534
+ c = !intersects && this.isover ?
13535
+ "isout" :
13536
+ ( intersects && !this.isover ? "isover" : null );
13537
+ if ( !c ) {
13538
+ return;
13539
+ }
13540
+
13541
+ if ( this.options.greedy ) {
13542
+
13543
+ // find droppable parents with same scope
13544
+ scope = this.options.scope;
13545
+ parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13546
+ return $( this ).droppable( "instance" ).options.scope === scope;
13547
+ } );
13548
+
13549
+ if ( parent.length ) {
13550
+ parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13551
+ parentInstance.greedyChild = ( c === "isover" );
13552
+ }
13553
+ }
13554
+
13555
+ // We just moved into a greedy child
13556
+ if ( parentInstance && c === "isover" ) {
13557
+ parentInstance.isover = false;
13558
+ parentInstance.isout = true;
13559
+ parentInstance._out.call( parentInstance, event );
13560
+ }
13561
+
13562
+ this[ c ] = true;
13563
+ this[ c === "isout" ? "isover" : "isout" ] = false;
13564
+ this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13565
+
13566
+ // We just moved out of a greedy child
13567
+ if ( parentInstance && c === "isout" ) {
13568
+ parentInstance.isout = false;
13569
+ parentInstance.isover = true;
13570
+ parentInstance._over.call( parentInstance, event );
13571
+ }
13572
+ } );
13573
+
13574
+ },
13575
+ dragStop: function( draggable, event ) {
13576
+ draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13577
+
13578
+ // Call prepareOffsets one final time since IE does not fire return scroll events when
13579
+ // overflow was caused by drag (see #5003)
13580
+ if ( !draggable.options.refreshPositions ) {
13581
+ $.ui.ddmanager.prepareOffsets( draggable, event );
13582
+ }
13583
+ }
13584
+ };
13585
+
13586
+ // DEPRECATED
13587
+ // TODO: switch return back to widget declaration at top of file when this is removed
13588
+ if ( $.uiBackCompat !== false ) {
13589
+
13590
+ // Backcompat for activeClass and hoverClass options
13591
+ $.widget( "ui.droppable", $.ui.droppable, {
13592
+ options: {
13593
+ hoverClass: false,
13594
+ activeClass: false
13595
+ },
13596
+ _addActiveClass: function() {
13597
+ this._super();
13598
+ if ( this.options.activeClass ) {
13599
+ this.element.addClass( this.options.activeClass );
13600
+ }
13601
+ },
13602
+ _removeActiveClass: function() {
13603
+ this._super();
13604
+ if ( this.options.activeClass ) {
13605
+ this.element.removeClass( this.options.activeClass );
13606
+ }
13607
+ },
13608
+ _addHoverClass: function() {
13609
+ this._super();
13610
+ if ( this.options.hoverClass ) {
13611
+ this.element.addClass( this.options.hoverClass );
13612
+ }
13613
+ },
13614
+ _removeHoverClass: function() {
13615
+ this._super();
13616
+ if ( this.options.hoverClass ) {
13617
+ this.element.removeClass( this.options.hoverClass );
13618
+ }
13619
+ }
13620
+ } );
13621
+ }
13622
+
13623
+ var widgetsDroppable = $.ui.droppable;
13624
+
13625
+
13626
+ /*!
13627
+ * jQuery UI Progressbar 1.13.1
13628
+ * http://jqueryui.com
13629
+ *
13630
+ * Copyright jQuery Foundation and other contributors
13631
+ * Released under the MIT license.
13632
+ * http://jquery.org/license
13633
+ */
13634
+
13635
+ //>>label: Progressbar
13636
+ //>>group: Widgets
13637
+ /* eslint-disable max-len */
13638
+ //>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13639
+ /* eslint-enable max-len */
13640
+ //>>docs: http://api.jqueryui.com/progressbar/
13641
+ //>>demos: http://jqueryui.com/progressbar/
13642
+ //>>css.structure: ../../themes/base/core.css
13643
+ //>>css.structure: ../../themes/base/progressbar.css
13644
+ //>>css.theme: ../../themes/base/theme.css
13645
+
13646
+
13647
+ var widgetsProgressbar = $.widget( "ui.progressbar", {
13648
+ version: "1.13.1",
13649
+ options: {
13650
+ classes: {
13651
+ "ui-progressbar": "ui-corner-all",
13652
+ "ui-progressbar-value": "ui-corner-left",
13653
+ "ui-progressbar-complete": "ui-corner-right"
13654
+ },
13655
+ max: 100,
13656
+ value: 0,
13657
+
13658
+ change: null,
13659
+ complete: null
13660
+ },
13661
+
13662
+ min: 0,
13663
+
13664
+ _create: function() {
13665
+
13666
+ // Constrain initial value
13667
+ this.oldValue = this.options.value = this._constrainedValue();
13668
+
13669
+ this.element.attr( {
13670
+
13671
+ // Only set static values; aria-valuenow and aria-valuemax are
13672
+ // set inside _refreshValue()
13673
+ role: "progressbar",
13674
+ "aria-valuemin": this.min
13675
+ } );
13676
+ this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13677
+
13678
+ this.valueDiv = $( "<div>" ).appendTo( this.element );
13679
+ this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13680
+ this._refreshValue();
13681
+ },
13682
+
13683
+ _destroy: function() {
13684
+ this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13685
+
13686
+ this.valueDiv.remove();
13687
+ },
13688
+
13689
+ value: function( newValue ) {
13690
+ if ( newValue === undefined ) {
13691
+ return this.options.value;
13692
+ }
13693
+
13694
+ this.options.value = this._constrainedValue( newValue );
13695
+ this._refreshValue();
13696
+ },
13697
+
13698
+ _constrainedValue: function( newValue ) {
13699
+ if ( newValue === undefined ) {
13700
+ newValue = this.options.value;
13701
+ }
13702
+
13703
+ this.indeterminate = newValue === false;
13704
+
13705
+ // Sanitize value
13706
+ if ( typeof newValue !== "number" ) {
13707
+ newValue = 0;
13708
+ }
13709
+
13710
+ return this.indeterminate ? false :
13711
+ Math.min( this.options.max, Math.max( this.min, newValue ) );
13712
+ },
13713
+
13714
+ _setOptions: function( options ) {
13715
+
13716
+ // Ensure "value" option is set after other values (like max)
13717
+ var value = options.value;
13718
+ delete options.value;
13719
+
13720
+ this._super( options );
13721
+
13722
+ this.options.value = this._constrainedValue( value );
13723
+ this._refreshValue();
13724
+ },
13725
+
13726
+ _setOption: function( key, value ) {
13727
+ if ( key === "max" ) {
13728
+
13729
+ // Don't allow a max less than min
13730
+ value = Math.max( this.min, value );
13731
+ }
13732
+ this._super( key, value );
13733
+ },
13734
+
13735
+ _setOptionDisabled: function( value ) {
13736
+ this._super( value );
13737
+
13738
+ this.element.attr( "aria-disabled", value );
13739
+ this._toggleClass( null, "ui-state-disabled", !!value );
13740
+ },
13741
+
13742
+ _percentage: function() {
13743
+ return this.indeterminate ?
13744
+ 100 :
13745
+ 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13746
+ },
13747
+
13748
+ _refreshValue: function() {
13749
+ var value = this.options.value,
13750
+ percentage = this._percentage();
13751
+
13752
+ this.valueDiv
13753
+ .toggle( this.indeterminate || value > this.min )
13754
+ .width( percentage.toFixed( 0 ) + "%" );
13755
+
13756
+ this
13757
+ ._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13758
+ value === this.options.max )
13759
+ ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13760
+
13761
+ if ( this.indeterminate ) {
13762
+ this.element.removeAttr( "aria-valuenow" );
13763
+ if ( !this.overlayDiv ) {
13764
+ this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13765
+ this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13766
+ }
13767
+ } else {
13768
+ this.element.attr( {
13769
+ "aria-valuemax": this.options.max,
13770
+ "aria-valuenow": value
13771
+ } );
13772
+ if ( this.overlayDiv ) {
13773
+ this.overlayDiv.remove();
13774
+ this.overlayDiv = null;
13775
+ }
13776
+ }
13777
+
13778
+ if ( this.oldValue !== value ) {
13779
+ this.oldValue = value;
13780
+ this._trigger( "change" );
13781
+ }
13782
+ if ( value === this.options.max ) {
13783
+ this._trigger( "complete" );
13784
+ }
13785
+ }
13786
+ } );
13787
+
13788
+
13789
+ /*!
13790
+ * jQuery UI Selectable 1.13.1
13791
+ * http://jqueryui.com
13792
+ *
13793
+ * Copyright jQuery Foundation and other contributors
13794
+ * Released under the MIT license.
13795
+ * http://jquery.org/license
13796
+ */
13797
+
13798
+ //>>label: Selectable
13799
+ //>>group: Interactions
13800
+ //>>description: Allows groups of elements to be selected with the mouse.
13801
+ //>>docs: http://api.jqueryui.com/selectable/
13802
+ //>>demos: http://jqueryui.com/selectable/
13803
+ //>>css.structure: ../../themes/base/selectable.css
13804
+
13805
+
13806
+ var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13807
+ version: "1.13.1",
13808
+ options: {
13809
+ appendTo: "body",
13810
+ autoRefresh: true,
13811
+ distance: 0,
13812
+ filter: "*",
13813
+ tolerance: "touch",
13814
+
13815
+ // Callbacks
13816
+ selected: null,
13817
+ selecting: null,
13818
+ start: null,
13819
+ stop: null,
13820
+ unselected: null,
13821
+ unselecting: null
13822
+ },
13823
+ _create: function() {
13824
+ var that = this;
13825
+
13826
+ this._addClass( "ui-selectable" );
13827
+
13828
+ this.dragged = false;
13829
+
13830
+ // Cache selectee children based on filter
13831
+ this.refresh = function() {
13832
+ that.elementPos = $( that.element[ 0 ] ).offset();
13833
+ that.selectees = $( that.options.filter, that.element[ 0 ] );
13834
+ that._addClass( that.selectees, "ui-selectee" );
13835
+ that.selectees.each( function() {
13836
+ var $this = $( this ),
13837
+ selecteeOffset = $this.offset(),
13838
+ pos = {
13839
+ left: selecteeOffset.left - that.elementPos.left,
13840
+ top: selecteeOffset.top - that.elementPos.top
13841
+ };
13842
+ $.data( this, "selectable-item", {
13843
+ element: this,
13844
+ $element: $this,
13845
+ left: pos.left,
13846
+ top: pos.top,
13847
+ right: pos.left + $this.outerWidth(),
13848
+ bottom: pos.top + $this.outerHeight(),
13849
+ startselected: false,
13850
+ selected: $this.hasClass( "ui-selected" ),
13851
+ selecting: $this.hasClass( "ui-selecting" ),
13852
+ unselecting: $this.hasClass( "ui-unselecting" )
13853
+ } );
13854
+ } );
13855
+ };
13856
+ this.refresh();
13857
+
13858
+ this._mouseInit();
13859
+
13860
+ this.helper = $( "<div>" );
13861
+ this._addClass( this.helper, "ui-selectable-helper" );
13862
+ },
13863
+
13864
+ _destroy: function() {
13865
+ this.selectees.removeData( "selectable-item" );
13866
+ this._mouseDestroy();
13867
+ },
13868
+
13869
+ _mouseStart: function( event ) {
13870
+ var that = this,
13871
+ options = this.options;
13872
+
13873
+ this.opos = [ event.pageX, event.pageY ];
13874
+ this.elementPos = $( this.element[ 0 ] ).offset();
13875
+
13876
+ if ( this.options.disabled ) {
13877
+ return;
13878
+ }
13879
+
13880
+ this.selectees = $( options.filter, this.element[ 0 ] );
13881
+
13882
+ this._trigger( "start", event );
13883
+
13884
+ $( options.appendTo ).append( this.helper );
13885
+
13886
+ // position helper (lasso)
13887
+ this.helper.css( {
13888
+ "left": event.pageX,
13889
+ "top": event.pageY,
13890
+ "width": 0,
13891
+ "height": 0
13892
+ } );
13893
+
13894
+ if ( options.autoRefresh ) {
13895
+ this.refresh();
13896
+ }
13897
+
13898
+ this.selectees.filter( ".ui-selected" ).each( function() {
13899
+ var selectee = $.data( this, "selectable-item" );
13900
+ selectee.startselected = true;
13901
+ if ( !event.metaKey && !event.ctrlKey ) {
13902
+ that._removeClass( selectee.$element, "ui-selected" );
13903
+ selectee.selected = false;
13904
+ that._addClass( selectee.$element, "ui-unselecting" );
13905
+ selectee.unselecting = true;
13906
+
13907
+ // selectable UNSELECTING callback
13908
+ that._trigger( "unselecting", event, {
13909
+ unselecting: selectee.element
13910
+ } );
13911
+ }
13912
+ } );
13913
+
13914
+ $( event.target ).parents().addBack().each( function() {
13915
+ var doSelect,
13916
+ selectee = $.data( this, "selectable-item" );
13917
+ if ( selectee ) {
13918
+ doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13919
+ !selectee.$element.hasClass( "ui-selected" );
13920
+ that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13921
+ ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13922
+ selectee.unselecting = !doSelect;
13923
+ selectee.selecting = doSelect;
13924
+ selectee.selected = doSelect;
13925
+
13926
+ // selectable (UN)SELECTING callback
13927
+ if ( doSelect ) {
13928
+ that._trigger( "selecting", event, {
13929
+ selecting: selectee.element
13930
+ } );
13931
+ } else {
13932
+ that._trigger( "unselecting", event, {
13933
+ unselecting: selectee.element
13934
+ } );
13935
+ }
13936
+ return false;
13937
+ }
13938
+ } );
13939
+
13940
+ },
13941
+
13942
+ _mouseDrag: function( event ) {
13943
+
13944
+ this.dragged = true;
13945
+
13946
+ if ( this.options.disabled ) {
13947
+ return;
13948
+ }
13949
+
13950
+ var tmp,
13951
+ that = this,
13952
+ options = this.options,
13953
+ x1 = this.opos[ 0 ],
13954
+ y1 = this.opos[ 1 ],
13955
+ x2 = event.pageX,
13956
+ y2 = event.pageY;
13957
+
13958
+ if ( x1 > x2 ) {
13959
+ tmp = x2; x2 = x1; x1 = tmp;
13960
+ }
13961
+ if ( y1 > y2 ) {
13962
+ tmp = y2; y2 = y1; y1 = tmp;
13963
+ }
13964
+ this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13965
+
13966
+ this.selectees.each( function() {
13967
+ var selectee = $.data( this, "selectable-item" ),
13968
+ hit = false,
13969
+ offset = {};
13970
+
13971
+ //prevent helper from being selected if appendTo: selectable
13972
+ if ( !selectee || selectee.element === that.element[ 0 ] ) {
13973
+ return;
13974
+ }
13975
+
13976
+ offset.left = selectee.left + that.elementPos.left;
13977
+ offset.right = selectee.right + that.elementPos.left;
13978
+ offset.top = selectee.top + that.elementPos.top;
13979
+ offset.bottom = selectee.bottom + that.elementPos.top;
13980
+
13981
+ if ( options.tolerance === "touch" ) {
13982
+ hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13983
+ offset.bottom < y1 ) );
13984
+ } else if ( options.tolerance === "fit" ) {
13985
+ hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13986
+ offset.bottom < y2 );
13987
+ }
13988
+
13989
+ if ( hit ) {
13990
+
13991
+ // SELECT
13992
+ if ( selectee.selected ) {
13993
+ that._removeClass( selectee.$element, "ui-selected" );
13994
+ selectee.selected = false;
13995
+ }
13996
+ if ( selectee.unselecting ) {
13997
+ that._removeClass( selectee.$element, "ui-unselecting" );
13998
+ selectee.unselecting = false;
13999
+ }
14000
+ if ( !selectee.selecting ) {
14001
+ that._addClass( selectee.$element, "ui-selecting" );
14002
+ selectee.selecting = true;
14003
+
14004
+ // selectable SELECTING callback
14005
+ that._trigger( "selecting", event, {
14006
+ selecting: selectee.element
14007
+ } );
14008
+ }
14009
+ } else {
14010
+
14011
+ // UNSELECT
14012
+ if ( selectee.selecting ) {
14013
+ if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
14014
+ that._removeClass( selectee.$element, "ui-selecting" );
14015
+ selectee.selecting = false;
14016
+ that._addClass( selectee.$element, "ui-selected" );
14017
+ selectee.selected = true;
14018
+ } else {
14019
+ that._removeClass( selectee.$element, "ui-selecting" );
14020
+ selectee.selecting = false;
14021
+ if ( selectee.startselected ) {
14022
+ that._addClass( selectee.$element, "ui-unselecting" );
14023
+ selectee.unselecting = true;
14024
+ }
14025
+
14026
+ // selectable UNSELECTING callback
14027
+ that._trigger( "unselecting", event, {
14028
+ unselecting: selectee.element
14029
+ } );
14030
+ }
14031
+ }
14032
+ if ( selectee.selected ) {
14033
+ if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
14034
+ that._removeClass( selectee.$element, "ui-selected" );
14035
+ selectee.selected = false;
14036
+
14037
+ that._addClass( selectee.$element, "ui-unselecting" );
14038
+ selectee.unselecting = true;
14039
+
14040
+ // selectable UNSELECTING callback
14041
+ that._trigger( "unselecting", event, {
14042
+ unselecting: selectee.element
14043
+ } );
14044
+ }
14045
+ }
14046
+ }
14047
+ } );
14048
+
14049
+ return false;
14050
+ },
14051
+
14052
+ _mouseStop: function( event ) {
14053
+ var that = this;
14054
+
14055
+ this.dragged = false;
14056
+
14057
+ $( ".ui-unselecting", this.element[ 0 ] ).each( function() {
14058
+ var selectee = $.data( this, "selectable-item" );
14059
+ that._removeClass( selectee.$element, "ui-unselecting" );
14060
+ selectee.unselecting = false;
14061
+ selectee.startselected = false;
14062
+ that._trigger( "unselected", event, {
14063
+ unselected: selectee.element
14064
+ } );
14065
+ } );
14066
+ $( ".ui-selecting", this.element[ 0 ] ).each( function() {
14067
+ var selectee = $.data( this, "selectable-item" );
14068
+ that._removeClass( selectee.$element, "ui-selecting" )
14069
+ ._addClass( selectee.$element, "ui-selected" );
14070
+ selectee.selecting = false;
14071
+ selectee.selected = true;
14072
+ selectee.startselected = true;
14073
+ that._trigger( "selected", event, {
14074
+ selected: selectee.element
14075
+ } );
14076
+ } );
14077
+ this._trigger( "stop", event );
14078
+
14079
+ this.helper.remove();
14080
+
14081
+ return false;
14082
+ }
14083
+
14084
+ } );
14085
+
14086
+
14087
+ /*!
14088
+ * jQuery UI Selectmenu 1.13.1
14089
+ * http://jqueryui.com
14090
+ *
14091
+ * Copyright jQuery Foundation and other contributors
14092
+ * Released under the MIT license.
14093
+ * http://jquery.org/license
14094
+ */
14095
+
14096
+ //>>label: Selectmenu
14097
+ //>>group: Widgets
14098
+ /* eslint-disable max-len */
14099
+ //>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
14100
+ /* eslint-enable max-len */
14101
+ //>>docs: http://api.jqueryui.com/selectmenu/
14102
+ //>>demos: http://jqueryui.com/selectmenu/
14103
+ //>>css.structure: ../../themes/base/core.css
14104
+ //>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
14105
+ //>>css.theme: ../../themes/base/theme.css
14106
+
14107
+
14108
+ var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
14109
+ version: "1.13.1",
14110
+ defaultElement: "<select>",
14111
+ options: {
14112
+ appendTo: null,
14113
+ classes: {
14114
+ "ui-selectmenu-button-open": "ui-corner-top",
14115
+ "ui-selectmenu-button-closed": "ui-corner-all"
14116
+ },
14117
+ disabled: null,
14118
+ icons: {
14119
+ button: "ui-icon-triangle-1-s"
14120
+ },
14121
+ position: {
14122
+ my: "left top",
14123
+ at: "left bottom",
14124
+ collision: "none"
14125
+ },
14126
+ width: false,
14127
+
14128
+ // Callbacks
14129
+ change: null,
14130
+ close: null,
14131
+ focus: null,
14132
+ open: null,
14133
+ select: null
14134
+ },
14135
+
14136
+ _create: function() {
14137
+ var selectmenuId = this.element.uniqueId().attr( "id" );
14138
+ this.ids = {
14139
+ element: selectmenuId,
14140
+ button: selectmenuId + "-button",
14141
+ menu: selectmenuId + "-menu"
14142
+ };
14143
+
14144
+ this._drawButton();
14145
+ this._drawMenu();
14146
+ this._bindFormResetHandler();
14147
+
14148
+ this._rendered = false;
14149
+ this.menuItems = $();
14150
+ },
14151
+
14152
+ _drawButton: function() {
14153
+ var icon,
14154
+ that = this,
14155
+ item = this._parseOption(
14156
+ this.element.find( "option:selected" ),
14157
+ this.element[ 0 ].selectedIndex
14158
+ );
14159
+
14160
+ // Associate existing label with the new button
14161
+ this.labels = this.element.labels().attr( "for", this.ids.button );
14162
+ this._on( this.labels, {
14163
+ click: function( event ) {
14164
+ this.button.trigger( "focus" );
14165
+ event.preventDefault();
14166
+ }
14167
+ } );
14168
+
14169
+ // Hide original select element
14170
+ this.element.hide();
14171
+
14172
+ // Create button
14173
+ this.button = $( "<span>", {
14174
+ tabindex: this.options.disabled ? -1 : 0,
14175
+ id: this.ids.button,
14176
+ role: "combobox",
14177
+ "aria-expanded": "false",
14178
+ "aria-autocomplete": "list",
14179
+ "aria-owns": this.ids.menu,
14180
+ "aria-haspopup": "true",
14181
+ title: this.element.attr( "title" )
14182
+ } )
14183
+ .insertAfter( this.element );
14184
+
14185
+ this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14186
+ "ui-button ui-widget" );
14187
+
14188
+ icon = $( "<span>" ).appendTo( this.button );
14189
+ this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14190
+ this.buttonItem = this._renderButtonItem( item )
14191
+ .appendTo( this.button );
14192
+
14193
+ if ( this.options.width !== false ) {
14194
+ this._resizeButton();
14195
+ }
14196
+
14197
+ this._on( this.button, this._buttonEvents );
14198
+ this.button.one( "focusin", function() {
14199
+
14200
+ // Delay rendering the menu items until the button receives focus.
14201
+ // The menu may have already been rendered via a programmatic open.
14202
+ if ( !that._rendered ) {
14203
+ that._refreshMenu();
14204
+ }
14205
+ } );
14206
+ },
14207
+
14208
+ _drawMenu: function() {
14209
+ var that = this;
14210
+
14211
+ // Create menu
14212
+ this.menu = $( "<ul>", {
14213
+ "aria-hidden": "true",
14214
+ "aria-labelledby": this.ids.button,
14215
+ id: this.ids.menu
14216
+ } );
14217
+
14218
+ // Wrap menu
14219
+ this.menuWrap = $( "<div>" ).append( this.menu );
14220
+ this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14221
+ this.menuWrap.appendTo( this._appendTo() );
14222
+
14223
+ // Initialize menu widget
14224
+ this.menuInstance = this.menu
14225
+ .menu( {
14226
+ classes: {
14227
+ "ui-menu": "ui-corner-bottom"
14228
+ },
14229
+ role: "listbox",
14230
+ select: function( event, ui ) {
14231
+ event.preventDefault();
14232
+
14233
+ // Support: IE8
14234
+ // If the item was selected via a click, the text selection
14235
+ // will be destroyed in IE
14236
+ that._setSelection();
14237
+
14238
+ that._select( ui.item.data( "ui-selectmenu-item" ), event );
14239
+ },
14240
+ focus: function( event, ui ) {
14241
+ var item = ui.item.data( "ui-selectmenu-item" );
14242
+
14243
+ // Prevent inital focus from firing and check if its a newly focused item
14244
+ if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14245
+ that._trigger( "focus", event, { item: item } );
14246
+ if ( !that.isOpen ) {
14247
+ that._select( item, event );
14248
+ }
14249
+ }
14250
+ that.focusIndex = item.index;
14251
+
14252
+ that.button.attr( "aria-activedescendant",
14253
+ that.menuItems.eq( item.index ).attr( "id" ) );
14254
+ }
14255
+ } )
14256
+ .menu( "instance" );
14257
+
14258
+ // Don't close the menu on mouseleave
14259
+ this.menuInstance._off( this.menu, "mouseleave" );
14260
+
14261
+ // Cancel the menu's collapseAll on document click
14262
+ this.menuInstance._closeOnDocumentClick = function() {
14263
+ return false;
14264
+ };
14265
+
14266
+ // Selects often contain empty items, but never contain dividers
14267
+ this.menuInstance._isDivider = function() {
14268
+ return false;
14269
+ };
14270
+ },
14271
+
14272
+ refresh: function() {
14273
+ this._refreshMenu();
14274
+ this.buttonItem.replaceWith(
14275
+ this.buttonItem = this._renderButtonItem(
14276
+
14277
+ // Fall back to an empty object in case there are no options
14278
+ this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14279
+ )
14280
+ );
14281
+ if ( this.options.width === null ) {
14282
+ this._resizeButton();
14283
+ }
14284
+ },
14285
+
14286
+ _refreshMenu: function() {
14287
+ var item,
14288
+ options = this.element.find( "option" );
14289
+
14290
+ this.menu.empty();
14291
+
14292
+ this._parseOptions( options );
14293
+ this._renderMenu( this.menu, this.items );
14294
+
14295
+ this.menuInstance.refresh();
14296
+ this.menuItems = this.menu.find( "li" )
14297
+ .not( ".ui-selectmenu-optgroup" )
14298
+ .find( ".ui-menu-item-wrapper" );
14299
+
14300
+ this._rendered = true;
14301
+
14302
+ if ( !options.length ) {
14303
+ return;
14304
+ }
14305
+
14306
+ item = this._getSelectedItem();
14307
+
14308
+ // Update the menu to have the correct item focused
14309
+ this.menuInstance.focus( null, item );
14310
+ this._setAria( item.data( "ui-selectmenu-item" ) );
14311
+
14312
+ // Set disabled state
14313
+ this._setOption( "disabled", this.element.prop( "disabled" ) );
14314
+ },
14315
+
14316
+ open: function( event ) {
14317
+ if ( this.options.disabled ) {
14318
+ return;
14319
+ }
14320
+
14321
+ // If this is the first time the menu is being opened, render the items
14322
+ if ( !this._rendered ) {
14323
+ this._refreshMenu();
14324
+ } else {
14325
+
14326
+ // Menu clears focus on close, reset focus to selected item
14327
+ this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14328
+ this.menuInstance.focus( null, this._getSelectedItem() );
14329
+ }
14330
+
14331
+ // If there are no options, don't open the menu
14332
+ if ( !this.menuItems.length ) {
14333
+ return;
14334
+ }
14335
+
14336
+ this.isOpen = true;
14337
+ this._toggleAttr();
14338
+ this._resizeMenu();
14339
+ this._position();
14340
+
14341
+ this._on( this.document, this._documentClick );
14342
+
14343
+ this._trigger( "open", event );
14344
+ },
14345
+
14346
+ _position: function() {
14347
+ this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14348
+ },
14349
+
14350
+ close: function( event ) {
14351
+ if ( !this.isOpen ) {
14352
+ return;
14353
+ }
14354
+
14355
+ this.isOpen = false;
14356
+ this._toggleAttr();
14357
+
14358
+ this.range = null;
14359
+ this._off( this.document );
14360
+
14361
+ this._trigger( "close", event );
14362
+ },
14363
+
14364
+ widget: function() {
14365
+ return this.button;
14366
+ },
14367
+
14368
+ menuWidget: function() {
14369
+ return this.menu;
14370
+ },
14371
+
14372
+ _renderButtonItem: function( item ) {
14373
+ var buttonItem = $( "<span>" );
14374
+
14375
+ this._setText( buttonItem, item.label );
14376
+ this._addClass( buttonItem, "ui-selectmenu-text" );
14377
+
14378
+ return buttonItem;
14379
+ },
14380
+
14381
+ _renderMenu: function( ul, items ) {
14382
+ var that = this,
14383
+ currentOptgroup = "";
14384
+
14385
+ $.each( items, function( index, item ) {
14386
+ var li;
14387
+
14388
+ if ( item.optgroup !== currentOptgroup ) {
14389
+ li = $( "<li>", {
14390
+ text: item.optgroup
14391
+ } );
14392
+ that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14393
+ ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14394
+ " ui-state-disabled" :
14395
+ "" ) );
14396
+
14397
+ li.appendTo( ul );
14398
+
14399
+ currentOptgroup = item.optgroup;
14400
+ }
14401
+
14402
+ that._renderItemData( ul, item );
14403
+ } );
14404
+ },
14405
+
14406
+ _renderItemData: function( ul, item ) {
14407
+ return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14408
+ },
14409
+
14410
+ _renderItem: function( ul, item ) {
14411
+ var li = $( "<li>" ),
14412
+ wrapper = $( "<div>", {
14413
+ title: item.element.attr( "title" )
14414
+ } );
14415
+
14416
+ if ( item.disabled ) {
14417
+ this._addClass( li, null, "ui-state-disabled" );
14418
+ }
14419
+ this._setText( wrapper, item.label );
14420
+
14421
+ return li.append( wrapper ).appendTo( ul );
14422
+ },
14423
+
14424
+ _setText: function( element, value ) {
14425
+ if ( value ) {
14426
+ element.text( value );
14427
+ } else {
14428
+ element.html( "&#160;" );
14429
+ }
14430
+ },
14431
+
14432
+ _move: function( direction, event ) {
14433
+ var item, next,
14434
+ filter = ".ui-menu-item";
14435
+
14436
+ if ( this.isOpen ) {
14437
+ item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14438
+ } else {
14439
+ item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14440
+ filter += ":not(.ui-state-disabled)";
14441
+ }
14442
+
14443
+ if ( direction === "first" || direction === "last" ) {
14444
+ next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14445
+ } else {
14446
+ next = item[ direction + "All" ]( filter ).eq( 0 );
14447
+ }
14448
+
14449
+ if ( next.length ) {
14450
+ this.menuInstance.focus( event, next );
14451
+ }
14452
+ },
14453
+
14454
+ _getSelectedItem: function() {
14455
+ return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14456
+ },
14457
+
14458
+ _toggle: function( event ) {
14459
+ this[ this.isOpen ? "close" : "open" ]( event );
14460
+ },
14461
+
14462
+ _setSelection: function() {
14463
+ var selection;
14464
+
14465
+ if ( !this.range ) {
14466
+ return;
14467
+ }
14468
+
14469
+ if ( window.getSelection ) {
14470
+ selection = window.getSelection();
14471
+ selection.removeAllRanges();
14472
+ selection.addRange( this.range );
14473
+
14474
+ // Support: IE8
14475
+ } else {
14476
+ this.range.select();
14477
+ }
14478
+
14479
+ // Support: IE
14480
+ // Setting the text selection kills the button focus in IE, but
14481
+ // restoring the focus doesn't kill the selection.
14482
+ this.button.focus();
14483
+ },
14484
+
14485
+ _documentClick: {
14486
+ mousedown: function( event ) {
14487
+ if ( !this.isOpen ) {
14488
+ return;
14489
+ }
14490
+
14491
+ if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14492
+ $.escapeSelector( this.ids.button ) ).length ) {
14493
+ this.close( event );
14494
+ }
14495
+ }
14496
+ },
14497
+
14498
+ _buttonEvents: {
14499
+
14500
+ // Prevent text selection from being reset when interacting with the selectmenu (#10144)
14501
+ mousedown: function() {
14502
+ var selection;
14503
+
14504
+ if ( window.getSelection ) {
14505
+ selection = window.getSelection();
14506
+ if ( selection.rangeCount ) {
14507
+ this.range = selection.getRangeAt( 0 );
14508
+ }
14509
+
14510
+ // Support: IE8
14511
+ } else {
14512
+ this.range = document.selection.createRange();
14513
+ }
14514
+ },
14515
+
14516
+ click: function( event ) {
14517
+ this._setSelection();
14518
+ this._toggle( event );
14519
+ },
14520
+
14521
+ keydown: function( event ) {
14522
+ var preventDefault = true;
14523
+ switch ( event.keyCode ) {
14524
+ case $.ui.keyCode.TAB:
14525
+ case $.ui.keyCode.ESCAPE:
14526
+ this.close( event );
14527
+ preventDefault = false;
14528
+ break;
14529
+ case $.ui.keyCode.ENTER:
14530
+ if ( this.isOpen ) {
14531
+ this._selectFocusedItem( event );
14532
+ }
14533
+ break;
14534
+ case $.ui.keyCode.UP:
14535
+ if ( event.altKey ) {
14536
+ this._toggle( event );
14537
+ } else {
14538
+ this._move( "prev", event );
14539
+ }
14540
+ break;
14541
+ case $.ui.keyCode.DOWN:
14542
+ if ( event.altKey ) {
14543
+ this._toggle( event );
14544
+ } else {
14545
+ this._move( "next", event );
14546
+ }
14547
+ break;
14548
+ case $.ui.keyCode.SPACE:
14549
+ if ( this.isOpen ) {
14550
+ this._selectFocusedItem( event );
14551
+ } else {
14552
+ this._toggle( event );
14553
+ }
14554
+ break;
14555
+ case $.ui.keyCode.LEFT:
14556
+ this._move( "prev", event );
14557
+ break;
14558
+ case $.ui.keyCode.RIGHT:
14559
+ this._move( "next", event );
14560
+ break;
14561
+ case $.ui.keyCode.HOME:
14562
+ case $.ui.keyCode.PAGE_UP:
14563
+ this._move( "first", event );
14564
+ break;
14565
+ case $.ui.keyCode.END:
14566
+ case $.ui.keyCode.PAGE_DOWN:
14567
+ this._move( "last", event );
14568
+ break;
14569
+ default:
14570
+ this.menu.trigger( event );
14571
+ preventDefault = false;
14572
+ }
14573
+
14574
+ if ( preventDefault ) {
14575
+ event.preventDefault();
14576
+ }
14577
+ }
14578
+ },
14579
+
14580
+ _selectFocusedItem: function( event ) {
14581
+ var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14582
+ if ( !item.hasClass( "ui-state-disabled" ) ) {
14583
+ this._select( item.data( "ui-selectmenu-item" ), event );
14584
+ }
14585
+ },
14586
+
14587
+ _select: function( item, event ) {
14588
+ var oldIndex = this.element[ 0 ].selectedIndex;
14589
+
14590
+ // Change native select element
14591
+ this.element[ 0 ].selectedIndex = item.index;
14592
+ this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14593
+ this._setAria( item );
14594
+ this._trigger( "select", event, { item: item } );
14595
+
14596
+ if ( item.index !== oldIndex ) {
14597
+ this._trigger( "change", event, { item: item } );
14598
+ }
14599
+
14600
+ this.close( event );
14601
+ },
14602
+
14603
+ _setAria: function( item ) {
14604
+ var id = this.menuItems.eq( item.index ).attr( "id" );
14605
+
14606
+ this.button.attr( {
14607
+ "aria-labelledby": id,
14608
+ "aria-activedescendant": id
14609
+ } );
14610
+ this.menu.attr( "aria-activedescendant", id );
14611
+ },
14612
+
14613
+ _setOption: function( key, value ) {
14614
+ if ( key === "icons" ) {
14615
+ var icon = this.button.find( "span.ui-icon" );
14616
+ this._removeClass( icon, null, this.options.icons.button )
14617
+ ._addClass( icon, null, value.button );
14618
+ }
14619
+
14620
+ this._super( key, value );
14621
+
14622
+ if ( key === "appendTo" ) {
14623
+ this.menuWrap.appendTo( this._appendTo() );
14624
+ }
14625
+
14626
+ if ( key === "width" ) {
14627
+ this._resizeButton();
14628
+ }
14629
+ },
14630
+
14631
+ _setOptionDisabled: function( value ) {
14632
+ this._super( value );
14633
+
14634
+ this.menuInstance.option( "disabled", value );
14635
+ this.button.attr( "aria-disabled", value );
14636
+ this._toggleClass( this.button, null, "ui-state-disabled", value );
14637
+
14638
+ this.element.prop( "disabled", value );
14639
+ if ( value ) {
14640
+ this.button.attr( "tabindex", -1 );
14641
+ this.close();
14642
+ } else {
14643
+ this.button.attr( "tabindex", 0 );
14644
+ }
14645
+ },
14646
+
14647
+ _appendTo: function() {
14648
+ var element = this.options.appendTo;
14649
+
14650
+ if ( element ) {
14651
+ element = element.jquery || element.nodeType ?
14652
+ $( element ) :
14653
+ this.document.find( element ).eq( 0 );
14654
+ }
14655
+
14656
+ if ( !element || !element[ 0 ] ) {
14657
+ element = this.element.closest( ".ui-front, dialog" );
14658
+ }
14659
+
14660
+ if ( !element.length ) {
14661
+ element = this.document[ 0 ].body;
14662
+ }
14663
+
14664
+ return element;
14665
+ },
14666
+
14667
+ _toggleAttr: function() {
14668
+ this.button.attr( "aria-expanded", this.isOpen );
14669
+
14670
+ // We can't use two _toggleClass() calls here, because we need to make sure
14671
+ // we always remove classes first and add them second, otherwise if both classes have the
14672
+ // same theme class, it will be removed after we add it.
14673
+ this._removeClass( this.button, "ui-selectmenu-button-" +
14674
+ ( this.isOpen ? "closed" : "open" ) )
14675
+ ._addClass( this.button, "ui-selectmenu-button-" +
14676
+ ( this.isOpen ? "open" : "closed" ) )
14677
+ ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14678
+
14679
+ this.menu.attr( "aria-hidden", !this.isOpen );
14680
+ },
14681
+
14682
+ _resizeButton: function() {
14683
+ var width = this.options.width;
14684
+
14685
+ // For `width: false`, just remove inline style and stop
14686
+ if ( width === false ) {
14687
+ this.button.css( "width", "" );
14688
+ return;
14689
+ }
14690
+
14691
+ // For `width: null`, match the width of the original element
14692
+ if ( width === null ) {
14693
+ width = this.element.show().outerWidth();
14694
+ this.element.hide();
14695
+ }
14696
+
14697
+ this.button.outerWidth( width );
14698
+ },
14699
+
14700
+ _resizeMenu: function() {
14701
+ this.menu.outerWidth( Math.max(
14702
+ this.button.outerWidth(),
14703
+
14704
+ // Support: IE10
14705
+ // IE10 wraps long text (possibly a rounding bug)
14706
+ // so we add 1px to avoid the wrapping
14707
+ this.menu.width( "" ).outerWidth() + 1
14708
+ ) );
14709
+ },
14710
+
14711
+ _getCreateOptions: function() {
14712
+ var options = this._super();
14713
+
14714
+ options.disabled = this.element.prop( "disabled" );
14715
+
14716
+ return options;
14717
+ },
14718
+
14719
+ _parseOptions: function( options ) {
14720
+ var that = this,
14721
+ data = [];
14722
+ options.each( function( index, item ) {
14723
+ if ( item.hidden ) {
14724
+ return;
14725
+ }
14726
+
14727
+ data.push( that._parseOption( $( item ), index ) );
14728
+ } );
14729
+ this.items = data;
14730
+ },
14731
+
14732
+ _parseOption: function( option, index ) {
14733
+ var optgroup = option.parent( "optgroup" );
14734
+
14735
+ return {
14736
+ element: option,
14737
+ index: index,
14738
+ value: option.val(),
14739
+ label: option.text(),
14740
+ optgroup: optgroup.attr( "label" ) || "",
14741
+ disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14742
+ };
14743
+ },
14744
+
14745
+ _destroy: function() {
14746
+ this._unbindFormResetHandler();
14747
+ this.menuWrap.remove();
14748
+ this.button.remove();
14749
+ this.element.show();
14750
+ this.element.removeUniqueId();
14751
+ this.labels.attr( "for", this.ids.element );
14752
+ }
14753
+ } ] );
14754
+
14755
+
14756
+ /*!
14757
+ * jQuery UI Slider 1.13.1
14758
+ * http://jqueryui.com
14759
+ *
14760
+ * Copyright jQuery Foundation and other contributors
14761
+ * Released under the MIT license.
14762
+ * http://jquery.org/license
14763
+ */
14764
+
14765
+ //>>label: Slider
14766
+ //>>group: Widgets
14767
+ //>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14768
+ //>>docs: http://api.jqueryui.com/slider/
14769
+ //>>demos: http://jqueryui.com/slider/
14770
+ //>>css.structure: ../../themes/base/core.css
14771
+ //>>css.structure: ../../themes/base/slider.css
14772
+ //>>css.theme: ../../themes/base/theme.css
14773
+
14774
+
14775
+ var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14776
+ version: "1.13.1",
14777
+ widgetEventPrefix: "slide",
14778
+
14779
+ options: {
14780
+ animate: false,
14781
+ classes: {
14782
+ "ui-slider": "ui-corner-all",
14783
+ "ui-slider-handle": "ui-corner-all",
14784
+
14785
+ // Note: ui-widget-header isn't the most fittingly semantic framework class for this
14786
+ // element, but worked best visually with a variety of themes
14787
+ "ui-slider-range": "ui-corner-all ui-widget-header"
14788
+ },
14789
+ distance: 0,
14790
+ max: 100,
14791
+ min: 0,
14792
+ orientation: "horizontal",
14793
+ range: false,
14794
+ step: 1,
14795
+ value: 0,
14796
+ values: null,
14797
+
14798
+ // Callbacks
14799
+ change: null,
14800
+ slide: null,
14801
+ start: null,
14802
+ stop: null
14803
+ },
14804
+
14805
+ // Number of pages in a slider
14806
+ // (how many times can you page up/down to go through the whole range)
14807
+ numPages: 5,
14808
+
14809
+ _create: function() {
14810
+ this._keySliding = false;
14811
+ this._mouseSliding = false;
14812
+ this._animateOff = true;
14813
+ this._handleIndex = null;
14814
+ this._detectOrientation();
14815
+ this._mouseInit();
14816
+ this._calculateNewMax();
14817
+
14818
+ this._addClass( "ui-slider ui-slider-" + this.orientation,
14819
+ "ui-widget ui-widget-content" );
14820
+
14821
+ this._refresh();
14822
+
14823
+ this._animateOff = false;
14824
+ },
14825
+
14826
+ _refresh: function() {
14827
+ this._createRange();
14828
+ this._createHandles();
14829
+ this._setupEvents();
14830
+ this._refreshValue();
14831
+ },
14832
+
14833
+ _createHandles: function() {
14834
+ var i, handleCount,
14835
+ options = this.options,
14836
+ existingHandles = this.element.find( ".ui-slider-handle" ),
14837
+ handle = "<span tabindex='0'></span>",
14838
+ handles = [];
14839
+
14840
+ handleCount = ( options.values && options.values.length ) || 1;
14841
+
14842
+ if ( existingHandles.length > handleCount ) {
14843
+ existingHandles.slice( handleCount ).remove();
14844
+ existingHandles = existingHandles.slice( 0, handleCount );
14845
+ }
14846
+
14847
+ for ( i = existingHandles.length; i < handleCount; i++ ) {
14848
+ handles.push( handle );
14849
+ }
14850
+
14851
+ this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14852
+
14853
+ this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14854
+
14855
+ this.handle = this.handles.eq( 0 );
14856
+
14857
+ this.handles.each( function( i ) {
14858
+ $( this )
14859
+ .data( "ui-slider-handle-index", i )
14860
+ .attr( "tabIndex", 0 );
14861
+ } );
14862
+ },
14863
+
14864
+ _createRange: function() {
14865
+ var options = this.options;
14866
+
14867
+ if ( options.range ) {
14868
+ if ( options.range === true ) {
14869
+ if ( !options.values ) {
14870
+ options.values = [ this._valueMin(), this._valueMin() ];
14871
+ } else if ( options.values.length && options.values.length !== 2 ) {
14872
+ options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14873
+ } else if ( Array.isArray( options.values ) ) {
14874
+ options.values = options.values.slice( 0 );
14875
+ }
14876
+ }
14877
+
14878
+ if ( !this.range || !this.range.length ) {
14879
+ this.range = $( "<div>" )
14880
+ .appendTo( this.element );
14881
+
14882
+ this._addClass( this.range, "ui-slider-range" );
14883
+ } else {
14884
+ this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14885
+
14886
+ // Handle range switching from true to min/max
14887
+ this.range.css( {
14888
+ "left": "",
14889
+ "bottom": ""
14890
+ } );
14891
+ }
14892
+ if ( options.range === "min" || options.range === "max" ) {
14893
+ this._addClass( this.range, "ui-slider-range-" + options.range );
14894
+ }
14895
+ } else {
14896
+ if ( this.range ) {
14897
+ this.range.remove();
14898
+ }
14899
+ this.range = null;
14900
+ }
14901
+ },
14902
+
14903
+ _setupEvents: function() {
14904
+ this._off( this.handles );
14905
+ this._on( this.handles, this._handleEvents );
14906
+ this._hoverable( this.handles );
14907
+ this._focusable( this.handles );
14908
+ },
14909
+
14910
+ _destroy: function() {
14911
+ this.handles.remove();
14912
+ if ( this.range ) {
14913
+ this.range.remove();
14914
+ }
14915
+
14916
+ this._mouseDestroy();
14917
+ },
14918
+
14919
+ _mouseCapture: function( event ) {
14920
+ var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14921
+ that = this,
14922
+ o = this.options;
14923
+
14924
+ if ( o.disabled ) {
14925
+ return false;
14926
+ }
14927
+
14928
+ this.elementSize = {
14929
+ width: this.element.outerWidth(),
14930
+ height: this.element.outerHeight()
14931
+ };
14932
+ this.elementOffset = this.element.offset();
14933
+
14934
+ position = { x: event.pageX, y: event.pageY };
14935
+ normValue = this._normValueFromMouse( position );
14936
+ distance = this._valueMax() - this._valueMin() + 1;
14937
+ this.handles.each( function( i ) {
14938
+ var thisDistance = Math.abs( normValue - that.values( i ) );
14939
+ if ( ( distance > thisDistance ) ||
14940
+ ( distance === thisDistance &&
14941
+ ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14942
+ distance = thisDistance;
14943
+ closestHandle = $( this );
14944
+ index = i;
14945
+ }
14946
+ } );
14947
+
14948
+ allowed = this._start( event, index );
14949
+ if ( allowed === false ) {
14950
+ return false;
14951
+ }
14952
+ this._mouseSliding = true;
14953
+
14954
+ this._handleIndex = index;
14955
+
14956
+ this._addClass( closestHandle, null, "ui-state-active" );
14957
+ closestHandle.trigger( "focus" );
14958
+
14959
+ offset = closestHandle.offset();
14960
+ mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14961
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14962
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14963
+ top: event.pageY - offset.top -
14964
+ ( closestHandle.height() / 2 ) -
14965
+ ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14966
+ ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14967
+ ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14968
+ };
14969
+
14970
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14971
+ this._slide( event, index, normValue );
14972
+ }
14973
+ this._animateOff = true;
14974
+ return true;
14975
+ },
14976
+
14977
+ _mouseStart: function() {
14978
+ return true;
14979
+ },
14980
+
14981
+ _mouseDrag: function( event ) {
14982
+ var position = { x: event.pageX, y: event.pageY },
14983
+ normValue = this._normValueFromMouse( position );
14984
+
14985
+ this._slide( event, this._handleIndex, normValue );
14986
+
14987
+ return false;
14988
+ },
14989
+
14990
+ _mouseStop: function( event ) {
14991
+ this._removeClass( this.handles, null, "ui-state-active" );
14992
+ this._mouseSliding = false;
14993
+
14994
+ this._stop( event, this._handleIndex );
14995
+ this._change( event, this._handleIndex );
14996
+
14997
+ this._handleIndex = null;
14998
+ this._clickOffset = null;
14999
+ this._animateOff = false;
15000
+
15001
+ return false;
15002
+ },
15003
+
15004
+ _detectOrientation: function() {
15005
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
15006
+ },
15007
+
15008
+ _normValueFromMouse: function( position ) {
15009
+ var pixelTotal,
15010
+ pixelMouse,
15011
+ percentMouse,
15012
+ valueTotal,
15013
+ valueMouse;
15014
+
15015
+ if ( this.orientation === "horizontal" ) {
15016
+ pixelTotal = this.elementSize.width;
15017
+ pixelMouse = position.x - this.elementOffset.left -
15018
+ ( this._clickOffset ? this._clickOffset.left : 0 );
15019
+ } else {
15020
+ pixelTotal = this.elementSize.height;
15021
+ pixelMouse = position.y - this.elementOffset.top -
15022
+ ( this._clickOffset ? this._clickOffset.top : 0 );
15023
+ }
15024
+
15025
+ percentMouse = ( pixelMouse / pixelTotal );
15026
+ if ( percentMouse > 1 ) {
15027
+ percentMouse = 1;
15028
+ }
15029
+ if ( percentMouse < 0 ) {
15030
+ percentMouse = 0;
15031
+ }
15032
+ if ( this.orientation === "vertical" ) {
15033
+ percentMouse = 1 - percentMouse;
15034
+ }
15035
+
15036
+ valueTotal = this._valueMax() - this._valueMin();
15037
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
15038
+
15039
+ return this._trimAlignValue( valueMouse );
15040
+ },
15041
+
15042
+ _uiHash: function( index, value, values ) {
15043
+ var uiHash = {
15044
+ handle: this.handles[ index ],
15045
+ handleIndex: index,
15046
+ value: value !== undefined ? value : this.value()
15047
+ };
15048
+
15049
+ if ( this._hasMultipleValues() ) {
15050
+ uiHash.value = value !== undefined ? value : this.values( index );
15051
+ uiHash.values = values || this.values();
15052
+ }
15053
+
15054
+ return uiHash;
15055
+ },
15056
+
15057
+ _hasMultipleValues: function() {
15058
+ return this.options.values && this.options.values.length;
15059
+ },
15060
+
15061
+ _start: function( event, index ) {
15062
+ return this._trigger( "start", event, this._uiHash( index ) );
15063
+ },
15064
+
15065
+ _slide: function( event, index, newVal ) {
15066
+ var allowed, otherVal,
15067
+ currentValue = this.value(),
15068
+ newValues = this.values();
15069
+
15070
+ if ( this._hasMultipleValues() ) {
15071
+ otherVal = this.values( index ? 0 : 1 );
15072
+ currentValue = this.values( index );
15073
+
15074
+ if ( this.options.values.length === 2 && this.options.range === true ) {
15075
+ newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
15076
+ }
15077
+
15078
+ newValues[ index ] = newVal;
15079
+ }
15080
+
15081
+ if ( newVal === currentValue ) {
15082
+ return;
15083
+ }
15084
+
15085
+ allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
15086
+
15087
+ // A slide can be canceled by returning false from the slide callback
15088
+ if ( allowed === false ) {
15089
+ return;
15090
+ }
15091
+
15092
+ if ( this._hasMultipleValues() ) {
15093
+ this.values( index, newVal );
15094
+ } else {
15095
+ this.value( newVal );
15096
+ }
15097
+ },
15098
+
15099
+ _stop: function( event, index ) {
15100
+ this._trigger( "stop", event, this._uiHash( index ) );
15101
+ },
15102
+
15103
+ _change: function( event, index ) {
15104
+ if ( !this._keySliding && !this._mouseSliding ) {
15105
+
15106
+ //store the last changed value index for reference when handles overlap
15107
+ this._lastChangedValue = index;
15108
+ this._trigger( "change", event, this._uiHash( index ) );
15109
+ }
15110
+ },
15111
+
15112
+ value: function( newValue ) {
15113
+ if ( arguments.length ) {
15114
+ this.options.value = this._trimAlignValue( newValue );
15115
+ this._refreshValue();
15116
+ this._change( null, 0 );
15117
+ return;
15118
+ }
15119
+
15120
+ return this._value();
15121
+ },
15122
+
15123
+ values: function( index, newValue ) {
15124
+ var vals,
15125
+ newValues,
15126
+ i;
15127
+
15128
+ if ( arguments.length > 1 ) {
15129
+ this.options.values[ index ] = this._trimAlignValue( newValue );
15130
+ this._refreshValue();
15131
+ this._change( null, index );
15132
+ return;
15133
+ }
15134
+
15135
+ if ( arguments.length ) {
15136
+ if ( Array.isArray( arguments[ 0 ] ) ) {
15137
+ vals = this.options.values;
15138
+ newValues = arguments[ 0 ];
15139
+ for ( i = 0; i < vals.length; i += 1 ) {
15140
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
15141
+ this._change( null, i );
15142
+ }
15143
+ this._refreshValue();
15144
+ } else {
15145
+ if ( this._hasMultipleValues() ) {
15146
+ return this._values( index );
15147
+ } else {
15148
+ return this.value();
15149
+ }
15150
+ }
15151
+ } else {
15152
+ return this._values();
15153
+ }
15154
+ },
15155
+
15156
+ _setOption: function( key, value ) {
15157
+ var i,
15158
+ valsLength = 0;
15159
+
15160
+ if ( key === "range" && this.options.range === true ) {
15161
+ if ( value === "min" ) {
15162
+ this.options.value = this._values( 0 );
15163
+ this.options.values = null;
15164
+ } else if ( value === "max" ) {
15165
+ this.options.value = this._values( this.options.values.length - 1 );
15166
+ this.options.values = null;
15167
+ }
15168
+ }
15169
+
15170
+ if ( Array.isArray( this.options.values ) ) {
15171
+ valsLength = this.options.values.length;
15172
+ }
15173
+
15174
+ this._super( key, value );
15175
+
15176
+ switch ( key ) {
15177
+ case "orientation":
15178
+ this._detectOrientation();
15179
+ this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
15180
+ ._addClass( "ui-slider-" + this.orientation );
15181
+ this._refreshValue();
15182
+ if ( this.options.range ) {
15183
+ this._refreshRange( value );
15184
+ }
15185
+
15186
+ // Reset positioning from previous orientation
15187
+ this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15188
+ break;
15189
+ case "value":
15190
+ this._animateOff = true;
15191
+ this._refreshValue();
15192
+ this._change( null, 0 );
15193
+ this._animateOff = false;
15194
+ break;
15195
+ case "values":
15196
+ this._animateOff = true;
15197
+ this._refreshValue();
15198
+
15199
+ // Start from the last handle to prevent unreachable handles (#9046)
15200
+ for ( i = valsLength - 1; i >= 0; i-- ) {
15201
+ this._change( null, i );
15202
+ }
15203
+ this._animateOff = false;
15204
+ break;
15205
+ case "step":
15206
+ case "min":
15207
+ case "max":
15208
+ this._animateOff = true;
15209
+ this._calculateNewMax();
15210
+ this._refreshValue();
15211
+ this._animateOff = false;
15212
+ break;
15213
+ case "range":
15214
+ this._animateOff = true;
15215
+ this._refresh();
15216
+ this._animateOff = false;
15217
+ break;
15218
+ }
15219
+ },
15220
+
15221
+ _setOptionDisabled: function( value ) {
15222
+ this._super( value );
15223
+
15224
+ this._toggleClass( null, "ui-state-disabled", !!value );
15225
+ },
15226
+
15227
+ //internal value getter
15228
+ // _value() returns value trimmed by min and max, aligned by step
15229
+ _value: function() {
15230
+ var val = this.options.value;
15231
+ val = this._trimAlignValue( val );
15232
+
15233
+ return val;
15234
+ },
15235
+
15236
+ //internal values getter
15237
+ // _values() returns array of values trimmed by min and max, aligned by step
15238
+ // _values( index ) returns single value trimmed by min and max, aligned by step
15239
+ _values: function( index ) {
15240
+ var val,
15241
+ vals,
15242
+ i;
15243
+
15244
+ if ( arguments.length ) {
15245
+ val = this.options.values[ index ];
15246
+ val = this._trimAlignValue( val );
15247
+
15248
+ return val;
15249
+ } else if ( this._hasMultipleValues() ) {
15250
+
15251
+ // .slice() creates a copy of the array
15252
+ // this copy gets trimmed by min and max and then returned
15253
+ vals = this.options.values.slice();
15254
+ for ( i = 0; i < vals.length; i += 1 ) {
15255
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
15256
+ }
15257
+
15258
+ return vals;
15259
+ } else {
15260
+ return [];
15261
+ }
15262
+ },
15263
+
15264
+ // Returns the step-aligned value that val is closest to, between (inclusive) min and max
15265
+ _trimAlignValue: function( val ) {
15266
+ if ( val <= this._valueMin() ) {
15267
+ return this._valueMin();
15268
+ }
15269
+ if ( val >= this._valueMax() ) {
15270
+ return this._valueMax();
15271
+ }
15272
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
15273
+ valModStep = ( val - this._valueMin() ) % step,
15274
+ alignValue = val - valModStep;
15275
+
15276
+ if ( Math.abs( valModStep ) * 2 >= step ) {
15277
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
15278
+ }
15279
+
15280
+ // Since JavaScript has problems with large floats, round
15281
+ // the final value to 5 digits after the decimal point (see #4124)
15282
+ return parseFloat( alignValue.toFixed( 5 ) );
15283
+ },
15284
+
15285
+ _calculateNewMax: function() {
15286
+ var max = this.options.max,
15287
+ min = this._valueMin(),
15288
+ step = this.options.step,
15289
+ aboveMin = Math.round( ( max - min ) / step ) * step;
15290
+ max = aboveMin + min;
15291
+ if ( max > this.options.max ) {
15292
+
15293
+ //If max is not divisible by step, rounding off may increase its value
15294
+ max -= step;
15295
+ }
15296
+ this.max = parseFloat( max.toFixed( this._precision() ) );
15297
+ },
15298
+
15299
+ _precision: function() {
15300
+ var precision = this._precisionOf( this.options.step );
15301
+ if ( this.options.min !== null ) {
15302
+ precision = Math.max( precision, this._precisionOf( this.options.min ) );
15303
+ }
15304
+ return precision;
15305
+ },
15306
+
15307
+ _precisionOf: function( num ) {
15308
+ var str = num.toString(),
15309
+ decimal = str.indexOf( "." );
15310
+ return decimal === -1 ? 0 : str.length - decimal - 1;
15311
+ },
15312
+
15313
+ _valueMin: function() {
15314
+ return this.options.min;
15315
+ },
15316
+
15317
+ _valueMax: function() {
15318
+ return this.max;
15319
+ },
15320
+
15321
+ _refreshRange: function( orientation ) {
15322
+ if ( orientation === "vertical" ) {
15323
+ this.range.css( { "width": "", "left": "" } );
15324
+ }
15325
+ if ( orientation === "horizontal" ) {
15326
+ this.range.css( { "height": "", "bottom": "" } );
15327
+ }
15328
+ },
15329
+
15330
+ _refreshValue: function() {
15331
+ var lastValPercent, valPercent, value, valueMin, valueMax,
15332
+ oRange = this.options.range,
15333
+ o = this.options,
15334
+ that = this,
15335
+ animate = ( !this._animateOff ) ? o.animate : false,
15336
+ _set = {};
15337
+
15338
+ if ( this._hasMultipleValues() ) {
15339
+ this.handles.each( function( i ) {
15340
+ valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15341
+ that._valueMin() ) * 100;
15342
+ _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15343
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15344
+ if ( that.options.range === true ) {
15345
+ if ( that.orientation === "horizontal" ) {
15346
+ if ( i === 0 ) {
15347
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15348
+ left: valPercent + "%"
15349
+ }, o.animate );
15350
+ }
15351
+ if ( i === 1 ) {
15352
+ that.range[ animate ? "animate" : "css" ]( {
15353
+ width: ( valPercent - lastValPercent ) + "%"
15354
+ }, {
15355
+ queue: false,
15356
+ duration: o.animate
15357
+ } );
15358
+ }
15359
+ } else {
15360
+ if ( i === 0 ) {
15361
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15362
+ bottom: ( valPercent ) + "%"
15363
+ }, o.animate );
15364
+ }
15365
+ if ( i === 1 ) {
15366
+ that.range[ animate ? "animate" : "css" ]( {
15367
+ height: ( valPercent - lastValPercent ) + "%"
15368
+ }, {
15369
+ queue: false,
15370
+ duration: o.animate
15371
+ } );
15372
+ }
15373
+ }
15374
+ }
15375
+ lastValPercent = valPercent;
15376
+ } );
15377
+ } else {
15378
+ value = this.value();
15379
+ valueMin = this._valueMin();
15380
+ valueMax = this._valueMax();
15381
+ valPercent = ( valueMax !== valueMin ) ?
15382
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15383
+ 0;
15384
+ _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15385
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15386
+
15387
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
15388
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15389
+ width: valPercent + "%"
15390
+ }, o.animate );
15391
+ }
15392
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
15393
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15394
+ width: ( 100 - valPercent ) + "%"
15395
+ }, o.animate );
15396
+ }
15397
+ if ( oRange === "min" && this.orientation === "vertical" ) {
15398
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15399
+ height: valPercent + "%"
15400
+ }, o.animate );
15401
+ }
15402
+ if ( oRange === "max" && this.orientation === "vertical" ) {
15403
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15404
+ height: ( 100 - valPercent ) + "%"
15405
+ }, o.animate );
15406
+ }
15407
+ }
15408
+ },
15409
+
15410
+ _handleEvents: {
15411
+ keydown: function( event ) {
15412
+ var allowed, curVal, newVal, step,
15413
+ index = $( event.target ).data( "ui-slider-handle-index" );
15414
+
15415
+ switch ( event.keyCode ) {
15416
+ case $.ui.keyCode.HOME:
15417
+ case $.ui.keyCode.END:
15418
+ case $.ui.keyCode.PAGE_UP:
15419
+ case $.ui.keyCode.PAGE_DOWN:
15420
+ case $.ui.keyCode.UP:
15421
+ case $.ui.keyCode.RIGHT:
15422
+ case $.ui.keyCode.DOWN:
15423
+ case $.ui.keyCode.LEFT:
15424
+ event.preventDefault();
15425
+ if ( !this._keySliding ) {
15426
+ this._keySliding = true;
15427
+ this._addClass( $( event.target ), null, "ui-state-active" );
15428
+ allowed = this._start( event, index );
15429
+ if ( allowed === false ) {
15430
+ return;
15431
+ }
15432
+ }
15433
+ break;
15434
+ }
15435
+
15436
+ step = this.options.step;
15437
+ if ( this._hasMultipleValues() ) {
15438
+ curVal = newVal = this.values( index );
15439
+ } else {
15440
+ curVal = newVal = this.value();
15441
+ }
15442
+
15443
+ switch ( event.keyCode ) {
15444
+ case $.ui.keyCode.HOME:
15445
+ newVal = this._valueMin();
15446
+ break;
15447
+ case $.ui.keyCode.END:
15448
+ newVal = this._valueMax();
15449
+ break;
15450
+ case $.ui.keyCode.PAGE_UP:
15451
+ newVal = this._trimAlignValue(
15452
+ curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15453
+ );
15454
+ break;
15455
+ case $.ui.keyCode.PAGE_DOWN:
15456
+ newVal = this._trimAlignValue(
15457
+ curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15458
+ break;
15459
+ case $.ui.keyCode.UP:
15460
+ case $.ui.keyCode.RIGHT:
15461
+ if ( curVal === this._valueMax() ) {
15462
+ return;
15463
+ }
15464
+ newVal = this._trimAlignValue( curVal + step );
15465
+ break;
15466
+ case $.ui.keyCode.DOWN:
15467
+ case $.ui.keyCode.LEFT:
15468
+ if ( curVal === this._valueMin() ) {
15469
+ return;
15470
+ }
15471
+ newVal = this._trimAlignValue( curVal - step );
15472
+ break;
15473
+ }
15474
+
15475
+ this._slide( event, index, newVal );
15476
+ },
15477
+ keyup: function( event ) {
15478
+ var index = $( event.target ).data( "ui-slider-handle-index" );
15479
+
15480
+ if ( this._keySliding ) {
15481
+ this._keySliding = false;
15482
+ this._stop( event, index );
15483
+ this._change( event, index );
15484
+ this._removeClass( $( event.target ), null, "ui-state-active" );
15485
+ }
15486
+ }
15487
+ }
15488
+ } );
15489
+
15490
+
15491
+ /*!
15492
+ * jQuery UI Sortable 1.13.1
15493
+ * http://jqueryui.com
15494
+ *
15495
+ * Copyright jQuery Foundation and other contributors
15496
+ * Released under the MIT license.
15497
+ * http://jquery.org/license
15498
+ */
15499
+
15500
+ //>>label: Sortable
15501
+ //>>group: Interactions
15502
+ //>>description: Enables items in a list to be sorted using the mouse.
15503
+ //>>docs: http://api.jqueryui.com/sortable/
15504
+ //>>demos: http://jqueryui.com/sortable/
15505
+ //>>css.structure: ../../themes/base/sortable.css
15506
+
15507
+
15508
+ var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15509
+ version: "1.13.1",
15510
+ widgetEventPrefix: "sort",
15511
+ ready: false,
15512
+ options: {
15513
+ appendTo: "parent",
15514
+ axis: false,
15515
+ connectWith: false,
15516
+ containment: false,
15517
+ cursor: "auto",
15518
+ cursorAt: false,
15519
+ dropOnEmpty: true,
15520
+ forcePlaceholderSize: false,
15521
+ forceHelperSize: false,
15522
+ grid: false,
15523
+ handle: false,
15524
+ helper: "original",
15525
+ items: "> *",
15526
+ opacity: false,
15527
+ placeholder: false,
15528
+ revert: false,
15529
+ scroll: true,
15530
+ scrollSensitivity: 20,
15531
+ scrollSpeed: 20,
15532
+ scope: "default",
15533
+ tolerance: "intersect",
15534
+ zIndex: 1000,
15535
+
15536
+ // Callbacks
15537
+ activate: null,
15538
+ beforeStop: null,
15539
+ change: null,
15540
+ deactivate: null,
15541
+ out: null,
15542
+ over: null,
15543
+ receive: null,
15544
+ remove: null,
15545
+ sort: null,
15546
+ start: null,
15547
+ stop: null,
15548
+ update: null
15549
+ },
15550
+
15551
+ _isOverAxis: function( x, reference, size ) {
15552
+ return ( x >= reference ) && ( x < ( reference + size ) );
15553
+ },
15554
+
15555
+ _isFloating: function( item ) {
15556
+ return ( /left|right/ ).test( item.css( "float" ) ) ||
15557
+ ( /inline|table-cell/ ).test( item.css( "display" ) );
15558
+ },
15559
+
15560
+ _create: function() {
15561
+ this.containerCache = {};
15562
+ this._addClass( "ui-sortable" );
15563
+
15564
+ //Get the items
15565
+ this.refresh();
15566
+
15567
+ //Let's determine the parent's offset
15568
+ this.offset = this.element.offset();
15569
+
15570
+ //Initialize mouse events for interaction
15571
+ this._mouseInit();
15572
+
15573
+ this._setHandleClassName();
15574
+
15575
+ //We're ready to go
15576
+ this.ready = true;
15577
+
15578
+ },
15579
+
15580
+ _setOption: function( key, value ) {
15581
+ this._super( key, value );
15582
+
15583
+ if ( key === "handle" ) {
15584
+ this._setHandleClassName();
15585
+ }
15586
+ },
15587
+
15588
+ _setHandleClassName: function() {
15589
+ var that = this;
15590
+ this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15591
+ $.each( this.items, function() {
15592
+ that._addClass(
15593
+ this.instance.options.handle ?
15594
+ this.item.find( this.instance.options.handle ) :
15595
+ this.item,
15596
+ "ui-sortable-handle"
15597
+ );
15598
+ } );
15599
+ },
15600
+
15601
+ _destroy: function() {
15602
+ this._mouseDestroy();
15603
+
15604
+ for ( var i = this.items.length - 1; i >= 0; i-- ) {
15605
+ this.items[ i ].item.removeData( this.widgetName + "-item" );
15606
+ }
15607
+
15608
+ return this;
15609
+ },
15610
+
15611
+ _mouseCapture: function( event, overrideHandle ) {
15612
+ var currentItem = null,
15613
+ validHandle = false,
15614
+ that = this;
15615
+
15616
+ if ( this.reverting ) {
15617
+ return false;
15618
+ }
15619
+
15620
+ if ( this.options.disabled || this.options.type === "static" ) {
15621
+ return false;
15622
+ }
15623
+
15624
+ //We have to refresh the items data once first
15625
+ this._refreshItems( event );
15626
+
15627
+ //Find out if the clicked node (or one of its parents) is a actual item in this.items
15628
+ $( event.target ).parents().each( function() {
15629
+ if ( $.data( this, that.widgetName + "-item" ) === that ) {
15630
+ currentItem = $( this );
15631
+ return false;
15632
+ }
15633
+ } );
15634
+ if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15635
+ currentItem = $( event.target );
15636
+ }
15637
+
15638
+ if ( !currentItem ) {
15639
+ return false;
15640
+ }
15641
+ if ( this.options.handle && !overrideHandle ) {
15642
+ $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15643
+ if ( this === event.target ) {
15644
+ validHandle = true;
15645
+ }
15646
+ } );
15647
+ if ( !validHandle ) {
15648
+ return false;
15649
+ }
15650
+ }
15651
+
15652
+ this.currentItem = currentItem;
15653
+ this._removeCurrentsFromItems();
15654
+ return true;
15655
+
15656
+ },
15657
+
15658
+ _mouseStart: function( event, overrideHandle, noActivation ) {
15659
+
15660
+ var i, body,
15661
+ o = this.options;
15662
+
15663
+ this.currentContainer = this;
15664
+
15665
+ //We only need to call refreshPositions, because the refreshItems call has been moved to
15666
+ // mouseCapture
15667
+ this.refreshPositions();
15668
+
15669
+ //Prepare the dragged items parent
15670
+ this.appendTo = $( o.appendTo !== "parent" ?
15671
+ o.appendTo :
15672
+ this.currentItem.parent() );
15673
+
15674
+ //Create and append the visible helper
15675
+ this.helper = this._createHelper( event );
15676
+
15677
+ //Cache the helper size
15678
+ this._cacheHelperProportions();
15679
+
15680
+ /*
15681
+ * - Position generation -
15682
+ * This block generates everything position related - it's the core of draggables.
15683
+ */
15684
+
15685
+ //Cache the margins of the original element
15686
+ this._cacheMargins();
15687
+
15688
+ //The element's absolute position on the page minus margins
15689
+ this.offset = this.currentItem.offset();
15690
+ this.offset = {
15691
+ top: this.offset.top - this.margins.top,
15692
+ left: this.offset.left - this.margins.left
15693
+ };
15694
+
15695
+ $.extend( this.offset, {
15696
+ click: { //Where the click happened, relative to the element
15697
+ left: event.pageX - this.offset.left,
15698
+ top: event.pageY - this.offset.top
15699
+ },
15700
+
15701
+ // This is a relative to absolute position minus the actual position calculation -
15702
+ // only used for relative positioned helper
15703
+ relative: this._getRelativeOffset()
15704
+ } );
15705
+
15706
+ // After we get the helper offset, but before we get the parent offset we can
15707
+ // change the helper's position to absolute
15708
+ // TODO: Still need to figure out a way to make relative sorting possible
15709
+ this.helper.css( "position", "absolute" );
15710
+ this.cssPosition = this.helper.css( "position" );
15711
+
15712
+ //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15713
+ if ( o.cursorAt ) {
15714
+ this._adjustOffsetFromHelper( o.cursorAt );
15715
+ }
15716
+
15717
+ //Cache the former DOM position
15718
+ this.domPosition = {
15719
+ prev: this.currentItem.prev()[ 0 ],
15720
+ parent: this.currentItem.parent()[ 0 ]
15721
+ };
15722
+
15723
+ // If the helper is not the original, hide the original so it's not playing any role during
15724
+ // the drag, won't cause anything bad this way
15725
+ if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15726
+ this.currentItem.hide();
15727
+ }
15728
+
15729
+ //Create the placeholder
15730
+ this._createPlaceholder();
15731
+
15732
+ //Get the next scrolling parent
15733
+ this.scrollParent = this.placeholder.scrollParent();
15734
+
15735
+ $.extend( this.offset, {
15736
+ parent: this._getParentOffset()
15737
+ } );
15738
+
15739
+ //Set a containment if given in the options
15740
+ if ( o.containment ) {
15741
+ this._setContainment();
15742
+ }
15743
+
15744
+ if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15745
+ body = this.document.find( "body" );
15746
+
15747
+ // Support: IE
15748
+ this.storedCursor = body.css( "cursor" );
15749
+ body.css( "cursor", o.cursor );
15750
+
15751
+ this.storedStylesheet =
15752
+ $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15753
+ }
15754
+
15755
+ // We need to make sure to grab the zIndex before setting the
15756
+ // opacity, because setting the opacity to anything lower than 1
15757
+ // causes the zIndex to change from "auto" to 0.
15758
+ if ( o.zIndex ) { // zIndex option
15759
+ if ( this.helper.css( "zIndex" ) ) {
15760
+ this._storedZIndex = this.helper.css( "zIndex" );
15761
+ }
15762
+ this.helper.css( "zIndex", o.zIndex );
15763
+ }
15764
+
15765
+ if ( o.opacity ) { // opacity option
15766
+ if ( this.helper.css( "opacity" ) ) {
15767
+ this._storedOpacity = this.helper.css( "opacity" );
15768
+ }
15769
+ this.helper.css( "opacity", o.opacity );
15770
+ }
15771
+
15772
+ //Prepare scrolling
15773
+ if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15774
+ this.scrollParent[ 0 ].tagName !== "HTML" ) {
15775
+ this.overflowOffset = this.scrollParent.offset();
15776
+ }
15777
+
15778
+ //Call callbacks
15779
+ this._trigger( "start", event, this._uiHash() );
15780
+
15781
+ //Recache the helper size
15782
+ if ( !this._preserveHelperProportions ) {
15783
+ this._cacheHelperProportions();
15784
+ }
15785
+
15786
+ //Post "activate" events to possible containers
15787
+ if ( !noActivation ) {
15788
+ for ( i = this.containers.length - 1; i >= 0; i-- ) {
15789
+ this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15790
+ }
15791
+ }
15792
+
15793
+ //Prepare possible droppables
15794
+ if ( $.ui.ddmanager ) {
15795
+ $.ui.ddmanager.current = this;
15796
+ }
15797
+
15798
+ if ( $.ui.ddmanager && !o.dropBehaviour ) {
15799
+ $.ui.ddmanager.prepareOffsets( this, event );
15800
+ }
15801
+
15802
+ this.dragging = true;
15803
+
15804
+ this._addClass( this.helper, "ui-sortable-helper" );
15805
+
15806
+ //Move the helper, if needed
15807
+ if ( !this.helper.parent().is( this.appendTo ) ) {
15808
+ this.helper.detach().appendTo( this.appendTo );
15809
+
15810
+ //Update position
15811
+ this.offset.parent = this._getParentOffset();
15812
+ }
15813
+
15814
+ //Generate the original position
15815
+ this.position = this.originalPosition = this._generatePosition( event );
15816
+ this.originalPageX = event.pageX;
15817
+ this.originalPageY = event.pageY;
15818
+ this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15819
+
15820
+ this._mouseDrag( event );
15821
+
15822
+ return true;
15823
+
15824
+ },
15825
+
15826
+ _scroll: function( event ) {
15827
+ var o = this.options,
15828
+ scrolled = false;
15829
+
15830
+ if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15831
+ this.scrollParent[ 0 ].tagName !== "HTML" ) {
15832
+
15833
+ if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15834
+ event.pageY < o.scrollSensitivity ) {
15835
+ this.scrollParent[ 0 ].scrollTop =
15836
+ scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15837
+ } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15838
+ this.scrollParent[ 0 ].scrollTop =
15839
+ scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15840
+ }
15841
+
15842
+ if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15843
+ event.pageX < o.scrollSensitivity ) {
15844
+ this.scrollParent[ 0 ].scrollLeft = scrolled =
15845
+ this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15846
+ } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15847
+ this.scrollParent[ 0 ].scrollLeft = scrolled =
15848
+ this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15849
+ }
15850
+
15851
+ } else {
15852
+
15853
+ if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15854
+ scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15855
+ } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15856
+ o.scrollSensitivity ) {
15857
+ scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15858
+ }
15859
+
15860
+ if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15861
+ scrolled = this.document.scrollLeft(
15862
+ this.document.scrollLeft() - o.scrollSpeed
15863
+ );
15864
+ } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15865
+ o.scrollSensitivity ) {
15866
+ scrolled = this.document.scrollLeft(
15867
+ this.document.scrollLeft() + o.scrollSpeed
15868
+ );
15869
+ }
15870
+
15871
+ }
15872
+
15873
+ return scrolled;
15874
+ },
15875
+
15876
+ _mouseDrag: function( event ) {
15877
+ var i, item, itemElement, intersection,
15878
+ o = this.options;
15879
+
15880
+ //Compute the helpers position
15881
+ this.position = this._generatePosition( event );
15882
+ this.positionAbs = this._convertPositionTo( "absolute" );
15883
+
15884
+ //Set the helper position
15885
+ if ( !this.options.axis || this.options.axis !== "y" ) {
15886
+ this.helper[ 0 ].style.left = this.position.left + "px";
15887
+ }
15888
+ if ( !this.options.axis || this.options.axis !== "x" ) {
15889
+ this.helper[ 0 ].style.top = this.position.top + "px";
15890
+ }
15891
+
15892
+ //Do scrolling
15893
+ if ( o.scroll ) {
15894
+ if ( this._scroll( event ) !== false ) {
15895
+
15896
+ //Update item positions used in position checks
15897
+ this._refreshItemPositions( true );
15898
+
15899
+ if ( $.ui.ddmanager && !o.dropBehaviour ) {
15900
+ $.ui.ddmanager.prepareOffsets( this, event );
15901
+ }
15902
+ }
15903
+ }
15904
+
15905
+ this.dragDirection = {
15906
+ vertical: this._getDragVerticalDirection(),
15907
+ horizontal: this._getDragHorizontalDirection()
15908
+ };
15909
+
15910
+ //Rearrange
15911
+ for ( i = this.items.length - 1; i >= 0; i-- ) {
15912
+
15913
+ //Cache variables and intersection, continue if no intersection
15914
+ item = this.items[ i ];
15915
+ itemElement = item.item[ 0 ];
15916
+ intersection = this._intersectsWithPointer( item );
15917
+ if ( !intersection ) {
15918
+ continue;
15919
+ }
15920
+
15921
+ // Only put the placeholder inside the current Container, skip all
15922
+ // items from other containers. This works because when moving
15923
+ // an item from one container to another the
15924
+ // currentContainer is switched before the placeholder is moved.
15925
+ //
15926
+ // Without this, moving items in "sub-sortables" can cause
15927
+ // the placeholder to jitter between the outer and inner container.
15928
+ if ( item.instance !== this.currentContainer ) {
15929
+ continue;
15930
+ }
15931
+
15932
+ // Cannot intersect with itself
15933
+ // no useless actions that have been done before
15934
+ // no action if the item moved is the parent of the item checked
15935
+ if ( itemElement !== this.currentItem[ 0 ] &&
15936
+ this.placeholder[ intersection === 1 ?
15937
+ "next" : "prev" ]()[ 0 ] !== itemElement &&
15938
+ !$.contains( this.placeholder[ 0 ], itemElement ) &&
15939
+ ( this.options.type === "semi-dynamic" ?
15940
+ !$.contains( this.element[ 0 ], itemElement ) :
15941
+ true
15942
+ )
15943
+ ) {
15944
+
15945
+ this.direction = intersection === 1 ? "down" : "up";
15946
+
15947
+ if ( this.options.tolerance === "pointer" ||
15948
+ this._intersectsWithSides( item ) ) {
15949
+ this._rearrange( event, item );
15950
+ } else {
15951
+ break;
15952
+ }
15953
+
15954
+ this._trigger( "change", event, this._uiHash() );
15955
+ break;
15956
+ }
15957
+ }
15958
+
15959
+ //Post events to containers
15960
+ this._contactContainers( event );
15961
+
15962
+ //Interconnect with droppables
15963
+ if ( $.ui.ddmanager ) {
15964
+ $.ui.ddmanager.drag( this, event );
15965
+ }
15966
+
15967
+ //Call callbacks
15968
+ this._trigger( "sort", event, this._uiHash() );
15969
+
15970
+ this.lastPositionAbs = this.positionAbs;
15971
+ return false;
15972
+
15973
+ },
15974
+
15975
+ _mouseStop: function( event, noPropagation ) {
15976
+
15977
+ if ( !event ) {
15978
+ return;
15979
+ }
15980
+
15981
+ //If we are using droppables, inform the manager about the drop
15982
+ if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15983
+ $.ui.ddmanager.drop( this, event );
15984
+ }
15985
+
15986
+ if ( this.options.revert ) {
15987
+ var that = this,
15988
+ cur = this.placeholder.offset(),
15989
+ axis = this.options.axis,
15990
+ animation = {};
15991
+
15992
+ if ( !axis || axis === "x" ) {
15993
+ animation.left = cur.left - this.offset.parent.left - this.margins.left +
15994
+ ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15995
+ 0 :
15996
+ this.offsetParent[ 0 ].scrollLeft
15997
+ );
15998
+ }
15999
+ if ( !axis || axis === "y" ) {
16000
+ animation.top = cur.top - this.offset.parent.top - this.margins.top +
16001
+ ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
16002
+ 0 :
16003
+ this.offsetParent[ 0 ].scrollTop
16004
+ );
16005
+ }
16006
+ this.reverting = true;
16007
+ $( this.helper ).animate(
16008
+ animation,
16009
+ parseInt( this.options.revert, 10 ) || 500,
16010
+ function() {
16011
+ that._clear( event );
16012
+ }
16013
+ );
16014
+ } else {
16015
+ this._clear( event, noPropagation );
16016
+ }
16017
+
16018
+ return false;
16019
+
16020
+ },
16021
+
16022
+ cancel: function() {
16023
+
16024
+ if ( this.dragging ) {
16025
+
16026
+ this._mouseUp( new $.Event( "mouseup", { target: null } ) );
16027
+
16028
+ if ( this.options.helper === "original" ) {
16029
+ this.currentItem.css( this._storedCSS );
16030
+ this._removeClass( this.currentItem, "ui-sortable-helper" );
16031
+ } else {
16032
+ this.currentItem.show();
16033
+ }
16034
+
16035
+ //Post deactivating events to containers
16036
+ for ( var i = this.containers.length - 1; i >= 0; i-- ) {
16037
+ this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
16038
+ if ( this.containers[ i ].containerCache.over ) {
16039
+ this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
16040
+ this.containers[ i ].containerCache.over = 0;
16041
+ }
16042
+ }
16043
+
16044
+ }
16045
+
16046
+ if ( this.placeholder ) {
16047
+
16048
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16049
+ // it unbinds ALL events from the original node!
16050
+ if ( this.placeholder[ 0 ].parentNode ) {
16051
+ this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16052
+ }
16053
+ if ( this.options.helper !== "original" && this.helper &&
16054
+ this.helper[ 0 ].parentNode ) {
16055
+ this.helper.remove();
16056
+ }
16057
+
16058
+ $.extend( this, {
16059
+ helper: null,
16060
+ dragging: false,
16061
+ reverting: false,
16062
+ _noFinalSort: null
16063
+ } );
16064
+
16065
+ if ( this.domPosition.prev ) {
16066
+ $( this.domPosition.prev ).after( this.currentItem );
16067
+ } else {
16068
+ $( this.domPosition.parent ).prepend( this.currentItem );
16069
+ }
16070
+ }
16071
+
16072
+ return this;
16073
+
16074
+ },
16075
+
16076
+ serialize: function( o ) {
16077
+
16078
+ var items = this._getItemsAsjQuery( o && o.connected ),
16079
+ str = [];
16080
+ o = o || {};
16081
+
16082
+ $( items ).each( function() {
16083
+ var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
16084
+ .match( o.expression || ( /(.+)[\-=_](.+)/ ) );
16085
+ if ( res ) {
16086
+ str.push(
16087
+ ( o.key || res[ 1 ] + "[]" ) +
16088
+ "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
16089
+ }
16090
+ } );
16091
+
16092
+ if ( !str.length && o.key ) {
16093
+ str.push( o.key + "=" );
16094
+ }
16095
+
16096
+ return str.join( "&" );
16097
+
16098
+ },
16099
+
16100
+ toArray: function( o ) {
16101
+
16102
+ var items = this._getItemsAsjQuery( o && o.connected ),
16103
+ ret = [];
16104
+
16105
+ o = o || {};
16106
+
16107
+ items.each( function() {
16108
+ ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
16109
+ } );
16110
+ return ret;
16111
+
16112
+ },
16113
+
16114
+ /* Be careful with the following core functions */
16115
+ _intersectsWith: function( item ) {
16116
+
16117
+ var x1 = this.positionAbs.left,
16118
+ x2 = x1 + this.helperProportions.width,
16119
+ y1 = this.positionAbs.top,
16120
+ y2 = y1 + this.helperProportions.height,
16121
+ l = item.left,
16122
+ r = l + item.width,
16123
+ t = item.top,
16124
+ b = t + item.height,
16125
+ dyClick = this.offset.click.top,
16126
+ dxClick = this.offset.click.left,
16127
+ isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
16128
+ ( y1 + dyClick ) < b ),
16129
+ isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
16130
+ ( x1 + dxClick ) < r ),
16131
+ isOverElement = isOverElementHeight && isOverElementWidth;
16132
+
16133
+ if ( this.options.tolerance === "pointer" ||
16134
+ this.options.forcePointerForContainers ||
16135
+ ( this.options.tolerance !== "pointer" &&
16136
+ this.helperProportions[ this.floating ? "width" : "height" ] >
16137
+ item[ this.floating ? "width" : "height" ] )
16138
+ ) {
16139
+ return isOverElement;
16140
+ } else {
16141
+
16142
+ return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
16143
+ x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
16144
+ t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
16145
+ y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
16146
+
16147
+ }
16148
+ },
16149
+
16150
+ _intersectsWithPointer: function( item ) {
16151
+ var verticalDirection, horizontalDirection,
16152
+ isOverElementHeight = ( this.options.axis === "x" ) ||
16153
+ this._isOverAxis(
16154
+ this.positionAbs.top + this.offset.click.top, item.top, item.height ),
16155
+ isOverElementWidth = ( this.options.axis === "y" ) ||
16156
+ this._isOverAxis(
16157
+ this.positionAbs.left + this.offset.click.left, item.left, item.width ),
16158
+ isOverElement = isOverElementHeight && isOverElementWidth;
16159
+
16160
+ if ( !isOverElement ) {
16161
+ return false;
16162
+ }
16163
+
16164
+ verticalDirection = this.dragDirection.vertical;
16165
+ horizontalDirection = this.dragDirection.horizontal;
16166
+
16167
+ return this.floating ?
16168
+ ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
16169
+ ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
16170
+
16171
+ },
16172
+
16173
+ _intersectsWithSides: function( item ) {
16174
+
16175
+ var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
16176
+ this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
16177
+ isOverRightHalf = this._isOverAxis( this.positionAbs.left +
16178
+ this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
16179
+ verticalDirection = this.dragDirection.vertical,
16180
+ horizontalDirection = this.dragDirection.horizontal;
16181
+
16182
+ if ( this.floating && horizontalDirection ) {
16183
+ return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
16184
+ ( horizontalDirection === "left" && !isOverRightHalf ) );
16185
+ } else {
16186
+ return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16187
+ ( verticalDirection === "up" && !isOverBottomHalf ) );
16188
+ }
16189
+
16190
+ },
16191
+
16192
+ _getDragVerticalDirection: function() {
16193
+ var delta = this.positionAbs.top - this.lastPositionAbs.top;
16194
+ return delta !== 0 && ( delta > 0 ? "down" : "up" );
16195
+ },
16196
+
16197
+ _getDragHorizontalDirection: function() {
16198
+ var delta = this.positionAbs.left - this.lastPositionAbs.left;
16199
+ return delta !== 0 && ( delta > 0 ? "right" : "left" );
16200
+ },
16201
+
16202
+ refresh: function( event ) {
16203
+ this._refreshItems( event );
16204
+ this._setHandleClassName();
16205
+ this.refreshPositions();
16206
+ return this;
16207
+ },
16208
+
16209
+ _connectWith: function() {
16210
+ var options = this.options;
16211
+ return options.connectWith.constructor === String ?
16212
+ [ options.connectWith ] :
16213
+ options.connectWith;
16214
+ },
16215
+
16216
+ _getItemsAsjQuery: function( connected ) {
16217
+
16218
+ var i, j, cur, inst,
16219
+ items = [],
16220
+ queries = [],
16221
+ connectWith = this._connectWith();
16222
+
16223
+ if ( connectWith && connected ) {
16224
+ for ( i = connectWith.length - 1; i >= 0; i-- ) {
16225
+ cur = $( connectWith[ i ], this.document[ 0 ] );
16226
+ for ( j = cur.length - 1; j >= 0; j-- ) {
16227
+ inst = $.data( cur[ j ], this.widgetFullName );
16228
+ if ( inst && inst !== this && !inst.options.disabled ) {
16229
+ queries.push( [ typeof inst.options.items === "function" ?
16230
+ inst.options.items.call( inst.element ) :
16231
+ $( inst.options.items, inst.element )
16232
+ .not( ".ui-sortable-helper" )
16233
+ .not( ".ui-sortable-placeholder" ), inst ] );
16234
+ }
16235
+ }
16236
+ }
16237
+ }
16238
+
16239
+ queries.push( [ typeof this.options.items === "function" ?
16240
+ this.options.items
16241
+ .call( this.element, null, { options: this.options, item: this.currentItem } ) :
16242
+ $( this.options.items, this.element )
16243
+ .not( ".ui-sortable-helper" )
16244
+ .not( ".ui-sortable-placeholder" ), this ] );
16245
+
16246
+ function addItems() {
16247
+ items.push( this );
16248
+ }
16249
+ for ( i = queries.length - 1; i >= 0; i-- ) {
16250
+ queries[ i ][ 0 ].each( addItems );
16251
+ }
16252
+
16253
+ return $( items );
16254
+
16255
+ },
16256
+
16257
+ _removeCurrentsFromItems: function() {
16258
+
16259
+ var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16260
+
16261
+ this.items = $.grep( this.items, function( item ) {
16262
+ for ( var j = 0; j < list.length; j++ ) {
16263
+ if ( list[ j ] === item.item[ 0 ] ) {
16264
+ return false;
16265
+ }
16266
+ }
16267
+ return true;
16268
+ } );
16269
+
16270
+ },
16271
+
16272
+ _refreshItems: function( event ) {
16273
+
16274
+ this.items = [];
16275
+ this.containers = [ this ];
16276
+
16277
+ var i, j, cur, inst, targetData, _queries, item, queriesLength,
16278
+ items = this.items,
16279
+ queries = [ [ typeof this.options.items === "function" ?
16280
+ this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16281
+ $( this.options.items, this.element ), this ] ],
16282
+ connectWith = this._connectWith();
16283
+
16284
+ //Shouldn't be run the first time through due to massive slow-down
16285
+ if ( connectWith && this.ready ) {
16286
+ for ( i = connectWith.length - 1; i >= 0; i-- ) {
16287
+ cur = $( connectWith[ i ], this.document[ 0 ] );
16288
+ for ( j = cur.length - 1; j >= 0; j-- ) {
16289
+ inst = $.data( cur[ j ], this.widgetFullName );
16290
+ if ( inst && inst !== this && !inst.options.disabled ) {
16291
+ queries.push( [ typeof inst.options.items === "function" ?
16292
+ inst.options.items
16293
+ .call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16294
+ $( inst.options.items, inst.element ), inst ] );
16295
+ this.containers.push( inst );
16296
+ }
16297
+ }
16298
+ }
16299
+ }
16300
+
16301
+ for ( i = queries.length - 1; i >= 0; i-- ) {
16302
+ targetData = queries[ i ][ 1 ];
16303
+ _queries = queries[ i ][ 0 ];
16304
+
16305
+ for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16306
+ item = $( _queries[ j ] );
16307
+
16308
+ // Data for target checking (mouse manager)
16309
+ item.data( this.widgetName + "-item", targetData );
16310
+
16311
+ items.push( {
16312
+ item: item,
16313
+ instance: targetData,
16314
+ width: 0, height: 0,
16315
+ left: 0, top: 0
16316
+ } );
16317
+ }
16318
+ }
16319
+
16320
+ },
16321
+
16322
+ _refreshItemPositions: function( fast ) {
16323
+ var i, item, t, p;
16324
+
16325
+ for ( i = this.items.length - 1; i >= 0; i-- ) {
16326
+ item = this.items[ i ];
16327
+
16328
+ //We ignore calculating positions of all connected containers when we're not over them
16329
+ if ( this.currentContainer && item.instance !== this.currentContainer &&
16330
+ item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16331
+ continue;
16332
+ }
16333
+
16334
+ t = this.options.toleranceElement ?
16335
+ $( this.options.toleranceElement, item.item ) :
16336
+ item.item;
16337
+
16338
+ if ( !fast ) {
16339
+ item.width = t.outerWidth();
16340
+ item.height = t.outerHeight();
16341
+ }
16342
+
16343
+ p = t.offset();
16344
+ item.left = p.left;
16345
+ item.top = p.top;
16346
+ }
16347
+ },
16348
+
16349
+ refreshPositions: function( fast ) {
16350
+
16351
+ // Determine whether items are being displayed horizontally
16352
+ this.floating = this.items.length ?
16353
+ this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16354
+ false;
16355
+
16356
+ // This has to be redone because due to the item being moved out/into the offsetParent,
16357
+ // the offsetParent's position will change
16358
+ if ( this.offsetParent && this.helper ) {
16359
+ this.offset.parent = this._getParentOffset();
16360
+ }
16361
+
16362
+ this._refreshItemPositions( fast );
16363
+
16364
+ var i, p;
16365
+
16366
+ if ( this.options.custom && this.options.custom.refreshContainers ) {
16367
+ this.options.custom.refreshContainers.call( this );
16368
+ } else {
16369
+ for ( i = this.containers.length - 1; i >= 0; i-- ) {
16370
+ p = this.containers[ i ].element.offset();
16371
+ this.containers[ i ].containerCache.left = p.left;
16372
+ this.containers[ i ].containerCache.top = p.top;
16373
+ this.containers[ i ].containerCache.width =
16374
+ this.containers[ i ].element.outerWidth();
16375
+ this.containers[ i ].containerCache.height =
16376
+ this.containers[ i ].element.outerHeight();
16377
+ }
16378
+ }
16379
+
16380
+ return this;
16381
+ },
16382
+
16383
+ _createPlaceholder: function( that ) {
16384
+ that = that || this;
16385
+ var className, nodeName,
16386
+ o = that.options;
16387
+
16388
+ if ( !o.placeholder || o.placeholder.constructor === String ) {
16389
+ className = o.placeholder;
16390
+ nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16391
+ o.placeholder = {
16392
+ element: function() {
16393
+
16394
+ var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16395
+
16396
+ that._addClass( element, "ui-sortable-placeholder",
16397
+ className || that.currentItem[ 0 ].className )
16398
+ ._removeClass( element, "ui-sortable-helper" );
16399
+
16400
+ if ( nodeName === "tbody" ) {
16401
+ that._createTrPlaceholder(
16402
+ that.currentItem.find( "tr" ).eq( 0 ),
16403
+ $( "<tr>", that.document[ 0 ] ).appendTo( element )
16404
+ );
16405
+ } else if ( nodeName === "tr" ) {
16406
+ that._createTrPlaceholder( that.currentItem, element );
16407
+ } else if ( nodeName === "img" ) {
16408
+ element.attr( "src", that.currentItem.attr( "src" ) );
16409
+ }
16410
+
16411
+ if ( !className ) {
16412
+ element.css( "visibility", "hidden" );
16413
+ }
16414
+
16415
+ return element;
16416
+ },
16417
+ update: function( container, p ) {
16418
+
16419
+ // 1. If a className is set as 'placeholder option, we don't force sizes -
16420
+ // the class is responsible for that
16421
+ // 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16422
+ // class name is specified
16423
+ if ( className && !o.forcePlaceholderSize ) {
16424
+ return;
16425
+ }
16426
+
16427
+ // If the element doesn't have a actual height or width by itself (without
16428
+ // styles coming from a stylesheet), it receives the inline height and width
16429
+ // from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16430
+ // anyway since we're populating them with <td>s above, but they're unlikely to
16431
+ // be the correct height on their own if the row heights are dynamic, so we'll
16432
+ // always assign the height of the dragged item given forcePlaceholderSize
16433
+ // is true.
16434
+ if ( !p.height() || ( o.forcePlaceholderSize &&
16435
+ ( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16436
+ p.height(
16437
+ that.currentItem.innerHeight() -
16438
+ parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16439
+ parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16440
+ }
16441
+ if ( !p.width() ) {
16442
+ p.width(
16443
+ that.currentItem.innerWidth() -
16444
+ parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16445
+ parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16446
+ }
16447
+ }
16448
+ };
16449
+ }
16450
+
16451
+ //Create the placeholder
16452
+ that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16453
+
16454
+ //Append it after the actual current item
16455
+ that.currentItem.after( that.placeholder );
16456
+
16457
+ //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16458
+ o.placeholder.update( that, that.placeholder );
16459
+
16460
+ },
16461
+
16462
+ _createTrPlaceholder: function( sourceTr, targetTr ) {
16463
+ var that = this;
16464
+
16465
+ sourceTr.children().each( function() {
16466
+ $( "<td>&#160;</td>", that.document[ 0 ] )
16467
+ .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16468
+ .appendTo( targetTr );
16469
+ } );
16470
+ },
16471
+
16472
+ _contactContainers: function( event ) {
16473
+ var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16474
+ floating, axis,
16475
+ innermostContainer = null,
16476
+ innermostIndex = null;
16477
+
16478
+ // Get innermost container that intersects with item
16479
+ for ( i = this.containers.length - 1; i >= 0; i-- ) {
16480
+
16481
+ // Never consider a container that's located within the item itself
16482
+ if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16483
+ continue;
16484
+ }
16485
+
16486
+ if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16487
+
16488
+ // If we've already found a container and it's more "inner" than this, then continue
16489
+ if ( innermostContainer &&
16490
+ $.contains(
16491
+ this.containers[ i ].element[ 0 ],
16492
+ innermostContainer.element[ 0 ] ) ) {
16493
+ continue;
16494
+ }
16495
+
16496
+ innermostContainer = this.containers[ i ];
16497
+ innermostIndex = i;
16498
+
16499
+ } else {
16500
+
16501
+ // container doesn't intersect. trigger "out" event if necessary
16502
+ if ( this.containers[ i ].containerCache.over ) {
16503
+ this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16504
+ this.containers[ i ].containerCache.over = 0;
16505
+ }
16506
+ }
16507
+
16508
+ }
16509
+
16510
+ // If no intersecting containers found, return
16511
+ if ( !innermostContainer ) {
16512
+ return;
16513
+ }
16514
+
16515
+ // Move the item into the container if it's not there already
16516
+ if ( this.containers.length === 1 ) {
16517
+ if ( !this.containers[ innermostIndex ].containerCache.over ) {
16518
+ this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16519
+ this.containers[ innermostIndex ].containerCache.over = 1;
16520
+ }
16521
+ } else {
16522
+
16523
+ // When entering a new container, we will find the item with the least distance and
16524
+ // append our item near it
16525
+ dist = 10000;
16526
+ itemWithLeastDistance = null;
16527
+ floating = innermostContainer.floating || this._isFloating( this.currentItem );
16528
+ posProperty = floating ? "left" : "top";
16529
+ sizeProperty = floating ? "width" : "height";
16530
+ axis = floating ? "pageX" : "pageY";
16531
+
16532
+ for ( j = this.items.length - 1; j >= 0; j-- ) {
16533
+ if ( !$.contains(
16534
+ this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16535
+ ) {
16536
+ continue;
16537
+ }
16538
+ if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16539
+ continue;
16540
+ }
16541
+
16542
+ cur = this.items[ j ].item.offset()[ posProperty ];
16543
+ nearBottom = false;
16544
+ if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16545
+ nearBottom = true;
16546
+ }
16547
+
16548
+ if ( Math.abs( event[ axis ] - cur ) < dist ) {
16549
+ dist = Math.abs( event[ axis ] - cur );
16550
+ itemWithLeastDistance = this.items[ j ];
16551
+ this.direction = nearBottom ? "up" : "down";
16552
+ }
16553
+ }
16554
+
16555
+ //Check if dropOnEmpty is enabled
16556
+ if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16557
+ return;
16558
+ }
16559
+
16560
+ if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16561
+ if ( !this.currentContainer.containerCache.over ) {
16562
+ this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16563
+ this.currentContainer.containerCache.over = 1;
16564
+ }
16565
+ return;
16566
+ }
16567
+
16568
+ if ( itemWithLeastDistance ) {
16569
+ this._rearrange( event, itemWithLeastDistance, null, true );
16570
+ } else {
16571
+ this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16572
+ }
16573
+ this._trigger( "change", event, this._uiHash() );
16574
+ this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16575
+ this.currentContainer = this.containers[ innermostIndex ];
16576
+
16577
+ //Update the placeholder
16578
+ this.options.placeholder.update( this.currentContainer, this.placeholder );
16579
+
16580
+ //Update scrollParent
16581
+ this.scrollParent = this.placeholder.scrollParent();
16582
+
16583
+ //Update overflowOffset
16584
+ if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16585
+ this.scrollParent[ 0 ].tagName !== "HTML" ) {
16586
+ this.overflowOffset = this.scrollParent.offset();
16587
+ }
16588
+
16589
+ this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16590
+ this.containers[ innermostIndex ].containerCache.over = 1;
16591
+ }
16592
+
16593
+ },
16594
+
16595
+ _createHelper: function( event ) {
16596
+
16597
+ var o = this.options,
16598
+ helper = typeof o.helper === "function" ?
16599
+ $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16600
+ ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16601
+
16602
+ //Add the helper to the DOM if that didn't happen already
16603
+ if ( !helper.parents( "body" ).length ) {
16604
+ this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16605
+ }
16606
+
16607
+ if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16608
+ this._storedCSS = {
16609
+ width: this.currentItem[ 0 ].style.width,
16610
+ height: this.currentItem[ 0 ].style.height,
16611
+ position: this.currentItem.css( "position" ),
16612
+ top: this.currentItem.css( "top" ),
16613
+ left: this.currentItem.css( "left" )
16614
+ };
16615
+ }
16616
+
16617
+ if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16618
+ helper.width( this.currentItem.width() );
16619
+ }
16620
+ if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16621
+ helper.height( this.currentItem.height() );
16622
+ }
16623
+
16624
+ return helper;
16625
+
16626
+ },
16627
+
16628
+ _adjustOffsetFromHelper: function( obj ) {
16629
+ if ( typeof obj === "string" ) {
16630
+ obj = obj.split( " " );
16631
+ }
16632
+ if ( Array.isArray( obj ) ) {
16633
+ obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16634
+ }
16635
+ if ( "left" in obj ) {
16636
+ this.offset.click.left = obj.left + this.margins.left;
16637
+ }
16638
+ if ( "right" in obj ) {
16639
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16640
+ }
16641
+ if ( "top" in obj ) {
16642
+ this.offset.click.top = obj.top + this.margins.top;
16643
+ }
16644
+ if ( "bottom" in obj ) {
16645
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16646
+ }
16647
+ },
16648
+
16649
+ _getParentOffset: function() {
16650
+
16651
+ //Get the offsetParent and cache its position
16652
+ this.offsetParent = this.helper.offsetParent();
16653
+ var po = this.offsetParent.offset();
16654
+
16655
+ // This is a special case where we need to modify a offset calculated on start, since the
16656
+ // following happened:
16657
+ // 1. The position of the helper is absolute, so it's position is calculated based on the
16658
+ // next positioned parent
16659
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16660
+ // the document, which means that the scroll is included in the initial calculation of the
16661
+ // offset of the parent, and never recalculated upon drag
16662
+ if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16663
+ $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16664
+ po.left += this.scrollParent.scrollLeft();
16665
+ po.top += this.scrollParent.scrollTop();
16666
+ }
16667
+
16668
+ // This needs to be actually done for all browsers, since pageX/pageY includes this
16669
+ // information with an ugly IE fix
16670
+ if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
16671
+ ( this.offsetParent[ 0 ].tagName &&
16672
+ this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
16673
+ po = { top: 0, left: 0 };
16674
+ }
16675
+
16676
+ return {
16677
+ top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16678
+ left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16679
+ };
16680
+
16681
+ },
16682
+
16683
+ _getRelativeOffset: function() {
16684
+
16685
+ if ( this.cssPosition === "relative" ) {
16686
+ var p = this.currentItem.position();
16687
+ return {
16688
+ top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16689
+ this.scrollParent.scrollTop(),
16690
+ left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16691
+ this.scrollParent.scrollLeft()
16692
+ };
16693
+ } else {
16694
+ return { top: 0, left: 0 };
16695
+ }
16696
+
16697
+ },
16698
+
16699
+ _cacheMargins: function() {
16700
+ this.margins = {
16701
+ left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16702
+ top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16703
+ };
16704
+ },
16705
+
16706
+ _cacheHelperProportions: function() {
16707
+ this.helperProportions = {
16708
+ width: this.helper.outerWidth(),
16709
+ height: this.helper.outerHeight()
16710
+ };
16711
+ },
16712
+
16713
+ _setContainment: function() {
16714
+
16715
+ var ce, co, over,
16716
+ o = this.options;
16717
+ if ( o.containment === "parent" ) {
16718
+ o.containment = this.helper[ 0 ].parentNode;
16719
+ }
16720
+ if ( o.containment === "document" || o.containment === "window" ) {
16721
+ this.containment = [
16722
+ 0 - this.offset.relative.left - this.offset.parent.left,
16723
+ 0 - this.offset.relative.top - this.offset.parent.top,
16724
+ o.containment === "document" ?
16725
+ this.document.width() :
16726
+ this.window.width() - this.helperProportions.width - this.margins.left,
16727
+ ( o.containment === "document" ?
16728
+ ( this.document.height() || document.body.parentNode.scrollHeight ) :
16729
+ this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16730
+ ) - this.helperProportions.height - this.margins.top
16731
+ ];
16732
+ }
16733
+
16734
+ if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16735
+ ce = $( o.containment )[ 0 ];
16736
+ co = $( o.containment ).offset();
16737
+ over = ( $( ce ).css( "overflow" ) !== "hidden" );
16738
+
16739
+ this.containment = [
16740
+ co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16741
+ ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16742
+ co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16743
+ ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16744
+ co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16745
+ ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16746
+ ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16747
+ this.helperProportions.width - this.margins.left,
16748
+ co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16749
+ ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16750
+ ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16751
+ this.helperProportions.height - this.margins.top
16752
+ ];
16753
+ }
16754
+
16755
+ },
16756
+
16757
+ _convertPositionTo: function( d, pos ) {
16758
+
16759
+ if ( !pos ) {
16760
+ pos = this.position;
16761
+ }
16762
+ var mod = d === "absolute" ? 1 : -1,
16763
+ scroll = this.cssPosition === "absolute" &&
16764
+ !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16765
+ $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16766
+ this.offsetParent :
16767
+ this.scrollParent,
16768
+ scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16769
+
16770
+ return {
16771
+ top: (
16772
+
16773
+ // The absolute mouse position
16774
+ pos.top +
16775
+
16776
+ // Only for relative positioned nodes: Relative offset from element to offset parent
16777
+ this.offset.relative.top * mod +
16778
+
16779
+ // The offsetParent's offset without borders (offset + border)
16780
+ this.offset.parent.top * mod -
16781
+ ( ( this.cssPosition === "fixed" ?
16782
+ -this.scrollParent.scrollTop() :
16783
+ ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16784
+ ),
16785
+ left: (
16786
+
16787
+ // The absolute mouse position
16788
+ pos.left +
16789
+
16790
+ // Only for relative positioned nodes: Relative offset from element to offset parent
16791
+ this.offset.relative.left * mod +
16792
+
16793
+ // The offsetParent's offset without borders (offset + border)
16794
+ this.offset.parent.left * mod -
16795
+ ( ( this.cssPosition === "fixed" ?
16796
+ -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16797
+ scroll.scrollLeft() ) * mod )
16798
+ )
16799
+ };
16800
+
16801
+ },
16802
+
16803
+ _generatePosition: function( event ) {
16804
+
16805
+ var top, left,
16806
+ o = this.options,
16807
+ pageX = event.pageX,
16808
+ pageY = event.pageY,
16809
+ scroll = this.cssPosition === "absolute" &&
16810
+ !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16811
+ $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16812
+ this.offsetParent :
16813
+ this.scrollParent,
16814
+ scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16815
+
16816
+ // This is another very weird special case that only happens for relative elements:
16817
+ // 1. If the css position is relative
16818
+ // 2. and the scroll parent is the document or similar to the offset parent
16819
+ // we have to refresh the relative offset during the scroll so there are no jumps
16820
+ if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16821
+ this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16822
+ this.offset.relative = this._getRelativeOffset();
16823
+ }
16824
+
16825
+ /*
16826
+ * - Position constraining -
16827
+ * Constrain the position to a mix of grid, containment.
16828
+ */
16829
+
16830
+ if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16831
+
16832
+ if ( this.containment ) {
16833
+ if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16834
+ pageX = this.containment[ 0 ] + this.offset.click.left;
16835
+ }
16836
+ if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16837
+ pageY = this.containment[ 1 ] + this.offset.click.top;
16838
+ }
16839
+ if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16840
+ pageX = this.containment[ 2 ] + this.offset.click.left;
16841
+ }
16842
+ if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16843
+ pageY = this.containment[ 3 ] + this.offset.click.top;
16844
+ }
16845
+ }
16846
+
16847
+ if ( o.grid ) {
16848
+ top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16849
+ o.grid[ 1 ] ) * o.grid[ 1 ];
16850
+ pageY = this.containment ?
16851
+ ( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16852
+ top - this.offset.click.top <= this.containment[ 3 ] ) ?
16853
+ top :
16854
+ ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16855
+ top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16856
+ top;
16857
+
16858
+ left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16859
+ o.grid[ 0 ] ) * o.grid[ 0 ];
16860
+ pageX = this.containment ?
16861
+ ( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16862
+ left - this.offset.click.left <= this.containment[ 2 ] ) ?
16863
+ left :
16864
+ ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16865
+ left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16866
+ left;
16867
+ }
16868
+
16869
+ }
16870
+
16871
+ return {
16872
+ top: (
16873
+
16874
+ // The absolute mouse position
16875
+ pageY -
16876
+
16877
+ // Click offset (relative to the element)
16878
+ this.offset.click.top -
16879
+
16880
+ // Only for relative positioned nodes: Relative offset from element to offset parent
16881
+ this.offset.relative.top -
16882
+
16883
+ // The offsetParent's offset without borders (offset + border)
16884
+ this.offset.parent.top +
16885
+ ( ( this.cssPosition === "fixed" ?
16886
+ -this.scrollParent.scrollTop() :
16887
+ ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16888
+ ),
16889
+ left: (
16890
+
16891
+ // The absolute mouse position
16892
+ pageX -
16893
+
16894
+ // Click offset (relative to the element)
16895
+ this.offset.click.left -
16896
+
16897
+ // Only for relative positioned nodes: Relative offset from element to offset parent
16898
+ this.offset.relative.left -
16899
+
16900
+ // The offsetParent's offset without borders (offset + border)
16901
+ this.offset.parent.left +
16902
+ ( ( this.cssPosition === "fixed" ?
16903
+ -this.scrollParent.scrollLeft() :
16904
+ scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16905
+ )
16906
+ };
16907
+
16908
+ },
16909
+
16910
+ _rearrange: function( event, i, a, hardRefresh ) {
16911
+
16912
+ if ( a ) {
16913
+ a[ 0 ].appendChild( this.placeholder[ 0 ] );
16914
+ } else {
16915
+ i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16916
+ ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16917
+ }
16918
+
16919
+ //Various things done here to improve the performance:
16920
+ // 1. we create a setTimeout, that calls refreshPositions
16921
+ // 2. on the instance, we have a counter variable, that get's higher after every append
16922
+ // 3. on the local scope, we copy the counter variable, and check in the timeout,
16923
+ // if it's still the same
16924
+ // 4. this lets only the last addition to the timeout stack through
16925
+ this.counter = this.counter ? ++this.counter : 1;
16926
+ var counter = this.counter;
16927
+
16928
+ this._delay( function() {
16929
+ if ( counter === this.counter ) {
16930
+
16931
+ //Precompute after each DOM insertion, NOT on mousemove
16932
+ this.refreshPositions( !hardRefresh );
16933
+ }
16934
+ } );
16935
+
16936
+ },
16937
+
16938
+ _clear: function( event, noPropagation ) {
16939
+
16940
+ this.reverting = false;
16941
+
16942
+ // We delay all events that have to be triggered to after the point where the placeholder
16943
+ // has been removed and everything else normalized again
16944
+ var i,
16945
+ delayedTriggers = [];
16946
+
16947
+ // We first have to update the dom position of the actual currentItem
16948
+ // Note: don't do it if the current item is already removed (by a user), or it gets
16949
+ // reappended (see #4088)
16950
+ if ( !this._noFinalSort && this.currentItem.parent().length ) {
16951
+ this.placeholder.before( this.currentItem );
16952
+ }
16953
+ this._noFinalSort = null;
16954
+
16955
+ if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16956
+ for ( i in this._storedCSS ) {
16957
+ if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16958
+ this._storedCSS[ i ] = "";
16959
+ }
16960
+ }
16961
+ this.currentItem.css( this._storedCSS );
16962
+ this._removeClass( this.currentItem, "ui-sortable-helper" );
16963
+ } else {
16964
+ this.currentItem.show();
16965
+ }
16966
+
16967
+ if ( this.fromOutside && !noPropagation ) {
16968
+ delayedTriggers.push( function( event ) {
16969
+ this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16970
+ } );
16971
+ }
16972
+ if ( ( this.fromOutside ||
16973
+ this.domPosition.prev !==
16974
+ this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16975
+ this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16976
+
16977
+ // Trigger update callback if the DOM position has changed
16978
+ delayedTriggers.push( function( event ) {
16979
+ this._trigger( "update", event, this._uiHash() );
16980
+ } );
16981
+ }
16982
+
16983
+ // Check if the items Container has Changed and trigger appropriate
16984
+ // events.
16985
+ if ( this !== this.currentContainer ) {
16986
+ if ( !noPropagation ) {
16987
+ delayedTriggers.push( function( event ) {
16988
+ this._trigger( "remove", event, this._uiHash() );
16989
+ } );
16990
+ delayedTriggers.push( ( function( c ) {
16991
+ return function( event ) {
16992
+ c._trigger( "receive", event, this._uiHash( this ) );
16993
+ };
16994
+ } ).call( this, this.currentContainer ) );
16995
+ delayedTriggers.push( ( function( c ) {
16996
+ return function( event ) {
16997
+ c._trigger( "update", event, this._uiHash( this ) );
16998
+ };
16999
+ } ).call( this, this.currentContainer ) );
17000
+ }
17001
+ }
17002
+
17003
+ //Post events to containers
17004
+ function delayEvent( type, instance, container ) {
17005
+ return function( event ) {
17006
+ container._trigger( type, event, instance._uiHash( instance ) );
17007
+ };
17008
+ }
17009
+ for ( i = this.containers.length - 1; i >= 0; i-- ) {
17010
+ if ( !noPropagation ) {
17011
+ delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
17012
+ }
17013
+ if ( this.containers[ i ].containerCache.over ) {
17014
+ delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
17015
+ this.containers[ i ].containerCache.over = 0;
17016
+ }
17017
+ }
17018
+
17019
+ //Do what was originally in plugins
17020
+ if ( this.storedCursor ) {
17021
+ this.document.find( "body" ).css( "cursor", this.storedCursor );
17022
+ this.storedStylesheet.remove();
17023
+ }
17024
+ if ( this._storedOpacity ) {
17025
+ this.helper.css( "opacity", this._storedOpacity );
17026
+ }
17027
+ if ( this._storedZIndex ) {
17028
+ this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
17029
+ }
17030
+
17031
+ this.dragging = false;
17032
+
17033
+ if ( !noPropagation ) {
17034
+ this._trigger( "beforeStop", event, this._uiHash() );
17035
+ }
17036
+
17037
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
17038
+ // it unbinds ALL events from the original node!
17039
+ this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
17040
+
17041
+ if ( !this.cancelHelperRemoval ) {
17042
+ if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
17043
+ this.helper.remove();
17044
+ }
17045
+ this.helper = null;
17046
+ }
17047
+
17048
+ if ( !noPropagation ) {
17049
+ for ( i = 0; i < delayedTriggers.length; i++ ) {
17050
+
17051
+ // Trigger all delayed events
17052
+ delayedTriggers[ i ].call( this, event );
17053
+ }
17054
+ this._trigger( "stop", event, this._uiHash() );
17055
+ }
17056
+
17057
+ this.fromOutside = false;
17058
+ return !this.cancelHelperRemoval;
17059
+
17060
+ },
17061
+
17062
+ _trigger: function() {
17063
+ if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
17064
+ this.cancel();
17065
+ }
17066
+ },
17067
+
17068
+ _uiHash: function( _inst ) {
17069
+ var inst = _inst || this;
17070
+ return {
17071
+ helper: inst.helper,
17072
+ placeholder: inst.placeholder || $( [] ),
17073
+ position: inst.position,
17074
+ originalPosition: inst.originalPosition,
17075
+ offset: inst.positionAbs,
17076
+ item: inst.currentItem,
17077
+ sender: _inst ? _inst.element : null
17078
+ };
17079
+ }
17080
+
17081
+ } );
17082
+
17083
+
17084
+ /*!
17085
+ * jQuery UI Spinner 1.13.1
17086
+ * http://jqueryui.com
17087
+ *
17088
+ * Copyright jQuery Foundation and other contributors
17089
+ * Released under the MIT license.
17090
+ * http://jquery.org/license
17091
+ */
17092
+
17093
+ //>>label: Spinner
17094
+ //>>group: Widgets
17095
+ //>>description: Displays buttons to easily input numbers via the keyboard or mouse.
17096
+ //>>docs: http://api.jqueryui.com/spinner/
17097
+ //>>demos: http://jqueryui.com/spinner/
17098
+ //>>css.structure: ../../themes/base/core.css
17099
+ //>>css.structure: ../../themes/base/spinner.css
17100
+ //>>css.theme: ../../themes/base/theme.css
17101
+
17102
+
17103
+ function spinnerModifier( fn ) {
17104
+ return function() {
17105
+ var previous = this.element.val();
17106
+ fn.apply( this, arguments );
17107
+ this._refresh();
17108
+ if ( previous !== this.element.val() ) {
17109
+ this._trigger( "change" );
17110
+ }
17111
+ };
17112
+ }
17113
+
17114
+ $.widget( "ui.spinner", {
17115
+ version: "1.13.1",
17116
+ defaultElement: "<input>",
17117
+ widgetEventPrefix: "spin",
17118
+ options: {
17119
+ classes: {
17120
+ "ui-spinner": "ui-corner-all",
17121
+ "ui-spinner-down": "ui-corner-br",
17122
+ "ui-spinner-up": "ui-corner-tr"
17123
+ },
17124
+ culture: null,
17125
+ icons: {
17126
+ down: "ui-icon-triangle-1-s",
17127
+ up: "ui-icon-triangle-1-n"
17128
+ },
17129
+ incremental: true,
17130
+ max: null,
17131
+ min: null,
17132
+ numberFormat: null,
17133
+ page: 10,
17134
+ step: 1,
17135
+
17136
+ change: null,
17137
+ spin: null,
17138
+ start: null,
17139
+ stop: null
17140
+ },
17141
+
17142
+ _create: function() {
17143
+
17144
+ // handle string values that need to be parsed
17145
+ this._setOption( "max", this.options.max );
17146
+ this._setOption( "min", this.options.min );
17147
+ this._setOption( "step", this.options.step );
17148
+
17149
+ // Only format if there is a value, prevents the field from being marked
17150
+ // as invalid in Firefox, see #9573.
17151
+ if ( this.value() !== "" ) {
17152
+
17153
+ // Format the value, but don't constrain.
17154
+ this._value( this.element.val(), true );
17155
+ }
17156
+
17157
+ this._draw();
17158
+ this._on( this._events );
17159
+ this._refresh();
17160
+
17161
+ // Turning off autocomplete prevents the browser from remembering the
17162
+ // value when navigating through history, so we re-enable autocomplete
17163
+ // if the page is unloaded before the widget is destroyed. #7790
17164
+ this._on( this.window, {
17165
+ beforeunload: function() {
17166
+ this.element.removeAttr( "autocomplete" );
17167
+ }
17168
+ } );
17169
+ },
17170
+
17171
+ _getCreateOptions: function() {
17172
+ var options = this._super();
17173
+ var element = this.element;
17174
+
17175
+ $.each( [ "min", "max", "step" ], function( i, option ) {
17176
+ var value = element.attr( option );
17177
+ if ( value != null && value.length ) {
17178
+ options[ option ] = value;
17179
+ }
17180
+ } );
17181
+
17182
+ return options;
17183
+ },
17184
+
17185
+ _events: {
17186
+ keydown: function( event ) {
17187
+ if ( this._start( event ) && this._keydown( event ) ) {
17188
+ event.preventDefault();
17189
+ }
17190
+ },
17191
+ keyup: "_stop",
17192
+ focus: function() {
17193
+ this.previous = this.element.val();
17194
+ },
17195
+ blur: function( event ) {
17196
+ if ( this.cancelBlur ) {
17197
+ delete this.cancelBlur;
17198
+ return;
17199
+ }
17200
+
17201
+ this._stop();
17202
+ this._refresh();
17203
+ if ( this.previous !== this.element.val() ) {
17204
+ this._trigger( "change", event );
17205
+ }
17206
+ },
17207
+ mousewheel: function( event, delta ) {
17208
+ var activeElement = $.ui.safeActiveElement( this.document[ 0 ] );
17209
+ var isActive = this.element[ 0 ] === activeElement;
17210
+
17211
+ if ( !isActive || !delta ) {
17212
+ return;
17213
+ }
17214
+
17215
+ if ( !this.spinning && !this._start( event ) ) {
17216
+ return false;
17217
+ }
17218
+
17219
+ this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17220
+ clearTimeout( this.mousewheelTimer );
17221
+ this.mousewheelTimer = this._delay( function() {
17222
+ if ( this.spinning ) {
17223
+ this._stop( event );
17224
+ }
17225
+ }, 100 );
17226
+ event.preventDefault();
17227
+ },
17228
+ "mousedown .ui-spinner-button": function( event ) {
17229
+ var previous;
17230
+
17231
+ // We never want the buttons to have focus; whenever the user is
17232
+ // interacting with the spinner, the focus should be on the input.
17233
+ // If the input is focused then this.previous is properly set from
17234
+ // when the input first received focus. If the input is not focused
17235
+ // then we need to set this.previous based on the value before spinning.
17236
+ previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
17237
+ this.previous : this.element.val();
17238
+ function checkFocus() {
17239
+ var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
17240
+ if ( !isActive ) {
17241
+ this.element.trigger( "focus" );
17242
+ this.previous = previous;
17243
+
17244
+ // support: IE
17245
+ // IE sets focus asynchronously, so we need to check if focus
17246
+ // moved off of the input because the user clicked on the button.
17247
+ this._delay( function() {
17248
+ this.previous = previous;
17249
+ } );
17250
+ }
17251
+ }
17252
+
17253
+ // Ensure focus is on (or stays on) the text field
17254
+ event.preventDefault();
17255
+ checkFocus.call( this );
17256
+
17257
+ // Support: IE
17258
+ // IE doesn't prevent moving focus even with event.preventDefault()
17259
+ // so we set a flag to know when we should ignore the blur event
17260
+ // and check (again) if focus moved off of the input.
17261
+ this.cancelBlur = true;
17262
+ this._delay( function() {
17263
+ delete this.cancelBlur;
17264
+ checkFocus.call( this );
17265
+ } );
17266
+
17267
+ if ( this._start( event ) === false ) {
17268
+ return;
17269
+ }
17270
+
17271
+ this._repeat( null, $( event.currentTarget )
17272
+ .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17273
+ },
17274
+ "mouseup .ui-spinner-button": "_stop",
17275
+ "mouseenter .ui-spinner-button": function( event ) {
17276
+
17277
+ // button will add ui-state-active if mouse was down while mouseleave and kept down
17278
+ if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17279
+ return;
17280
+ }
17281
+
17282
+ if ( this._start( event ) === false ) {
17283
+ return false;
17284
+ }
17285
+ this._repeat( null, $( event.currentTarget )
17286
+ .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17287
+ },
17288
+
17289
+ // TODO: do we really want to consider this a stop?
17290
+ // shouldn't we just stop the repeater and wait until mouseup before
17291
+ // we trigger the stop event?
17292
+ "mouseleave .ui-spinner-button": "_stop"
17293
+ },
17294
+
17295
+ // Support mobile enhanced option and make backcompat more sane
17296
+ _enhance: function() {
17297
+ this.uiSpinner = this.element
17298
+ .attr( "autocomplete", "off" )
17299
+ .wrap( "<span>" )
17300
+ .parent()
17301
+
17302
+ // Add buttons
17303
+ .append(
17304
+ "<a></a><a></a>"
17305
+ );
17306
+ },
17307
+
17308
+ _draw: function() {
17309
+ this._enhance();
17310
+
17311
+ this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17312
+ this._addClass( "ui-spinner-input" );
17313
+
17314
+ this.element.attr( "role", "spinbutton" );
17315
+
17316
+ // Button bindings
17317
+ this.buttons = this.uiSpinner.children( "a" )
17318
+ .attr( "tabIndex", -1 )
17319
+ .attr( "aria-hidden", true )
17320
+ .button( {
17321
+ classes: {
17322
+ "ui-button": ""
17323
+ }
17324
+ } );
17325
+
17326
+ // TODO: Right now button does not support classes this is already updated in button PR
17327
+ this._removeClass( this.buttons, "ui-corner-all" );
17328
+
17329
+ this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17330
+ this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17331
+ this.buttons.first().button( {
17332
+ "icon": this.options.icons.up,
17333
+ "showLabel": false
17334
+ } );
17335
+ this.buttons.last().button( {
17336
+ "icon": this.options.icons.down,
17337
+ "showLabel": false
17338
+ } );
17339
+
17340
+ // IE 6 doesn't understand height: 50% for the buttons
17341
+ // unless the wrapper has an explicit height
17342
+ if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17343
+ this.uiSpinner.height() > 0 ) {
17344
+ this.uiSpinner.height( this.uiSpinner.height() );
17345
+ }
17346
+ },
17347
+
17348
+ _keydown: function( event ) {
17349
+ var options = this.options,
17350
+ keyCode = $.ui.keyCode;
17351
+
17352
+ switch ( event.keyCode ) {
17353
+ case keyCode.UP:
17354
+ this._repeat( null, 1, event );
17355
+ return true;
17356
+ case keyCode.DOWN:
17357
+ this._repeat( null, -1, event );
17358
+ return true;
17359
+ case keyCode.PAGE_UP:
17360
+ this._repeat( null, options.page, event );
17361
+ return true;
17362
+ case keyCode.PAGE_DOWN:
17363
+ this._repeat( null, -options.page, event );
17364
+ return true;
17365
+ }
17366
+
17367
+ return false;
17368
+ },
17369
+
17370
+ _start: function( event ) {
17371
+ if ( !this.spinning && this._trigger( "start", event ) === false ) {
17372
+ return false;
17373
+ }
17374
+
17375
+ if ( !this.counter ) {
17376
+ this.counter = 1;
17377
+ }
17378
+ this.spinning = true;
17379
+ return true;
17380
+ },
17381
+
17382
+ _repeat: function( i, steps, event ) {
17383
+ i = i || 500;
17384
+
17385
+ clearTimeout( this.timer );
17386
+ this.timer = this._delay( function() {
17387
+ this._repeat( 40, steps, event );
17388
+ }, i );
17389
+
17390
+ this._spin( steps * this.options.step, event );
17391
+ },
17392
+
17393
+ _spin: function( step, event ) {
17394
+ var value = this.value() || 0;
17395
+
17396
+ if ( !this.counter ) {
17397
+ this.counter = 1;
17398
+ }
17399
+
17400
+ value = this._adjustValue( value + step * this._increment( this.counter ) );
17401
+
17402
+ if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17403
+ this._value( value );
17404
+ this.counter++;
17405
+ }
17406
+ },
17407
+
17408
+ _increment: function( i ) {
17409
+ var incremental = this.options.incremental;
17410
+
17411
+ if ( incremental ) {
17412
+ return typeof incremental === "function" ?
17413
+ incremental( i ) :
17414
+ Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17415
+ }
17416
+
17417
+ return 1;
17418
+ },
17419
+
17420
+ _precision: function() {
17421
+ var precision = this._precisionOf( this.options.step );
17422
+ if ( this.options.min !== null ) {
17423
+ precision = Math.max( precision, this._precisionOf( this.options.min ) );
17424
+ }
17425
+ return precision;
17426
+ },
17427
+
17428
+ _precisionOf: function( num ) {
17429
+ var str = num.toString(),
17430
+ decimal = str.indexOf( "." );
17431
+ return decimal === -1 ? 0 : str.length - decimal - 1;
17432
+ },
17433
+
17434
+ _adjustValue: function( value ) {
17435
+ var base, aboveMin,
17436
+ options = this.options;
17437
+
17438
+ // Make sure we're at a valid step
17439
+ // - find out where we are relative to the base (min or 0)
17440
+ base = options.min !== null ? options.min : 0;
17441
+ aboveMin = value - base;
17442
+
17443
+ // - round to the nearest step
17444
+ aboveMin = Math.round( aboveMin / options.step ) * options.step;
17445
+
17446
+ // - rounding is based on 0, so adjust back to our base
17447
+ value = base + aboveMin;
17448
+
17449
+ // Fix precision from bad JS floating point math
17450
+ value = parseFloat( value.toFixed( this._precision() ) );
17451
+
17452
+ // Clamp the value
17453
+ if ( options.max !== null && value > options.max ) {
17454
+ return options.max;
17455
+ }
17456
+ if ( options.min !== null && value < options.min ) {
17457
+ return options.min;
17458
+ }
17459
+
17460
+ return value;
17461
+ },
17462
+
17463
+ _stop: function( event ) {
17464
+ if ( !this.spinning ) {
17465
+ return;
17466
+ }
17467
+
17468
+ clearTimeout( this.timer );
17469
+ clearTimeout( this.mousewheelTimer );
17470
+ this.counter = 0;
17471
+ this.spinning = false;
17472
+ this._trigger( "stop", event );
17473
+ },
17474
+
17475
+ _setOption: function( key, value ) {
17476
+ var prevValue, first, last;
17477
+
17478
+ if ( key === "culture" || key === "numberFormat" ) {
17479
+ prevValue = this._parse( this.element.val() );
17480
+ this.options[ key ] = value;
17481
+ this.element.val( this._format( prevValue ) );
17482
+ return;
17483
+ }
17484
+
17485
+ if ( key === "max" || key === "min" || key === "step" ) {
17486
+ if ( typeof value === "string" ) {
17487
+ value = this._parse( value );
17488
+ }
17489
+ }
17490
+ if ( key === "icons" ) {
17491
+ first = this.buttons.first().find( ".ui-icon" );
17492
+ this._removeClass( first, null, this.options.icons.up );
17493
+ this._addClass( first, null, value.up );
17494
+ last = this.buttons.last().find( ".ui-icon" );
17495
+ this._removeClass( last, null, this.options.icons.down );
17496
+ this._addClass( last, null, value.down );
17497
+ }
17498
+
17499
+ this._super( key, value );
17500
+ },
17501
+
17502
+ _setOptionDisabled: function( value ) {
17503
+ this._super( value );
17504
+
17505
+ this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17506
+ this.element.prop( "disabled", !!value );
17507
+ this.buttons.button( value ? "disable" : "enable" );
17508
+ },
17509
+
17510
+ _setOptions: spinnerModifier( function( options ) {
17511
+ this._super( options );
17512
+ } ),
17513
+
17514
+ _parse: function( val ) {
17515
+ if ( typeof val === "string" && val !== "" ) {
17516
+ val = window.Globalize && this.options.numberFormat ?
17517
+ Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17518
+ }
17519
+ return val === "" || isNaN( val ) ? null : val;
17520
+ },
17521
+
17522
+ _format: function( value ) {
17523
+ if ( value === "" ) {
17524
+ return "";
17525
+ }
17526
+ return window.Globalize && this.options.numberFormat ?
17527
+ Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17528
+ value;
17529
+ },
17530
+
17531
+ _refresh: function() {
17532
+ this.element.attr( {
17533
+ "aria-valuemin": this.options.min,
17534
+ "aria-valuemax": this.options.max,
17535
+
17536
+ // TODO: what should we do with values that can't be parsed?
17537
+ "aria-valuenow": this._parse( this.element.val() )
17538
+ } );
17539
+ },
17540
+
17541
+ isValid: function() {
17542
+ var value = this.value();
17543
+
17544
+ // Null is invalid
17545
+ if ( value === null ) {
17546
+ return false;
17547
+ }
17548
+
17549
+ // If value gets adjusted, it's invalid
17550
+ return value === this._adjustValue( value );
17551
+ },
17552
+
17553
+ // Update the value without triggering change
17554
+ _value: function( value, allowAny ) {
17555
+ var parsed;
17556
+ if ( value !== "" ) {
17557
+ parsed = this._parse( value );
17558
+ if ( parsed !== null ) {
17559
+ if ( !allowAny ) {
17560
+ parsed = this._adjustValue( parsed );
17561
+ }
17562
+ value = this._format( parsed );
17563
+ }
17564
+ }
17565
+ this.element.val( value );
17566
+ this._refresh();
17567
+ },
17568
+
17569
+ _destroy: function() {
17570
+ this.element
17571
+ .prop( "disabled", false )
17572
+ .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17573
+
17574
+ this.uiSpinner.replaceWith( this.element );
17575
+ },
17576
+
17577
+ stepUp: spinnerModifier( function( steps ) {
17578
+ this._stepUp( steps );
17579
+ } ),
17580
+ _stepUp: function( steps ) {
17581
+ if ( this._start() ) {
17582
+ this._spin( ( steps || 1 ) * this.options.step );
17583
+ this._stop();
17584
+ }
17585
+ },
17586
+
17587
+ stepDown: spinnerModifier( function( steps ) {
17588
+ this._stepDown( steps );
17589
+ } ),
17590
+ _stepDown: function( steps ) {
17591
+ if ( this._start() ) {
17592
+ this._spin( ( steps || 1 ) * -this.options.step );
17593
+ this._stop();
17594
+ }
17595
+ },
17596
+
17597
+ pageUp: spinnerModifier( function( pages ) {
17598
+ this._stepUp( ( pages || 1 ) * this.options.page );
17599
+ } ),
17600
+
17601
+ pageDown: spinnerModifier( function( pages ) {
17602
+ this._stepDown( ( pages || 1 ) * this.options.page );
17603
+ } ),
17604
+
17605
+ value: function( newVal ) {
17606
+ if ( !arguments.length ) {
17607
+ return this._parse( this.element.val() );
17608
+ }
17609
+ spinnerModifier( this._value ).call( this, newVal );
17610
+ },
17611
+
17612
+ widget: function() {
17613
+ return this.uiSpinner;
17614
+ }
17615
+ } );
17616
+
17617
+ // DEPRECATED
17618
+ // TODO: switch return back to widget declaration at top of file when this is removed
17619
+ if ( $.uiBackCompat !== false ) {
17620
+
17621
+ // Backcompat for spinner html extension points
17622
+ $.widget( "ui.spinner", $.ui.spinner, {
17623
+ _enhance: function() {
17624
+ this.uiSpinner = this.element
17625
+ .attr( "autocomplete", "off" )
17626
+ .wrap( this._uiSpinnerHtml() )
17627
+ .parent()
17628
+
17629
+ // Add buttons
17630
+ .append( this._buttonHtml() );
17631
+ },
17632
+ _uiSpinnerHtml: function() {
17633
+ return "<span>";
17634
+ },
17635
+
17636
+ _buttonHtml: function() {
17637
+ return "<a></a><a></a>";
17638
+ }
17639
+ } );
17640
+ }
17641
+
17642
+ var widgetsSpinner = $.ui.spinner;
17643
+
17644
+
17645
+ /*!
17646
+ * jQuery UI Tabs 1.13.1
17647
+ * http://jqueryui.com
17648
+ *
17649
+ * Copyright jQuery Foundation and other contributors
17650
+ * Released under the MIT license.
17651
+ * http://jquery.org/license
17652
+ */
17653
+
17654
+ //>>label: Tabs
17655
+ //>>group: Widgets
17656
+ //>>description: Transforms a set of container elements into a tab structure.
17657
+ //>>docs: http://api.jqueryui.com/tabs/
17658
+ //>>demos: http://jqueryui.com/tabs/
17659
+ //>>css.structure: ../../themes/base/core.css
17660
+ //>>css.structure: ../../themes/base/tabs.css
17661
+ //>>css.theme: ../../themes/base/theme.css
17662
+
17663
+
17664
+ $.widget( "ui.tabs", {
17665
+ version: "1.13.1",
17666
+ delay: 300,
17667
+ options: {
17668
+ active: null,
17669
+ classes: {
17670
+ "ui-tabs": "ui-corner-all",
17671
+ "ui-tabs-nav": "ui-corner-all",
17672
+ "ui-tabs-panel": "ui-corner-bottom",
17673
+ "ui-tabs-tab": "ui-corner-top"
17674
+ },
17675
+ collapsible: false,
17676
+ event: "click",
17677
+ heightStyle: "content",
17678
+ hide: null,
17679
+ show: null,
17680
+
17681
+ // Callbacks
17682
+ activate: null,
17683
+ beforeActivate: null,
17684
+ beforeLoad: null,
17685
+ load: null
17686
+ },
17687
+
17688
+ _isLocal: ( function() {
17689
+ var rhash = /#.*$/;
17690
+
17691
+ return function( anchor ) {
17692
+ var anchorUrl, locationUrl;
17693
+
17694
+ anchorUrl = anchor.href.replace( rhash, "" );
17695
+ locationUrl = location.href.replace( rhash, "" );
17696
+
17697
+ // Decoding may throw an error if the URL isn't UTF-8 (#9518)
17698
+ try {
17699
+ anchorUrl = decodeURIComponent( anchorUrl );
17700
+ } catch ( error ) {}
17701
+ try {
17702
+ locationUrl = decodeURIComponent( locationUrl );
17703
+ } catch ( error ) {}
17704
+
17705
+ return anchor.hash.length > 1 && anchorUrl === locationUrl;
17706
+ };
17707
+ } )(),
17708
+
17709
+ _create: function() {
17710
+ var that = this,
17711
+ options = this.options;
17712
+
17713
+ this.running = false;
17714
+
17715
+ this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17716
+ this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17717
+
17718
+ this._processTabs();
17719
+ options.active = this._initialActive();
17720
+
17721
+ // Take disabling tabs via class attribute from HTML
17722
+ // into account and update option properly.
17723
+ if ( Array.isArray( options.disabled ) ) {
17724
+ options.disabled = $.uniqueSort( options.disabled.concat(
17725
+ $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17726
+ return that.tabs.index( li );
17727
+ } )
17728
+ ) ).sort();
17729
+ }
17730
+
17731
+ // Check for length avoids error when initializing empty list
17732
+ if ( this.options.active !== false && this.anchors.length ) {
17733
+ this.active = this._findActive( options.active );
17734
+ } else {
17735
+ this.active = $();
17736
+ }
17737
+
17738
+ this._refresh();
17739
+
17740
+ if ( this.active.length ) {
17741
+ this.load( options.active );
17742
+ }
17743
+ },
17744
+
17745
+ _initialActive: function() {
17746
+ var active = this.options.active,
17747
+ collapsible = this.options.collapsible,
17748
+ locationHash = location.hash.substring( 1 );
17749
+
17750
+ if ( active === null ) {
17751
+
17752
+ // check the fragment identifier in the URL
17753
+ if ( locationHash ) {
17754
+ this.tabs.each( function( i, tab ) {
17755
+ if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
17756
+ active = i;
17757
+ return false;
17758
+ }
17759
+ } );
17760
+ }
17761
+
17762
+ // Check for a tab marked active via a class
17763
+ if ( active === null ) {
17764
+ active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17765
+ }
17766
+
17767
+ // No active tab, set to false
17768
+ if ( active === null || active === -1 ) {
17769
+ active = this.tabs.length ? 0 : false;
17770
+ }
17771
+ }
17772
+
17773
+ // Handle numbers: negative, out of range
17774
+ if ( active !== false ) {
17775
+ active = this.tabs.index( this.tabs.eq( active ) );
17776
+ if ( active === -1 ) {
17777
+ active = collapsible ? false : 0;
17778
+ }
17779
+ }
17780
+
17781
+ // Don't allow collapsible: false and active: false
17782
+ if ( !collapsible && active === false && this.anchors.length ) {
17783
+ active = 0;
17784
+ }
17785
+
17786
+ return active;
17787
+ },
17788
+
17789
+ _getCreateEventData: function() {
17790
+ return {
17791
+ tab: this.active,
17792
+ panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17793
+ };
17794
+ },
17795
+
17796
+ _tabKeydown: function( event ) {
17797
+ var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
17798
+ selectedIndex = this.tabs.index( focusedTab ),
17799
+ goingForward = true;
17800
+
17801
+ if ( this._handlePageNav( event ) ) {
17802
+ return;
17803
+ }
17804
+
17805
+ switch ( event.keyCode ) {
17806
+ case $.ui.keyCode.RIGHT:
17807
+ case $.ui.keyCode.DOWN:
17808
+ selectedIndex++;
17809
+ break;
17810
+ case $.ui.keyCode.UP:
17811
+ case $.ui.keyCode.LEFT:
17812
+ goingForward = false;
17813
+ selectedIndex--;
17814
+ break;
17815
+ case $.ui.keyCode.END:
17816
+ selectedIndex = this.anchors.length - 1;
17817
+ break;
17818
+ case $.ui.keyCode.HOME:
17819
+ selectedIndex = 0;
17820
+ break;
17821
+ case $.ui.keyCode.SPACE:
17822
+
17823
+ // Activate only, no collapsing
17824
+ event.preventDefault();
17825
+ clearTimeout( this.activating );
17826
+ this._activate( selectedIndex );
17827
+ return;
17828
+ case $.ui.keyCode.ENTER:
17829
+
17830
+ // Toggle (cancel delayed activation, allow collapsing)
17831
+ event.preventDefault();
17832
+ clearTimeout( this.activating );
17833
+
17834
+ // Determine if we should collapse or activate
17835
+ this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17836
+ return;
17837
+ default:
17838
+ return;
17839
+ }
17840
+
17841
+ // Focus the appropriate tab, based on which key was pressed
17842
+ event.preventDefault();
17843
+ clearTimeout( this.activating );
17844
+ selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17845
+
17846
+ // Navigating with control/command key will prevent automatic activation
17847
+ if ( !event.ctrlKey && !event.metaKey ) {
17848
+
17849
+ // Update aria-selected immediately so that AT think the tab is already selected.
17850
+ // Otherwise AT may confuse the user by stating that they need to activate the tab,
17851
+ // but the tab will already be activated by the time the announcement finishes.
17852
+ focusedTab.attr( "aria-selected", "false" );
17853
+ this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17854
+
17855
+ this.activating = this._delay( function() {
17856
+ this.option( "active", selectedIndex );
17857
+ }, this.delay );
17858
+ }
17859
+ },
17860
+
17861
+ _panelKeydown: function( event ) {
17862
+ if ( this._handlePageNav( event ) ) {
17863
+ return;
17864
+ }
17865
+
17866
+ // Ctrl+up moves focus to the current tab
17867
+ if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17868
+ event.preventDefault();
17869
+ this.active.trigger( "focus" );
17870
+ }
17871
+ },
17872
+
17873
+ // Alt+page up/down moves focus to the previous/next tab (and activates)
17874
+ _handlePageNav: function( event ) {
17875
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17876
+ this._activate( this._focusNextTab( this.options.active - 1, false ) );
17877
+ return true;
17878
+ }
17879
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17880
+ this._activate( this._focusNextTab( this.options.active + 1, true ) );
17881
+ return true;
17882
+ }
17883
+ },
17884
+
17885
+ _findNextTab: function( index, goingForward ) {
17886
+ var lastTabIndex = this.tabs.length - 1;
17887
+
17888
+ function constrain() {
17889
+ if ( index > lastTabIndex ) {
17890
+ index = 0;
17891
+ }
17892
+ if ( index < 0 ) {
17893
+ index = lastTabIndex;
17894
+ }
17895
+ return index;
17896
+ }
17897
+
17898
+ while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17899
+ index = goingForward ? index + 1 : index - 1;
17900
+ }
17901
+
17902
+ return index;
17903
+ },
17904
+
17905
+ _focusNextTab: function( index, goingForward ) {
17906
+ index = this._findNextTab( index, goingForward );
17907
+ this.tabs.eq( index ).trigger( "focus" );
17908
+ return index;
17909
+ },
17910
+
17911
+ _setOption: function( key, value ) {
17912
+ if ( key === "active" ) {
17913
+
17914
+ // _activate() will handle invalid values and update this.options
17915
+ this._activate( value );
17916
+ return;
17917
+ }
17918
+
17919
+ this._super( key, value );
17920
+
17921
+ if ( key === "collapsible" ) {
17922
+ this._toggleClass( "ui-tabs-collapsible", null, value );
17923
+
17924
+ // Setting collapsible: false while collapsed; open first panel
17925
+ if ( !value && this.options.active === false ) {
17926
+ this._activate( 0 );
17927
+ }
17928
+ }
17929
+
17930
+ if ( key === "event" ) {
17931
+ this._setupEvents( value );
17932
+ }
17933
+
17934
+ if ( key === "heightStyle" ) {
17935
+ this._setupHeightStyle( value );
17936
+ }
17937
+ },
17938
+
17939
+ _sanitizeSelector: function( hash ) {
17940
+ return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
17941
+ },
17942
+
17943
+ refresh: function() {
17944
+ var options = this.options,
17945
+ lis = this.tablist.children( ":has(a[href])" );
17946
+
17947
+ // Get disabled tabs from class attribute from HTML
17948
+ // this will get converted to a boolean if needed in _refresh()
17949
+ options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17950
+ return lis.index( tab );
17951
+ } );
17952
+
17953
+ this._processTabs();
17954
+
17955
+ // Was collapsed or no tabs
17956
+ if ( options.active === false || !this.anchors.length ) {
17957
+ options.active = false;
17958
+ this.active = $();
17959
+
17960
+ // was active, but active tab is gone
17961
+ } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17962
+
17963
+ // all remaining tabs are disabled
17964
+ if ( this.tabs.length === options.disabled.length ) {
17965
+ options.active = false;
17966
+ this.active = $();
17967
+
17968
+ // activate previous tab
17969
+ } else {
17970
+ this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17971
+ }
17972
+
17973
+ // was active, active tab still exists
17974
+ } else {
17975
+
17976
+ // make sure active index is correct
17977
+ options.active = this.tabs.index( this.active );
17978
+ }
17979
+
17980
+ this._refresh();
17981
+ },
17982
+
17983
+ _refresh: function() {
17984
+ this._setOptionDisabled( this.options.disabled );
17985
+ this._setupEvents( this.options.event );
17986
+ this._setupHeightStyle( this.options.heightStyle );
17987
+
17988
+ this.tabs.not( this.active ).attr( {
17989
+ "aria-selected": "false",
17990
+ "aria-expanded": "false",
17991
+ tabIndex: -1
17992
+ } );
17993
+ this.panels.not( this._getPanelForTab( this.active ) )
17994
+ .hide()
17995
+ .attr( {
17996
+ "aria-hidden": "true"
17997
+ } );
17998
+
17999
+ // Make sure one tab is in the tab order
18000
+ if ( !this.active.length ) {
18001
+ this.tabs.eq( 0 ).attr( "tabIndex", 0 );
18002
+ } else {
18003
+ this.active
18004
+ .attr( {
18005
+ "aria-selected": "true",
18006
+ "aria-expanded": "true",
18007
+ tabIndex: 0
18008
+ } );
18009
+ this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
18010
+ this._getPanelForTab( this.active )
18011
+ .show()
18012
+ .attr( {
18013
+ "aria-hidden": "false"
18014
+ } );
18015
+ }
18016
+ },
18017
+
18018
+ _processTabs: function() {
18019
+ var that = this,
18020
+ prevTabs = this.tabs,
18021
+ prevAnchors = this.anchors,
18022
+ prevPanels = this.panels;
18023
+
18024
+ this.tablist = this._getList().attr( "role", "tablist" );
18025
+ this._addClass( this.tablist, "ui-tabs-nav",
18026
+ "ui-helper-reset ui-helper-clearfix ui-widget-header" );
18027
+
18028
+ // Prevent users from focusing disabled tabs via click
18029
+ this.tablist
18030
+ .on( "mousedown" + this.eventNamespace, "> li", function( event ) {
18031
+ if ( $( this ).is( ".ui-state-disabled" ) ) {
18032
+ event.preventDefault();
18033
+ }
18034
+ } )
18035
+
18036
+ // Support: IE <9
18037
+ // Preventing the default action in mousedown doesn't prevent IE
18038
+ // from focusing the element, so if the anchor gets focused, blur.
18039
+ // We don't have to worry about focusing the previously focused
18040
+ // element since clicking on a non-focusable element should focus
18041
+ // the body anyway.
18042
+ .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
18043
+ if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
18044
+ this.blur();
18045
+ }
18046
+ } );
18047
+
18048
+ this.tabs = this.tablist.find( "> li:has(a[href])" )
18049
+ .attr( {
18050
+ role: "tab",
18051
+ tabIndex: -1
18052
+ } );
18053
+ this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
18054
+
18055
+ this.anchors = this.tabs.map( function() {
18056
+ return $( "a", this )[ 0 ];
18057
+ } )
18058
+ .attr( {
18059
+ tabIndex: -1
18060
+ } );
18061
+ this._addClass( this.anchors, "ui-tabs-anchor" );
18062
+
18063
+ this.panels = $();
18064
+
18065
+ this.anchors.each( function( i, anchor ) {
18066
+ var selector, panel, panelId,
18067
+ anchorId = $( anchor ).uniqueId().attr( "id" ),
18068
+ tab = $( anchor ).closest( "li" ),
18069
+ originalAriaControls = tab.attr( "aria-controls" );
18070
+
18071
+ // Inline tab
18072
+ if ( that._isLocal( anchor ) ) {
18073
+ selector = anchor.hash;
18074
+ panelId = selector.substring( 1 );
18075
+ panel = that.element.find( that._sanitizeSelector( selector ) );
18076
+
18077
+ // remote tab
18078
+ } else {
18079
+
18080
+ // If the tab doesn't already have aria-controls,
18081
+ // generate an id by using a throw-away element
18082
+ panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
18083
+ selector = "#" + panelId;
18084
+ panel = that.element.find( selector );
18085
+ if ( !panel.length ) {
18086
+ panel = that._createPanel( panelId );
18087
+ panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
18088
+ }
18089
+ panel.attr( "aria-live", "polite" );
18090
+ }
18091
+
18092
+ if ( panel.length ) {
18093
+ that.panels = that.panels.add( panel );
18094
+ }
18095
+ if ( originalAriaControls ) {
18096
+ tab.data( "ui-tabs-aria-controls", originalAriaControls );
18097
+ }
18098
+ tab.attr( {
18099
+ "aria-controls": panelId,
18100
+ "aria-labelledby": anchorId
18101
+ } );
18102
+ panel.attr( "aria-labelledby", anchorId );
18103
+ } );
18104
+
18105
+ this.panels.attr( "role", "tabpanel" );
18106
+ this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
18107
+
18108
+ // Avoid memory leaks (#10056)
18109
+ if ( prevTabs ) {
18110
+ this._off( prevTabs.not( this.tabs ) );
18111
+ this._off( prevAnchors.not( this.anchors ) );
18112
+ this._off( prevPanels.not( this.panels ) );
18113
+ }
18114
+ },
18115
+
18116
+ // Allow overriding how to find the list for rare usage scenarios (#7715)
18117
+ _getList: function() {
18118
+ return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
18119
+ },
18120
+
18121
+ _createPanel: function( id ) {
18122
+ return $( "<div>" )
18123
+ .attr( "id", id )
18124
+ .data( "ui-tabs-destroy", true );
18125
+ },
18126
+
18127
+ _setOptionDisabled: function( disabled ) {
18128
+ var currentItem, li, i;
18129
+
18130
+ if ( Array.isArray( disabled ) ) {
18131
+ if ( !disabled.length ) {
18132
+ disabled = false;
18133
+ } else if ( disabled.length === this.anchors.length ) {
18134
+ disabled = true;
18135
+ }
18136
+ }
18137
+
18138
+ // Disable tabs
18139
+ for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
18140
+ currentItem = $( li );
18141
+ if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
18142
+ currentItem.attr( "aria-disabled", "true" );
18143
+ this._addClass( currentItem, null, "ui-state-disabled" );
18144
+ } else {
18145
+ currentItem.removeAttr( "aria-disabled" );
18146
+ this._removeClass( currentItem, null, "ui-state-disabled" );
18147
+ }
18148
+ }
18149
+
18150
+ this.options.disabled = disabled;
18151
+
18152
+ this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
18153
+ disabled === true );
18154
+ },
18155
+
18156
+ _setupEvents: function( event ) {
18157
+ var events = {};
18158
+ if ( event ) {
18159
+ $.each( event.split( " " ), function( index, eventName ) {
18160
+ events[ eventName ] = "_eventHandler";
18161
+ } );
18162
+ }
18163
+
18164
+ this._off( this.anchors.add( this.tabs ).add( this.panels ) );
18165
+
18166
+ // Always prevent the default action, even when disabled
18167
+ this._on( true, this.anchors, {
18168
+ click: function( event ) {
18169
+ event.preventDefault();
18170
+ }
18171
+ } );
18172
+ this._on( this.anchors, events );
18173
+ this._on( this.tabs, { keydown: "_tabKeydown" } );
18174
+ this._on( this.panels, { keydown: "_panelKeydown" } );
18175
+
18176
+ this._focusable( this.tabs );
18177
+ this._hoverable( this.tabs );
18178
+ },
18179
+
18180
+ _setupHeightStyle: function( heightStyle ) {
18181
+ var maxHeight,
18182
+ parent = this.element.parent();
18183
+
18184
+ if ( heightStyle === "fill" ) {
18185
+ maxHeight = parent.height();
18186
+ maxHeight -= this.element.outerHeight() - this.element.height();
18187
+
18188
+ this.element.siblings( ":visible" ).each( function() {
18189
+ var elem = $( this ),
18190
+ position = elem.css( "position" );
18191
+
18192
+ if ( position === "absolute" || position === "fixed" ) {
18193
+ return;
18194
+ }
18195
+ maxHeight -= elem.outerHeight( true );
18196
+ } );
18197
+
18198
+ this.element.children().not( this.panels ).each( function() {
18199
+ maxHeight -= $( this ).outerHeight( true );
18200
+ } );
18201
+
18202
+ this.panels.each( function() {
18203
+ $( this ).height( Math.max( 0, maxHeight -
18204
+ $( this ).innerHeight() + $( this ).height() ) );
18205
+ } )
18206
+ .css( "overflow", "auto" );
18207
+ } else if ( heightStyle === "auto" ) {
18208
+ maxHeight = 0;
18209
+ this.panels.each( function() {
18210
+ maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
18211
+ } ).height( maxHeight );
18212
+ }
18213
+ },
18214
+
18215
+ _eventHandler: function( event ) {
18216
+ var options = this.options,
18217
+ active = this.active,
18218
+ anchor = $( event.currentTarget ),
18219
+ tab = anchor.closest( "li" ),
18220
+ clickedIsActive = tab[ 0 ] === active[ 0 ],
18221
+ collapsing = clickedIsActive && options.collapsible,
18222
+ toShow = collapsing ? $() : this._getPanelForTab( tab ),
18223
+ toHide = !active.length ? $() : this._getPanelForTab( active ),
18224
+ eventData = {
18225
+ oldTab: active,
18226
+ oldPanel: toHide,
18227
+ newTab: collapsing ? $() : tab,
18228
+ newPanel: toShow
18229
+ };
18230
+
18231
+ event.preventDefault();
18232
+
18233
+ if ( tab.hasClass( "ui-state-disabled" ) ||
18234
+
18235
+ // tab is already loading
18236
+ tab.hasClass( "ui-tabs-loading" ) ||
18237
+
18238
+ // can't switch durning an animation
18239
+ this.running ||
18240
+
18241
+ // click on active header, but not collapsible
18242
+ ( clickedIsActive && !options.collapsible ) ||
18243
+
18244
+ // allow canceling activation
18245
+ ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18246
+ return;
18247
+ }
18248
+
18249
+ options.active = collapsing ? false : this.tabs.index( tab );
18250
+
18251
+ this.active = clickedIsActive ? $() : tab;
18252
+ if ( this.xhr ) {
18253
+ this.xhr.abort();
18254
+ }
18255
+
18256
+ if ( !toHide.length && !toShow.length ) {
18257
+ $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18258
+ }
18259
+
18260
+ if ( toShow.length ) {
18261
+ this.load( this.tabs.index( tab ), event );
18262
+ }
18263
+ this._toggle( event, eventData );
18264
+ },
18265
+
18266
+ // Handles show/hide for selecting tabs
18267
+ _toggle: function( event, eventData ) {
18268
+ var that = this,
18269
+ toShow = eventData.newPanel,
18270
+ toHide = eventData.oldPanel;
18271
+
18272
+ this.running = true;
18273
+
18274
+ function complete() {
18275
+ that.running = false;
18276
+ that._trigger( "activate", event, eventData );
18277
+ }
18278
+
18279
+ function show() {
18280
+ that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18281
+
18282
+ if ( toShow.length && that.options.show ) {
18283
+ that._show( toShow, that.options.show, complete );
18284
+ } else {
18285
+ toShow.show();
18286
+ complete();
18287
+ }
18288
+ }
18289
+
18290
+ // Start out by hiding, then showing, then completing
18291
+ if ( toHide.length && this.options.hide ) {
18292
+ this._hide( toHide, this.options.hide, function() {
18293
+ that._removeClass( eventData.oldTab.closest( "li" ),
18294
+ "ui-tabs-active", "ui-state-active" );
18295
+ show();
18296
+ } );
18297
+ } else {
18298
+ this._removeClass( eventData.oldTab.closest( "li" ),
18299
+ "ui-tabs-active", "ui-state-active" );
18300
+ toHide.hide();
18301
+ show();
18302
+ }
18303
+
18304
+ toHide.attr( "aria-hidden", "true" );
18305
+ eventData.oldTab.attr( {
18306
+ "aria-selected": "false",
18307
+ "aria-expanded": "false"
18308
+ } );
18309
+
18310
+ // If we're switching tabs, remove the old tab from the tab order.
18311
+ // If we're opening from collapsed state, remove the previous tab from the tab order.
18312
+ // If we're collapsing, then keep the collapsing tab in the tab order.
18313
+ if ( toShow.length && toHide.length ) {
18314
+ eventData.oldTab.attr( "tabIndex", -1 );
18315
+ } else if ( toShow.length ) {
18316
+ this.tabs.filter( function() {
18317
+ return $( this ).attr( "tabIndex" ) === 0;
18318
+ } )
18319
+ .attr( "tabIndex", -1 );
18320
+ }
18321
+
18322
+ toShow.attr( "aria-hidden", "false" );
18323
+ eventData.newTab.attr( {
18324
+ "aria-selected": "true",
18325
+ "aria-expanded": "true",
18326
+ tabIndex: 0
18327
+ } );
18328
+ },
18329
+
18330
+ _activate: function( index ) {
18331
+ var anchor,
18332
+ active = this._findActive( index );
18333
+
18334
+ // Trying to activate the already active panel
18335
+ if ( active[ 0 ] === this.active[ 0 ] ) {
18336
+ return;
18337
+ }
18338
+
18339
+ // Trying to collapse, simulate a click on the current active header
18340
+ if ( !active.length ) {
18341
+ active = this.active;
18342
+ }
18343
+
18344
+ anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18345
+ this._eventHandler( {
18346
+ target: anchor,
18347
+ currentTarget: anchor,
18348
+ preventDefault: $.noop
18349
+ } );
18350
+ },
18351
+
18352
+ _findActive: function( index ) {
18353
+ return index === false ? $() : this.tabs.eq( index );
18354
+ },
18355
+
18356
+ _getIndex: function( index ) {
18357
+
18358
+ // meta-function to give users option to provide a href string instead of a numerical index.
18359
+ if ( typeof index === "string" ) {
18360
+ index = this.anchors.index( this.anchors.filter( "[href$='" +
18361
+ $.escapeSelector( index ) + "']" ) );
18362
+ }
18363
+
18364
+ return index;
18365
+ },
18366
+
18367
+ _destroy: function() {
18368
+ if ( this.xhr ) {
18369
+ this.xhr.abort();
18370
+ }
18371
+
18372
+ this.tablist
18373
+ .removeAttr( "role" )
18374
+ .off( this.eventNamespace );
18375
+
18376
+ this.anchors
18377
+ .removeAttr( "role tabIndex" )
18378
+ .removeUniqueId();
18379
+
18380
+ this.tabs.add( this.panels ).each( function() {
18381
+ if ( $.data( this, "ui-tabs-destroy" ) ) {
18382
+ $( this ).remove();
18383
+ } else {
18384
+ $( this ).removeAttr( "role tabIndex " +
18385
+ "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18386
+ }
18387
+ } );
18388
+
18389
+ this.tabs.each( function() {
18390
+ var li = $( this ),
18391
+ prev = li.data( "ui-tabs-aria-controls" );
18392
+ if ( prev ) {
18393
+ li
18394
+ .attr( "aria-controls", prev )
18395
+ .removeData( "ui-tabs-aria-controls" );
18396
+ } else {
18397
+ li.removeAttr( "aria-controls" );
18398
+ }
18399
+ } );
18400
+
18401
+ this.panels.show();
18402
+
18403
+ if ( this.options.heightStyle !== "content" ) {
18404
+ this.panels.css( "height", "" );
18405
+ }
18406
+ },
18407
+
18408
+ enable: function( index ) {
18409
+ var disabled = this.options.disabled;
18410
+ if ( disabled === false ) {
18411
+ return;
18412
+ }
18413
+
18414
+ if ( index === undefined ) {
18415
+ disabled = false;
18416
+ } else {
18417
+ index = this._getIndex( index );
18418
+ if ( Array.isArray( disabled ) ) {
18419
+ disabled = $.map( disabled, function( num ) {
18420
+ return num !== index ? num : null;
18421
+ } );
18422
+ } else {
18423
+ disabled = $.map( this.tabs, function( li, num ) {
18424
+ return num !== index ? num : null;
18425
+ } );
18426
+ }
18427
+ }
18428
+ this._setOptionDisabled( disabled );
18429
+ },
18430
+
18431
+ disable: function( index ) {
18432
+ var disabled = this.options.disabled;
18433
+ if ( disabled === true ) {
18434
+ return;
18435
+ }
18436
+
18437
+ if ( index === undefined ) {
18438
+ disabled = true;
18439
+ } else {
18440
+ index = this._getIndex( index );
18441
+ if ( $.inArray( index, disabled ) !== -1 ) {
18442
+ return;
18443
+ }
18444
+ if ( Array.isArray( disabled ) ) {
18445
+ disabled = $.merge( [ index ], disabled ).sort();
18446
+ } else {
18447
+ disabled = [ index ];
18448
+ }
18449
+ }
18450
+ this._setOptionDisabled( disabled );
18451
+ },
18452
+
18453
+ load: function( index, event ) {
18454
+ index = this._getIndex( index );
18455
+ var that = this,
18456
+ tab = this.tabs.eq( index ),
18457
+ anchor = tab.find( ".ui-tabs-anchor" ),
18458
+ panel = this._getPanelForTab( tab ),
18459
+ eventData = {
18460
+ tab: tab,
18461
+ panel: panel
18462
+ },
18463
+ complete = function( jqXHR, status ) {
18464
+ if ( status === "abort" ) {
18465
+ that.panels.stop( false, true );
18466
+ }
18467
+
18468
+ that._removeClass( tab, "ui-tabs-loading" );
18469
+ panel.removeAttr( "aria-busy" );
18470
+
18471
+ if ( jqXHR === that.xhr ) {
18472
+ delete that.xhr;
18473
+ }
18474
+ };
18475
+
18476
+ // Not remote
18477
+ if ( this._isLocal( anchor[ 0 ] ) ) {
18478
+ return;
18479
+ }
18480
+
18481
+ this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18482
+
18483
+ // Support: jQuery <1.8
18484
+ // jQuery <1.8 returns false if the request is canceled in beforeSend,
18485
+ // but as of 1.8, $.ajax() always returns a jqXHR object.
18486
+ if ( this.xhr && this.xhr.statusText !== "canceled" ) {
18487
+ this._addClass( tab, "ui-tabs-loading" );
18488
+ panel.attr( "aria-busy", "true" );
18489
+
18490
+ this.xhr
18491
+ .done( function( response, status, jqXHR ) {
18492
+
18493
+ // support: jQuery <1.8
18494
+ // http://bugs.jquery.com/ticket/11778
18495
+ setTimeout( function() {
18496
+ panel.html( response );
18497
+ that._trigger( "load", event, eventData );
18498
+
18499
+ complete( jqXHR, status );
18500
+ }, 1 );
18501
+ } )
18502
+ .fail( function( jqXHR, status ) {
18503
+
18504
+ // support: jQuery <1.8
18505
+ // http://bugs.jquery.com/ticket/11778
18506
+ setTimeout( function() {
18507
+ complete( jqXHR, status );
18508
+ }, 1 );
18509
+ } );
18510
+ }
18511
+ },
18512
+
18513
+ _ajaxSettings: function( anchor, event, eventData ) {
18514
+ var that = this;
18515
+ return {
18516
+
18517
+ // Support: IE <11 only
18518
+ // Strip any hash that exists to prevent errors with the Ajax request
18519
+ url: anchor.attr( "href" ).replace( /#.*$/, "" ),
18520
+ beforeSend: function( jqXHR, settings ) {
18521
+ return that._trigger( "beforeLoad", event,
18522
+ $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18523
+ }
18524
+ };
18525
+ },
18526
+
18527
+ _getPanelForTab: function( tab ) {
18528
+ var id = $( tab ).attr( "aria-controls" );
18529
+ return this.element.find( this._sanitizeSelector( "#" + id ) );
18530
+ }
18531
+ } );
18532
+
18533
+ // DEPRECATED
18534
+ // TODO: Switch return back to widget declaration at top of file when this is removed
18535
+ if ( $.uiBackCompat !== false ) {
18536
+
18537
+ // Backcompat for ui-tab class (now ui-tabs-tab)
18538
+ $.widget( "ui.tabs", $.ui.tabs, {
18539
+ _processTabs: function() {
18540
+ this._superApply( arguments );
18541
+ this._addClass( this.tabs, "ui-tab" );
18542
+ }
18543
+ } );
18544
+ }
18545
+
18546
+ var widgetsTabs = $.ui.tabs;
18547
+
18548
+
18549
+ /*!
18550
+ * jQuery UI Tooltip 1.13.1
18551
+ * http://jqueryui.com
18552
+ *
18553
+ * Copyright jQuery Foundation and other contributors
18554
+ * Released under the MIT license.
18555
+ * http://jquery.org/license
18556
+ */
18557
+
18558
+ //>>label: Tooltip
18559
+ //>>group: Widgets
18560
+ //>>description: Shows additional information for any element on hover or focus.
18561
+ //>>docs: http://api.jqueryui.com/tooltip/
18562
+ //>>demos: http://jqueryui.com/tooltip/
18563
+ //>>css.structure: ../../themes/base/core.css
18564
+ //>>css.structure: ../../themes/base/tooltip.css
18565
+ //>>css.theme: ../../themes/base/theme.css
18566
+
18567
+
18568
+ $.widget( "ui.tooltip", {
18569
+ version: "1.13.1",
18570
+ options: {
18571
+ classes: {
18572
+ "ui-tooltip": "ui-corner-all ui-widget-shadow"
18573
+ },
18574
+ content: function() {
18575
+ var title = $( this ).attr( "title" );
18576
+
18577
+ // Escape title, since we're going from an attribute to raw HTML
18578
+ return $( "<a>" ).text( title ).html();
18579
+ },
18580
+ hide: true,
18581
+
18582
+ // Disabled elements have inconsistent behavior across browsers (#8661)
18583
+ items: "[title]:not([disabled])",
18584
+ position: {
18585
+ my: "left top+15",
18586
+ at: "left bottom",
18587
+ collision: "flipfit flip"
18588
+ },
18589
+ show: true,
18590
+ track: false,
18591
+
18592
+ // Callbacks
18593
+ close: null,
18594
+ open: null
18595
+ },
18596
+
18597
+ _addDescribedBy: function( elem, id ) {
18598
+ var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18599
+ describedby.push( id );
18600
+ elem
18601
+ .data( "ui-tooltip-id", id )
18602
+ .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18603
+ },
18604
+
18605
+ _removeDescribedBy: function( elem ) {
18606
+ var id = elem.data( "ui-tooltip-id" ),
18607
+ describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18608
+ index = $.inArray( id, describedby );
18609
+
18610
+ if ( index !== -1 ) {
18611
+ describedby.splice( index, 1 );
18612
+ }
18613
+
18614
+ elem.removeData( "ui-tooltip-id" );
18615
+ describedby = String.prototype.trim.call( describedby.join( " " ) );
18616
+ if ( describedby ) {
18617
+ elem.attr( "aria-describedby", describedby );
18618
+ } else {
18619
+ elem.removeAttr( "aria-describedby" );
18620
+ }
18621
+ },
18622
+
18623
+ _create: function() {
18624
+ this._on( {
18625
+ mouseover: "open",
18626
+ focusin: "open"
18627
+ } );
18628
+
18629
+ // IDs of generated tooltips, needed for destroy
18630
+ this.tooltips = {};
18631
+
18632
+ // IDs of parent tooltips where we removed the title attribute
18633
+ this.parents = {};
18634
+
18635
+ // Append the aria-live region so tooltips announce correctly
18636
+ this.liveRegion = $( "<div>" )
18637
+ .attr( {
18638
+ role: "log",
18639
+ "aria-live": "assertive",
18640
+ "aria-relevant": "additions"
18641
+ } )
18642
+ .appendTo( this.document[ 0 ].body );
18643
+ this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18644
+
18645
+ this.disabledTitles = $( [] );
18646
+ },
18647
+
18648
+ _setOption: function( key, value ) {
18649
+ var that = this;
18650
+
18651
+ this._super( key, value );
18652
+
18653
+ if ( key === "content" ) {
18654
+ $.each( this.tooltips, function( id, tooltipData ) {
18655
+ that._updateContent( tooltipData.element );
18656
+ } );
18657
+ }
18658
+ },
18659
+
18660
+ _setOptionDisabled: function( value ) {
18661
+ this[ value ? "_disable" : "_enable" ]();
18662
+ },
18663
+
18664
+ _disable: function() {
18665
+ var that = this;
18666
+
18667
+ // Close open tooltips
18668
+ $.each( this.tooltips, function( id, tooltipData ) {
18669
+ var event = $.Event( "blur" );
18670
+ event.target = event.currentTarget = tooltipData.element[ 0 ];
18671
+ that.close( event, true );
18672
+ } );
18673
+
18674
+ // Remove title attributes to prevent native tooltips
18675
+ this.disabledTitles = this.disabledTitles.add(
18676
+ this.element.find( this.options.items ).addBack()
18677
+ .filter( function() {
18678
+ var element = $( this );
18679
+ if ( element.is( "[title]" ) ) {
18680
+ return element
18681
+ .data( "ui-tooltip-title", element.attr( "title" ) )
18682
+ .removeAttr( "title" );
18683
+ }
18684
+ } )
18685
+ );
18686
+ },
18687
+
18688
+ _enable: function() {
18689
+
18690
+ // restore title attributes
18691
+ this.disabledTitles.each( function() {
18692
+ var element = $( this );
18693
+ if ( element.data( "ui-tooltip-title" ) ) {
18694
+ element.attr( "title", element.data( "ui-tooltip-title" ) );
18695
+ }
18696
+ } );
18697
+ this.disabledTitles = $( [] );
18698
+ },
18699
+
18700
+ open: function( event ) {
18701
+ var that = this,
18702
+ target = $( event ? event.target : this.element )
18703
+
18704
+ // we need closest here due to mouseover bubbling,
18705
+ // but always pointing at the same event target
18706
+ .closest( this.options.items );
18707
+
18708
+ // No element to show a tooltip for or the tooltip is already open
18709
+ if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18710
+ return;
18711
+ }
18712
+
18713
+ if ( target.attr( "title" ) ) {
18714
+ target.data( "ui-tooltip-title", target.attr( "title" ) );
18715
+ }
18716
+
18717
+ target.data( "ui-tooltip-open", true );
18718
+
18719
+ // Kill parent tooltips, custom or native, for hover
18720
+ if ( event && event.type === "mouseover" ) {
18721
+ target.parents().each( function() {
18722
+ var parent = $( this ),
18723
+ blurEvent;
18724
+ if ( parent.data( "ui-tooltip-open" ) ) {
18725
+ blurEvent = $.Event( "blur" );
18726
+ blurEvent.target = blurEvent.currentTarget = this;
18727
+ that.close( blurEvent, true );
18728
+ }
18729
+ if ( parent.attr( "title" ) ) {
18730
+ parent.uniqueId();
18731
+ that.parents[ this.id ] = {
18732
+ element: this,
18733
+ title: parent.attr( "title" )
18734
+ };
18735
+ parent.attr( "title", "" );
18736
+ }
18737
+ } );
18738
+ }
18739
+
18740
+ this._registerCloseHandlers( event, target );
18741
+ this._updateContent( target, event );
18742
+ },
18743
+
18744
+ _updateContent: function( target, event ) {
18745
+ var content,
18746
+ contentOption = this.options.content,
18747
+ that = this,
18748
+ eventType = event ? event.type : null;
18749
+
18750
+ if ( typeof contentOption === "string" || contentOption.nodeType ||
18751
+ contentOption.jquery ) {
18752
+ return this._open( event, target, contentOption );
18753
+ }
18754
+
18755
+ content = contentOption.call( target[ 0 ], function( response ) {
18756
+
18757
+ // IE may instantly serve a cached response for ajax requests
18758
+ // delay this call to _open so the other call to _open runs first
18759
+ that._delay( function() {
18760
+
18761
+ // Ignore async response if tooltip was closed already
18762
+ if ( !target.data( "ui-tooltip-open" ) ) {
18763
+ return;
18764
+ }
18765
+
18766
+ // JQuery creates a special event for focusin when it doesn't
18767
+ // exist natively. To improve performance, the native event
18768
+ // object is reused and the type is changed. Therefore, we can't
18769
+ // rely on the type being correct after the event finished
18770
+ // bubbling, so we set it back to the previous value. (#8740)
18771
+ if ( event ) {
18772
+ event.type = eventType;
18773
+ }
18774
+ this._open( event, target, response );
18775
+ } );
18776
+ } );
18777
+ if ( content ) {
18778
+ this._open( event, target, content );
18779
+ }
18780
+ },
18781
+
18782
+ _open: function( event, target, content ) {
18783
+ var tooltipData, tooltip, delayedShow, a11yContent,
18784
+ positionOption = $.extend( {}, this.options.position );
18785
+
18786
+ if ( !content ) {
18787
+ return;
18788
+ }
18789
+
18790
+ // Content can be updated multiple times. If the tooltip already
18791
+ // exists, then just update the content and bail.
18792
+ tooltipData = this._find( target );
18793
+ if ( tooltipData ) {
18794
+ tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18795
+ return;
18796
+ }
18797
+
18798
+ // If we have a title, clear it to prevent the native tooltip
18799
+ // we have to check first to avoid defining a title if none exists
18800
+ // (we don't want to cause an element to start matching [title])
18801
+ //
18802
+ // We use removeAttr only for key events, to allow IE to export the correct
18803
+ // accessible attributes. For mouse events, set to empty string to avoid
18804
+ // native tooltip showing up (happens only when removing inside mouseover).
18805
+ if ( target.is( "[title]" ) ) {
18806
+ if ( event && event.type === "mouseover" ) {
18807
+ target.attr( "title", "" );
18808
+ } else {
18809
+ target.removeAttr( "title" );
18810
+ }
18811
+ }
18812
+
18813
+ tooltipData = this._tooltip( target );
18814
+ tooltip = tooltipData.tooltip;
18815
+ this._addDescribedBy( target, tooltip.attr( "id" ) );
18816
+ tooltip.find( ".ui-tooltip-content" ).html( content );
18817
+
18818
+ // Support: Voiceover on OS X, JAWS on IE <= 9
18819
+ // JAWS announces deletions even when aria-relevant="additions"
18820
+ // Voiceover will sometimes re-read the entire log region's contents from the beginning
18821
+ this.liveRegion.children().hide();
18822
+ a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18823
+ a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18824
+ a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18825
+ a11yContent.appendTo( this.liveRegion );
18826
+
18827
+ function position( event ) {
18828
+ positionOption.of = event;
18829
+ if ( tooltip.is( ":hidden" ) ) {
18830
+ return;
18831
+ }
18832
+ tooltip.position( positionOption );
18833
+ }
18834
+ if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18835
+ this._on( this.document, {
18836
+ mousemove: position
18837
+ } );
18838
+
18839
+ // trigger once to override element-relative positioning
18840
+ position( event );
18841
+ } else {
18842
+ tooltip.position( $.extend( {
18843
+ of: target
18844
+ }, this.options.position ) );
18845
+ }
18846
+
18847
+ tooltip.hide();
18848
+
18849
+ this._show( tooltip, this.options.show );
18850
+
18851
+ // Handle tracking tooltips that are shown with a delay (#8644). As soon
18852
+ // as the tooltip is visible, position the tooltip using the most recent
18853
+ // event.
18854
+ // Adds the check to add the timers only when both delay and track options are set (#14682)
18855
+ if ( this.options.track && this.options.show && this.options.show.delay ) {
18856
+ delayedShow = this.delayedShow = setInterval( function() {
18857
+ if ( tooltip.is( ":visible" ) ) {
18858
+ position( positionOption.of );
18859
+ clearInterval( delayedShow );
18860
+ }
18861
+ }, 13 );
18862
+ }
18863
+
18864
+ this._trigger( "open", event, { tooltip: tooltip } );
18865
+ },
18866
+
18867
+ _registerCloseHandlers: function( event, target ) {
18868
+ var events = {
18869
+ keyup: function( event ) {
18870
+ if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18871
+ var fakeEvent = $.Event( event );
18872
+ fakeEvent.currentTarget = target[ 0 ];
18873
+ this.close( fakeEvent, true );
18874
+ }
18875
+ }
18876
+ };
18877
+
18878
+ // Only bind remove handler for delegated targets. Non-delegated
18879
+ // tooltips will handle this in destroy.
18880
+ if ( target[ 0 ] !== this.element[ 0 ] ) {
18881
+ events.remove = function() {
18882
+ var targetElement = this._find( target );
18883
+ if ( targetElement ) {
18884
+ this._removeTooltip( targetElement.tooltip );
18885
+ }
18886
+ };
18887
+ }
18888
+
18889
+ if ( !event || event.type === "mouseover" ) {
18890
+ events.mouseleave = "close";
18891
+ }
18892
+ if ( !event || event.type === "focusin" ) {
18893
+ events.focusout = "close";
18894
+ }
18895
+ this._on( true, target, events );
18896
+ },
18897
+
18898
+ close: function( event ) {
18899
+ var tooltip,
18900
+ that = this,
18901
+ target = $( event ? event.currentTarget : this.element ),
18902
+ tooltipData = this._find( target );
18903
+
18904
+ // The tooltip may already be closed
18905
+ if ( !tooltipData ) {
18906
+
18907
+ // We set ui-tooltip-open immediately upon open (in open()), but only set the
18908
+ // additional data once there's actually content to show (in _open()). So even if the
18909
+ // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18910
+ // the period between open() and _open().
18911
+ target.removeData( "ui-tooltip-open" );
18912
+ return;
18913
+ }
18914
+
18915
+ tooltip = tooltipData.tooltip;
18916
+
18917
+ // Disabling closes the tooltip, so we need to track when we're closing
18918
+ // to avoid an infinite loop in case the tooltip becomes disabled on close
18919
+ if ( tooltipData.closing ) {
18920
+ return;
18921
+ }
18922
+
18923
+ // Clear the interval for delayed tracking tooltips
18924
+ clearInterval( this.delayedShow );
18925
+
18926
+ // Only set title if we had one before (see comment in _open())
18927
+ // If the title attribute has changed since open(), don't restore
18928
+ if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18929
+ target.attr( "title", target.data( "ui-tooltip-title" ) );
18930
+ }
18931
+
18932
+ this._removeDescribedBy( target );
18933
+
18934
+ tooltipData.hiding = true;
18935
+ tooltip.stop( true );
18936
+ this._hide( tooltip, this.options.hide, function() {
18937
+ that._removeTooltip( $( this ) );
18938
+ } );
18939
+
18940
+ target.removeData( "ui-tooltip-open" );
18941
+ this._off( target, "mouseleave focusout keyup" );
18942
+
18943
+ // Remove 'remove' binding only on delegated targets
18944
+ if ( target[ 0 ] !== this.element[ 0 ] ) {
18945
+ this._off( target, "remove" );
18946
+ }
18947
+ this._off( this.document, "mousemove" );
18948
+
18949
+ if ( event && event.type === "mouseleave" ) {
18950
+ $.each( this.parents, function( id, parent ) {
18951
+ $( parent.element ).attr( "title", parent.title );
18952
+ delete that.parents[ id ];
18953
+ } );
18954
+ }
18955
+
18956
+ tooltipData.closing = true;
18957
+ this._trigger( "close", event, { tooltip: tooltip } );
18958
+ if ( !tooltipData.hiding ) {
18959
+ tooltipData.closing = false;
18960
+ }
18961
+ },
18962
+
18963
+ _tooltip: function( element ) {
18964
+ var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18965
+ content = $( "<div>" ).appendTo( tooltip ),
18966
+ id = tooltip.uniqueId().attr( "id" );
18967
+
18968
+ this._addClass( content, "ui-tooltip-content" );
18969
+ this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18970
+
18971
+ tooltip.appendTo( this._appendTo( element ) );
18972
+
18973
+ return this.tooltips[ id ] = {
18974
+ element: element,
18975
+ tooltip: tooltip
18976
+ };
18977
+ },
18978
+
18979
+ _find: function( target ) {
18980
+ var id = target.data( "ui-tooltip-id" );
18981
+ return id ? this.tooltips[ id ] : null;
18982
+ },
18983
+
18984
+ _removeTooltip: function( tooltip ) {
18985
+
18986
+ // Clear the interval for delayed tracking tooltips
18987
+ clearInterval( this.delayedShow );
18988
+
18989
+ tooltip.remove();
18990
+ delete this.tooltips[ tooltip.attr( "id" ) ];
18991
+ },
18992
+
18993
+ _appendTo: function( target ) {
18994
+ var element = target.closest( ".ui-front, dialog" );
18995
+
18996
+ if ( !element.length ) {
18997
+ element = this.document[ 0 ].body;
18998
+ }
18999
+
19000
+ return element;
19001
+ },
19002
+
19003
+ _destroy: function() {
19004
+ var that = this;
19005
+
19006
+ // Close open tooltips
19007
+ $.each( this.tooltips, function( id, tooltipData ) {
19008
+
19009
+ // Delegate to close method to handle common cleanup
19010
+ var event = $.Event( "blur" ),
19011
+ element = tooltipData.element;
19012
+ event.target = event.currentTarget = element[ 0 ];
19013
+ that.close( event, true );
19014
+
19015
+ // Remove immediately; destroying an open tooltip doesn't use the
19016
+ // hide animation
19017
+ $( "#" + id ).remove();
19018
+
19019
+ // Restore the title
19020
+ if ( element.data( "ui-tooltip-title" ) ) {
19021
+
19022
+ // If the title attribute has changed since open(), don't restore
19023
+ if ( !element.attr( "title" ) ) {
19024
+ element.attr( "title", element.data( "ui-tooltip-title" ) );
19025
+ }
19026
+ element.removeData( "ui-tooltip-title" );
19027
+ }
19028
+ } );
19029
+ this.liveRegion.remove();
19030
+ }
19031
+ } );
19032
+
19033
+ // DEPRECATED
19034
+ // TODO: Switch return back to widget declaration at top of file when this is removed
19035
+ if ( $.uiBackCompat !== false ) {
19036
+
19037
+ // Backcompat for tooltipClass option
19038
+ $.widget( "ui.tooltip", $.ui.tooltip, {
19039
+ options: {
19040
+ tooltipClass: null
19041
+ },
19042
+ _tooltip: function() {
19043
+ var tooltipData = this._superApply( arguments );
19044
+ if ( this.options.tooltipClass ) {
19045
+ tooltipData.tooltip.addClass( this.options.tooltipClass );
19046
+ }
19047
+ return tooltipData;
19048
+ }
19049
+ } );
19050
+ }
19051
+
19052
+ var widgetsTooltip = $.ui.tooltip;
19053
+
19054
+
19055
+
19056
+
19057
+ } );
composer.json CHANGED
@@ -1,5 +1,5 @@
1
  {
2
- "name": "publishpress/publishpress-capabilities",
3
  "type": "wordpress-plugin",
4
  "description": "",
5
  "license": "GPL-2",
1
  {
2
+ "name": "publishpress/capability-manager-enhanced",
3
  "type": "wordpress-plugin",
4
  "description": "",
5
  "license": "GPL-2",
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
  "This file is @generated automatically"
6
  ],
7
- "content-hash": "96fe9130ebcdf0f6476e7011ca19a2c4",
8
  "packages": [
9
  {
10
  "name": "pimple/pimple",
@@ -115,11 +115,11 @@
115
  },
116
  {
117
  "name": "publishpress/publishpress-instance-protection",
118
- "version": "v1.0.1",
119
  "source": {
120
  "type": "git",
121
  "url": "https://github.com/publishpress/publishpress-instance-protection",
122
- "reference": "ddfa4b1e07f77b41b26e46223626584a85800073"
123
  },
124
  "require": {
125
  "php": ">=5.6.20"
@@ -139,20 +139,20 @@
139
  "keywords": [
140
  "wordpress plugin"
141
  ],
142
- "time": "2022-05-03T13:25:31+00:00"
143
  },
144
  {
145
  "name": "publishpress/wordpress-banners",
146
- "version": "v1.2.8",
147
  "source": {
148
  "type": "git",
149
  "url": "https://github.com/publishpress/wordpress-banners.git",
150
- "reference": "79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c"
151
  },
152
  "dist": {
153
  "type": "zip",
154
- "url": "https://api.github.com/repos/publishpress/wordpress-banners/zipball/79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c",
155
- "reference": "79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c",
156
  "shasum": ""
157
  },
158
  "require": {
@@ -178,22 +178,22 @@
178
  "homepage": "http://publishpress.com/",
179
  "support": {
180
  "issues": "https://github.com/publishpress/wordpress-banners/issues",
181
- "source": "https://github.com/publishpress/wordpress-banners/tree/v1.2.8"
182
  },
183
- "time": "2022-03-18T14:49:29+00:00"
184
  },
185
  {
186
  "name": "publishpress/wordpress-reviews",
187
- "version": "v1.1.18",
188
  "source": {
189
  "type": "git",
190
  "url": "https://github.com/publishpress/wordpress-reviews.git",
191
- "reference": "0020705b8f6a7177fc393c6c42c82171bf9e2fbd"
192
  },
193
  "dist": {
194
  "type": "zip",
195
- "url": "https://api.github.com/repos/publishpress/wordpress-reviews/zipball/0020705b8f6a7177fc393c6c42c82171bf9e2fbd",
196
- "reference": "0020705b8f6a7177fc393c6c42c82171bf9e2fbd",
197
  "shasum": ""
198
  },
199
  "require": {
@@ -246,30 +246,41 @@
246
  ],
247
  "support": {
248
  "issues": "https://github.com/publishpress/wordpress-reviews/issues",
249
- "source": "https://github.com/publishpress/wordpress-reviews/tree/v1.1.18"
250
  },
251
- "time": "2021-12-15T00:03:53+00:00"
252
  },
253
  {
254
  "name": "publishpress/wordpress-version-notices",
255
- "version": "1.1.3",
256
  "source": {
257
  "type": "git",
258
  "url": "https://github.com/publishpress/WordPress-Version-Notices.git",
259
- "reference": "57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3"
260
  },
261
  "dist": {
262
  "type": "zip",
263
- "url": "https://api.github.com/repos/publishpress/WordPress-Version-Notices/zipball/57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3",
264
- "reference": "57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3",
265
  "shasum": ""
266
  },
267
  "require": {
268
  "php": ">=5.6.20",
269
- "pimple/pimple": "^3"
 
270
  },
271
  "require-dev": {
272
- "lucatume/wp-browser": "^2.4"
 
 
 
 
 
 
 
 
 
 
273
  },
274
  "type": "library",
275
  "autoload": {
@@ -292,9 +303,9 @@
292
  "description": "Library for displaying version notices for Pro plugins in WordPress.",
293
  "support": {
294
  "issues": "https://github.com/publishpress/WordPress-Version-Notices/issues",
295
- "source": "https://github.com/publishpress/WordPress-Version-Notices/tree/1.1.3"
296
  },
297
- "time": "2021-07-14T16:15:47+00:00"
298
  }
299
  ],
300
  "packages-dev": [
@@ -381,16 +392,16 @@
381
  },
382
  {
383
  "name": "consolidation/annotated-command",
384
- "version": "4.5.5",
385
  "source": {
386
  "type": "git",
387
  "url": "https://github.com/consolidation/annotated-command.git",
388
- "reference": "67cea8e8e7656b74da651ea6f49321853996c0fd"
389
  },
390
  "dist": {
391
  "type": "zip",
392
- "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/67cea8e8e7656b74da651ea6f49321853996c0fd",
393
- "reference": "67cea8e8e7656b74da651ea6f49321853996c0fd",
394
  "shasum": ""
395
  },
396
  "require": {
@@ -431,22 +442,22 @@
431
  "description": "Initialize Symfony Console commands from annotated command class methods.",
432
  "support": {
433
  "issues": "https://github.com/consolidation/annotated-command/issues",
434
- "source": "https://github.com/consolidation/annotated-command/tree/4.5.5"
435
  },
436
- "time": "2022-04-26T16:18:25+00:00"
437
  },
438
  {
439
  "name": "consolidation/config",
440
- "version": "2.1.0",
441
  "source": {
442
  "type": "git",
443
  "url": "https://github.com/consolidation/config.git",
444
- "reference": "0c15841b2bf60d9af1ce29884673e7d9d50c3b75"
445
  },
446
  "dist": {
447
  "type": "zip",
448
- "url": "https://api.github.com/repos/consolidation/config/zipball/0c15841b2bf60d9af1ce29884673e7d9d50c3b75",
449
- "reference": "0c15841b2bf60d9af1ce29884673e7d9d50c3b75",
450
  "shasum": ""
451
  },
452
  "require": {
@@ -491,9 +502,9 @@
491
  "description": "Provide configuration services for a commandline tool.",
492
  "support": {
493
  "issues": "https://github.com/consolidation/config/issues",
494
- "source": "https://github.com/consolidation/config/tree/2.1.0"
495
  },
496
- "time": "2022-02-24T00:32:42+00:00"
497
  },
498
  {
499
  "name": "consolidation/log",
@@ -967,16 +978,16 @@
967
  },
968
  {
969
  "name": "nelexa/zip",
970
- "version": "4.0.1",
971
  "source": {
972
  "type": "git",
973
  "url": "https://github.com/Ne-Lexa/php-zip.git",
974
- "reference": "a18f80db509b1b6e9798e2745dc100759107f50c"
975
  },
976
  "dist": {
977
  "type": "zip",
978
- "url": "https://api.github.com/repos/Ne-Lexa/php-zip/zipball/a18f80db509b1b6e9798e2745dc100759107f50c",
979
- "reference": "a18f80db509b1b6e9798e2745dc100759107f50c",
980
  "shasum": ""
981
  },
982
  "require": {
@@ -1034,9 +1045,9 @@
1034
  ],
1035
  "support": {
1036
  "issues": "https://github.com/Ne-Lexa/php-zip/issues",
1037
- "source": "https://github.com/Ne-Lexa/php-zip/tree/4.0.1"
1038
  },
1039
- "time": "2021-12-12T09:50:45+00:00"
1040
  },
1041
  {
1042
  "name": "psr/event-dispatcher",
@@ -1246,16 +1257,16 @@
1246
  },
1247
  {
1248
  "name": "symfony/console",
1249
- "version": "v5.4.8",
1250
  "source": {
1251
  "type": "git",
1252
  "url": "https://github.com/symfony/console.git",
1253
- "reference": "ffe3aed36c4d60da2cf1b0a1cee6b8f2e5fa881b"
1254
  },
1255
  "dist": {
1256
  "type": "zip",
1257
- "url": "https://api.github.com/repos/symfony/console/zipball/ffe3aed36c4d60da2cf1b0a1cee6b8f2e5fa881b",
1258
- "reference": "ffe3aed36c4d60da2cf1b0a1cee6b8f2e5fa881b",
1259
  "shasum": ""
1260
  },
1261
  "require": {
@@ -1325,7 +1336,7 @@
1325
  "terminal"
1326
  ],
1327
  "support": {
1328
- "source": "https://github.com/symfony/console/tree/v5.4.8"
1329
  },
1330
  "funding": [
1331
  {
@@ -1341,11 +1352,11 @@
1341
  "type": "tidelift"
1342
  }
1343
  ],
1344
- "time": "2022-04-12T16:02:29+00:00"
1345
  },
1346
  {
1347
  "name": "symfony/deprecation-contracts",
1348
- "version": "v2.5.1",
1349
  "source": {
1350
  "type": "git",
1351
  "url": "https://github.com/symfony/deprecation-contracts.git",
@@ -1392,7 +1403,7 @@
1392
  "description": "A generic function and convention to trigger deprecation notices",
1393
  "homepage": "https://symfony.com",
1394
  "support": {
1395
- "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1"
1396
  },
1397
  "funding": [
1398
  {
@@ -1412,16 +1423,16 @@
1412
  },
1413
  {
1414
  "name": "symfony/event-dispatcher",
1415
- "version": "v5.4.3",
1416
  "source": {
1417
  "type": "git",
1418
  "url": "https://github.com/symfony/event-dispatcher.git",
1419
- "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d"
1420
  },
1421
  "dist": {
1422
  "type": "zip",
1423
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dec8a9f58d20df252b9cd89f1c6c1530f747685d",
1424
- "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d",
1425
  "shasum": ""
1426
  },
1427
  "require": {
@@ -1477,7 +1488,7 @@
1477
  "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
1478
  "homepage": "https://symfony.com",
1479
  "support": {
1480
- "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.3"
1481
  },
1482
  "funding": [
1483
  {
@@ -1493,11 +1504,11 @@
1493
  "type": "tidelift"
1494
  }
1495
  ],
1496
- "time": "2022-01-02T09:53:40+00:00"
1497
  },
1498
  {
1499
  "name": "symfony/event-dispatcher-contracts",
1500
- "version": "v2.5.1",
1501
  "source": {
1502
  "type": "git",
1503
  "url": "https://github.com/symfony/event-dispatcher-contracts.git",
@@ -1556,7 +1567,7 @@
1556
  "standards"
1557
  ],
1558
  "support": {
1559
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.1"
1560
  },
1561
  "funding": [
1562
  {
@@ -1576,16 +1587,16 @@
1576
  },
1577
  {
1578
  "name": "symfony/filesystem",
1579
- "version": "v5.4.7",
1580
  "source": {
1581
  "type": "git",
1582
  "url": "https://github.com/symfony/filesystem.git",
1583
- "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f"
1584
  },
1585
  "dist": {
1586
  "type": "zip",
1587
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/3a4442138d80c9f7b600fb297534ac718b61d37f",
1588
- "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f",
1589
  "shasum": ""
1590
  },
1591
  "require": {
@@ -1620,7 +1631,7 @@
1620
  "description": "Provides basic utilities for the filesystem",
1621
  "homepage": "https://symfony.com",
1622
  "support": {
1623
- "source": "https://github.com/symfony/filesystem/tree/v5.4.7"
1624
  },
1625
  "funding": [
1626
  {
@@ -1636,7 +1647,7 @@
1636
  "type": "tidelift"
1637
  }
1638
  ],
1639
- "time": "2022-04-01T12:33:59+00:00"
1640
  },
1641
  {
1642
  "name": "symfony/finder",
@@ -1703,16 +1714,16 @@
1703
  },
1704
  {
1705
  "name": "symfony/polyfill-ctype",
1706
- "version": "v1.25.0",
1707
  "source": {
1708
  "type": "git",
1709
  "url": "https://github.com/symfony/polyfill-ctype.git",
1710
- "reference": "30885182c981ab175d4d034db0f6f469898070ab"
1711
  },
1712
  "dist": {
1713
  "type": "zip",
1714
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
1715
- "reference": "30885182c981ab175d4d034db0f6f469898070ab",
1716
  "shasum": ""
1717
  },
1718
  "require": {
@@ -1727,7 +1738,7 @@
1727
  "type": "library",
1728
  "extra": {
1729
  "branch-alias": {
1730
- "dev-main": "1.23-dev"
1731
  },
1732
  "thanks": {
1733
  "name": "symfony/polyfill",
@@ -1765,7 +1776,7 @@
1765
  "portable"
1766
  ],
1767
  "support": {
1768
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
1769
  },
1770
  "funding": [
1771
  {
@@ -1781,20 +1792,20 @@
1781
  "type": "tidelift"
1782
  }
1783
  ],
1784
- "time": "2021-10-20T20:35:02+00:00"
1785
  },
1786
  {
1787
  "name": "symfony/polyfill-intl-grapheme",
1788
- "version": "v1.25.0",
1789
  "source": {
1790
  "type": "git",
1791
  "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
1792
- "reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
1793
  },
1794
  "dist": {
1795
  "type": "zip",
1796
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
1797
- "reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
1798
  "shasum": ""
1799
  },
1800
  "require": {
@@ -1806,7 +1817,7 @@
1806
  "type": "library",
1807
  "extra": {
1808
  "branch-alias": {
1809
- "dev-main": "1.23-dev"
1810
  },
1811
  "thanks": {
1812
  "name": "symfony/polyfill",
@@ -1846,7 +1857,7 @@
1846
  "shim"
1847
  ],
1848
  "support": {
1849
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
1850
  },
1851
  "funding": [
1852
  {
@@ -1862,20 +1873,20 @@
1862
  "type": "tidelift"
1863
  }
1864
  ],
1865
- "time": "2021-11-23T21:10:46+00:00"
1866
  },
1867
  {
1868
  "name": "symfony/polyfill-intl-normalizer",
1869
- "version": "v1.25.0",
1870
  "source": {
1871
  "type": "git",
1872
  "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
1873
- "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
1874
  },
1875
  "dist": {
1876
  "type": "zip",
1877
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
1878
- "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
1879
  "shasum": ""
1880
  },
1881
  "require": {
@@ -1887,7 +1898,7 @@
1887
  "type": "library",
1888
  "extra": {
1889
  "branch-alias": {
1890
- "dev-main": "1.23-dev"
1891
  },
1892
  "thanks": {
1893
  "name": "symfony/polyfill",
@@ -1930,7 +1941,7 @@
1930
  "shim"
1931
  ],
1932
  "support": {
1933
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
1934
  },
1935
  "funding": [
1936
  {
@@ -1946,20 +1957,20 @@
1946
  "type": "tidelift"
1947
  }
1948
  ],
1949
- "time": "2021-02-19T12:13:01+00:00"
1950
  },
1951
  {
1952
  "name": "symfony/polyfill-mbstring",
1953
- "version": "v1.25.0",
1954
  "source": {
1955
  "type": "git",
1956
  "url": "https://github.com/symfony/polyfill-mbstring.git",
1957
- "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
1958
  },
1959
  "dist": {
1960
  "type": "zip",
1961
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
1962
- "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
1963
  "shasum": ""
1964
  },
1965
  "require": {
@@ -1974,7 +1985,7 @@
1974
  "type": "library",
1975
  "extra": {
1976
  "branch-alias": {
1977
- "dev-main": "1.23-dev"
1978
  },
1979
  "thanks": {
1980
  "name": "symfony/polyfill",
@@ -2013,7 +2024,7 @@
2013
  "shim"
2014
  ],
2015
  "support": {
2016
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
2017
  },
2018
  "funding": [
2019
  {
@@ -2029,20 +2040,20 @@
2029
  "type": "tidelift"
2030
  }
2031
  ],
2032
- "time": "2021-11-30T18:21:41+00:00"
2033
  },
2034
  {
2035
  "name": "symfony/polyfill-php73",
2036
- "version": "v1.25.0",
2037
  "source": {
2038
  "type": "git",
2039
  "url": "https://github.com/symfony/polyfill-php73.git",
2040
- "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5"
2041
  },
2042
  "dist": {
2043
  "type": "zip",
2044
- "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5",
2045
- "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5",
2046
  "shasum": ""
2047
  },
2048
  "require": {
@@ -2051,7 +2062,7 @@
2051
  "type": "library",
2052
  "extra": {
2053
  "branch-alias": {
2054
- "dev-main": "1.23-dev"
2055
  },
2056
  "thanks": {
2057
  "name": "symfony/polyfill",
@@ -2092,7 +2103,7 @@
2092
  "shim"
2093
  ],
2094
  "support": {
2095
- "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
2096
  },
2097
  "funding": [
2098
  {
@@ -2108,20 +2119,20 @@
2108
  "type": "tidelift"
2109
  }
2110
  ],
2111
- "time": "2021-06-05T21:20:04+00:00"
2112
  },
2113
  {
2114
  "name": "symfony/polyfill-php80",
2115
- "version": "v1.25.0",
2116
  "source": {
2117
  "type": "git",
2118
  "url": "https://github.com/symfony/polyfill-php80.git",
2119
- "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
2120
  },
2121
  "dist": {
2122
  "type": "zip",
2123
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
2124
- "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
2125
  "shasum": ""
2126
  },
2127
  "require": {
@@ -2130,7 +2141,7 @@
2130
  "type": "library",
2131
  "extra": {
2132
  "branch-alias": {
2133
- "dev-main": "1.23-dev"
2134
  },
2135
  "thanks": {
2136
  "name": "symfony/polyfill",
@@ -2175,7 +2186,7 @@
2175
  "shim"
2176
  ],
2177
  "support": {
2178
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
2179
  },
2180
  "funding": [
2181
  {
@@ -2191,7 +2202,7 @@
2191
  "type": "tidelift"
2192
  }
2193
  ],
2194
- "time": "2022-03-04T08:16:47+00:00"
2195
  },
2196
  {
2197
  "name": "symfony/process",
@@ -2336,16 +2347,16 @@
2336
  },
2337
  {
2338
  "name": "symfony/string",
2339
- "version": "v5.4.8",
2340
  "source": {
2341
  "type": "git",
2342
  "url": "https://github.com/symfony/string.git",
2343
- "reference": "3c061a76bff6d6ea427d85e12ad1bb8ed8cd43e8"
2344
  },
2345
  "dist": {
2346
  "type": "zip",
2347
- "url": "https://api.github.com/repos/symfony/string/zipball/3c061a76bff6d6ea427d85e12ad1bb8ed8cd43e8",
2348
- "reference": "3c061a76bff6d6ea427d85e12ad1bb8ed8cd43e8",
2349
  "shasum": ""
2350
  },
2351
  "require": {
@@ -2402,7 +2413,7 @@
2402
  "utf8"
2403
  ],
2404
  "support": {
2405
- "source": "https://github.com/symfony/string/tree/v5.4.8"
2406
  },
2407
  "funding": [
2408
  {
@@ -2418,20 +2429,20 @@
2418
  "type": "tidelift"
2419
  }
2420
  ],
2421
- "time": "2022-04-19T10:40:37+00:00"
2422
  },
2423
  {
2424
  "name": "symfony/yaml",
2425
- "version": "v5.4.3",
2426
  "source": {
2427
  "type": "git",
2428
  "url": "https://github.com/symfony/yaml.git",
2429
- "reference": "e80f87d2c9495966768310fc531b487ce64237a2"
2430
  },
2431
  "dist": {
2432
  "type": "zip",
2433
- "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2",
2434
- "reference": "e80f87d2c9495966768310fc531b487ce64237a2",
2435
  "shasum": ""
2436
  },
2437
  "require": {
@@ -2477,7 +2488,7 @@
2477
  "description": "Loads and dumps YAML files",
2478
  "homepage": "https://symfony.com",
2479
  "support": {
2480
- "source": "https://github.com/symfony/yaml/tree/v5.4.3"
2481
  },
2482
  "funding": [
2483
  {
@@ -2493,7 +2504,7 @@
2493
  "type": "tidelift"
2494
  }
2495
  ],
2496
- "time": "2022-01-26T16:32:32+00:00"
2497
  }
2498
  ],
2499
  "aliases": [],
@@ -2505,5 +2516,5 @@
2505
  "php": ">=5.6.20"
2506
  },
2507
  "platform-dev": [],
2508
- "plugin-api-version": "2.3.0"
2509
  }
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
  "This file is @generated automatically"
6
  ],
7
+ "content-hash": "bd313db8ff0c3f0bde999242b878defb",
8
  "packages": [
9
  {
10
  "name": "pimple/pimple",
115
  },
116
  {
117
  "name": "publishpress/publishpress-instance-protection",
118
+ "version": "v1.0.2",
119
  "source": {
120
  "type": "git",
121
  "url": "https://github.com/publishpress/publishpress-instance-protection",
122
+ "reference": "ef1a631a41b723ce2e856f534ff4befbe914e964"
123
  },
124
  "require": {
125
  "php": ">=5.6.20"
139
  "keywords": [
140
  "wordpress plugin"
141
  ],
142
+ "time": "2022-06-03T17:41:36+00:00"
143
  },
144
  {
145
  "name": "publishpress/wordpress-banners",
146
+ "version": "v1.3.0",
147
  "source": {
148
  "type": "git",
149
  "url": "https://github.com/publishpress/wordpress-banners.git",
150
+ "reference": "08e20b98320367bdbc59105095c72e7ccbf968f1"
151
  },
152
  "dist": {
153
  "type": "zip",
154
+ "url": "https://api.github.com/repos/publishpress/wordpress-banners/zipball/08e20b98320367bdbc59105095c72e7ccbf968f1",
155
+ "reference": "08e20b98320367bdbc59105095c72e7ccbf968f1",
156
  "shasum": ""
157
  },
158
  "require": {
178
  "homepage": "http://publishpress.com/",
179
  "support": {
180
  "issues": "https://github.com/publishpress/wordpress-banners/issues",
181
+ "source": "https://github.com/publishpress/wordpress-banners/tree/v1.3.0"
182
  },
183
+ "time": "2022-06-03T15:45:27+00:00"
184
  },
185
  {
186
  "name": "publishpress/wordpress-reviews",
187
+ "version": "v1.1.19",
188
  "source": {
189
  "type": "git",
190
  "url": "https://github.com/publishpress/wordpress-reviews.git",
191
+ "reference": "028e573eb7c5da2455a7a823cabbbe5e3f89ca9c"
192
  },
193
  "dist": {
194
  "type": "zip",
195
+ "url": "https://api.github.com/repos/publishpress/wordpress-reviews/zipball/028e573eb7c5da2455a7a823cabbbe5e3f89ca9c",
196
+ "reference": "028e573eb7c5da2455a7a823cabbbe5e3f89ca9c",
197
  "shasum": ""
198
  },
199
  "require": {
246
  ],
247
  "support": {
248
  "issues": "https://github.com/publishpress/wordpress-reviews/issues",
249
+ "source": "https://github.com/publishpress/wordpress-reviews/tree/v1.1.19"
250
  },
251
+ "time": "2022-06-03T13:38:53+00:00"
252
  },
253
  {
254
  "name": "publishpress/wordpress-version-notices",
255
+ "version": "1.1.4",
256
  "source": {
257
  "type": "git",
258
  "url": "https://github.com/publishpress/WordPress-Version-Notices.git",
259
+ "reference": "a46b552ac4cbec26d743307611e5dd8d56f80a57"
260
  },
261
  "dist": {
262
  "type": "zip",
263
+ "url": "https://api.github.com/repos/publishpress/WordPress-Version-Notices/zipball/a46b552ac4cbec26d743307611e5dd8d56f80a57",
264
+ "reference": "a46b552ac4cbec26d743307611e5dd8d56f80a57",
265
  "shasum": ""
266
  },
267
  "require": {
268
  "php": ">=5.6.20",
269
+ "pimple/pimple": "~3.2.0",
270
+ "psr/container": "~1.0.0"
271
  },
272
  "require-dev": {
273
+ "codeception/module-asserts": "^1.0",
274
+ "codeception/module-cli": "^1.0",
275
+ "codeception/module-db": "^1.0",
276
+ "codeception/module-filesystem": "^1.0",
277
+ "codeception/module-phpbrowser": "^1.0",
278
+ "codeception/module-rest": "^1.3",
279
+ "codeception/module-webdriver": "^1.0",
280
+ "codeception/util-universalframework": "^1.0",
281
+ "composer/composer": "2.2.12",
282
+ "lucatume/wp-browser": "^3",
283
+ "overtrue/phplint": "^2.1"
284
  },
285
  "type": "library",
286
  "autoload": {
303
  "description": "Library for displaying version notices for Pro plugins in WordPress.",
304
  "support": {
305
  "issues": "https://github.com/publishpress/WordPress-Version-Notices/issues",
306
+ "source": "https://github.com/publishpress/WordPress-Version-Notices/tree/1.1.4"
307
  },
308
+ "time": "2022-06-06T15:45:54+00:00"
309
  }
310
  ],
311
  "packages-dev": [
392
  },
393
  {
394
  "name": "consolidation/annotated-command",
395
+ "version": "4.5.6",
396
  "source": {
397
  "type": "git",
398
  "url": "https://github.com/consolidation/annotated-command.git",
399
+ "reference": "3968070538761628546270935f0733a0cc408e1f"
400
  },
401
  "dist": {
402
  "type": "zip",
403
+ "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/3968070538761628546270935f0733a0cc408e1f",
404
+ "reference": "3968070538761628546270935f0733a0cc408e1f",
405
  "shasum": ""
406
  },
407
  "require": {
442
  "description": "Initialize Symfony Console commands from annotated command class methods.",
443
  "support": {
444
  "issues": "https://github.com/consolidation/annotated-command/issues",
445
+ "source": "https://github.com/consolidation/annotated-command/tree/4.5.6"
446
  },
447
+ "time": "2022-06-22T20:17:12+00:00"
448
  },
449
  {
450
  "name": "consolidation/config",
451
+ "version": "2.1.1",
452
  "source": {
453
  "type": "git",
454
  "url": "https://github.com/consolidation/config.git",
455
+ "reference": "dae810c162f0e799ea3f35cc2f40b0797b6e4d26"
456
  },
457
  "dist": {
458
  "type": "zip",
459
+ "url": "https://api.github.com/repos/consolidation/config/zipball/dae810c162f0e799ea3f35cc2f40b0797b6e4d26",
460
+ "reference": "dae810c162f0e799ea3f35cc2f40b0797b6e4d26",
461
  "shasum": ""
462
  },
463
  "require": {
502
  "description": "Provide configuration services for a commandline tool.",
503
  "support": {
504
  "issues": "https://github.com/consolidation/config/issues",
505
+ "source": "https://github.com/consolidation/config/tree/2.1.1"
506
  },
507
+ "time": "2022-06-22T19:59:34+00:00"
508
  },
509
  {
510
  "name": "consolidation/log",
978
  },
979
  {
980
  "name": "nelexa/zip",
981
+ "version": "4.0.2",
982
  "source": {
983
  "type": "git",
984
  "url": "https://github.com/Ne-Lexa/php-zip.git",
985
+ "reference": "88a1b6549be813278ff2dd3b6b2ac188827634a7"
986
  },
987
  "dist": {
988
  "type": "zip",
989
+ "url": "https://api.github.com/repos/Ne-Lexa/php-zip/zipball/88a1b6549be813278ff2dd3b6b2ac188827634a7",
990
+ "reference": "88a1b6549be813278ff2dd3b6b2ac188827634a7",
991
  "shasum": ""
992
  },
993
  "require": {
1045
  ],
1046
  "support": {
1047
  "issues": "https://github.com/Ne-Lexa/php-zip/issues",
1048
+ "source": "https://github.com/Ne-Lexa/php-zip/tree/4.0.2"
1049
  },
1050
+ "time": "2022-06-17T11:17:46+00:00"
1051
  },
1052
  {
1053
  "name": "psr/event-dispatcher",
1257
  },
1258
  {
1259
  "name": "symfony/console",
1260
+ "version": "v5.4.10",
1261
  "source": {
1262
  "type": "git",
1263
  "url": "https://github.com/symfony/console.git",
1264
+ "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000"
1265
  },
1266
  "dist": {
1267
  "type": "zip",
1268
+ "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000",
1269
+ "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000",
1270
  "shasum": ""
1271
  },
1272
  "require": {
1336
  "terminal"
1337
  ],
1338
  "support": {
1339
+ "source": "https://github.com/symfony/console/tree/v5.4.10"
1340
  },
1341
  "funding": [
1342
  {
1352
  "type": "tidelift"
1353
  }
1354
  ],
1355
+ "time": "2022-06-26T13:00:04+00:00"
1356
  },
1357
  {
1358
  "name": "symfony/deprecation-contracts",
1359
+ "version": "v2.5.2",
1360
  "source": {
1361
  "type": "git",
1362
  "url": "https://github.com/symfony/deprecation-contracts.git",
1403
  "description": "A generic function and convention to trigger deprecation notices",
1404
  "homepage": "https://symfony.com",
1405
  "support": {
1406
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
1407
  },
1408
  "funding": [
1409
  {
1423
  },
1424
  {
1425
  "name": "symfony/event-dispatcher",
1426
+ "version": "v5.4.9",
1427
  "source": {
1428
  "type": "git",
1429
  "url": "https://github.com/symfony/event-dispatcher.git",
1430
+ "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc"
1431
  },
1432
  "dist": {
1433
  "type": "zip",
1434
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc",
1435
+ "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc",
1436
  "shasum": ""
1437
  },
1438
  "require": {
1488
  "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
1489
  "homepage": "https://symfony.com",
1490
  "support": {
1491
+ "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.9"
1492
  },
1493
  "funding": [
1494
  {
1504
  "type": "tidelift"
1505
  }
1506
  ],
1507
+ "time": "2022-05-05T16:45:39+00:00"
1508
  },
1509
  {
1510
  "name": "symfony/event-dispatcher-contracts",
1511
+ "version": "v2.5.2",
1512
  "source": {
1513
  "type": "git",
1514
  "url": "https://github.com/symfony/event-dispatcher-contracts.git",
1567
  "standards"
1568
  ],
1569
  "support": {
1570
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2"
1571
  },
1572
  "funding": [
1573
  {
1587
  },
1588
  {
1589
  "name": "symfony/filesystem",
1590
+ "version": "v5.4.9",
1591
  "source": {
1592
  "type": "git",
1593
  "url": "https://github.com/symfony/filesystem.git",
1594
+ "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba"
1595
  },
1596
  "dist": {
1597
  "type": "zip",
1598
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/36a017fa4cce1eff1b8e8129ff53513abcef05ba",
1599
+ "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba",
1600
  "shasum": ""
1601
  },
1602
  "require": {
1631
  "description": "Provides basic utilities for the filesystem",
1632
  "homepage": "https://symfony.com",
1633
  "support": {
1634
+ "source": "https://github.com/symfony/filesystem/tree/v5.4.9"
1635
  },
1636
  "funding": [
1637
  {
1647
  "type": "tidelift"
1648
  }
1649
  ],
1650
+ "time": "2022-05-20T13:55:35+00:00"
1651
  },
1652
  {
1653
  "name": "symfony/finder",
1714
  },
1715
  {
1716
  "name": "symfony/polyfill-ctype",
1717
+ "version": "v1.26.0",
1718
  "source": {
1719
  "type": "git",
1720
  "url": "https://github.com/symfony/polyfill-ctype.git",
1721
+ "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
1722
  },
1723
  "dist": {
1724
  "type": "zip",
1725
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
1726
+ "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
1727
  "shasum": ""
1728
  },
1729
  "require": {
1738
  "type": "library",
1739
  "extra": {
1740
  "branch-alias": {
1741
+ "dev-main": "1.26-dev"
1742
  },
1743
  "thanks": {
1744
  "name": "symfony/polyfill",
1776
  "portable"
1777
  ],
1778
  "support": {
1779
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
1780
  },
1781
  "funding": [
1782
  {
1792
  "type": "tidelift"
1793
  }
1794
  ],
1795
+ "time": "2022-05-24T11:49:31+00:00"
1796
  },
1797
  {
1798
  "name": "symfony/polyfill-intl-grapheme",
1799
+ "version": "v1.26.0",
1800
  "source": {
1801
  "type": "git",
1802
  "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
1803
+ "reference": "433d05519ce6990bf3530fba6957499d327395c2"
1804
  },
1805
  "dist": {
1806
  "type": "zip",
1807
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
1808
+ "reference": "433d05519ce6990bf3530fba6957499d327395c2",
1809
  "shasum": ""
1810
  },
1811
  "require": {
1817
  "type": "library",
1818
  "extra": {
1819
  "branch-alias": {
1820
+ "dev-main": "1.26-dev"
1821
  },
1822
  "thanks": {
1823
  "name": "symfony/polyfill",
1857
  "shim"
1858
  ],
1859
  "support": {
1860
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
1861
  },
1862
  "funding": [
1863
  {
1873
  "type": "tidelift"
1874
  }
1875
  ],
1876
+ "time": "2022-05-24T11:49:31+00:00"
1877
  },
1878
  {
1879
  "name": "symfony/polyfill-intl-normalizer",
1880
+ "version": "v1.26.0",
1881
  "source": {
1882
  "type": "git",
1883
  "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
1884
+ "reference": "219aa369ceff116e673852dce47c3a41794c14bd"
1885
  },
1886
  "dist": {
1887
  "type": "zip",
1888
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
1889
+ "reference": "219aa369ceff116e673852dce47c3a41794c14bd",
1890
  "shasum": ""
1891
  },
1892
  "require": {
1898
  "type": "library",
1899
  "extra": {
1900
  "branch-alias": {
1901
+ "dev-main": "1.26-dev"
1902
  },
1903
  "thanks": {
1904
  "name": "symfony/polyfill",
1941
  "shim"
1942
  ],
1943
  "support": {
1944
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
1945
  },
1946
  "funding": [
1947
  {
1957
  "type": "tidelift"
1958
  }
1959
  ],
1960
+ "time": "2022-05-24T11:49:31+00:00"
1961
  },
1962
  {
1963
  "name": "symfony/polyfill-mbstring",
1964
+ "version": "v1.26.0",
1965
  "source": {
1966
  "type": "git",
1967
  "url": "https://github.com/symfony/polyfill-mbstring.git",
1968
+ "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
1969
  },
1970
  "dist": {
1971
  "type": "zip",
1972
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
1973
+ "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
1974
  "shasum": ""
1975
  },
1976
  "require": {
1985
  "type": "library",
1986
  "extra": {
1987
  "branch-alias": {
1988
+ "dev-main": "1.26-dev"
1989
  },
1990
  "thanks": {
1991
  "name": "symfony/polyfill",
2024
  "shim"
2025
  ],
2026
  "support": {
2027
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
2028
  },
2029
  "funding": [
2030
  {
2040
  "type": "tidelift"
2041
  }
2042
  ],
2043
+ "time": "2022-05-24T11:49:31+00:00"
2044
  },
2045
  {
2046
  "name": "symfony/polyfill-php73",
2047
+ "version": "v1.26.0",
2048
  "source": {
2049
  "type": "git",
2050
  "url": "https://github.com/symfony/polyfill-php73.git",
2051
+ "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
2052
  },
2053
  "dist": {
2054
  "type": "zip",
2055
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
2056
+ "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
2057
  "shasum": ""
2058
  },
2059
  "require": {
2062
  "type": "library",
2063
  "extra": {
2064
  "branch-alias": {
2065
+ "dev-main": "1.26-dev"
2066
  },
2067
  "thanks": {
2068
  "name": "symfony/polyfill",
2103
  "shim"
2104
  ],
2105
  "support": {
2106
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
2107
  },
2108
  "funding": [
2109
  {
2119
  "type": "tidelift"
2120
  }
2121
  ],
2122
+ "time": "2022-05-24T11:49:31+00:00"
2123
  },
2124
  {
2125
  "name": "symfony/polyfill-php80",
2126
+ "version": "v1.26.0",
2127
  "source": {
2128
  "type": "git",
2129
  "url": "https://github.com/symfony/polyfill-php80.git",
2130
+ "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
2131
  },
2132
  "dist": {
2133
  "type": "zip",
2134
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
2135
+ "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
2136
  "shasum": ""
2137
  },
2138
  "require": {
2141
  "type": "library",
2142
  "extra": {
2143
  "branch-alias": {
2144
+ "dev-main": "1.26-dev"
2145
  },
2146
  "thanks": {
2147
  "name": "symfony/polyfill",
2186
  "shim"
2187
  ],
2188
  "support": {
2189
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
2190
  },
2191
  "funding": [
2192
  {
2202
  "type": "tidelift"
2203
  }
2204
  ],
2205
+ "time": "2022-05-10T07:21:04+00:00"
2206
  },
2207
  {
2208
  "name": "symfony/process",
2347
  },
2348
  {
2349
  "name": "symfony/string",
2350
+ "version": "v5.4.10",
2351
  "source": {
2352
  "type": "git",
2353
  "url": "https://github.com/symfony/string.git",
2354
+ "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097"
2355
  },
2356
  "dist": {
2357
  "type": "zip",
2358
+ "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097",
2359
+ "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097",
2360
  "shasum": ""
2361
  },
2362
  "require": {
2413
  "utf8"
2414
  ],
2415
  "support": {
2416
+ "source": "https://github.com/symfony/string/tree/v5.4.10"
2417
  },
2418
  "funding": [
2419
  {
2429
  "type": "tidelift"
2430
  }
2431
  ],
2432
+ "time": "2022-06-26T15:57:47+00:00"
2433
  },
2434
  {
2435
  "name": "symfony/yaml",
2436
+ "version": "v5.4.10",
2437
  "source": {
2438
  "type": "git",
2439
  "url": "https://github.com/symfony/yaml.git",
2440
+ "reference": "04e42926429d9e8b39c174387ab990bf7817f7a2"
2441
  },
2442
  "dist": {
2443
  "type": "zip",
2444
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/04e42926429d9e8b39c174387ab990bf7817f7a2",
2445
+ "reference": "04e42926429d9e8b39c174387ab990bf7817f7a2",
2446
  "shasum": ""
2447
  },
2448
  "require": {
2488
  "description": "Loads and dumps YAML files",
2489
  "homepage": "https://symfony.com",
2490
  "support": {
2491
+ "source": "https://github.com/symfony/yaml/tree/v5.4.10"
2492
  },
2493
  "funding": [
2494
  {
2504
  "type": "tidelift"
2505
  }
2506
  ],
2507
+ "time": "2022-06-20T11:50:59+00:00"
2508
  }
2509
  ],
2510
  "aliases": [],
2516
  "php": ">=5.6.20"
2517
  },
2518
  "platform-dev": [],
2519
+ "plugin-api-version": "2.2.0"
2520
  }
includes/admin-load.php CHANGED
@@ -39,7 +39,7 @@ class PP_Capabilities_Admin_UI {
39
 
40
  || (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], ['pp-roles-add-role', 'pp-roles-delete-role', 'pp-roles-hide-role', 'pp-roles-unhide-role']))
41
  || ( ! empty($_SERVER['SCRIPT_NAME']) && strpos(sanitize_text_field($_SERVER['SCRIPT_NAME']), 'p-admin/plugins.php' ) && ! empty($_REQUEST['action'] ) )
42
- || ( isset($_GET['action']) && ('reset-defaults' == $_GET['action']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'capsman-reset-defaults') )
43
  || in_array( $pagenow, array( 'users.php', 'user-edit.php', 'profile.php', 'user-new.php' ) )
44
  ) ) {
45
  global $capsman;
@@ -80,6 +80,87 @@ class PP_Capabilities_Admin_UI {
80
 
81
 
82
  add_filter('pp_capabilities_feature_post_types', [$this, 'fltEditorFeaturesPostTypes'], 5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
84
 
85
  public function fltEditorFeaturesPostTypes($def_post_types) {
@@ -172,6 +253,13 @@ class PP_Capabilities_Admin_UI {
172
  CAPSMAN_VERSION
173
  );
174
 
 
 
 
 
 
 
 
175
  wp_enqueue_script(
176
  'pp-capabilities-roles-profile-js',
177
  plugin_dir_url(CME_FILE) . 'common/js/profile.js',
@@ -202,7 +290,8 @@ class PP_Capabilities_Admin_UI {
202
  'pp-capabilities-roles-profile-js',
203
  'ppCapabilitiesProfileData',
204
  [
205
- 'selected_roles' => $roles
 
206
  ]
207
  );
208
  }
@@ -274,21 +363,19 @@ class PP_Capabilities_Admin_UI {
274
  return;
275
  }
276
 
277
- // Remove unselected roles
278
  foreach ($currentRoles as $role) {
279
  // Check if it is a bbPress rule. If so, don't remove it.
280
  $isBBPressRole = preg_match('/^bbp_/', $role);
281
 
282
- if (!in_array($role, $newRoles) && !$isBBPressRole) {
283
  $user->remove_role($role);
284
  }
285
  }
286
 
287
- // Add new roles
288
  foreach ($newRoles as $role) {
289
- if (!in_array($role, $currentRoles)) {
290
- $user->add_role($role);
291
- }
292
  }
293
  }
294
  }
39
 
40
  || (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], ['pp-roles-add-role', 'pp-roles-delete-role', 'pp-roles-hide-role', 'pp-roles-unhide-role']))
41
  || ( ! empty($_SERVER['SCRIPT_NAME']) && strpos(sanitize_text_field($_SERVER['SCRIPT_NAME']), 'p-admin/plugins.php' ) && ! empty($_REQUEST['action'] ) )
42
+ || ( isset($_GET['action']) && ('reset-defaults' == $_GET['action']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'capsman-reset-defaults') )
43
  || in_array( $pagenow, array( 'users.php', 'user-edit.php', 'profile.php', 'user-new.php' ) )
44
  ) ) {
45
  global $capsman;
80
 
81
 
82
  add_filter('pp_capabilities_feature_post_types', [$this, 'fltEditorFeaturesPostTypes'], 5);
83
+ add_filter('block_editor_settings_all', [$this, 'filterCodeEditingStatus'], 999);
84
+ add_filter('classic_editor_enabled_editors_for_post_type', [$this, 'filterRolePostTypeEditor'], 10, 2);
85
+ add_filter('classic_editor_plugin_settings', [$this, 'filterRoleEditorSettings']);
86
+ }
87
+
88
+ /**
89
+ * Filters the editors that are enabled for the post type.
90
+ *
91
+ * @param array $editors Associative array of the editors and whether they are enabled for the post type.
92
+ * @param string $post_type The post type.
93
+ */
94
+ public function filterRolePostTypeEditor($editors, $post_type) {
95
+ $user = wp_get_current_user();
96
+
97
+ if (is_object($user) && isset($user->roles)) {
98
+ $current_user_editors = [];
99
+ foreach ($user->roles as $user_role) {
100
+ //get role option
101
+ $role_option = get_option("pp_capabilities_{$user_role}_role_option", []);
102
+ if (is_array($role_option) && !empty($role_option) && !empty($role_option['role_editor'])) {
103
+ $current_user_editors = array_merge($current_user_editors, $role_option['role_editor']);
104
+ }
105
+ }
106
+
107
+ if (!empty($current_user_editors)) {
108
+ $current_user_editors = array_unique($current_user_editors);
109
+ $editors = array(
110
+ 'classic_editor' => in_array('classic_editor', $current_user_editors) ? true : false,
111
+ 'block_editor' => in_array('block_editor', $current_user_editors) ? true : false,
112
+ );
113
+ }
114
+ }
115
+
116
+ return $editors;
117
+ }
118
+
119
+ /**
120
+ * Override the classic editor plugin's settings.
121
+ *
122
+ * @param bool $settings
123
+ * @return mixed
124
+ */
125
+ public function filterRoleEditorSettings($settings) {
126
+ $user = wp_get_current_user();
127
+
128
+ if (is_object($user) && isset($user->roles)) {
129
+ $current_user_editors = [];
130
+ foreach ($user->roles as $user_role) {
131
+ //get role option
132
+ $role_option = get_option("pp_capabilities_{$user_role}_role_option", []);
133
+ if (is_array($role_option) && !empty($role_option) && !empty($role_option['role_editor'])) {
134
+ $current_user_editors = array_merge($current_user_editors, $role_option['role_editor']);
135
+ }
136
+ }
137
+
138
+ if (!empty($current_user_editors)) {
139
+ $current_user_editors = array_unique($current_user_editors);
140
+ $settings = [];
141
+ $settings['editor'] = ($current_user_editors[0] === 'classic_editor') ? 'classic' : 'block';
142
+ $settings['allow-users'] = count($current_user_editors) > 1 ? true : false;
143
+ }
144
+ }
145
+
146
+ return $settings;
147
+ }
148
+
149
+ public function filterCodeEditingStatus($settings) {
150
+ $user = wp_get_current_user();
151
+
152
+ if (is_object($user) && isset($user->roles)) {
153
+ foreach ($user->roles as $user_role) {
154
+ //get role option
155
+ $role_option = get_option("pp_capabilities_{$user_role}_role_option", []);
156
+ if (is_array($role_option) && !empty($role_option) && !empty($role_option['disable_code_editor']) && (int)$role_option['disable_code_editor'] > 0) {
157
+ $settings['codeEditingEnabled'] = false;
158
+ break;
159
+ }
160
+ }
161
+ }
162
+
163
+ return $settings;
164
  }
165
 
166
  public function fltEditorFeaturesPostTypes($def_post_types) {
253
  CAPSMAN_VERSION
254
  );
255
 
256
+ wp_enqueue_script(
257
+ 'pp-capabilities-jquery-ui',
258
+ plugin_dir_url(CME_FILE) . 'common/libs/jquery/jquery-ui.js',
259
+ ['jquery'],
260
+ CAPSMAN_VERSION
261
+ );
262
+
263
  wp_enqueue_script(
264
  'pp-capabilities-roles-profile-js',
265
  plugin_dir_url(CME_FILE) . 'common/js/profile.js',
290
  'pp-capabilities-roles-profile-js',
291
  'ppCapabilitiesProfileData',
292
  [
293
+ 'role_description' => esc_html__('Drag multiple roles selection to change order.', 'capsman-enhanced'),
294
+ 'selected_roles' => $roles
295
  ]
296
  );
297
  }
363
  return;
364
  }
365
 
366
+ // Remove all roles
367
  foreach ($currentRoles as $role) {
368
  // Check if it is a bbPress rule. If so, don't remove it.
369
  $isBBPressRole = preg_match('/^bbp_/', $role);
370
 
371
+ if (!$isBBPressRole) {
372
  $user->remove_role($role);
373
  }
374
  }
375
 
376
+ // Add new roles in order
377
  foreach ($newRoles as $role) {
378
+ $user->add_role($role);
 
 
379
  }
380
  }
381
  }
includes/admin.php CHANGED
@@ -199,21 +199,13 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
199
  $cap_properties['edit']['type'][]= 'edit_others_posts';
200
  $cap_properties['edit']['type'] = array_merge( $cap_properties['edit']['type'], array( 'publish_posts', 'edit_published_posts', 'edit_private_posts' ) );
201
 
202
- $cap_properties['edit']['taxonomy'] = array( 'manage_terms' );
203
-
204
- if ( ! defined( 'OLD_PRESSPERMIT_ACTIVE' ) )
205
- $cap_properties['edit']['taxonomy'] = array_merge( $cap_properties['edit']['taxonomy'], array( 'edit_terms', 'assign_terms' ) );
206
-
207
  $cap_properties['delete']['type'] = array( 'delete_posts', 'delete_others_posts' );
208
  $cap_properties['delete']['type'] = array_merge( $cap_properties['delete']['type'], array( 'delete_published_posts', 'delete_private_posts' ) );
209
 
210
- if ( ! defined( 'OLD_PRESSPERMIT_ACTIVE' ) )
211
- $cap_properties['delete']['taxonomy'] = array( 'delete_terms' );
212
- else
213
- $cap_properties['delete']['taxonomy'] = array();
214
 
215
  $cap_properties['read']['type'] = array( 'read_private_posts' );
216
- $cap_properties['read']['taxonomy'] = array();
 
217
 
218
  $stati = get_post_stati( array( 'internal' => false ) );
219
 
@@ -221,7 +213,8 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
221
  '' => __( '&nbsp;', 'capsman-enhanced' ),
222
  'read' => __( 'Reading', 'capsman-enhanced' ),
223
  'edit' => __( 'Editing', 'capsman-enhanced' ),
224
- 'delete' => __( 'Deletion', 'capsman-enhanced' )
 
225
  );
226
 
227
  $cap_tips = array(
@@ -300,7 +293,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
300
  if ($extra_tabs = apply_filters('pp_capabilities_extra_post_capability_tabs', [])) {
301
  foreach($extra_tabs as $tab_slug => $tab_caption) {
302
  $tab_slug = esc_attr($tab_slug);
303
-
304
  $tab_id = "cme-cap-type-tables-{$tab_slug}";
305
  $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
306
 
@@ -310,166 +303,316 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
310
  }
311
  }
312
 
313
- // caps: other
314
- $tab_id = "cme-cap-type-tables-other";
315
- $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
316
- $tab_caption = esc_html__( 'WordPress Core', 'capsman-enhanced' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
- echo '<li data-slug="other" data-content="' . esc_attr($tab_id) . '" class="' . esc_attr($tab_active) . '">' . esc_html($tab_caption) . '</li>';
 
 
 
319
 
320
  // caps: plugins
321
  $plugin_caps = [];
322
- if (defined('PUBLISHPRESS_VERSION')) {
323
- $plugin_caps['PublishPress'] = apply_filters('cme_publishpress_capabilities',
324
- array(
325
- 'edit_metadata',
326
- 'edit_post_subscriptions',
327
- 'pp_manage_roles',
328
- 'pp_set_notification_channel',
329
- 'pp_view_calendar',
330
- 'pp_view_content_overview',
331
- )
332
- );
333
- }
334
 
335
  //PublishPress Capabilities Capabilities
336
  $plugin_caps['PublishPress Capabilities'] = apply_filters('cme_publishpress_capabilities_capabilities',
337
- array(
338
- 'manage_capabilities',
339
- )
340
  );
341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  if (defined('PUBLISHPRESS_MULTIPLE_AUTHORS_VERSION')) {
343
- if ($_caps = apply_filters('cme_multiple_authors_capabilities', array())) {
344
  $plugin_caps['PublishPress Authors'] = $_caps;
345
  }
346
  }
347
 
348
  if (defined('PRESSPERMIT_VERSION')) {
349
  $plugin_caps['PublishPress Permissions'] = apply_filters('cme_presspermit_capabilities',
350
- array(
351
- 'edit_own_attachments',
352
- 'list_others_unattached_files',
353
- 'pp_administer_content',
354
- 'pp_assign_roles',
355
- 'pp_associate_any_page',
356
- 'pp_create_groups',
357
- 'pp_create_network_groups',
358
- 'pp_define_moderation',
359
- 'pp_define_post_status',
360
- 'pp_define_privacy',
361
- 'pp_delete_groups',
362
- 'pp_edit_groups',
363
- 'pp_exempt_edit_circle',
364
- 'pp_exempt_read_circle',
365
- 'pp_force_quick_edit',
366
- 'pp_list_all_files',
367
- 'pp_manage_capabilities',
368
- 'pp_manage_members',
369
- 'pp_manage_network_members',
370
- 'pp_manage_settings',
371
- 'pp_moderate_any',
372
- 'pp_set_associate_exceptions',
373
- 'pp_set_edit_exceptions',
374
- 'pp_set_read_exceptions',
375
- 'pp_set_revise_exceptions',
376
- 'pp_set_term_assign_exceptions',
377
- 'pp_set_term_associate_exceptions',
378
- 'pp_set_term_manage_exceptions',
379
- 'pp_unfiltered',
380
- 'set_posts_status',
381
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  );
383
  }
384
 
385
  if (defined('WC_PLUGIN_FILE')) {
386
  $plugin_caps['WooCommerce'] = apply_filters('cme_woocommerce_capabilities',
387
- array(
388
- 'assign_product_terms',
389
- 'assign_shop_coupon_terms',
390
- 'assign_shop_discount_terms',
391
- 'assign_shop_order_terms',
392
- 'assign_shop_payment_terms',
393
- 'create_shop_orders',
394
- 'delete_others_products',
395
- 'delete_others_shop_coupons',
396
- 'delete_others_shop_discounts',
397
- 'delete_others_shop_orders',
398
- 'delete_others_shop_payments',
399
- 'delete_private_products',
400
- 'delete_private_shop_coupons',
401
- 'delete_private_shop_orders',
402
- 'delete_private_shop_discounts',
403
- 'delete_private_shop_payments',
404
- 'delete_product_terms',
405
- 'delete_products',
406
- 'delete_published_products',
407
- 'delete_published_shop_coupons',
408
- 'delete_published_shop_discounts',
409
- 'delete_published_shop_orders',
410
- 'delete_published_shop_payments',
411
- 'delete_shop_coupons',
412
- 'delete_shop_coupon_terms',
413
- 'delete_shop_discount_terms',
414
- 'delete_shop_discounts',
415
- 'delete_shop_order_terms',
416
- 'delete_shop_orders',
417
- 'delete_shop_payments',
418
- 'delete_shop_payment_terms',
419
- 'edit_others_products',
420
- 'edit_others_shop_coupons',
421
- 'edit_others_shop_discounts',
422
- 'edit_others_shop_orders',
423
- 'edit_others_shop_payments',
424
- 'edit_private_products',
425
- 'edit_private_shop_coupons',
426
- 'edit_private_shop_discounts',
427
- 'edit_private_shop_orders',
428
- 'edit_private_shop_payments',
429
- 'edit_product_terms',
430
- 'edit_products',
431
- 'edit_published_products',
432
- 'edit_published_shop_coupons',
433
- 'edit_published_shop_discounts',
434
- 'edit_published_shop_orders',
435
- 'edit_published_shop_payments',
436
- 'edit_shop_coupon_terms',
437
- 'edit_shop_coupons',
438
- 'edit_shop_discounts',
439
- 'edit_shop_discount_terms',
440
- 'edit_shop_order_terms',
441
- 'edit_shop_orders',
442
- 'edit_shop_payments',
443
- 'edit_shop_payment_terms',
444
- 'export_shop_payments',
445
- 'export_shop_reports',
446
- 'import_shop_discounts',
447
- 'import_shop_payments',
448
- 'manage_product_terms',
449
- 'manage_shop_coupon_terms',
450
- 'manage_shop_discounts',
451
- 'manage_shop_discount_terms',
452
- 'manage_shop_payment_terms',
453
- 'manage_shop_order_terms',
454
- 'manage_shop_settings',
455
- 'manage_woocommerce',
456
- 'publish_products',
457
- 'publish_shop_coupons',
458
- 'publish_shop_discounts',
459
- 'publish_shop_orders',
460
- 'publish_shop_payments',
461
- 'read_private_products',
462
- 'read_private_shop_coupons',
463
- 'read_private_shop_discounts',
464
- 'read_private_shop_payments',
465
- 'read_private_shop_orders',
466
- 'view_admin_dashboard',
467
- 'view_shop_discount_stats',
468
- 'view_shop_payment_stats',
469
- 'view_shop_reports',
470
- 'view_shop_sensitive_data',
471
- 'view_woocommerce_reports',
472
- )
473
  );
474
  }
475
  $plugin_caps = apply_filters('cme_plugin_capabilities', $plugin_caps);
@@ -488,7 +631,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
488
  $tab_id = "cme-cap-type-tables-invalid";
489
  $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
490
  $tab_caption = esc_html__( 'Invalid Capabilities', 'capsman-enhanced' );
491
- echo '<li id="cme_tab_invalid_caps" data-slug="invalid" data-content="cme-cap-type-tables-' . esc_attr($tab_id) . '" class="' . esc_attr($tab_active) . '" style="display:none;">' . esc_html($tab_caption) . '</li>';
492
 
493
  $tab_id = "cme-cap-type-tables-additional";
494
  $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
@@ -503,23 +646,11 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
503
  foreach( array_keys($cap_properties) as $cap_type ) {
504
 
505
  foreach( array_keys($defined) as $item_type ) {
506
- if ( ( 'delete' == $cap_type ) && ( 'taxonomy' == $item_type ) ) {
507
- if ( defined('OLD_PRESSPERMIT_ACTIVE') ) {
508
- continue;
509
- }
510
-
511
- $any_term_deletion_caps = false;
512
- foreach( array_keys($defined['taxonomy']) as $_tax ) {
513
- if ( isset( $defined['taxonomy'][$_tax]->cap->delete_terms ) && ( 'manage_categories' != $defined['taxonomy'][$_tax]->cap->delete_terms ) && ! in_array( $_tax, $unfiltered['taxonomy'] ) ) {
514
- $any_term_deletion_caps = true;
515
- break;
516
- }
517
- }
518
 
519
- if ( ! $any_term_deletion_caps )
520
- continue;
521
- }
522
 
 
 
 
523
  if ( ! count( $cap_properties[$cap_type][$item_type] ) )
524
  continue;
525
 
@@ -582,8 +713,10 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
582
 
583
  $type_label = (defined('CME_LEGACY_MENU_NAME_LABEL') && !empty($type_obj->labels->menu_name)) ? $type_obj->labels->menu_name : $type_obj->labels->name;
584
 
585
- $row .= "<td><a class='cap_type' href='#toggle_type_caps'>" . esc_html($type_label) . '</a>';
586
- $row .= '<a href="#" class="neg-type-caps">&nbsp;x&nbsp;</a>';
 
 
587
  $row .= '</td>';
588
 
589
  $display_row = ! empty($force_distinct_ui);
@@ -659,6 +792,9 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
659
  $td_classes []= "cap-unreg";
660
  }
661
 
 
 
 
662
  $td_class = ( $td_classes ) ? implode(' ', $td_classes) : '';
663
 
664
  $row .= '<td class="' . esc_attr($td_class) . '" title="' . esc_attr($cap_title) . '"' . "><span class='cap-x'>X</span>$checkbox";
@@ -672,20 +808,28 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
672
  }
673
 
674
  if ('taxonomy' == $item_type) {
675
- for ($i = $col_count; $i < 3; $i++) {
676
  $row .= "<td></td>";
677
  }
678
  }
679
 
680
  if (!empty($type_obj->map_meta_cap) && !defined('PP_CAPABILITIES_NO_INVALID_SECTION')) {
681
  if ('type' == $item_type) {
682
- $type_metacaps[$type_obj->cap->read_post] = true;
683
- $type_metacaps[$type_obj->cap->edit_post] = isset($type_obj->cap->edit_posts) && ($type_obj->cap->edit_post != $type_obj->cap->edit_posts);
684
- $type_metacaps[$type_obj->cap->delete_post] = isset($type_obj->cap->delete_posts) && ($type_obj->cap->delete_post != $type_obj->cap->delete_posts);
685
-
 
 
 
 
686
  } elseif ('taxonomy' == $item_type && !empty($type_obj->cap->edit_term) && !empty($type_obj->cap->delete_term)) {
687
- $type_metacaps[$type_obj->cap->edit_term] = true;
688
- $type_metacaps[$type_obj->cap->delete_term] = true;
 
 
 
 
689
  }
690
  }
691
  }
@@ -721,15 +865,21 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
721
  $type_caps = apply_filters('publishpress_caps_manager_typecaps', $type_caps);
722
 
723
  // clicking on post type name toggles corresponding checkbox selections
724
- // caps: other
725
 
726
- $tab_id = "cme-cap-type-tables-other";
727
- $div_display = ($tab_id == $active_tab_id) ? 'block' : 'none';
728
- ?>
729
- <div id="<?php echo esc_attr($tab_id);?>" style="display:<?php echo esc_attr($div_display);?>">
730
- <?php
731
 
732
- echo '<h3>' . esc_html__( 'WordPress Core Capabilities', 'capsman-enhanced' ) . '</h3>';
 
 
 
 
 
 
 
 
 
 
733
 
734
  echo '<div class="ppc-filter-wrapper">';
735
  echo '<input type="text" class="regular-text ppc-filter-text" placeholder="' . esc_attr__('Filter by capability', 'capsman-enhanced') . '">';
@@ -737,7 +887,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
737
  echo '</div>';
738
  echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
739
 
740
- echo '<table class="widefat fixed striped form-table cme-checklist">';
741
 
742
  $centinel_ = true;
743
  $checks_per_row = get_option( 'cme_form-rows', 1 );
@@ -746,18 +896,20 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
746
  ?>
747
  <tr class="cme-bulk-select">
748
  <td colspan="<?php echo (int) $checks_per_row;?>">
749
- <input type="checkbox" class="cme-check-all" autocomplete="off" title="<?php esc_attr_e('check / uncheck all', 'capsman-enhanced');?>"> <span><?php _e('Capability Name', 'capsman-enhanced');?></span>
750
  <span style="float:right">
751
  &nbsp;&nbsp;<a class="cme-neg-all" href="#" title="<?php esc_attr_e('negate all (storing as disabled capabilities)', 'capsman-enhanced');?>">X</a> <a class="cme-switch-all" href="#" title="<?php esc_attr_e('negate none (add/remove all capabilities normally)', 'capsman-enhanced');?>">X</a>
752
  </span>
753
  </td>
754
  </tr>
755
-
756
  <?php
757
- $core_caps = _cme_core_caps();
758
- foreach( array_keys($core_caps) as $cap_name ) {
759
  $cap_name = sanitize_key($cap_name);
760
 
 
 
 
 
761
  if ( ! $is_administrator && ! current_user_can($cap_name) )
762
  continue;
763
 
@@ -786,43 +938,20 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
786
 
787
  $disabled = '';
788
  $checked = checked(1, ! empty($rcaps[$cap_name]), false );
789
- $lock_capability = false;
790
  $cap_title = $title_text;
791
-
792
- if ( 'read' == $cap_name ) {
793
- if ( ! empty( $block_read_removal ) ) {
794
- // prevent the read capability from being removed from a core role, but don't force it to be added
795
- if ( $checked || apply_filters( 'pp_caps_force_capability_storage', false, 'read', $default ) ) {
796
- if ( apply_filters( 'pp_caps_lock_capability', true, 'read', $default ) ) {
797
- $lock_capability = true;
798
- $class .= ' cap-locked';
799
- $disabled = ' disabled ';
800
- if ( 'administrator' != $this->current ) {
801
- $cap_title = __('Lockout Prevention: To remove read capability, first remove WordPress admin / editing capabilities, or add "dashboard_lockout_ok" capability', 'capsman-enhanced' );
802
- }
803
- }
804
- }
805
- }
806
- }
807
-
808
  ?>
809
- <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($cap_title);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" autocomplete="off" value="1" <?php echo esc_attr($checked) . esc_attr($disabled);?> />
810
  <span>
811
  <?php
812
  echo esc_html(str_replace( '_', ' ', $cap_name));
813
  ?>
814
- </span></label><a href="#" class="neg-cap">&nbsp;x&nbsp;</a>
815
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
816
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
817
  <?php endif; ?>
818
  </td>
819
 
820
  <?php
821
-
822
- if ( $lock_capability ) {
823
- echo '<input type="hidden" name="caps[' . esc_attr($cap_name) . ']" value="1" />';
824
- }
825
-
826
  ++$i;
827
  }
828
 
@@ -847,6 +976,52 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
847
  </td>
848
  </tr>
849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
850
  </table>
851
  </div>
852
 
@@ -875,7 +1050,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
875
  echo '</div>';
876
  echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
877
 
878
- echo '<table class="widefat fixed striped form-table cme-checklist">';
879
 
880
  $centinel_ = true;
881
  $checks_per_row = get_option( 'cme_form-rows', 1 );
@@ -894,7 +1069,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
894
  foreach( array_keys($_plugin_caps) as $cap_name ) {
895
  $cap_name = sanitize_key($cap_name);
896
 
897
- if ( isset( $type_caps[$cap_name] ) || isset($core_caps[$cap_name]) || isset($type_metacaps[$cap_name]) ) {
898
  continue;
899
  }
900
 
@@ -928,12 +1103,12 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
928
  $checked = checked(1, ! empty($rcaps[$cap_name]), false );
929
  $cap_title = $title_text;
930
  ?>
931
- <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($cap_title);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" autocomplete="off" value="1" <?php echo esc_attr($checked) . esc_attr($disabled);?> />
932
  <span>
933
  <?php
934
  echo esc_html(str_replace( '_', ' ', $cap_name));
935
  ?>
936
- </span></label><a href="#" class="neg-cap">&nbsp;x&nbsp;</a>
937
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
938
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
939
  <?php endif; ?>
@@ -978,25 +1153,17 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
978
  echo '<h3 class="cme-cap-section">' . esc_html__( 'Invalid Capabilities', 'capsman-enhanced' ) . '</h3>';
979
  ?>
980
 
981
- <script type="text/javascript">
982
- /* <![CDATA[ */
983
- jQuery(document).ready( function($) {
984
- $('#cme_tab_invalid_caps').show();
985
- });
986
- /* ]]> */
987
- </script>
988
-
989
  <div>
990
  <span class="cme-subtext">
991
- <?php esc_html_e('The following entries have no effect. Please assign desired capabilities in the Read / Edit / Delete grid above.', 'capsman-enhanced');?>
992
  </span>
993
  </div>
994
 
995
- <table class="widefat fixed striped form-table cme-checklist">
996
  <tr>
997
  <?php
998
  $i = 0; $first_row = true;
999
-
1000
  foreach( $all_capabilities as $cap_name ) {
1001
  if ( ! isset($this->capabilities[$cap_name]) )
1002
  $this->capabilities[$cap_name] = str_replace( '_', ' ', $cap_name );
@@ -1029,13 +1196,14 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1029
 
1030
  $disabled = '';
1031
  $checked = checked(1, ! empty($rcaps[$cap_name]), false );
 
1032
  ?>
1033
- <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($title_text);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" autocomplete="off" value="1" <?php echo esc_attr($checked) . esc_attr($disabled);?> />
1034
  <span>
1035
  <?php
1036
  echo esc_html(str_replace( '_', ' ', $cap ));
1037
  ?>
1038
- </span></label><a href="#" class="neg-cap">&nbsp;x&nbsp;</a>
1039
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
1040
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
1041
  <?php endif; ?>
@@ -1062,6 +1230,16 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1062
  }
1063
  ?>
1064
 
 
 
 
 
 
 
 
 
 
 
1065
  </table>
1066
  </div>
1067
  <?php
@@ -1081,7 +1259,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1081
  echo '</div>';
1082
  echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
1083
  ?>
1084
- <table class="widefat fixed striped form-table cme-checklist">
1085
 
1086
  <tr class="cme-bulk-select">
1087
  <td colspan="<?php echo (int) $checks_per_row;?>">
@@ -1107,10 +1285,9 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1107
 
1108
  foreach ($additional_caps as $cap_name => $cap) :
1109
  $cap_name = sanitize_key($cap_name);
1110
-
1111
 
1112
  if ((isset($type_caps[$cap_name]) && !isset($type_metacaps[$cap_name]))
1113
- || isset($core_caps[$cap_name])
1114
  || (isset($type_metacaps[$cap_name]) && !empty($rcaps[$cap_name])) ) {
1115
  continue;
1116
  }
@@ -1168,12 +1345,12 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1168
  }
1169
  }
1170
  ?>
1171
- <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($title_text);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" autocomplete="off" value="1" <?php echo esc_attr($checked) . ' ' . esc_attr($disabled);?> />
1172
  <span>
1173
  <?php
1174
  echo esc_html(str_replace( '_', ' ', $cap ));
1175
  ?>
1176
- </span></label><a href="#" class="neg-cap">&nbsp;x&nbsp;</a>
1177
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
1178
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
1179
  <?php endif; ?>
@@ -1344,7 +1521,7 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1344
  <input type="hidden" name="action" value="update" />
1345
  <input type="hidden" name="current" value="<?php echo esc_attr($default); ?>" />
1346
 
1347
- <?php
1348
  $save_caption = (in_array(sanitize_key(get_locale()), ['en_EN', 'en_US'])) ? 'Save Capabilities' : __('Save Changes', 'capsman-enhanced');
1349
  ?>
1350
  <input type="submit" name="SaveRole" value="<?php echo esc_attr($save_caption);?>" class="button-primary" /> &nbsp;
@@ -1364,7 +1541,9 @@ if( defined('PRESSPERMIT_ACTIVE') ) {
1364
  restore an earlier version of your roles and capabilities.', 'capsman-enhanced' )
1365
  ),
1366
  admin_url( 'admin.php?page=pp-capabilities-backup' ),
1367
- __( 'Go to the Backup feature', 'capsman-enhanced' )
 
 
1368
  );
1369
  ?>
1370
 
199
  $cap_properties['edit']['type'][]= 'edit_others_posts';
200
  $cap_properties['edit']['type'] = array_merge( $cap_properties['edit']['type'], array( 'publish_posts', 'edit_published_posts', 'edit_private_posts' ) );
201
 
 
 
 
 
 
202
  $cap_properties['delete']['type'] = array( 'delete_posts', 'delete_others_posts' );
203
  $cap_properties['delete']['type'] = array_merge( $cap_properties['delete']['type'], array( 'delete_published_posts', 'delete_private_posts' ) );
204
 
 
 
 
 
205
 
206
  $cap_properties['read']['type'] = array( 'read_private_posts' );
207
+
208
+ $cap_properties['taxonomies']['taxonomy'] = array( 'manage_terms', 'edit_terms', 'assign_terms', 'delete_terms' );
209
 
210
  $stati = get_post_stati( array( 'internal' => false ) );
211
 
213
  '' => __( '&nbsp;', 'capsman-enhanced' ),
214
  'read' => __( 'Reading', 'capsman-enhanced' ),
215
  'edit' => __( 'Editing', 'capsman-enhanced' ),
216
+ 'delete' => __( 'Deletion', 'capsman-enhanced' ),
217
+ 'taxonomies' => __( 'Taxonomies', 'capsman-enhanced' ),
218
  );
219
 
220
  $cap_tips = array(
293
  if ($extra_tabs = apply_filters('pp_capabilities_extra_post_capability_tabs', [])) {
294
  foreach($extra_tabs as $tab_slug => $tab_caption) {
295
  $tab_slug = esc_attr($tab_slug);
296
+
297
  $tab_id = "cme-cap-type-tables-{$tab_slug}";
298
  $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
299
 
303
  }
304
  }
305
 
306
+ //grouped capabilities
307
+ $grouped_caps = [];
308
+ $grouped_caps_lists = [];
309
+
310
+ //add media related caps
311
+ $grouped_caps['Media'] = [
312
+ 'edit_files',
313
+ 'upload_files',
314
+ 'unfiltered_upload',
315
+ ];
316
+ $grouped_caps_lists = array_merge($grouped_caps_lists, $grouped_caps['Media']);
317
+
318
+ //add comments related caps
319
+ $grouped_caps['Comments'] = [
320
+ 'moderate_comments'
321
+ ];
322
+ if (isset($rcaps['edit_comment'])) {
323
+ $type_metacaps['edit_comment'] = 1;
324
+ }
325
+ $grouped_caps_lists = array_merge($grouped_caps_lists, $grouped_caps['Comments']);
326
+
327
+ //add users related caps
328
+ $grouped_caps['Users'] = [
329
+ 'add_users',
330
+ 'create_users',
331
+ 'delete_users',
332
+ 'edit_users',
333
+ 'list_users',
334
+ 'promote_users',
335
+ 'remove_users',
336
+ ];
337
+ $grouped_caps_lists = array_merge($grouped_caps_lists, $grouped_caps['Users']);
338
+
339
+ //add admin options related caps
340
+ $grouped_caps['Admin'] = [
341
+ 'manage_options',
342
+ 'edit_dashboard',
343
+ 'export',
344
+ 'import',
345
+ 'read',
346
+ 'update_core',
347
+ 'unfiltered_html',
348
+ ];
349
+ $grouped_caps_lists = array_merge($grouped_caps_lists, $grouped_caps['Admin']);
350
+
351
+ //add themes related caps
352
+ $grouped_caps['Themes'] = [
353
+ 'delete_themes',
354
+ 'edit_themes',
355
+ 'install_themes',
356
+ 'switch_themes',
357
+ 'update_themes',
358
+ 'edit_theme_options',
359
+ 'manage_links',
360
+ ];
361
+ $grouped_caps_lists = array_merge($grouped_caps_lists, $grouped_caps['Themes']);
362
+
363
+ //add plugin related caps
364
+ $grouped_caps['Plugins'] = [
365
+ 'activate_plugins',
366
+ 'delete_plugins',
367
+ 'edit_plugins',
368
+ 'install_plugins',
369
+ 'update_plugins',
370
+ ];
371
+ $grouped_caps_lists = array_merge($grouped_caps_lists, $grouped_caps['Plugins']);
372
+
373
+ $grouped_caps = apply_filters('cme_grouped_capabilities', $grouped_caps);
374
+
375
+ foreach($grouped_caps as $grouped_title => $__grouped_caps) {
376
+ $grouped_title = esc_html($grouped_title);
377
+
378
+ $tab_slug = str_replace(' ', '-', strtolower(sanitize_title($grouped_title)));
379
+ $tab_id = 'cme-cap-type-tables-' . $tab_slug;
380
+ $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
381
 
382
+ echo '<li data-slug="' . esc_attr($tab_slug) . '" data-content="' . esc_attr($tab_id) . '" class="' . esc_attr($tab_active) . '">'
383
+ . esc_html(str_replace('_', ' ', $grouped_title)) .
384
+ '</li>';
385
+ }
386
 
387
  // caps: plugins
388
  $plugin_caps = [];
 
 
 
 
 
 
 
 
 
 
 
 
389
 
390
  //PublishPress Capabilities Capabilities
391
  $plugin_caps['PublishPress Capabilities'] = apply_filters('cme_publishpress_capabilities_capabilities',
392
+ [
393
+ 'manage_capabilities',
394
+ ]
395
  );
396
 
397
+ if (defined('PUBLISHPRESS_VERSION')) {
398
+ $plugin_caps['PublishPress'] = apply_filters('cme_publishpress_capabilities',
399
+ [
400
+ 'edit_metadata',
401
+ 'edit_post_subscriptions',
402
+ 'pp_manage_roles',
403
+ 'pp_set_notification_channel',
404
+ 'pp_view_calendar',
405
+ 'pp_view_content_overview',
406
+ ]
407
+ );
408
+ }
409
+
410
  if (defined('PUBLISHPRESS_MULTIPLE_AUTHORS_VERSION')) {
411
+ if ($_caps = apply_filters('cme_multiple_authors_capabilities', [])) {
412
  $plugin_caps['PublishPress Authors'] = $_caps;
413
  }
414
  }
415
 
416
  if (defined('PRESSPERMIT_VERSION')) {
417
  $plugin_caps['PublishPress Permissions'] = apply_filters('cme_presspermit_capabilities',
418
+ [
419
+ 'edit_own_attachments',
420
+ 'list_others_unattached_files',
421
+ 'pp_administer_content',
422
+ 'pp_assign_roles',
423
+ 'pp_associate_any_page',
424
+ 'pp_create_groups',
425
+ 'pp_create_network_groups',
426
+ 'pp_define_moderation',
427
+ 'pp_define_post_status',
428
+ 'pp_define_privacy',
429
+ 'pp_delete_groups',
430
+ 'pp_edit_groups',
431
+ 'pp_exempt_edit_circle',
432
+ 'pp_exempt_read_circle',
433
+ 'pp_force_quick_edit',
434
+ 'pp_list_all_files',
435
+ 'pp_manage_capabilities',
436
+ 'pp_manage_members',
437
+ 'pp_manage_network_members',
438
+ 'pp_manage_settings',
439
+ 'pp_moderate_any',
440
+ 'pp_set_associate_exceptions',
441
+ 'pp_set_edit_exceptions',
442
+ 'pp_set_read_exceptions',
443
+ 'pp_set_revise_exceptions',
444
+ 'pp_set_term_assign_exceptions',
445
+ 'pp_set_term_associate_exceptions',
446
+ 'pp_set_term_manage_exceptions',
447
+ 'pp_unfiltered',
448
+ 'set_posts_status',
449
+ ]
450
+ );
451
+ }
452
+
453
+ if (defined('GF_PLUGIN_DIR_PATH')) {
454
+ $plugin_caps['Gravity Forms'] = apply_filters('cme_gravityforms_capabilities',
455
+ [
456
+ 'gravityforms_create_form',
457
+ 'gravityforms_delete_forms',
458
+ 'gravityforms_edit_forms',
459
+ 'gravityforms_preview_forms',
460
+ 'gravityforms_view_entries',
461
+ 'gravityforms_edit_entries',
462
+ 'gravityforms_delete_entries',
463
+ 'gravityforms_view_entry_notes',
464
+ 'gravityforms_edit_entry_notes',
465
+ 'gravityforms_export_entries',
466
+ 'gravityforms_view_settings',
467
+ 'gravityforms_edit_settings',
468
+ 'gravityforms_view_updates',
469
+ 'gravityforms_view_addons',
470
+ 'gravityforms_system_status',
471
+ 'gravityforms_uninstall',
472
+ 'gravityforms_logging',
473
+ 'gravityforms_api_settings',
474
+ ]
475
+ );
476
+ }
477
+
478
+ if (defined('WPML_PLUGIN_FILE')) {
479
+ $plugin_caps['WPML'] = apply_filters('cme_wpml_capabilities',
480
+ [
481
+ 'wpml_manage_translation_management',
482
+ 'wpml_manage_languages',
483
+ 'wpml_manage_translation_options',
484
+ 'wpml_manage_troubleshooting',
485
+ 'wpml_manage_taxonomy_translation',
486
+ 'wpml_manage_wp_menus_sync',
487
+ 'wpml_manage_translation_analytics',
488
+ 'wpml_manage_string_translation',
489
+ 'wpml_manage_sticky_links',
490
+ 'wpml_manage_navigation',
491
+ 'wpml_manage_theme_and_plugin_localization',
492
+ 'wpml_manage_media_translation',
493
+ 'wpml_manage_support',
494
+ 'wpml_manage_woocommerce_multilingual',
495
+ 'wpml_operate_woocommerce_multilingual',
496
+ ]
497
+ );
498
+ }
499
+
500
+ if (defined('WS_FORM_VERSION')) {
501
+ $plugin_caps['WS Form'] = apply_filters('cme_wsform_capabilities',
502
+ [
503
+ 'create_form',
504
+ 'delete_form',
505
+ 'edit_form',
506
+ 'export_form',
507
+ 'import_form',
508
+ 'publish_form',
509
+ 'read_form',
510
+ 'delete_submission',
511
+ 'edit_submission',
512
+ 'export_submission',
513
+ 'read_submission',
514
+ 'manage_options_wsform',
515
+ ]
516
+ );
517
+ }
518
+
519
+ if (defined('STAGS_VERSION')) {
520
+ $plugin_caps['TaxoPress'] = apply_filters('cme_taxopress_capabilities',
521
+ [
522
+ 'simple_tags',
523
+ 'admin_simple_tags'
524
+ ]
525
  );
526
  }
527
 
528
  if (defined('WC_PLUGIN_FILE')) {
529
  $plugin_caps['WooCommerce'] = apply_filters('cme_woocommerce_capabilities',
530
+ [
531
+ 'assign_product_terms',
532
+ 'assign_shop_coupon_terms',
533
+ 'assign_shop_discount_terms',
534
+ 'assign_shop_order_terms',
535
+ 'assign_shop_payment_terms',
536
+ 'create_shop_orders',
537
+ 'delete_others_products',
538
+ 'delete_others_shop_coupons',
539
+ 'delete_others_shop_discounts',
540
+ 'delete_others_shop_orders',
541
+ 'delete_others_shop_payments',
542
+ 'delete_private_products',
543
+ 'delete_private_shop_coupons',
544
+ 'delete_private_shop_orders',
545
+ 'delete_private_shop_discounts',
546
+ 'delete_private_shop_payments',
547
+ 'delete_product_terms',
548
+ 'delete_products',
549
+ 'delete_published_products',
550
+ 'delete_published_shop_coupons',
551
+ 'delete_published_shop_discounts',
552
+ 'delete_published_shop_orders',
553
+ 'delete_published_shop_payments',
554
+ 'delete_shop_coupons',
555
+ 'delete_shop_coupon_terms',
556
+ 'delete_shop_discount_terms',
557
+ 'delete_shop_discounts',
558
+ 'delete_shop_order_terms',
559
+ 'delete_shop_orders',
560
+ 'delete_shop_payments',
561
+ 'delete_shop_payment_terms',
562
+ 'edit_others_products',
563
+ 'edit_others_shop_coupons',
564
+ 'edit_others_shop_discounts',
565
+ 'edit_others_shop_orders',
566
+ 'edit_others_shop_payments',
567
+ 'edit_private_products',
568
+ 'edit_private_shop_coupons',
569
+ 'edit_private_shop_discounts',
570
+ 'edit_private_shop_orders',
571
+ 'edit_private_shop_payments',
572
+ 'edit_product_terms',
573
+ 'edit_products',
574
+ 'edit_published_products',
575
+ 'edit_published_shop_coupons',
576
+ 'edit_published_shop_discounts',
577
+ 'edit_published_shop_orders',
578
+ 'edit_published_shop_payments',
579
+ 'edit_shop_coupon_terms',
580
+ 'edit_shop_coupons',
581
+ 'edit_shop_discounts',
582
+ 'edit_shop_discount_terms',
583
+ 'edit_shop_order_terms',
584
+ 'edit_shop_orders',
585
+ 'edit_shop_payments',
586
+ 'edit_shop_payment_terms',
587
+ 'export_shop_payments',
588
+ 'export_shop_reports',
589
+ 'import_shop_discounts',
590
+ 'import_shop_payments',
591
+ 'manage_product_terms',
592
+ 'manage_shop_coupon_terms',
593
+ 'manage_shop_discounts',
594
+ 'manage_shop_discount_terms',
595
+ 'manage_shop_payment_terms',
596
+ 'manage_shop_order_terms',
597
+ 'manage_shop_settings',
598
+ 'manage_woocommerce',
599
+ 'publish_products',
600
+ 'publish_shop_coupons',
601
+ 'publish_shop_discounts',
602
+ 'publish_shop_orders',
603
+ 'publish_shop_payments',
604
+ 'read_private_products',
605
+ 'read_private_shop_coupons',
606
+ 'read_private_shop_discounts',
607
+ 'read_private_shop_payments',
608
+ 'read_private_shop_orders',
609
+ 'view_admin_dashboard',
610
+ 'view_shop_discount_stats',
611
+ 'view_shop_payment_stats',
612
+ 'view_shop_reports',
613
+ 'view_shop_sensitive_data',
614
+ 'view_woocommerce_reports',
615
+ ]
616
  );
617
  }
618
  $plugin_caps = apply_filters('cme_plugin_capabilities', $plugin_caps);
631
  $tab_id = "cme-cap-type-tables-invalid";
632
  $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
633
  $tab_caption = esc_html__( 'Invalid Capabilities', 'capsman-enhanced' );
634
+ echo '<li id="cme_tab_invalid_caps" data-slug="invalid" data-content="' . esc_attr($tab_id) . '" class="' . esc_attr($tab_active) . '" style="display:none;">' . esc_html($tab_caption) . '</li>';
635
 
636
  $tab_id = "cme-cap-type-tables-additional";
637
  $tab_active = ($tab_id == $active_tab_id) ? $ppc_tab_active : '';
646
  foreach( array_keys($cap_properties) as $cap_type ) {
647
 
648
  foreach( array_keys($defined) as $item_type ) {
 
 
 
 
 
 
 
 
 
 
 
 
649
 
 
 
 
650
 
651
+ if (!isset($cap_properties[$cap_type][$item_type])) {
652
+ continue;
653
+ }
654
  if ( ! count( $cap_properties[$cap_type][$item_type] ) )
655
  continue;
656
 
713
 
714
  $type_label = (defined('CME_LEGACY_MENU_NAME_LABEL') && !empty($type_obj->labels->menu_name)) ? $type_obj->labels->menu_name : $type_obj->labels->name;
715
 
716
+ $row .= "<td>";
717
+ $row .= '<input type="checkbox" class="pp-row-action-rotate excluded-input"> &nbsp;';
718
+ $row .= "<a class='cap_type' href='#toggle_type_caps'>" . esc_html($type_label) . '</a>';
719
+ $row .= '<a style="display: none;" href="#" class="neg-type-caps">&nbsp;x&nbsp;</a>';
720
  $row .= '</td>';
721
 
722
  $display_row = ! empty($force_distinct_ui);
792
  $td_classes []= "cap-unreg";
793
  }
794
 
795
+ $td_classes[] = 'capability-checkbox-rotate';
796
+ $td_classes[] = $cap_name;
797
+
798
  $td_class = ( $td_classes ) ? implode(' ', $td_classes) : '';
799
 
800
  $row .= '<td class="' . esc_attr($td_class) . '" title="' . esc_attr($cap_title) . '"' . "><span class='cap-x'>X</span>$checkbox";
808
  }
809
 
810
  if ('taxonomy' == $item_type) {
811
+ for ($i = $col_count; $i < 4; $i++) {
812
  $row .= "<td></td>";
813
  }
814
  }
815
 
816
  if (!empty($type_obj->map_meta_cap) && !defined('PP_CAPABILITIES_NO_INVALID_SECTION')) {
817
  if ('type' == $item_type) {
818
+ if (!in_array($type_obj->cap->read_post, $grouped_caps_lists)
819
+ && !in_array($type_obj->cap->edit_post, $grouped_caps_lists)
820
+ && !in_array($type_obj->cap->delete_post, $grouped_caps_lists)
821
+ ) {
822
+ $type_metacaps[$type_obj->cap->read_post] = true;
823
+ $type_metacaps[$type_obj->cap->edit_post] = isset($type_obj->cap->edit_posts) && ($type_obj->cap->edit_post != $type_obj->cap->edit_posts);
824
+ $type_metacaps[$type_obj->cap->delete_post] = isset($type_obj->cap->delete_posts) && ($type_obj->cap->delete_post != $type_obj->cap->delete_posts);
825
+ }
826
  } elseif ('taxonomy' == $item_type && !empty($type_obj->cap->edit_term) && !empty($type_obj->cap->delete_term)) {
827
+ if (!in_array($type_obj->cap->edit_term, $grouped_caps_lists)
828
+ && !in_array($type_obj->cap->delete_term, $grouped_caps_lists)
829
+ ) {
830
+ $type_metacaps[$type_obj->cap->edit_term] = true;
831
+ $type_metacaps[$type_obj->cap->delete_term] = true;
832
+ }
833
  }
834
  }
835
  }
865
  $type_caps = apply_filters('publishpress_caps_manager_typecaps', $type_caps);
866
 
867
  // clicking on post type name toggles corresponding checkbox selections
 
868
 
869
+ // caps: grouped
870
+ $grouped_caps = apply_filters('cme_grouped_capabilities', $grouped_caps);
 
 
 
871
 
872
+ foreach($grouped_caps as $grouped_title => $__grouped_caps) {
873
+ $grouped_title = esc_html($grouped_title);
874
+
875
+ $_grouped_caps = array_fill_keys($__grouped_caps, true);
876
+
877
+ $tab_id = 'cme-cap-type-tables-' . esc_attr(str_replace( ' ', '-', strtolower($grouped_title)));
878
+ $div_display = ($tab_id == $active_tab_id) ? 'block' : 'none';
879
+
880
+ echo '<div id="' . esc_attr($tab_id) . '" style="display:' . esc_attr($div_display) . '">';
881
+
882
+ echo '<h3 class="cme-cap-section">' . esc_html(str_replace('_', ' ', $grouped_title)) . '</h3>';
883
 
884
  echo '<div class="ppc-filter-wrapper">';
885
  echo '<input type="text" class="regular-text ppc-filter-text" placeholder="' . esc_attr__('Filter by capability', 'capsman-enhanced') . '">';
887
  echo '</div>';
888
  echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
889
 
890
+ echo '<table class="widefat fixed striped form-table cme-checklist single-checkbox-table">';
891
 
892
  $centinel_ = true;
893
  $checks_per_row = get_option( 'cme_form-rows', 1 );
896
  ?>
897
  <tr class="cme-bulk-select">
898
  <td colspan="<?php echo (int) $checks_per_row;?>">
899
+ <input type="checkbox" class="cme-check-all" title="<?php esc_attr_e('check / uncheck all', 'capsman-enhanced');?>"> <span><?php _e('Capability Name', 'capsman-enhanced');?></span>
900
  <span style="float:right">
901
  &nbsp;&nbsp;<a class="cme-neg-all" href="#" title="<?php esc_attr_e('negate all (storing as disabled capabilities)', 'capsman-enhanced');?>">X</a> <a class="cme-switch-all" href="#" title="<?php esc_attr_e('negate none (add/remove all capabilities normally)', 'capsman-enhanced');?>">X</a>
902
  </span>
903
  </td>
904
  </tr>
 
905
  <?php
906
+ foreach( array_keys($_grouped_caps) as $cap_name ) {
 
907
  $cap_name = sanitize_key($cap_name);
908
 
909
+ if ( isset( $type_caps[$cap_name] ) || isset($type_metacaps[$cap_name]) ) {
910
+ continue;
911
+ }
912
+
913
  if ( ! $is_administrator && ! current_user_can($cap_name) )
914
  continue;
915
 
938
 
939
  $disabled = '';
940
  $checked = checked(1, ! empty($rcaps[$cap_name]), false );
 
941
  $cap_title = $title_text;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
942
  ?>
943
+ <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($cap_title);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" class="pp-single-action-rotate" autocomplete="off" value="1" <?php echo esc_attr($checked) . esc_attr($disabled);?> />
944
  <span>
945
  <?php
946
  echo esc_html(str_replace( '_', ' ', $cap_name));
947
  ?>
948
+ </span></label><a href="#" class="neg-cap" style="visibility: hidden;">&nbsp;x&nbsp;</a>
949
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
950
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
951
  <?php endif; ?>
952
  </td>
953
 
954
  <?php
 
 
 
 
 
955
  ++$i;
956
  }
957
 
976
  </td>
977
  </tr>
978
 
979
+ </table>
980
+ </div>
981
+ <?php
982
+ }
983
+
984
+ // caps: other
985
+
986
+ $tab_id = "cme-cap-type-tables-other";
987
+ $div_display = ($tab_id == $active_tab_id) ? 'block' : 'none';
988
+ ?>
989
+ <div id="<?php echo esc_attr($tab_id);?>" style="display:<?php echo esc_attr($div_display);?>">
990
+ <?php
991
+
992
+ echo '<h3>' . esc_html__( 'WordPress Core Capabilities', 'capsman-enhanced' ) . '</h3>';
993
+
994
+ echo '<div class="ppc-filter-wrapper">';
995
+ echo '<input type="text" class="regular-text ppc-filter-text" placeholder="' . esc_attr__('Filter by capability', 'capsman-enhanced') . '">';
996
+ echo ' <button class="button secondary-button ppc-filter-text-reset" type="button">' . esc_html__('Clear', 'capsman-enhanced') . '</button>';
997
+ echo '</div>';
998
+ echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
999
+
1000
+ echo '<table class="widefat fixed striped form-table cme-checklist">';
1001
+
1002
+ $centinel_ = true;
1003
+ $checks_per_row = get_option( 'cme_form-rows', 1 );
1004
+ $i = 0; $first_row = true;
1005
+
1006
+ ?>
1007
+ <tr class="cme-bulk-select">
1008
+ <td colspan="<?php echo (int) $checks_per_row;?>">
1009
+ <input type="checkbox" class="cme-check-all" autocomplete="off" title="<?php esc_attr_e('check / uncheck all', 'capsman-enhanced');?>"> <span><?php _e('Capability Name', 'capsman-enhanced');?></span>
1010
+ <span style="float:right">
1011
+ &nbsp;&nbsp;<a class="cme-neg-all" href="#" title="<?php esc_attr_e('negate all (storing as disabled capabilities)', 'capsman-enhanced');?>">X</a> <a class="cme-switch-all" href="#" title="<?php esc_attr_e('negate none (add/remove all capabilities normally)', 'capsman-enhanced');?>">X</a>
1012
+ </span>
1013
+ </td>
1014
+ </tr>
1015
+
1016
+ <tr class="cme-bulk-select">
1017
+ <td colspan="<?php echo (int) $checks_per_row;?>">
1018
+ <input type="checkbox" class="cme-check-all" autocomplete="off" title="<?php esc_attr_e('check / uncheck all', 'capsman-enhanced');?>"> <span><?php _e('Capability Name', 'capsman-enhanced');?></span>
1019
+ <span style="float:right">
1020
+ &nbsp;&nbsp;<a class="cme-neg-all" href="#" title="<?php esc_attr_e('negate all (storing as disabled capabilities)', 'capsman-enhanced');?>">X</a> <a class="cme-switch-all" href="#" title="<?php esc_attr_e('negate none (add/remove all capabilities normally)', 'capsman-enhanced');?>">X</a>
1021
+ </span>
1022
+ </td>
1023
+ </tr>
1024
+
1025
  </table>
1026
  </div>
1027
 
1050
  echo '</div>';
1051
  echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
1052
 
1053
+ echo '<table class="widefat fixed striped form-table cme-checklist single-checkbox-table">';
1054
 
1055
  $centinel_ = true;
1056
  $checks_per_row = get_option( 'cme_form-rows', 1 );
1069
  foreach( array_keys($_plugin_caps) as $cap_name ) {
1070
  $cap_name = sanitize_key($cap_name);
1071
 
1072
+ if ( isset( $type_caps[$cap_name] ) || in_array($cap_name, $grouped_caps_lists) || isset($type_metacaps[$cap_name]) ) {
1073
  continue;
1074
  }
1075
 
1103
  $checked = checked(1, ! empty($rcaps[$cap_name]), false );
1104
  $cap_title = $title_text;
1105
  ?>
1106
+ <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($cap_title);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" class="pp-single-action-rotate" autocomplete="off" value="1" <?php echo esc_attr($checked) . esc_attr($disabled);?> />
1107
  <span>
1108
  <?php
1109
  echo esc_html(str_replace( '_', ' ', $cap_name));
1110
  ?>
1111
+ </span></label><a href="#" class="neg-cap" style="visibility: hidden;">&nbsp;x&nbsp;</a>
1112
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
1113
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
1114
  <?php endif; ?>
1153
  echo '<h3 class="cme-cap-section">' . esc_html__( 'Invalid Capabilities', 'capsman-enhanced' ) . '</h3>';
1154
  ?>
1155
 
 
 
 
 
 
 
 
 
1156
  <div>
1157
  <span class="cme-subtext">
1158
+ <?php esc_html_e('The following entries have no effect. Please assign desired capabilities on the Editing / Deletion / Reading tabs.', 'capsman-enhanced');?>
1159
  </span>
1160
  </div>
1161
 
1162
+ <table class="widefat fixed striped form-table cme-checklist single-checkbox-table">
1163
  <tr>
1164
  <?php
1165
  $i = 0; $first_row = true;
1166
+ $invalid_caps_capabilities = [];
1167
  foreach( $all_capabilities as $cap_name ) {
1168
  if ( ! isset($this->capabilities[$cap_name]) )
1169
  $this->capabilities[$cap_name] = str_replace( '_', ' ', $cap_name );
1196
 
1197
  $disabled = '';
1198
  $checked = checked(1, ! empty($rcaps[$cap_name]), false );
1199
+ $invalid_caps_capabilities[] = $cap_name;
1200
  ?>
1201
+ <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($title_text);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" class="pp-single-action-rotate" autocomplete="off" value="1" <?php echo esc_attr($checked) . esc_attr($disabled);?> />
1202
  <span>
1203
  <?php
1204
  echo esc_html(str_replace( '_', ' ', $cap ));
1205
  ?>
1206
+ </span></label><a href="#" class="neg-cap" style="visibility: hidden;">&nbsp;x&nbsp;</a>
1207
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
1208
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
1209
  <?php endif; ?>
1230
  }
1231
  ?>
1232
 
1233
+ <?php if (!empty($invalid_caps_capabilities)) : ?>
1234
+ <script type="text/javascript">
1235
+ /* <![CDATA[ */
1236
+ jQuery(document).ready( function($) {
1237
+ $('#cme_tab_invalid_caps').show();
1238
+ });
1239
+ /* ]]> */
1240
+ </script>
1241
+ <?php endif; ?>
1242
+
1243
  </table>
1244
  </div>
1245
  <?php
1259
  echo '</div>';
1260
  echo '<div class="ppc-filter-no-results" style="display:none;">' . esc_html__( 'No results found. Please try again with a different word.', 'capsman-enhanced' ) . '</div>';
1261
  ?>
1262
+ <table class="widefat fixed striped form-table cme-checklist single-checkbox-table">
1263
 
1264
  <tr class="cme-bulk-select">
1265
  <td colspan="<?php echo (int) $checks_per_row;?>">
1285
 
1286
  foreach ($additional_caps as $cap_name => $cap) :
1287
  $cap_name = sanitize_key($cap_name);
 
1288
 
1289
  if ((isset($type_caps[$cap_name]) && !isset($type_metacaps[$cap_name]))
1290
+ || in_array($cap_name, $grouped_caps_lists)
1291
  || (isset($type_metacaps[$cap_name]) && !empty($rcaps[$cap_name])) ) {
1292
  continue;
1293
  }
1345
  }
1346
  }
1347
  ?>
1348
+ <td class="<?php echo esc_attr($class); ?>"><span class="cap-x">X</span><label title="<?php echo esc_attr($title_text);?>"><input type="checkbox" name="caps[<?php echo esc_attr($cap_name); ?>]" class="pp-single-action-rotate" autocomplete="off" value="1" <?php echo esc_attr($checked) . ' ' . esc_attr($disabled);?> />
1349
  <span>
1350
  <?php
1351
  echo esc_html(str_replace( '_', ' ', $cap ));
1352
  ?>
1353
+ </span></label><a href="#" class="neg-cap" style="visibility: hidden;">&nbsp;x&nbsp;</a>
1354
  <?php if ( false !== strpos( $class, 'cap-neg' ) ) :?>
1355
  <input type="hidden" class="cme-negation-input" name="caps[<?php echo esc_attr($cap_name); ?>]" value="" />
1356
  <?php endif; ?>
1521
  <input type="hidden" name="action" value="update" />
1522
  <input type="hidden" name="current" value="<?php echo esc_attr($default); ?>" />
1523
 
1524
+ <?php
1525
  $save_caption = (in_array(sanitize_key(get_locale()), ['en_EN', 'en_US'])) ? 'Save Capabilities' : __('Save Changes', 'capsman-enhanced');
1526
  ?>
1527
  <input type="submit" name="SaveRole" value="<?php echo esc_attr($save_caption);?>" class="button-primary" /> &nbsp;
1541
  restore an earlier version of your roles and capabilities.', 'capsman-enhanced' )
1542
  ),
1543
  admin_url( 'admin.php?page=pp-capabilities-backup' ),
1544
+ __( 'Go to the Backup feature', 'capsman-enhanced' ),
1545
+ '',
1546
+ 'button'
1547
  );
1548
  ?>
1549
 
includes/backup.php CHANGED
@@ -56,17 +56,14 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
56
  <tr>
57
  <td class="content">
58
 
59
- <dl id="ppcb-tab-backup" style="display:none;">
60
- <dt><?php esc_html_e('Backup Roles and Capabilities', 'capsman-enhanced'); ?></dt>
61
- <dd>
62
  <p class="description">
63
  <?php
64
  $max_auto_backups = (defined('CME_AUTOBACKUPS')) ? (int) CME_AUTOBACKUPS : 20;
65
  printf(esc_html__('PublishPress Capabilities automatically creates a backup on installation and whenever you save changes. The initial backup and last %d auto-backups are kept.', 'capsman-enhanced'), esc_attr($max_auto_backups));
66
  ?>
67
- </p>
68
-
69
- <p class="description">
70
  <?php esc_html_e('A backup created on this screen replaces any previous manual backups, but is never automatically replaced.', 'capsman-enhanced');?>
71
  </p>
72
 
@@ -75,9 +72,9 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
75
  value="<?php esc_attr_e('Manual Backup', 'capsman-enhanced') ?>"
76
  class="button-primary"/>
77
  </div>
78
- </dd>
79
 
80
- </dl>
81
 
82
  <?php
83
  $listed_manual_backup = false;
@@ -85,21 +82,19 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
85
  $last_caption = ($backup_datestamp) ? sprintf(esc_html__('Last Manual Backup - %s', 'capsman-enhanced'), date('j M Y, g:i a', $backup_datestamp)) : esc_html__('Last Backup', 'capsman-enhanced');
86
  ?>
87
 
88
- <dl id="ppcb-tab-restore">
89
- <dt><?php esc_html_e('Restore Previous Roles and Capabilities', 'capsman-enhanced'); ?></dt>
90
- <dd>
91
  <p class="description">
92
  <?php esc_html_e('PublishPress Capabilities automatically creates a backup on installation and whenever you save changes.', 'capsman-enhanced');?>
93
- </p>
94
-
95
- <p class="description">
96
  <?php esc_html_e('On this screen, you can restore an earlier version of your roles and capabilities.', 'capsman-enhanced');?>
97
  </p>
98
 
 
 
99
  <table width='100%' class="form-table">
100
  <tr>
101
- <th scope="row"><?php esc_html_e('Available Backups:', 'capsman-enhanced'); ?></th>
102
- <td>
103
  <div id="cme_select_restore_div">
104
  <ul id="cme_select_restore">
105
  <?php foreach ($auto_backups as $row):
@@ -151,9 +146,7 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
151
  value="<?php esc_attr_e('Restore Selected Roles', 'capsman-enhanced') ?>"
152
  class="button-primary"/>
153
 
154
- <div class="cme-selected-backup-caption">
155
- <span class="cme-selected-backup-caption cme-subtext"></span>
156
- </div>
157
  </div>
158
  </td>
159
 
@@ -184,7 +177,7 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
184
  $date_caption = str_replace(' ', ', ', $date_caption);
185
  $date_caption = str_replace(', am', ' am', $date_caption);
186
  $date_caption = str_replace(', pm', ' pm', $date_caption);
187
-
188
  $option_name = sanitize_key($row->option_name);
189
  $backups[$option_name] = "Auto-backup from " . $date_caption;
190
  }
@@ -280,93 +273,73 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
280
  </td>
281
  </tr>
282
  </table>
283
- </dd>
284
- </dl>
285
 
286
 
287
- <dl id="ppcb-tab-reset" style="display:none;">
288
- <dt><?php if (!in_array(get_locale(), ['en_EN', 'en_US'])) esc_html_e('Reset WordPress Defaults', 'capsman-enhanced'); else echo 'Reset Roles to WordPress Defaults'; ?></dt>
289
- <dd>
290
- <p><strong><span class="pp-caps-warning"><?php esc_html_e('WARNING:', 'capsman-enhanced'); ?></span> <?php if (!in_array(get_locale(), ['en_EN', 'en_US'])) esc_html_e('Reseting default Roles and Capabilities will set them to the WordPress install defaults.', 'capsman-enhanced'); else echo 'This will delete and/or modify stored role definitions.'; ?>
291
- </strong><br/>
292
- <br/>
293
  <?php
294
  esc_html_e('If you have installed any plugin that adds new roles or capabilities, these will be lost.', 'capsman-enhanced') ?>
295
- <br/>
296
- <strong><?php if (!in_array(get_locale(), ['en_EN', 'en_US'])) esc_html_e('It is recommended to use this only as a last resource!', 'capsman-enhanced'); else echo('It is recommended to use this only as a last resort!'); ?></strong>
297
  </p>
298
  <p><a class="ak-delete button-primary"
299
  title="<?php echo esc_attr__('Reset Roles and Capabilities to WordPress defaults', 'capsman-enhanced') ?>"
300
  href="<?php echo esc_url_raw(wp_nonce_url("admin.php?page=pp-capabilities-backup&amp;action=reset-defaults", 'capsman-reset-defaults')); ?>"
301
  onclick="if ( confirm('<?php echo esc_js(__("You are about to reset Roles and Capabilities to WordPress defaults.\n 'Cancel' to stop, 'OK' to reset.", 'capsman-enhanced')); ?>') ) { return true;}return false;"><?php esc_html_e('Reset to WordPress defaults', 'capsman-enhanced') ?></a>
302
 
303
- </dd>
304
- </dl>
305
-
306
-
307
- <dl id="ppcb-tab-import-export" style="display:none;">
308
- <dt><?php
309
- esc_html_e('Export / Import', 'capsman-enhanced'); ?></dt>
310
- <dd>
311
-
312
- <div class="metabox-holder">
313
- <div class="postbox">
314
- <h3><span><?php esc_html_e('Export Settings', 'capsman-enhanced'); ?></span></h3>
315
- <div class="inside">
316
- <p><?php esc_html_e('Export the plugin settings for this site as a .json file. This allows you to easily import the configuration into another site.', 'capsman-enhanced'); ?></p>
317
- <ul>
 
 
 
 
 
318
  <li>
319
- <input id="pp_capabilities_export_roles" name="pp_capabilities_export_section[]" type="checkbox" value="user_roles" checked />
320
- <label for="pp_capabilities_export_roles">
321
- <?php esc_html_e('Roles and Capabilities', 'capsman-enhanced'); ?>
322
- </label>
323
  </li>
324
- <?php
325
- $backup_sections = pp_capabilities_backup_sections();
326
- foreach($backup_sections as $backup_key => $backup_section){
327
- ?>
328
- <li>
329
- <input id="pp_capabilities_export_<?php echo esc_attr($backup_key); ?>" name="pp_capabilities_export_section[]" type="checkbox" value="<?php echo esc_attr($backup_key); ?>" checked />
330
- <label for="pp_capabilities_export_<?php echo esc_attr($backup_key); ?>"> <?php esc_html_e($backup_section['label']); ?> </label>
331
- </li>
332
- <?php
333
- }
334
- ?>
335
- </ul>
336
- <p>
337
- <input type="submit" name="export_backup"
338
- value="<?php esc_attr_e('Export', 'capsman-enhanced') ?>"
339
- class="button-primary"/>
340
- </p>
341
- </div>
342
- </div>
343
-
344
- <div class="postbox">
345
- <h3><span><?php esc_html_e('Import Settings', 'capsman-enhanced'); ?></span></h3>
346
- <div class="inside">
347
- <p><strong><span class="pp-caps-warning"><?php esc_html_e('WARNING:', 'capsman-enhanced'); ?></span> <?php esc_html_e('Please make a \'Manual Backup\' in the backup tab to enable backup restore in case anything goes wrong.', 'capsman-enhanced'); ?></p>
348
-
349
- <p><?php esc_html_e('Import the plugin settings from a .json file. This file can be obtained by exporting the settings on another site using the form above.', 'capsman-enhanced'); ?></p>
350
-
351
- <p><?php esc_html_e('Before importing, we recommend using the "Backup" tab to create a backup of your current settings.', 'capsman-enhanced'); ?></p>
352
-
353
- <br />
354
-
355
- <p>
356
- <input type="file" name="import_file"/>
357
- </p>
358
- <p>
359
- <input type="submit" name="import_backup"
360
- value="<?php esc_attr_e('Import', 'capsman-enhanced') ?>"
361
- class="button-primary"/>
362
- </p>
363
- </div>
364
- </div>
365
  </div>
366
-
367
- </dd>
368
- </dl>
369
-
 
 
 
 
 
 
 
 
 
 
 
 
370
 
371
  </td>
372
  </tr>
@@ -402,7 +375,8 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
402
  $('#cme_select_restore input[name="select_restore"]').on('change click', function () {
403
  $('div.cme-show-backup').hide();
404
 
405
- $('span.cme-selected-backup-caption').html($(this).next('label').html());
 
406
 
407
  var selected_val = $(this).val();
408
 
@@ -435,7 +409,7 @@ $auto_backups = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb-
435
  $('#publishpress-capability-backup-tabs').children('li').filter('.nav-tab-active').removeClass('nav-tab-active');
436
  $(this).addClass('nav-tab-active');
437
 
438
- $('dl[id^="ppcb-"]').hide();
439
  $($(this).find('a').first().attr('href')).show();
440
  });
441
 
56
  <tr>
57
  <td class="content">
58
 
59
+ <div id="ppcb-tab-backup" class="postbox ppc-postbox" style="display:none;">
60
+ <h2><?php esc_html_e('Backup Roles and Capabilities', 'capsman-enhanced'); ?></h2>
61
+ <div>
62
  <p class="description">
63
  <?php
64
  $max_auto_backups = (defined('CME_AUTOBACKUPS')) ? (int) CME_AUTOBACKUPS : 20;
65
  printf(esc_html__('PublishPress Capabilities automatically creates a backup on installation and whenever you save changes. The initial backup and last %d auto-backups are kept.', 'capsman-enhanced'), esc_attr($max_auto_backups));
66
  ?>
 
 
 
67
  <?php esc_html_e('A backup created on this screen replaces any previous manual backups, but is never automatically replaced.', 'capsman-enhanced');?>
68
  </p>
69
 
72
  value="<?php esc_attr_e('Manual Backup', 'capsman-enhanced') ?>"
73
  class="button-primary"/>
74
  </div>
75
+ </div>
76
 
77
+ </div>
78
 
79
  <?php
80
  $listed_manual_backup = false;
82
  $last_caption = ($backup_datestamp) ? sprintf(esc_html__('Last Manual Backup - %s', 'capsman-enhanced'), date('j M Y, g:i a', $backup_datestamp)) : esc_html__('Last Backup', 'capsman-enhanced');
83
  ?>
84
 
85
+ <div id="ppcb-tab-restore" class="postbox ppc-postbox">
86
+ <h2><?php esc_html_e('Restore Previous Roles and Capabilities', 'capsman-enhanced'); ?></h2>
87
+ <div>
88
  <p class="description">
89
  <?php esc_html_e('PublishPress Capabilities automatically creates a backup on installation and whenever you save changes.', 'capsman-enhanced');?>
 
 
 
90
  <?php esc_html_e('On this screen, you can restore an earlier version of your roles and capabilities.', 'capsman-enhanced');?>
91
  </p>
92
 
93
+ <p style="margin-top:15px;"><strong><?php esc_html_e('Available Backups:', 'capsman-enhanced'); ?></strong></p>
94
+
95
  <table width='100%' class="form-table">
96
  <tr>
97
+ <td class="cme-backup-list">
 
98
  <div id="cme_select_restore_div">
99
  <ul id="cme_select_restore">
100
  <?php foreach ($auto_backups as $row):
146
  value="<?php esc_attr_e('Restore Selected Roles', 'capsman-enhanced') ?>"
147
  class="button-primary"/>
148
 
149
+ <div class="cme-selected-backup-caption"></div>
 
 
150
  </div>
151
  </td>
152
 
177
  $date_caption = str_replace(' ', ', ', $date_caption);
178
  $date_caption = str_replace(', am', ' am', $date_caption);
179
  $date_caption = str_replace(', pm', ' pm', $date_caption);
180
+
181
  $option_name = sanitize_key($row->option_name);
182
  $backups[$option_name] = "Auto-backup from " . $date_caption;
183
  }
273
  </td>
274
  </tr>
275
  </table>
276
+ </div>
277
+ </div>
278
 
279
 
280
+ <div id="ppcb-tab-reset" class="postbox ppc-postbox" style="display:none;">
281
+ <h2><?php if (!in_array(get_locale(), ['en_EN', 'en_US'])) esc_html_e('Reset WordPress Defaults', 'capsman-enhanced'); else echo 'Reset Roles to WordPress Defaults'; ?></h2>
282
+ <div>
283
+ <p><span class="pp-caps-warning"><?php esc_html_e('Warning:', 'capsman-enhanced'); ?></span> <?php if (!in_array(get_locale(), ['en_EN', 'en_US'])) esc_html_e('Reseting default Roles and Capabilities will set them to the WordPress install defaults.', 'capsman-enhanced'); else echo 'This will delete and/or modify stored role definitions.'; ?>
 
 
284
  <?php
285
  esc_html_e('If you have installed any plugin that adds new roles or capabilities, these will be lost.', 'capsman-enhanced') ?>
286
+ <?php if (!in_array(get_locale(), ['en_EN', 'en_US'])) esc_html_e('It is recommended to use this only as a last resource!', 'capsman-enhanced'); else echo('It is recommended to use this only as a last resort!'); ?>
 
287
  </p>
288
  <p><a class="ak-delete button-primary"
289
  title="<?php echo esc_attr__('Reset Roles and Capabilities to WordPress defaults', 'capsman-enhanced') ?>"
290
  href="<?php echo esc_url_raw(wp_nonce_url("admin.php?page=pp-capabilities-backup&amp;action=reset-defaults", 'capsman-reset-defaults')); ?>"
291
  onclick="if ( confirm('<?php echo esc_js(__("You are about to reset Roles and Capabilities to WordPress defaults.\n 'Cancel' to stop, 'OK' to reset.", 'capsman-enhanced')); ?>') ) { return true;}return false;"><?php esc_html_e('Reset to WordPress defaults', 'capsman-enhanced') ?></a>
292
 
293
+ </div>
294
+ </div>
295
+
296
+
297
+ <div id="ppcb-tab-import-export" style="display:none;">
298
+ <div class="postbox ppc-postbox">
299
+ <h2><?php esc_html_e('Export Settings', 'capsman-enhanced'); ?></h2>
300
+ <div>
301
+ <p><?php esc_html_e('Export the plugin settings for this site as a .json file. This allows you to easily import the configuration into another site.', 'capsman-enhanced'); ?></p>
302
+ <ul>
303
+ <li>
304
+ <input id="pp_capabilities_export_roles" name="pp_capabilities_export_section[]" type="checkbox" value="user_roles" checked />
305
+ <label for="pp_capabilities_export_roles">
306
+ <?php esc_html_e('Roles and Capabilities', 'capsman-enhanced'); ?>
307
+ </label>
308
+ </li>
309
+ <?php
310
+ $backup_sections = pp_capabilities_backup_sections();
311
+ foreach($backup_sections as $backup_key => $backup_section){
312
+ ?>
313
  <li>
314
+ <input id="pp_capabilities_export_<?php echo esc_attr($backup_key); ?>" name="pp_capabilities_export_section[]" type="checkbox" value="<?php echo esc_attr($backup_key); ?>" checked />
315
+ <label for="pp_capabilities_export_<?php echo esc_attr($backup_key); ?>"> <?php esc_html_e($backup_section['label']); ?> </label>
 
 
316
  </li>
317
+ <?php
318
+ }
319
+ ?>
320
+ </ul>
321
+ <p>
322
+ <input type="submit" name="export_backup"
323
+ value="<?php esc_attr_e('Export', 'capsman-enhanced') ?>"
324
+ class="button-primary"/>
325
+ </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  </div>
327
+ </div>
328
+ <div class="postbox ppc-postbox">
329
+ <h2><?php esc_html_e('Import Settings', 'capsman-enhanced'); ?></h2>
330
+ <p><span class="pp-caps-warning"><?php esc_html_e('Warning:', 'capsman-enhanced'); ?></span> <?php esc_html_e('Please make a \'Manual Backup\' in the backup tab to enable backup restore in case anything goes wrong.', 'capsman-enhanced'); ?>
331
+ <?php esc_html_e('Import the plugin settings from a .json file. This file can be obtained by exporting the settings on another site using the form above.', 'capsman-enhanced'); ?>
332
+ <?php esc_html_e('Before importing, we recommend using the "Backup" tab to create a backup of your current settings.', 'capsman-enhanced'); ?></p>
333
+ <p>
334
+ <input type="file" name="import_file"/>
335
+ </p>
336
+ <p>
337
+ <input type="submit" name="import_backup"
338
+ value="<?php esc_attr_e('Import', 'capsman-enhanced') ?>"
339
+ class="button-primary"/>
340
+ </p>
341
+ </div>
342
+ </div>
343
 
344
  </td>
345
  </tr>
375
  $('#cme_select_restore input[name="select_restore"]').on('change click', function () {
376
  $('div.cme-show-backup').hide();
377
 
378
+ $('div.cme-selected-backup-caption').html($(this).next('label').html());
379
+ $('div.cme-selected-backup-caption').css('margin-top','30px');
380
 
381
  var selected_val = $(this).val();
382
 
409
  $('#publishpress-capability-backup-tabs').children('li').filter('.nav-tab-active').removeClass('nav-tab-active');
410
  $(this).addClass('nav-tab-active');
411
 
412
+ $('div[id^="ppcb-"]').hide();
413
  $($(this).find('a').first().attr('href')).show();
414
  });
415
 
includes/features/admin-features.php CHANGED
@@ -34,7 +34,7 @@ $admin_features_elements = PP_Capabilities_Admin_Features::elementsLayout();
34
 
35
  <div class="wrap publishpress-caps-manage pressshack-admin-wrapper pp-capability-menus-wrapper">
36
  <div id="icon-capsman-admin" class="icon32"></div>
37
- <h2><?php esc_html_e('Admin Feature Restrictions', 'capabilities-pro'); ?></h2>
38
 
39
  <form method="post" id="ppc-admin-features-form" action="admin.php?page=pp-capabilities-admin-features">
40
  <?php wp_nonce_field('pp-capabilities-admin-features'); ?>
@@ -51,7 +51,7 @@ $admin_features_elements = PP_Capabilities_Admin_Features::elementsLayout();
51
  <span class='pp-capability-role-caption'>
52
  <?php
53
  esc_html_e('Note: You are only restricting access to admin features screens. Some plugins may also add features to other areas of WordPress.',
54
- 'capabilities-pro');
55
  ?>
56
  </span>
57
  </span>
@@ -73,7 +73,7 @@ $admin_features_elements = PP_Capabilities_Admin_Features::elementsLayout();
73
  style="display: none">
74
 
75
  <input type="submit" name="admin-features-submit"
76
- value="<?php esc_attr_e('Save Changes', 'capabilities-pro') ?>"
77
  class="button-primary ppc-admin-features-submit" style="float:right"/>
78
  </div>
79
 
@@ -187,7 +187,7 @@ $admin_features_elements = PP_Capabilities_Admin_Features::elementsLayout();
187
  <?php
188
  if(isset($section_array['custom_element']) && ($section_array['custom_element'] === true)){
189
  echo esc_html($section_array['element_label']) . ' <small class="entry">(' . esc_html($section_array['element_items']). ')</small> &nbsp; '
190
- . '<span class="' . esc_attr($section_array['button_class']) . '" data-id="' . esc_attr($section_array['button_data_id']) . '"><small>(' . esc_html__('Delete', 'capabilities-pro') . ')</small></span>' . '';
191
  }else{
192
  echo esc_html($item_name);
193
  }
@@ -212,7 +212,7 @@ $admin_features_elements = PP_Capabilities_Admin_Features::elementsLayout();
212
  </div>
213
  </div>
214
  <input type="submit" name="admin-features-submit"
215
- value="<?php esc_attr_e('Save Changes', 'capabilities-pro') ?>"
216
  class="button-primary ppc-admin-features-submit"/>
217
  </td>
218
  </tr>
34
 
35
  <div class="wrap publishpress-caps-manage pressshack-admin-wrapper pp-capability-menus-wrapper">
36
  <div id="icon-capsman-admin" class="icon32"></div>
37
+ <h2><?php esc_html_e('Admin Feature Restrictions', 'capsman-enhanced'); ?></h2>
38
 
39
  <form method="post" id="ppc-admin-features-form" action="admin.php?page=pp-capabilities-admin-features">
40
  <?php wp_nonce_field('pp-capabilities-admin-features'); ?>
51
  <span class='pp-capability-role-caption'>
52
  <?php
53
  esc_html_e('Note: You are only restricting access to admin features screens. Some plugins may also add features to other areas of WordPress.',
54
+ 'capsman-enhanced');
55
  ?>
56
  </span>
57
  </span>
73
  style="display: none">
74
 
75
  <input type="submit" name="admin-features-submit"
76
+ value="<?php esc_attr_e('Save Changes', 'capsman-enhanced') ?>"
77
  class="button-primary ppc-admin-features-submit" style="float:right"/>
78
  </div>
79
 
187
  <?php
188
  if(isset($section_array['custom_element']) && ($section_array['custom_element'] === true)){
189
  echo esc_html($section_array['element_label']) . ' <small class="entry">(' . esc_html($section_array['element_items']). ')</small> &nbsp; '
190
+ . '<span class="' . esc_attr($section_array['button_class']) . '" data-id="' . esc_attr($section_array['button_data_id']) . '"><small>(' . esc_html__('Delete', 'capsman-enhanced') . ')</small></span>' . '';
191
  }else{
192
  echo esc_html($item_name);
193
  }
212
  </div>
213
  </div>
214
  <input type="submit" name="admin-features-submit"
215
+ value="<?php esc_attr_e('Save Changes', 'capsman-enhanced') ?>"
216
  class="button-primary ppc-admin-features-submit"/>
217
  </td>
218
  </tr>
includes/features/editor-features-classic.php CHANGED
@@ -14,10 +14,13 @@
14
 
15
  <tbody>
16
  <?php
 
17
  foreach ($ce_elements as $section_title => $arr) {
18
  $section_slug = strtolower(ppc_remove_non_alphanumeric_space_characters($section_title));
 
 
19
  ?>
20
- <tr class="ppc-menu-row parent-menu">
21
  <td colspan="2">
22
  <h4 class="ppc-menu-row-section"><?php echo esc_html($section_title);?></h4>
23
  <?php
@@ -40,6 +43,33 @@
40
  if (!$feature_slug) {
41
  continue;
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  ?>
44
  <tr class="ppc-menu-row parent-menu">
45
  <td class="menu-column ppc-menu-item">
@@ -50,7 +80,7 @@
50
  echo esc_html($arr_feature['element_label']) . ' <small class="entry">(' . esc_html($arr_feature['element_items']). ')</small> &nbsp; '
51
  . '<span class="' . esc_attr($arr_feature['button_class']) . '" data-id="' . esc_attr($arr_feature['button_data_id']) . '" data-parent="' . esc_attr($arr_feature['button_data_parent']) . '"><small>(' . esc_html__('Delete', 'capsman-enhanced') . ')</small></span>';
52
  }else{
53
- echo esc_html($arr_feature['label']);
54
  }
55
  ?>
56
  </strong></span>
@@ -64,6 +94,32 @@
64
  </tr>
65
  <?php
66
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
  do_action('pp_capabilities_features_classic_after_table_tr');
14
 
15
  <tbody>
16
  <?php
17
+
18
  foreach ($ce_elements as $section_title => $arr) {
19
  $section_slug = strtolower(ppc_remove_non_alphanumeric_space_characters($section_title));
20
+ //set empty feature value as true
21
+ $empty_post_type_feature[$type_obj->name][$section_slug] = 1;
22
  ?>
23
+ <tr class="ppc-menu-row parent-menu <?php esc_attr_e($type_obj->name); ?> <?php esc_attr_e($section_slug); ?>">
24
  <td colspan="2">
25
  <h4 class="ppc-menu-row-section"><?php echo esc_html($section_title);?></h4>
26
  <?php
43
  if (!$feature_slug) {
44
  continue;
45
  }
46
+
47
+ //check if post type support feature
48
+ if (isset($arr_feature['support_key'])) {
49
+ if (isset($arr_feature['support_type']) && $arr_feature['support_type'] === 'taxonomy') {
50
+ if (!in_array($arr_feature['support_key'], get_object_taxonomies($type_obj->name))) {
51
+ continue;
52
+ }
53
+ } elseif (isset($arr_feature['support_type']) && $arr_feature['support_type'] === 'metabox') {
54
+ if (!in_array($type_obj->name, $arr_feature['support_key'])) {
55
+ continue;
56
+ }
57
+ } else {
58
+ if (!post_type_supports($type_obj->name, $arr_feature['support_key'])) {
59
+ continue;
60
+ }
61
+ }
62
+ }
63
+
64
+ //unset if it has feature support
65
+ if (isset($empty_post_type_feature[$type_obj->name][$section_slug])) {
66
+ /**
67
+ * add phpcs ignore due to false alarm
68
+ * as the variable is defined in main page
69
+ */
70
+ // phpcs:ignore WordPressVIPMinimum.Variables.VariableAnalysis.UndefinedUnsetVariable
71
+ unset($empty_post_type_feature[$type_obj->name][$section_slug]);
72
+ }
73
  ?>
74
  <tr class="ppc-menu-row parent-menu">
75
  <td class="menu-column ppc-menu-item">
80
  echo esc_html($arr_feature['element_label']) . ' <small class="entry">(' . esc_html($arr_feature['element_items']). ')</small> &nbsp; '
81
  . '<span class="' . esc_attr($arr_feature['button_class']) . '" data-id="' . esc_attr($arr_feature['button_data_id']) . '" data-parent="' . esc_attr($arr_feature['button_data_parent']) . '"><small>(' . esc_html__('Delete', 'capsman-enhanced') . ')</small></span>';
82
  }else{
83
+ echo esc_html(wp_strip_all_tags($arr_feature['label']));
84
  }
85
  ?>
86
  </strong></span>
94
  </tr>
95
  <?php
96
  }
97
+ //add class to remove row list
98
+ if (isset($empty_post_type_feature[$type_obj->name][$section_slug])) {
99
+ if ($section_slug === 'metaboxes') {
100
+ //we want to leave metabox header with message
101
+ ?>
102
+ <tr class="ppc-menu-row parent-menu">
103
+ <td class="menu-column ppc-menu-item" colspan="2">
104
+ <p class="cme-subtext">
105
+ <?php printf(
106
+ esc_html__(
107
+ 'No metabox found for %1s. %2s Click here %3s to visit the %4s screen and refresh this page after to load new metabox',
108
+ 'capsman-enhanced'
109
+ ),
110
+ esc_html($type_obj->labels->singular_name),
111
+ '<a href="'. esc_url(admin_url('post-new.php?post_type='.$type_obj->name)) .'">',
112
+ '</a>',
113
+ esc_html($type_obj->labels->singular_name)
114
+ ); ?>
115
+ </p>
116
+ </td>
117
+ </tr>
118
+ <?php
119
+ } else {
120
+ $empty_post_type_feature_class[] = '.editor-features-classic .parent-menu.' . $type_obj->name . '.' . $section_slug . '';
121
+ }
122
+ }
123
  }
124
 
125
  do_action('pp_capabilities_features_classic_after_table_tr');
includes/features/editor-features-gutenberg.php CHANGED
@@ -16,8 +16,10 @@
16
  <?php
17
  foreach ($gutenberg_elements as $section_title => $arr) {
18
  $section_slug = strtolower(ppc_remove_non_alphanumeric_space_characters($section_title));
 
 
19
  ?>
20
- <tr class="ppc-menu-row parent-menu">
21
  <td colspan="2">
22
  <h4 class="ppc-menu-row-section"><?php echo esc_html($section_title);?></h4>
23
  <?php
@@ -39,6 +41,32 @@
39
  foreach ($arr as $feature_slug => $arr_feature) {
40
  $feature_slug = esc_attr($feature_slug);
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  ?>
43
  <tr class="ppc-menu-row parent-menu">
44
  <td class="menu-column ppc-menu-item">
@@ -49,7 +77,7 @@
49
  echo esc_html($arr_feature['element_label']) . ' <small class="entry">(' . esc_html($arr_feature['element_items']). ')</small> &nbsp; '
50
  . '<span class="' . esc_attr($arr_feature['button_class']) . '" data-id="' . esc_attr($arr_feature['button_data_id']) . '" data-parent="' . esc_attr($arr_feature['button_data_parent']) . '"><small>(' . esc_html__('Delete', 'capsman-enhanced') . ')</small></span>';
51
  }else{
52
- echo esc_html($arr_feature['label']);
53
  }
54
  ?>
55
  </strong></span>
@@ -63,6 +91,32 @@
63
  </tr>
64
  <?php
65
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
 
68
  do_action('pp_capabilities_features_gutenberg_after_table_tr');
16
  <?php
17
  foreach ($gutenberg_elements as $section_title => $arr) {
18
  $section_slug = strtolower(ppc_remove_non_alphanumeric_space_characters($section_title));
19
+ //set empty feature value as true
20
+ $empty_post_type_feature[$type_obj->name][$section_slug] = 1;
21
  ?>
22
+ <tr class="ppc-menu-row parent-menu <?php esc_attr_e($type_obj->name); ?> <?php esc_attr_e($section_slug); ?>">
23
  <td colspan="2">
24
  <h4 class="ppc-menu-row-section"><?php echo esc_html($section_title);?></h4>
25
  <?php
41
  foreach ($arr as $feature_slug => $arr_feature) {
42
  $feature_slug = esc_attr($feature_slug);
43
 
44
+ //check if post type support feature
45
+ if (isset($arr_feature['support_key'])) {
46
+ if (isset($arr_feature['support_type']) && $arr_feature['support_type'] === 'taxonomy') {
47
+ if (!in_array($arr_feature['support_key'], get_object_taxonomies($type_obj->name))) {
48
+ continue;
49
+ }
50
+ } elseif (isset($arr_feature['support_type']) && $arr_feature['support_type'] === 'metabox') {
51
+ if (!in_array($type_obj->name, $arr_feature['support_key'])) {
52
+ continue;
53
+ }
54
+ } else {
55
+ if (!post_type_supports($type_obj->name, $arr_feature['support_key'])) {
56
+ continue;
57
+ }
58
+ }
59
+ }
60
+
61
+ //unset if it has feature support
62
+ if (isset($empty_post_type_feature[$type_obj->name][$section_slug])) {
63
+ /**
64
+ * add phpcs ignore due to false alarm
65
+ * as the variable is defined in main page
66
+ */
67
+ // phpcs:ignore WordPressVIPMinimum.Variables.VariableAnalysis.UndefinedUnsetVariable
68
+ unset($empty_post_type_feature[$type_obj->name][$section_slug]);
69
+ }
70
  ?>
71
  <tr class="ppc-menu-row parent-menu">
72
  <td class="menu-column ppc-menu-item">
77
  echo esc_html($arr_feature['element_label']) . ' <small class="entry">(' . esc_html($arr_feature['element_items']). ')</small> &nbsp; '
78
  . '<span class="' . esc_attr($arr_feature['button_class']) . '" data-id="' . esc_attr($arr_feature['button_data_id']) . '" data-parent="' . esc_attr($arr_feature['button_data_parent']) . '"><small>(' . esc_html__('Delete', 'capsman-enhanced') . ')</small></span>';
79
  }else{
80
+ echo esc_html(wp_strip_all_tags($arr_feature['label']));
81
  }
82
  ?>
83
  </strong></span>
91
  </tr>
92
  <?php
93
  }
94
+ //add class to remove row list
95
+ if (isset($empty_post_type_feature[$type_obj->name][$section_slug])) {
96
+ if ($section_slug === 'metaboxes') {
97
+ //we want to leave metabox header with message
98
+ ?>
99
+ <tr class="ppc-menu-row parent-menu">
100
+ <td class="menu-column ppc-menu-item" colspan="2">
101
+ <p class="cme-subtext">
102
+ <?php printf(
103
+ esc_html__(
104
+ 'No metabox found for %1s. %2s Click here %3s to visit the %4s screen and refresh this page after to load new metabox',
105
+ 'capsman-enhanced'
106
+ ),
107
+ esc_html($type_obj->labels->singular_name),
108
+ '<a href="'. esc_url(admin_url('post-new.php?post_type='.$type_obj->name)) .'">',
109
+ '</a>',
110
+ esc_html($type_obj->labels->singular_name)
111
+ ); ?>
112
+ </p>
113
+ </td>
114
+ </tr>
115
+ <?php
116
+ } else {
117
+ $empty_post_type_feature_class[] = '.editor-features-gutenberg .parent-menu.' . $type_obj->name . '.' . $section_slug . '';
118
+ }
119
+ }
120
  }
121
 
122
  do_action('pp_capabilities_features_gutenberg_after_table_tr');
includes/features/editor-features.php CHANGED
@@ -64,7 +64,7 @@ $active_tab_text = is_object($active_tab_type_obj)
64
  $active_tab_type_obj->labels->singular_name : '';
65
  ?>
66
 
67
- <div class="wrap publishpress-caps-manage pressshack-admin-wrapper pp-capability-menus-wrapper">
68
  <div id="icon-capsman-admin" class="icon32"></div>
69
  <h2><?php esc_html_e('Editor Feature Restriction', 'capsman-enhanced'); ?></h2>
70
 
@@ -180,6 +180,9 @@ $active_tab_text = is_object($active_tab_type_obj)
180
 
181
  <div class="ppc-capabilities-content">
182
  <?php
 
 
 
183
  foreach($def_post_types as $type_name) {
184
  $type_obj = get_post_type_object($type_name);
185
  $active_style = ($type_name === $active_tab_slug) ? '' : 'display:none;';
@@ -207,14 +210,16 @@ $active_tab_text = is_object($active_tab_type_obj)
207
  </div>
208
 
209
 
210
- <input type="submit" name="editor-features-all-submit"
211
- value="<?php esc_attr_e('Save for all Post Types', 'capsman-enhanced') ?>"
212
- class="button-secondary ppc-editor-features-submit" style="float:right" />
 
213
 
214
- <input type="submit" name="editor-features-submit"
215
- value="<?php esc_attr_e(sprintf(esc_html__('Save %s Restrictions', 'capsman-enhanced'), esc_html($active_tab_text))); ?>"
216
- class="button-primary ppc-editor-features-submit" style="float:right"
217
- data-current_cpt="<?php esc_attr_e(sprintf(esc_html__('Save %s Restrictions', 'capsman-enhanced'), 'post_type')); ?>" />
 
218
 
219
  </td>
220
  </tr>
@@ -249,6 +254,12 @@ $active_tab_text = is_object($active_tab_type_obj)
249
  </div>
250
 
251
  <style>
 
 
 
 
 
 
252
  span.menu-item-link {
253
  webkit-user-select: none; /* Safari */
254
  -moz-user-select: none; /* Firefox */
@@ -273,9 +284,6 @@ $active_tab_text = is_object($active_tab_type_obj)
273
  input[name="editor-features-all-submit"].ppc-editor-features-submit {
274
  margin-left: 10px;
275
  }
276
- .pp-capability-menus-wrap {
277
- border: 1px solid #c3c4c7;
278
- }
279
  .pp-columns-wrapper .nav-tab-wrapper,
280
  .pp-columns-wrapper .postbox {
281
  border: unset;
@@ -283,6 +291,12 @@ $active_tab_text = is_object($active_tab_type_obj)
283
  .pp-capability-menus {
284
  overflow: initial;
285
  }
 
 
 
 
 
 
286
  </style>
287
 
288
  <script type="text/javascript">
64
  $active_tab_type_obj->labels->singular_name : '';
65
  ?>
66
 
67
+ <div class="wrap publishpress-caps-manage pressshack-admin-wrapper pp-capability-menus-wrapper editor-features">
68
  <div id="icon-capsman-admin" class="icon32"></div>
69
  <h2><?php esc_html_e('Editor Feature Restriction', 'capsman-enhanced'); ?></h2>
70
 
180
 
181
  <div class="ppc-capabilities-content">
182
  <?php
183
+ //we want to remove empty header for row without feature for post typr
184
+ $empty_post_type_feature = [];
185
+ $empty_post_type_feature_class = [];
186
  foreach($def_post_types as $type_name) {
187
  $type_obj = get_post_type_object($type_name);
188
  $active_style = ($type_name === $active_tab_slug) ? '' : 'display:none;';
210
  </div>
211
 
212
 
213
+ <div class="editor-features-footer-meta">
214
+ <input type="submit" name="editor-features-all-submit"
215
+ value="<?php esc_attr_e('Save for all Post Types', 'capsman-enhanced') ?>"
216
+ class="button-secondary ppc-editor-features-submit" style="float:right" />
217
 
218
+ <input type="submit" name="editor-features-submit"
219
+ value="<?php esc_attr_e(sprintf(esc_html__('Save %s Restrictions', 'capsman-enhanced'), esc_html($active_tab_text))); ?>"
220
+ class="button-primary ppc-editor-features-submit" style="float:right"
221
+ data-current_cpt="<?php esc_attr_e(sprintf(esc_html__('Save %s Restrictions', 'capsman-enhanced'), 'post_type')); ?>" />
222
+ </div
223
 
224
  </td>
225
  </tr>
254
  </div>
255
 
256
  <style>
257
+ <?php
258
+ if (!empty($empty_post_type_feature_class)) {
259
+ echo esc_html(implode(', ', $empty_post_type_feature_class));
260
+ echo esc_html('{display: none !important}');
261
+ }
262
+ ?>
263
  span.menu-item-link {
264
  webkit-user-select: none; /* Safari */
265
  -moz-user-select: none; /* Firefox */
284
  input[name="editor-features-all-submit"].ppc-editor-features-submit {
285
  margin-left: 10px;
286
  }
 
 
 
287
  .pp-columns-wrapper .nav-tab-wrapper,
288
  .pp-columns-wrapper .postbox {
289
  border: unset;
291
  .pp-capability-menus {
292
  overflow: initial;
293
  }
294
+ .pp-capability-menus-wrapper.editor-features #pp-capability-menus-general #ppc-capabilities-wrapper {
295
+ border: 1px solid #c3c4c7;
296
+ }
297
+ .pp-capability-menus-wrapper.editor-features #ppc-capabilities-wrapper .ppc-capabilities-content > div {
298
+ padding-bottom: 0 !important;
299
+ }
300
  </style>
301
 
302
  <script type="text/javascript">
includes/features/restrict-editor-features.php CHANGED
@@ -43,13 +43,35 @@ class PP_Capabilities_Post_Features {
43
  ];
44
 
45
  $elements[esc_html__('Editor', 'capsman-enhanced')] = [
46
- '.page-title-action' => ['label' => esc_html__('Add New', 'capsman-enhanced')],
47
- '#title' => ['label' => esc_html__('Title', 'capsman-enhanced'), 'elements' => '#titlediv, #title, #titlewrap'],
48
- '#postdivrich' => ['label' => esc_html__('Editor', 'capsman-enhanced')],
49
- '#pageslugdiv' => ['label' => esc_html__('Permalink', 'capsman-enhanced')],
50
- '#media_buttons' => ['label' => esc_html__('Media Buttons (all)', 'capsman-enhanced'), 'elements' => '#media-buttons, #wp-content-media-buttons'],
51
- '#html_editor_button' => ['label' => esc_html__('HTML Editor Button', 'capsman-enhanced'),'elements' => '#editor-toolbar #edButtonHTML, #quicktags, #content-html, .wp-switch-editor.switch-html'],
52
- '#wp-word-count' => ['label' => esc_html__('Word count', 'capsman-enhanced')],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  ];
54
 
55
  $elements[esc_html__('Publish Box', 'capsman-enhanced')] = [
@@ -66,9 +88,24 @@ class PP_Capabilities_Post_Features {
66
  ];
67
 
68
  $elements[esc_html__('Taxonomy Boxes', 'capsman-enhanced')] = [
69
- '#category' => ['label' => esc_html__('Categories', 'capsman-enhanced'), 'elements' => '#categories, #categorydiv, #categorydivsb, th.column-categories, td.categories'],
70
- '#category-add-toggle' => ['label' => esc_html__('Add New Category', 'capsman-enhanced')],
71
- '#post_tag' => ['label' => esc_html__('Tags', 'capsman-enhanced'), 'elements' => '#tags, #tagsdiv,#tagsdivsb,#tagsdiv-post_tag, th.column-tags, td.tags'],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  ];
73
 
74
  end($elements);
@@ -76,21 +113,52 @@ class PP_Capabilities_Post_Features {
76
 
77
  foreach (get_taxonomies(['show_ui' => true], 'object') as $taxonomy => $tx_obj) {
78
  if (!in_array($taxonomy, ['category', 'post_tag', 'link_category'])) {
79
- $elements[$k]["#{$tx_obj->name}div"] = ['label' => $tx_obj->label,'elements'=>"#{$tx_obj->name}, #{$tx_obj->name}div,#{$tx_obj->name}divsb,#tagsdiv-{$tx_obj->name}, th.column-{$tx_obj->name}, td.{$tx_obj->name}"];
 
 
 
 
 
80
  }
81
  }
82
 
83
  $elements[esc_html__('Page Boxes', 'capsman-enhanced')] = [
84
- '#pageparentdiv' => ['label' => esc_html__('Page Attributes', 'capsman-enhanced')],
85
- '#parent_id' => ['label' => esc_html__('Parent', 'capsman-enhanced'), 'elements' => 'p.parent-id-label-wrapper, #parent_id'],
86
- '#page_template' => ['label' => esc_html__('Page Template', 'capsman-enhanced')],
87
- 'p.menu-order-label-wrapper' => ['label' => esc_html__('Order', 'capsman-enhanced')],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  ];
89
 
90
  $elements[esc_html__('Other Boxes', 'capsman-enhanced')] = [
91
- '#postimagediv' => ['label' => esc_html__('Featured Image', 'capsman-enhanced')],
92
- '#slug' => ['label' => esc_html__('Post Slug', 'capsman-enhanced'), 'elements' => '#slugdiv,#edit-slug-box'],
93
- '#commentstatusdiv' => ['label' => esc_html__('Discussion', 'capsman-enhanced')],
 
 
 
 
 
 
 
 
 
 
 
94
  ];
95
 
96
  end($elements);
@@ -134,11 +202,12 @@ class PP_Capabilities_Post_Features {
134
  }
135
 
136
  $elements[$k][$feature] = [
137
- 'label' => $label,
138
  'elements' => '#' . $id
139
  . ', #' . $id . 'div'
140
  . ', th.column-' . $id
141
- . ', td.' . $id
 
142
  ]; //th and td for raw in edit screen
143
  }
144
 
@@ -157,6 +226,10 @@ class PP_Capabilities_Post_Features {
157
  return;
158
  }
159
 
 
 
 
 
160
  // Only restrictions associated with this user's role(s) will be applied
161
  $role_restrictions = array_intersect_key(
162
  get_option("capsman_feature_restrict_classic_{$post_type}", []),
@@ -224,6 +297,11 @@ class PP_Capabilities_Post_Features {
224
  {
225
  $restrict_elements = [];
226
 
 
 
 
 
 
227
  // Only restrictions associated with this user's role(s) will be applied
228
  $role_restrictions = array_intersect_key(
229
  get_option("capsman_feature_restrict_{$post_type}", []),
@@ -292,7 +370,7 @@ class PP_Capabilities_Post_Features {
292
  public static function elementsLayout()
293
  {
294
  $elements = [
295
- esc_html__('Top Bar - Left', 'capabilities-pro') => [
296
  'add_block' => ['label' => esc_html__('Add block', 'capsman-enhanced'), 'elements' => '.edit-post-header-toolbar .edit-post-header-toolbar__inserter-toggle.has-icon'],
297
  'modes' => ['label' => esc_html__('Modes', 'capsman-enhanced'), 'elements' => '.edit-post-header-toolbar .components-dropdown:first-of-type'],
298
  'undo' => ['label' => esc_html__('Undo', 'capsman-enhanced'), 'elements' => '.edit-post-header-toolbar .editor-history__undo'],
@@ -301,7 +379,7 @@ class PP_Capabilities_Post_Features {
301
  'outline' => ['label' => esc_html__('Outline', 'capsman-enhanced'), 'elements' => '.edit-post-header__toolbar .edit-post-header-toolbar__list-view-toggle'],
302
  ],
303
 
304
- esc_html__('Top Bar - Right', 'capabilities-pro') => [
305
  'save_draft' => ['label' => esc_html__('Save Draft', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .components-button.editor-post-save-draft'],
306
  'switch_to_draft' => ['label' => esc_html__('Switch to draft', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .components-button.editor-post-switch-to-draft'],
307
  'preview' => ['label' => esc_html__('Preview', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .block-editor-post-preview__dropdown'],
@@ -310,17 +388,44 @@ class PP_Capabilities_Post_Features {
310
  'options' => ['label' => esc_html__('Options', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .edit-post-more-menu .components-button'],
311
  ],
312
 
313
- esc_html__('Body', 'capabilities-pro') => [
314
- 'edit_title' => ['label' => esc_html__('Edit title', 'capsman-enhanced'), 'elements' => '.wp-block.editor-post-title__block, .wp-block.editor-post-title'],
315
- 'content' => ['label' => esc_html__('Content', 'capsman-enhanced'), 'elements' => '.block-editor-block-list__layout'],
 
 
 
 
 
 
 
 
 
 
 
 
316
  ],
317
 
318
- esc_html__('Document Panel', 'capabilities-pro') => [
319
  'status_visibility' => ['label' => esc_html__('Status & visibility', 'capsman-enhanced'), 'elements' => 'post-status'],
320
- 'template' => ['label' => esc_html__('Template', 'capsman-enhanced'), 'elements' => 'template'],
 
 
 
 
 
321
  'permalink' => ['label' => esc_html__('Permalink', 'capsman-enhanced'), 'elements' => 'post-link'],
322
- 'categories' => ['label' => esc_html__('Categories', 'capsman-enhanced'), 'elements' => 'taxonomy-panel-category'],
323
- 'tags' => ['label' => esc_html__('Tags', 'capsman-enhanced'), 'elements' => 'taxonomy-panel-post_tag'],
 
 
 
 
 
 
 
 
 
 
324
  ]
325
  ];
326
 
@@ -329,18 +434,39 @@ class PP_Capabilities_Post_Features {
329
 
330
  foreach (get_taxonomies(['show_ui' => true], 'object') as $taxonomy => $tx_obj) {
331
  if (!in_array($taxonomy, ['category', 'post_tag', 'link_category'])) {
332
- $elements[$k][$tx_obj->name] = ['label' => $tx_obj->label, 'elements' => "taxonomy-panel-$taxonomy"];
 
 
 
 
 
333
  }
334
  }
335
 
336
  $elements[$k] = array_merge($elements[$k], [
337
- 'featured_image' => ['label' => esc_html__('Featured image', 'capsman-enhanced'), 'elements' => 'featured-image'],
338
- 'excerpt' => ['label' => esc_html__('Excerpt', 'capsman-enhanced'), 'elements' => 'post-excerpt'],
339
- 'discussion' => ['label' => esc_html__('Discussion', 'capsman-enhanced'), 'elements' => 'discussion-panel'],
340
- 'post_attributes' => ['label' => esc_html__('Post Attributes', 'capsman-enhanced'), 'elements' => 'page-attributes'],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  ]);
342
 
343
- $elements[esc_html__('Block Panel', 'capabilities-pro')] = [
344
  'block_panel' => ['label' => esc_html__('Block Panel', 'capsman-enhanced'), 'elements' => '.block-editor-block-inspector'],
345
  'paragraph' => ['label' => esc_html__('Paragraph', 'capsman-enhanced'), 'elements' => '.block-editor-block-card'],
346
  'typography' => ['label' => esc_html__('Typography', 'capsman-enhanced'), 'elements' => '.block-editor-block-inspector .components-panel__body:first-of-type'],
43
  ];
44
 
45
  $elements[esc_html__('Editor', 'capsman-enhanced')] = [
46
+ '.page-title-action' => [
47
+ 'label' => esc_html__('Add New', 'capsman-enhanced')
48
+ ],
49
+ '#title' => [
50
+ 'label' => esc_html__('Title', 'capsman-enhanced'),
51
+ 'elements' => '#titlediv, #title, #titlewrap',
52
+ 'support_key' => 'title'
53
+ ],
54
+ '#postdivrich' => [
55
+ 'label' => esc_html__('Editor', 'capsman-enhanced'),
56
+ 'support_key' => 'editor'
57
+ ],
58
+ '#pageslugdiv' => [
59
+ 'label' => esc_html__('Permalink', 'capsman-enhanced')
60
+ ],
61
+ '#media_buttons' => [
62
+ 'label' => esc_html__('Media Buttons (all)', 'capsman-enhanced'),
63
+ 'elements' => '#media-buttons, #wp-content-media-buttons',
64
+ 'support_key' => 'editor'
65
+ ],
66
+ '#html_editor_button' => [
67
+ 'label' => esc_html__('HTML Editor Button', 'capsman-enhanced'),
68
+ 'elements' => '#editor-toolbar #edButtonHTML, #quicktags, #content-html, .wp-switch-editor.switch-html',
69
+ 'support_key' => 'editor'
70
+ ],
71
+ '#wp-word-count' => [
72
+ 'label' => esc_html__('Word count', 'capsman-enhanced'),
73
+ 'support_key' => 'editor'
74
+ ],
75
  ];
76
 
77
  $elements[esc_html__('Publish Box', 'capsman-enhanced')] = [
88
  ];
89
 
90
  $elements[esc_html__('Taxonomy Boxes', 'capsman-enhanced')] = [
91
+ '#category' => [
92
+ 'label' => esc_html__('Categories', 'capsman-enhanced'),
93
+ 'elements' => '#categories, #categorydiv, #categorydivsb, th.column-categories, td.categories',
94
+ 'support_key' => 'category',
95
+ 'support_type' => 'taxonomy'
96
+ ],
97
+ '#category-add-toggle' => [
98
+ 'label' => esc_html__('Add New Category', 'capsman-enhanced'),
99
+ 'elements' => '#category-add-toggle',
100
+ 'support_key' => 'category',
101
+ 'support_type' => 'taxonomy'
102
+ ],
103
+ '#post_tag' => [
104
+ 'label' => esc_html__('Tags', 'capsman-enhanced'),
105
+ 'elements' => '#tags, #tagsdiv,#tagsdivsb,#tagsdiv-post_tag, th.column-tags, td.tags',
106
+ 'support_key' => 'post_tag',
107
+ 'support_type' => 'taxonomy'
108
+ ],
109
  ];
110
 
111
  end($elements);
113
 
114
  foreach (get_taxonomies(['show_ui' => true], 'object') as $taxonomy => $tx_obj) {
115
  if (!in_array($taxonomy, ['category', 'post_tag', 'link_category'])) {
116
+ $elements[$k]["#{$tx_obj->name}div"] = [
117
+ 'label' => $tx_obj->label,
118
+ 'elements' => "#{$tx_obj->name}, #{$tx_obj->name}div,#{$tx_obj->name}divsb,#tagsdiv-{$tx_obj->name}, th.column-{$tx_obj->name}, td.{$tx_obj->name}",
119
+ 'support_key' => $tx_obj->name,
120
+ 'support_type' => 'taxonomy'
121
+ ];
122
  }
123
  }
124
 
125
  $elements[esc_html__('Page Boxes', 'capsman-enhanced')] = [
126
+ '#pageparentdiv' => [
127
+ 'label' => esc_html__('Page Attributes', 'capsman-enhanced'),
128
+ 'support_key' => 'page-attributes'
129
+ ],
130
+ '#parent_id' => [
131
+ 'label' => esc_html__('Parent', 'capsman-enhanced'),
132
+ 'elements' => 'p.parent-id-label-wrapper, #parent_id',
133
+ 'support_key' => 'page-attributes'
134
+ ],
135
+ '#page_template' => [
136
+ 'label' => esc_html__('Page Template', 'capsman-enhanced'),
137
+ 'elements' => '#page_template',
138
+ 'support_key' => 'page-attributes'
139
+ ],
140
+ 'p.menu-order-label-wrapper' => [
141
+ 'label' => esc_html__('Order', 'capsman-enhanced'),
142
+ 'elements' => 'p.menu-order-label-wrapper',
143
+ 'support_key' => 'page-attributes'
144
+ ],
145
  ];
146
 
147
  $elements[esc_html__('Other Boxes', 'capsman-enhanced')] = [
148
+ '#postimagediv' => [
149
+ 'label' => esc_html__('Featured Image', 'capsman-enhanced'),
150
+ 'elements' => '#postimagediv',
151
+ 'support_key' => 'thumbnail'
152
+ ],
153
+ '#slug' => [
154
+ 'label' => esc_html__('Post Slug', 'capsman-enhanced'),
155
+ 'elements' => '#slugdiv,#edit-slug-box'
156
+ ],
157
+ '#commentstatusdiv' => [
158
+ 'label' => esc_html__('Discussion', 'capsman-enhanced'),
159
+ 'elements' => '#commentstatusdiv',
160
+ 'support_key' => 'comments'
161
+ ],
162
  ];
163
 
164
  end($elements);
202
  }
203
 
204
  $elements[$k][$feature] = [
205
+ 'label' => $label,
206
  'elements' => '#' . $id
207
  . ', #' . $id . 'div'
208
  . ', th.column-' . $id
209
+ . ', td.' . $id,
210
+ 'support_key' => $feature
211
  ]; //th and td for raw in edit screen
212
  }
213
 
226
  return;
227
  }
228
 
229
+ if (!is_array(get_option("capsman_feature_restrict_classic_{$post_type}", []))) {
230
+ return;
231
+ }
232
+
233
  // Only restrictions associated with this user's role(s) will be applied
234
  $role_restrictions = array_intersect_key(
235
  get_option("capsman_feature_restrict_classic_{$post_type}", []),
297
  {
298
  $restrict_elements = [];
299
 
300
+
301
+ if (!is_array(get_option("capsman_feature_restrict_{$post_type}", []))) {
302
+ return;
303
+ }
304
+
305
  // Only restrictions associated with this user's role(s) will be applied
306
  $role_restrictions = array_intersect_key(
307
  get_option("capsman_feature_restrict_{$post_type}", []),
370
  public static function elementsLayout()
371
  {
372
  $elements = [
373
+ esc_html__('Top Bar - Left', 'capsman-enhanced') => [
374
  'add_block' => ['label' => esc_html__('Add block', 'capsman-enhanced'), 'elements' => '.edit-post-header-toolbar .edit-post-header-toolbar__inserter-toggle.has-icon'],
375
  'modes' => ['label' => esc_html__('Modes', 'capsman-enhanced'), 'elements' => '.edit-post-header-toolbar .components-dropdown:first-of-type'],
376
  'undo' => ['label' => esc_html__('Undo', 'capsman-enhanced'), 'elements' => '.edit-post-header-toolbar .editor-history__undo'],
379
  'outline' => ['label' => esc_html__('Outline', 'capsman-enhanced'), 'elements' => '.edit-post-header__toolbar .edit-post-header-toolbar__list-view-toggle'],
380
  ],
381
 
382
+ esc_html__('Top Bar - Right', 'capsman-enhanced') => [
383
  'save_draft' => ['label' => esc_html__('Save Draft', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .components-button.editor-post-save-draft'],
384
  'switch_to_draft' => ['label' => esc_html__('Switch to draft', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .components-button.editor-post-switch-to-draft'],
385
  'preview' => ['label' => esc_html__('Preview', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .block-editor-post-preview__dropdown'],
388
  'options' => ['label' => esc_html__('Options', 'capsman-enhanced'), 'elements' => '.edit-post-header__settings .edit-post-more-menu .components-button'],
389
  ],
390
 
391
+ esc_html__('Body', 'capsman-enhanced') => [
392
+ 'edit_title' => [
393
+ 'label' => esc_html__('Edit title', 'capsman-enhanced'),
394
+ 'elements' => '.wp-block.editor-post-title__block, .wp-block.editor-post-title',
395
+ 'support_key' => 'title'
396
+ ],
397
+ 'content' => [
398
+ 'label' => esc_html__('Content', 'capsman-enhanced'),
399
+ 'elements' => '.block-editor-block-list__layout',
400
+ 'support_key' => 'editor'
401
+ ],
402
+ 'add_new_block' => [
403
+ 'label' => esc_html__('Add new block', 'capsman-enhanced'),
404
+ 'elements' => '.block-editor-inserter__toggle'
405
+ ],
406
  ],
407
 
408
+ esc_html__('Document Panel', 'capsman-enhanced') => [
409
  'status_visibility' => ['label' => esc_html__('Status & visibility', 'capsman-enhanced'), 'elements' => 'post-status'],
410
+ 'template' => [
411
+ 'label' => esc_html__('Template', 'capsman-enhanced'),
412
+ 'elements' => 'template',
413
+ 'support_key' => 'page-attributes'
414
+ ],
415
+ 'revisions' => ['label' => esc_html__('Revisions', 'capsman-enhanced'), 'elements' => '.editor-post-last-revision__title'],
416
  'permalink' => ['label' => esc_html__('Permalink', 'capsman-enhanced'), 'elements' => 'post-link'],
417
+ 'categories' => [
418
+ 'label' => esc_html__('Categories', 'capsman-enhanced'),
419
+ 'elements' => 'taxonomy-panel-category',
420
+ 'support_key' => 'category',
421
+ 'support_type' => 'taxonomy'
422
+ ],
423
+ 'tags' => [
424
+ 'label' => esc_html__('Tags', 'capsman-enhanced'),
425
+ 'elements' => 'taxonomy-panel-post_tag',
426
+ 'support_key' => 'post_tag',
427
+ 'support_type' => 'taxonomy'
428
+ ],
429
  ]
430
  ];
431
 
434
 
435
  foreach (get_taxonomies(['show_ui' => true], 'object') as $taxonomy => $tx_obj) {
436
  if (!in_array($taxonomy, ['category', 'post_tag', 'link_category'])) {
437
+ $elements[$k][$tx_obj->name] = [
438
+ 'label' => $tx_obj->label,
439
+ 'elements' => "taxonomy-panel-$taxonomy",
440
+ 'support_key' => $tx_obj->name,
441
+ 'support_type' => 'taxonomy'
442
+ ];
443
  }
444
  }
445
 
446
  $elements[$k] = array_merge($elements[$k], [
447
+ 'featured_image' => [
448
+ 'label' => esc_html__('Featured image', 'capsman-enhanced'),
449
+ 'elements' => 'featured-image',
450
+ 'support_key' => 'thumbnail'
451
+ ],
452
+ 'excerpt' => [
453
+ 'label' => esc_html__('Excerpt', 'capsman-enhanced'),
454
+ 'elements' => 'post-excerpt',
455
+ 'support_key' => 'excerpt'
456
+ ],
457
+ 'discussion' => [
458
+ 'label' => esc_html__('Discussion', 'capsman-enhanced'),
459
+ 'elements' => 'discussion-panel',
460
+ 'support_key' => 'comments'
461
+ ],
462
+ 'post_attributes' => [
463
+ 'label' => esc_html__('Post Attributes', 'capsman-enhanced'),
464
+ 'elements' => 'page-attributes',
465
+ 'support_key' => 'page-attributes'
466
+ ],
467
  ]);
468
 
469
+ $elements[esc_html__('Block Panel', 'capsman-enhanced')] = [
470
  'block_panel' => ['label' => esc_html__('Block Panel', 'capsman-enhanced'), 'elements' => '.block-editor-block-inspector'],
471
  'paragraph' => ['label' => esc_html__('Paragraph', 'capsman-enhanced'), 'elements' => '.block-editor-block-card'],
472
  'typography' => ['label' => esc_html__('Typography', 'capsman-enhanced'), 'elements' => '.block-editor-block-inspector .components-panel__body:first-of-type'],
includes/functions.php CHANGED
@@ -253,6 +253,68 @@ function ppc_admin_feature_restrictions() {
253
  }
254
  add_action('init', 'ppc_admin_feature_restrictions', 999);
255
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  /**
257
  * List of capabilities admin pages
258
  *
253
  }
254
  add_action('init', 'ppc_admin_feature_restrictions', 999);
255
 
256
+ /**
257
+ * Redirect user to configured role login redirect
258
+ *
259
+ * @param string $redirect_to URL to redirect to.
260
+ * @param string $request URL the user is coming from.
261
+ * @param object $user Logged user's data.
262
+ * @return string
263
+ */
264
+ function ppc_roles_login_redirect($redirect_to, $request, $user) {
265
+
266
+ if (isset($user->roles) && is_array($user->roles)) {
267
+ foreach ($user->roles as $user_role) {
268
+ //get role option
269
+ $role_option = get_option("pp_capabilities_{$user_role}_role_option", []);
270
+
271
+ if (is_array($role_option) && !empty($role_option)
272
+ && !empty($role_option['custom_redirect']) && (int)$role_option['custom_redirect'] > 0
273
+ && !empty($role_option['login_redirect'])
274
+ ) {
275
+ //custom url redirect
276
+ $redirect_to = esc_url_raw($role_option['login_redirect']);
277
+ break;
278
+ } else if (is_array($role_option) && !empty($role_option)
279
+ && !empty($role_option['referer_redirect']) && (int)$role_option['referer_redirect'] > 0
280
+ && wp_get_referer()
281
+ ) {
282
+ //referer url redirect
283
+ $redirect_to = esc_url_raw(wp_get_referer());
284
+ break;
285
+ }
286
+ }
287
+ }
288
+
289
+ return $redirect_to;
290
+ }
291
+ add_filter('login_redirect', 'ppc_roles_login_redirect', 10, 3);
292
+
293
+ /**
294
+ * Redirect user to configured role logout redirect
295
+ *
296
+ * @param string $redirect_to URL to redirect to.
297
+ * @param string $request URL the user is coming from.
298
+ * @param object $user Logged user's data.
299
+ * @return string
300
+ */
301
+ function ppc_roles_logout_redirect($redirect_to, $request, $user) {
302
+
303
+ if (isset($user->roles) && is_array($user->roles)) {
304
+ foreach ($user->roles as $user_role) {
305
+ //get role option
306
+ $role_option = get_option("pp_capabilities_{$user_role}_role_option", []);
307
+ if (is_array($role_option) && !empty($role_option) && !empty($role_option['logout_redirect'])) {
308
+ $redirect_to = esc_url_raw($role_option['logout_redirect']);
309
+ break;
310
+ }
311
+ }
312
+ }
313
+
314
+ return $redirect_to;
315
+ }
316
+ add_filter('logout_redirect', 'ppc_roles_logout_redirect', 10, 3);
317
+
318
  /**
319
  * List of capabilities admin pages
320
  *
includes/manager.php CHANGED
@@ -461,7 +461,7 @@ class CapabilityManager
461
  public function ManageEditorFeatures() {
462
  if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
463
  // TODO: Implement exceptions.
464
- wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capabilities-pro') . '</strong>');
465
  }
466
 
467
  $this->generateNames();
@@ -483,7 +483,7 @@ class CapabilityManager
483
 
484
  if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-editor-features-role']) && !empty($_REQUEST['_wpnonce'])) {
485
  if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-editor-features')) {
486
- wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capabilities-pro') . '</strong>');
487
  } else {
488
  $this->set_current_role(sanitize_key($_POST['ppc-editor-features-role']));
489
 
@@ -518,7 +518,7 @@ class CapabilityManager
518
  update_option("capsman_feature_restrict_{$post_type}", $post_features_option, false);
519
  }
520
 
521
- ak_admin_notify(__('Settings updated.', 'capabilities-pro'));
522
  }
523
  }
524
 
@@ -534,7 +534,7 @@ class CapabilityManager
534
  public function ManageAdminFeatures() {
535
  if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
536
  // TODO: Implement exceptions.
537
- wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capabilities-pro') . '</strong>');
538
  }
539
 
540
  $this->generateNames();
@@ -556,7 +556,7 @@ class CapabilityManager
556
 
557
  if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-admin-features-role']) && !empty($_REQUEST['_wpnonce'])) {
558
  if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-admin-features')) {
559
- wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capabilities-pro') . '</strong>');
560
  } else {
561
  $features_role = sanitize_key($_POST['ppc-admin-features-role']);
562
 
@@ -572,7 +572,7 @@ class CapabilityManager
572
  $ppc_page_reload = '1';
573
  }
574
 
575
- ak_admin_notify(__('Settings updated.', 'capabilities-pro'));
576
  }
577
  }
578
 
461
  public function ManageEditorFeatures() {
462
  if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
463
  // TODO: Implement exceptions.
464
+ wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capsman-enhanced') . '</strong>');
465
  }
466
 
467
  $this->generateNames();
483
 
484
  if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-editor-features-role']) && !empty($_REQUEST['_wpnonce'])) {
485
  if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-editor-features')) {
486
+ wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capsman-enhanced') . '</strong>');
487
  } else {
488
  $this->set_current_role(sanitize_key($_POST['ppc-editor-features-role']));
489
 
518
  update_option("capsman_feature_restrict_{$post_type}", $post_features_option, false);
519
  }
520
 
521
+ ak_admin_notify(__('Settings updated.', 'capsman-enhanced'));
522
  }
523
  }
524
 
534
  public function ManageAdminFeatures() {
535
  if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
536
  // TODO: Implement exceptions.
537
+ wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capsman-enhanced') . '</strong>');
538
  }
539
 
540
  $this->generateNames();
556
 
557
  if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-admin-features-role']) && !empty($_REQUEST['_wpnonce'])) {
558
  if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-admin-features')) {
559
+ wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capsman-enhanced') . '</strong>');
560
  } else {
561
  $features_role = sanitize_key($_POST['ppc-admin-features-role']);
562
 
572
  $ppc_page_reload = '1';
573
  }
574
 
575
+ ak_admin_notify(__('Settings updated.', 'capsman-enhanced'));
576
  }
577
  }
578
 
includes/roles/class/class-pp-roles-actions.php CHANGED
@@ -252,6 +252,17 @@ class Pp_Roles_Actions
252
  }
253
  }
254
 
 
 
 
 
 
 
 
 
 
 
 
255
  /**
256
  * Copy all features to new role
257
  */
@@ -304,6 +315,7 @@ class Pp_Roles_Actions
304
  'page' => 'pp-capabilities-roles',
305
  'add' => 'new_item',
306
  'role_action' => 'edit',
 
307
  'role' => esc_attr($role['name'])
308
  ],
309
  admin_url('admin.php')
@@ -381,6 +393,15 @@ class Pp_Roles_Actions
381
  $current->add_cap( $cap, $grant );
382
  }
383
 
 
 
 
 
 
 
 
 
 
384
 
385
  /**
386
  * Notify user and redirect
@@ -393,6 +414,7 @@ class Pp_Roles_Actions
393
  'page' => 'pp-capabilities-roles',
394
  'add' => 'new_item',
395
  'role_action' => 'edit',
 
396
  'role' => esc_attr(sanitize_key($_REQUEST['current_role']))
397
  ],
398
  admin_url('admin.php')
@@ -493,6 +515,8 @@ class Pp_Roles_Actions
493
  if (false !== $moved_users) {
494
  $deleted++;
495
  $user_count = $user_count + $moved_users;
 
 
496
  }
497
  }
498
  }
252
  }
253
  }
254
 
255
+
256
+ //update role options
257
+ $role_option = [];
258
+ $role_option['role_editor'] = (!empty($_REQUEST['role_editor']) && is_array(($_REQUEST['role_editor']))) ? array_map('sanitize_text_field', $_REQUEST['role_editor']) : [];
259
+ $role_option['login_redirect'] = !empty($_REQUEST['login_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_REQUEST['login_redirect']))) : '';
260
+ $role_option['logout_redirect'] = !empty($_REQUEST['logout_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_REQUEST['logout_redirect']))) : '';
261
+ $role_option['referer_redirect'] = !empty($_REQUEST['referer_redirect']) ? (int) $_REQUEST['referer_redirect'] : 0;
262
+ $role_option['custom_redirect'] = !empty($_REQUEST['custom_redirect']) ? (int) $_REQUEST['custom_redirect'] : 0;
263
+ $role_option['disable_code_editor'] = !empty($_REQUEST['disable_code_editor']) ? (int) $_REQUEST['disable_code_editor'] : 0;
264
+ update_option('pp_capabilities_' . $role['name'] . '_role_option', $role_option);
265
+
266
  /**
267
  * Copy all features to new role
268
  */
315
  'page' => 'pp-capabilities-roles',
316
  'add' => 'new_item',
317
  'role_action' => 'edit',
318
+ 'active_tab' => !empty($_REQUEST['active_tab']) ? sanitize_key($_REQUEST['active_tab']) : 'general',
319
  'role' => esc_attr($role['name'])
320
  ],
321
  admin_url('admin.php')
393
  $current->add_cap( $cap, $grant );
394
  }
395
 
396
+ //update role options
397
+ $role_option = [];
398
+ $role_option['role_editor'] = (!empty($_REQUEST['role_editor']) && is_array(($_REQUEST['role_editor']))) ? array_map('sanitize_text_field', $_REQUEST['role_editor']) : [];
399
+ $role_option['login_redirect'] = !empty($_REQUEST['login_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_REQUEST['login_redirect']))) : '';
400
+ $role_option['logout_redirect'] = !empty($_REQUEST['logout_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_REQUEST['logout_redirect']))) : '';
401
+ $role_option['referer_redirect'] = !empty($_REQUEST['referer_redirect']) ? (int) $_REQUEST['referer_redirect'] : 0;
402
+ $role_option['custom_redirect'] = !empty($_REQUEST['custom_redirect']) ? (int) $_REQUEST['custom_redirect'] : 0;
403
+ $role_option['disable_code_editor'] = !empty($_REQUEST['disable_code_editor']) ? (int) $_REQUEST['disable_code_editor'] : 0;
404
+ update_option('pp_capabilities_' . sanitize_key($_REQUEST['current_role']) . '_role_option', $role_option);
405
 
406
  /**
407
  * Notify user and redirect
414
  'page' => 'pp-capabilities-roles',
415
  'add' => 'new_item',
416
  'role_action' => 'edit',
417
+ 'active_tab' => !empty($_REQUEST['active_tab']) ? sanitize_key($_REQUEST['active_tab']) : 'general',
418
  'role' => esc_attr(sanitize_key($_REQUEST['current_role']))
419
  ],
420
  admin_url('admin.php')
515
  if (false !== $moved_users) {
516
  $deleted++;
517
  $user_count = $user_count + $moved_users;
518
+ //delete role option
519
+ delete_option("pp_capabilities_{$role}_role_option");
520
  }
521
  }
522
  }
includes/roles/class/class-pp-roles-admin.php CHANGED
@@ -105,6 +105,14 @@ class Pp_Roles_Admin
105
  'label' => esc_html__('General', 'capsman-enhanced'),
106
  'icon' => 'dashicons dashicons-admin-tools',
107
  ],
 
 
 
 
 
 
 
 
108
  'advanced' => [
109
  'label' => esc_html__('Advanced', 'capsman-enhanced'),
110
  'icon' => 'dashicons dashicons-admin-generic',
@@ -140,55 +148,115 @@ class Pp_Roles_Admin
140
  */
141
  public static function get_fields($current, $role_edit, $role_copy)
142
  {
143
- $fields = [
144
- 'role_name' => [
145
- 'label' => esc_html__('Role Name', 'capsman-enhanced'),
146
- 'type' => 'text',
147
- 'value_key' => 'name',
148
- 'tab' => 'general',
149
- 'editable' => true,
150
- 'required' => true,
151
- ],
152
- 'role_slug' => [
153
- 'label' => esc_html__('Role Slug', 'capsman-enhanced'),
154
- 'description' => esc_html__('The "slug" is the URL-friendly version of the role. It is usually all lowercase and contains only letters, numbers and underscores.', 'capsman-enhanced'),
155
- 'type' => 'text',
156
- 'value_key' => 'role',
157
- 'tab' => 'general',
158
- 'editable' => ($role_edit) ? false : true,
159
- 'required' => false,
160
- ],
161
- 'role_level' => [
162
- 'label' => esc_html__('Role Level', 'capsman-enhanced'),
163
- 'description' => esc_html__('Each user role has a level from 0 to 10. The Subscriber role defaults to the lowest level (0). The Administrator role defaults to level 10.', 'capsman-enhanced'),
164
- 'type' => 'select',
165
- 'value_key' => '',
166
- 'tab' => 'advanced',
167
- 'editable' => true,
168
- 'options' => [
169
- '10' => '10',
170
- '9' => '9',
171
- '8' => '8',
172
- '7' => '7',
173
- '6' => '6',
174
- '5' => '5',
175
- '4' => '4',
176
- '3' => '3',
177
- '2' => '2',
178
- '1' => '1',
179
- '0' => '0',
180
- ],
181
- 'selected' => (is_array($current) && isset($current['capabilities'])) ? ak_caps2level($current['capabilities']) : '0',
182
- ],
183
- 'delete_role' => [
184
- 'label' => esc_html__('Delete role', 'capsman-enhanced'),
185
- 'description' => esc_html__('Deleting this role will completely remove it from database and is irrecoverable.', 'capsman-enhanced'),
186
- 'type' => 'button',
187
- 'value_key' => '',
188
- 'tab' => 'delete',
189
- 'editable' => true,
 
 
 
190
  ],
191
  ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
  /**
194
  * Customize fields presented on role screen.
@@ -205,8 +273,9 @@ class Pp_Roles_Admin
205
  * Get a rendered field partial
206
  *
207
  * @param array $args Arguments to render in the partial.
 
208
  */
209
- private static function get_rendered_role_partial($args)
210
  {
211
  $defaults = [
212
  'description' => '',
@@ -214,15 +283,16 @@ class Pp_Roles_Admin
214
  'tab' => 'general',
215
  'editable' => true,
216
  'required' => false,
 
217
  'value' => '',
218
  'options' => [],
219
- 'selected' => '',
220
  'label' => '',
221
  ];
222
  $args = array_merge($defaults, $args);
223
  $key = $args['key'];
 
224
  $tab_class = 'pp-roles-tab-tr pp-roles-' . $args['tab'] . '-tab';
225
- $tab_style = ($args['tab'] === 'general') ? '' : 'display:none;';
226
  ?>
227
  <tr valign="top"
228
  class="<?php echo esc_attr('form-field role-' . $key . '-wrap '. $tab_class); ?>"
@@ -245,13 +315,68 @@ class Pp_Roles_Admin
245
  </th>
246
  <td>
247
  <?php
248
- if ($args['type'] === 'select') : ?>
249
- <select name="<?php echo esc_attr($key); ?>" <?php echo ($args['required'] ? 'required="true"' : '');?>>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  <?php
251
  foreach ($args['options'] as $select_key => $select_label) {
 
 
 
 
 
252
  ?>
253
  <option value="<?php esc_attr_e($select_key); ?>"
254
- <?php selected($select_key, $args['selected']); ?>>
255
  <?php echo esc_html($select_label); ?>
256
  </option>
257
  <?php } ?>
@@ -270,23 +395,129 @@ class Pp_Roles_Admin
270
  elseif ($args['type'] === 'button') :
271
  ?>
272
  <input type="submit"
273
- class="button-secondary pp-roles-delete-botton"
274
- name="<?php echo esc_attr($key); ?>"
275
- value="<?php echo esc_attr($args['label']); ?>"
276
- onclick="return confirm('<?php esc_attr_e('Are you sure you want to delete this role?', 'capsman-enhanced'); ?>');"
277
- />
 
278
  <?php if (isset($args['description'])) : ?>
279
  <p class="description" style="color: red;"><?php echo esc_html($args['description']); ?></p>
280
  <?php endif; ?>
281
- <?php else : ?>
282
- <input name="<?php echo esc_attr($key); ?>" type="<?php echo esc_attr($args['type']); ?>"
283
- value="<?php echo esc_attr($args['value']); ?>"
284
- <?php echo ($args['required'] ? 'required="true"' : '');?>
285
- <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
286
-
287
- <?php if (isset($args['description'])) : ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  <p class="description"><?php echo esc_html($args['description']); ?></p>
289
  <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  <?php endif; ?>
291
  </td>
292
  </tr>
@@ -323,6 +554,16 @@ class Pp_Roles_Admin
323
  $current = $role_data;
324
  $role_copy = true;
325
  }
 
 
 
 
 
 
 
 
 
 
326
 
327
  $fields_tabs = apply_filters('pp_roles_fields_tabs', self::get_fields_tabs($current, $role_edit, $role_copy), $current, $role_edit, $role_copy);
328
  $fields = apply_filters('pp_roles_fields', self::get_fields($current, $role_edit, $role_copy), $current, $role_edit, $role_copy);
@@ -342,7 +583,7 @@ class Pp_Roles_Admin
342
  <h1>
343
  <?php
344
  if ($role_edit) {
345
- esc_html_e('Edit Role', 'capsman-enhanced');
346
  } elseif ($role_copy) {
347
  esc_html_e('Copy Role', 'capsman-enhanced');
348
  } else {
@@ -355,7 +596,7 @@ class Pp_Roles_Admin
355
  </h1>
356
  <div class="wp-clearfix"></div>
357
 
358
- <form method="post" action="">
359
  <input type="hidden" name="active_tab" class="ppc-roles-active-tab" value="<?php echo esc_attr($default_tab); ?>">
360
  <input type="hidden" name="role_action" value="<?php echo esc_attr($role_action); ?>">
361
  <input type="hidden" name="action" value="<?php echo ($role_action === 'edit' ? 'pp-roles-edit-role' : 'pp-roles-add-role'); ?>">
@@ -397,7 +638,7 @@ class Pp_Roles_Admin
397
  $args['key'] = $key;
398
  $args['value'] = (is_array($current) && isset($current[$args['value_key']])) ? $current[$args['value_key']] : '';
399
 
400
- self::get_rendered_role_partial($args);
401
  }
402
  ?>
403
  </table>
@@ -416,8 +657,9 @@ class Pp_Roles_Admin
416
  <div class="misc-pub-section misc-pub-section-last" style="margin:0;">
417
  <p>
418
  <input type="submit"
419
- value="<?php echo esc_attr($save_button_text); ?>" class="button-primary" id="publish" name="publish">
420
  </p>
 
421
  </div>
422
  </div>
423
 
@@ -433,7 +675,7 @@ class Pp_Roles_Admin
433
  'capsman-enhanced'
434
  ),
435
  ($role_action === 'edit') ? '<a href="' . esc_url(add_query_arg(['page' => 'pp-capabilities', 'role' => esc_attr($current_role)], admin_url('admin.php'))) .'">' : '',
436
- ($role_action === 'edit') ? '</a>' : ''
437
  );
438
  ?>
439
  </p>
105
  'label' => esc_html__('General', 'capsman-enhanced'),
106
  'icon' => 'dashicons dashicons-admin-tools',
107
  ],
108
+ 'editing' => [
109
+ 'label' => esc_html__('Editing', 'capsman-enhanced'),
110
+ 'icon' => 'dashicons dashicons-edit-page',
111
+ ],
112
+ 'redirects' => [
113
+ 'label' => esc_html__('Redirects', 'capsman-enhanced'),
114
+ 'icon' => 'dashicons dashicons-admin-links',
115
+ ],
116
  'advanced' => [
117
  'label' => esc_html__('Advanced', 'capsman-enhanced'),
118
  'icon' => 'dashicons dashicons-admin-generic',
148
  */
149
  public static function get_fields($current, $role_edit, $role_copy)
150
  {
151
+ $editor_options = [];
152
+
153
+ $editor_options['block_editor'] = esc_html__('Gutenberg editor', 'capsman-enhanced');
154
+ if (class_exists('Classic_Editor')) {
155
+ $editor_options['classic_editor'] = esc_html__('Classic editor', 'capsman-enhanced');
156
+ }
157
+
158
+ $fields = [];
159
+
160
+ //add role_name
161
+ $fields['role_name'] = [
162
+ 'label' => esc_html__('Role Name', 'capsman-enhanced'),
163
+ 'type' => 'text',
164
+ 'value_key' => 'name',
165
+ 'tab' => 'general',
166
+ 'editable' => true,
167
+ 'required' => true,
168
+ ];
169
+
170
+ //add role_slug
171
+ $fields['role_slug'] = [
172
+ 'label' => esc_html__('Role Slug', 'capsman-enhanced'),
173
+ 'description' => esc_html__('The "slug" is the URL-friendly version of the role. It is usually all lowercase and contains only letters, numbers and underscores.', 'capsman-enhanced'),
174
+ 'type' => 'text',
175
+ 'value_key' => 'role',
176
+ 'tab' => 'general',
177
+ 'editable' => ($role_edit) ? false : true,
178
+ 'required' => false,
179
+ ];
180
+
181
+ //add role_level
182
+ $fields['role_level'] = [
183
+ 'label' => esc_html__('Role Level', 'capsman-enhanced'),
184
+ 'description' => esc_html__('Each user role has a level from 0 to 10. The Subscriber role defaults to the lowest level (0). The Administrator role defaults to level 10.', 'capsman-enhanced'),
185
+ 'type' => 'select',
186
+ 'value_key' => 'role_level',
187
+ 'tab' => 'advanced',
188
+ 'editable' => true,
189
+ 'options' => [
190
+ '10' => '10',
191
+ '9' => '9',
192
+ '8' => '8',
193
+ '7' => '7',
194
+ '6' => '6',
195
+ '5' => '5',
196
+ '4' => '4',
197
+ '3' => '3',
198
+ '2' => '2',
199
+ '1' => '1',
200
+ '0' => '0',
201
  ],
202
  ];
203
+
204
+ //add delete_role
205
+ $fields['delete_role'] = [
206
+ 'label' => esc_html__('Delete role', 'capsman-enhanced'),
207
+ 'description' => esc_html__('Deleting this role will completely remove it from database and is irrecoverable.', 'capsman-enhanced'),
208
+ 'type' => 'button',
209
+ 'value_key' => '',
210
+ 'tab' => 'delete',
211
+ 'editable' => true,
212
+ ];
213
+
214
+ //add login_redirect
215
+ $fields['login_redirect'] = [
216
+ 'label' => esc_html__('Login Redirect', 'capsman-enhanced'),
217
+ 'description' => esc_html__('Enter the URL users in this role should be redirected to after login.', 'capsman-enhanced'),
218
+ 'type' => 'url',
219
+ 'value_key' => 'login_redirect',
220
+ 'tab' => 'redirects',
221
+ 'editable' => true,
222
+ 'required' => false,
223
+ ];
224
+
225
+ //add logout_redirect
226
+ $fields['logout_redirect'] = [
227
+ 'label' => esc_html__('Logout Redirect', 'capsman-enhanced'),
228
+ 'description' => esc_html__('Enter the URL users in this role should be redirected to after logout.', 'capsman-enhanced'),
229
+ 'type' => 'url',
230
+ 'value_key' => 'logout_redirect',
231
+ 'tab' => 'redirects',
232
+ 'editable' => true,
233
+ 'required' => false,
234
+ ];
235
+
236
+ //add disable_code_editor
237
+ $fields['disable_code_editor'] = [
238
+ 'label' => esc_html__('Disable Code Editor', 'capsman-enhanced'),
239
+ 'description' => esc_html__('Disable the "Code editor" option for the Gutenberg block editor.', 'capsman-enhanced'),
240
+ 'type' => 'checkbox',
241
+ 'value_key' => 'disable_code_editor',
242
+ 'tab' => 'editing',
243
+ 'editable' => true,
244
+ 'required' => false,
245
+ ];
246
+
247
+ if (count($editor_options) > 1) {
248
+ //add role_editor
249
+ $fields['role_editor'] = [
250
+ 'label' => esc_html__('Control Allowed Editors', 'capsman-enhanced'),
251
+ 'description' => esc_html__('Select the allowed editor options for users in this role.', 'capsman-enhanced'),
252
+ 'type' => 'select',
253
+ 'multiple' => true,
254
+ 'value_key' => 'role_editor',
255
+ 'tab' => 'editing',
256
+ 'editable' => true,
257
+ 'options' => $editor_options,
258
+ ];
259
+ }
260
 
261
  /**
262
  * Customize fields presented on role screen.
273
  * Get a rendered field partial
274
  *
275
  * @param array $args Arguments to render in the partial.
276
+ * @param array $current current form data.
277
  */
278
+ private static function get_rendered_role_partial($args, $current)
279
  {
280
  $defaults = [
281
  'description' => '',
283
  'tab' => 'general',
284
  'editable' => true,
285
  'required' => false,
286
+ 'multiple' => false,
287
  'value' => '',
288
  'options' => [],
 
289
  'label' => '',
290
  ];
291
  $args = array_merge($defaults, $args);
292
  $key = $args['key'];
293
+ $default_tab = (!empty($_GET) && !empty($_GET['active_tab'])) ? sanitize_key($_GET['active_tab']) : 'general';
294
  $tab_class = 'pp-roles-tab-tr pp-roles-' . $args['tab'] . '-tab';
295
+ $tab_style = ($args['tab'] === $default_tab) ? '' : 'display:none;';
296
  ?>
297
  <tr valign="top"
298
  class="<?php echo esc_attr('form-field role-' . $key . '-wrap '. $tab_class); ?>"
315
  </th>
316
  <td>
317
  <?php
318
+ if ($key === 'role_editor') : ?>
319
+ <?php
320
+ $allowed_editor = (isset($args['value']) && is_array($args['value']) && !empty($args['value'])) ? true : false;
321
+ $select_style = ($allowed_editor) ? '' : 'display:none;';
322
+ ?>
323
+ <div class="role-editor-toggle-box">
324
+ <input name="<?php echo esc_attr($key.'-toggle'); ?>"
325
+ id="<?php echo esc_attr($key); ?>"
326
+ class="allowed-editor-toggle"
327
+ type="checkbox"
328
+ value="1"
329
+ <?php checked(true, $allowed_editor); ?>/>
330
+ </div>
331
+
332
+ <div class="role-editor-select-box" style="<?php echo esc_attr($select_style); ?>">
333
+ <select
334
+ name="<?php echo esc_attr($key); ?><?php echo $args['multiple'] ? '[]' : '';?>"
335
+ id="<?php echo esc_attr($key.'-select'); ?>"
336
+ class="pp-capabilities-role-choosen"
337
+ data-placeholder="<?php esc_html_e('Select allowed editor', 'capsman-enhanced'); ?>"
338
+ data-message="<?php esc_attr_e('You must select at least one editor for the role when managing allowed editor.', 'capsman-enhanced'); ?>"
339
+ <?php echo ($args['multiple'] ? 'multiple' : '');?>
340
+ <?php echo ($args['required'] ? 'required="true"' : '');?>>
341
+ <?php
342
+ foreach ($args['options'] as $select_key => $select_label) {
343
+ if ($args['multiple']) {
344
+ $selected_option = (isset($args['value']) && is_array($args['value']) && in_array($select_key, $args['value'])) ? true : false;
345
+ } else {
346
+ $selected_option = (isset($args['value']) && $select_key == $args['value']) ? true : false;
347
+ }
348
+ ?>
349
+ <option value="<?php esc_attr_e($select_key); ?>"
350
+ <?php selected(true, $selected_option); ?>>
351
+ <?php echo esc_html($select_label); ?>
352
+ </option>
353
+ <?php } ?>
354
+ </select>
355
+ <?php if (isset($args['description'])) : ?>
356
+ <p class="description">
357
+ <?php echo esc_html($args['description']); ?>
358
+ </p>
359
+ <?php endif; ?>
360
+ </div>
361
+ <?php
362
+ elseif ($args['type'] === 'select') : ?>
363
+ <select
364
+ name="<?php echo esc_attr($key); ?><?php echo $args['multiple'] ? '[]' : '';?>"
365
+ id="<?php echo esc_attr($key); ?>"
366
+ class="pp-capabilities-role-choosen"
367
+ data-placeholder="<?php printf(esc_html__('Select %s', 'capsman-enhanced'), esc_html(strtolower($args['label']))); ?>"
368
+ <?php echo ($args['multiple'] ? 'multiple' : '');?>
369
+ <?php echo ($args['required'] ? 'required="true"' : '');?>>
370
  <?php
371
  foreach ($args['options'] as $select_key => $select_label) {
372
+ if ($args['multiple']) {
373
+ $selected_option = (isset($args['value']) && is_array($args['value']) && in_array($select_key, $args['value'])) ? true : false;
374
+ } else {
375
+ $selected_option = (isset($args['value']) && $select_key == $args['value']) ? true : false;
376
+ }
377
  ?>
378
  <option value="<?php esc_attr_e($select_key); ?>"
379
+ <?php selected(true, $selected_option); ?>>
380
  <?php echo esc_html($select_label); ?>
381
  </option>
382
  <?php } ?>
395
  elseif ($args['type'] === 'button') :
396
  ?>
397
  <input type="submit"
398
+ class="button-secondary pp-roles-delete-botton"
399
+ id="<?php echo esc_attr($key); ?>"
400
+ name="<?php echo esc_attr($key); ?>"
401
+ value="<?php echo esc_attr($args['label']); ?>"
402
+ onclick="return confirm('<?php esc_attr_e('Are you sure you want to delete this role?', 'capsman-enhanced'); ?>');"
403
+ />
404
  <?php if (isset($args['description'])) : ?>
405
  <p class="description" style="color: red;"><?php echo esc_html($args['description']); ?></p>
406
  <?php endif; ?>
407
+ <?php
408
+ elseif ($args['type'] === 'checkbox') :
409
+ ?>
410
+ <input name="<?php echo esc_attr($key); ?>"
411
+ id="<?php echo esc_attr($key); ?>"
412
+ type="<?php echo esc_attr($args['type']); ?>"
413
+ value="1"
414
+ <?php checked(1, (int)$args['value']); ?>
415
+ <?php echo ($args['required'] ? 'required="true"' : '');?>
416
+ <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
417
+ <?php if (isset($args['description'])) : ?>
418
+ <span class="description"><?php echo esc_html($args['description']); ?></span>
419
+ <?php endif; ?>
420
+ <?php elseif ($args['key'] === 'login_redirect') :
421
+ $referer_redirect = (is_array($current) && isset($current['referer_redirect']) && (int)$current['referer_redirect'] > 0) ? true : false;
422
+ $custom_redirect = (is_array($current) && isset($current['custom_redirect']) && (int)$current['custom_redirect'] > 0) ? true : false;
423
+ $custom_style = (!$custom_redirect) ? 'display:none;' : '';
424
+
425
+ $form_url = $args['value'];
426
+ $base_url = '';
427
+ if (!empty($form_url)) {
428
+ $base_url = str_replace(home_url(), '', $form_url);
429
+ }
430
+ ?>
431
+ <div class="login-redirect-option">
432
+ <label>
433
+ <input name="referer_redirect"
434
+ id="referer_redirect"
435
+ type="checkbox"
436
+ value="1"
437
+ <?php checked(true, $referer_redirect); ?>
438
+ <?php echo ($args['required'] ? 'required="true"' : '');?>
439
+ <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
440
+ <span class="description"><?php echo esc_html__('Redirect users to the URL they were viewing before login.', 'capsman-enhanced'); ?></span>
441
+ </label>
442
+ </div>
443
+ <div class="login-redirect-option">
444
+ <label>
445
+ <input name="custom_redirect"
446
+ id="custom_redirect"
447
+ type="checkbox"
448
+ value="1"
449
+ <?php checked(true, $custom_redirect); ?>
450
+ <?php echo ($args['required'] ? 'required="true"' : '');?>
451
+ <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
452
+ <span class="description"><?php echo esc_html__('Redirect users to a specified URL.', 'capsman-enhanced'); ?></span>
453
+ </label>
454
+ <div class="custom-url-wrapper" style="<?php esc_attr_e($custom_style); ?>">
455
+ <div class="pp-roles-internal-links-wrapper activated">
456
+ <div class="base-url">
457
+ <?php esc_html_e(home_url()); ?>
458
+ </div>
459
+ <div class="base-input">
460
+ <input name="<?php echo esc_attr($key); ?>"
461
+ id="<?php echo esc_attr($key); ?>"
462
+ type="text"
463
+ value="<?php echo esc_attr($base_url); ?>"
464
+ data-original_base="<?php echo esc_attr($base_url); ?>"
465
+ data-base="<?php echo esc_attr($base_url); ?>"
466
+ data-entry="<?php echo esc_attr($form_url); ?>"
467
+ data-home_url="<?php echo esc_url(home_url()); ?>"
468
+ data-message="<?php esc_attr_e('Enter the relative path only without domain for login redirect.', 'capsman-enhanced'); ?>"
469
+ data-required_message="<?php esc_attr_e('You must enter the Login Redirect URL.', 'capsman-enhanced'); ?>"
470
+ autocomplete="off"
471
+ <?php echo ($args['required'] ? 'required="true"' : '');?>
472
+ <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
473
+ </div>
474
+ </div>
475
+ <?php if (isset($args['description'])) : ?>
476
  <p class="description"><?php echo esc_html($args['description']); ?></p>
477
  <?php endif; ?>
478
+ </div>
479
+ </div>
480
+ <?php elseif ($args['key'] === 'logout_redirect') : ?>
481
+ <?php
482
+ $form_url = $args['value'];
483
+ $base_url = '';
484
+ if (!empty($form_url)) {
485
+ $base_url = str_replace(home_url(), '', $form_url);
486
+ }
487
+ ?>
488
+ <div class="pp-roles-internal-links-wrapper activated">
489
+ <div class="base-url">
490
+ <?php esc_html_e(home_url()); ?>
491
+ </div>
492
+ <div class="base-input">
493
+ <input name="<?php echo esc_attr($key); ?>"
494
+ id="<?php echo esc_attr($key); ?>"
495
+ type="text"
496
+ value="<?php echo esc_attr($base_url); ?>"
497
+ data-original_base="<?php echo esc_attr($base_url); ?>"
498
+ data-base="<?php echo esc_attr($base_url); ?>"
499
+ data-entry="<?php echo esc_attr($form_url); ?>"
500
+ data-home_url="<?php echo esc_url(home_url()); ?>"
501
+ data-message="<?php esc_attr_e('Enter the relative path only without domain for logout redirect.', 'capsman-enhanced'); ?>"
502
+ autocomplete="off"
503
+ <?php echo ($args['required'] ? 'required="true"' : '');?>
504
+ <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
505
+ </div>
506
+ </div>
507
+ <?php if (isset($args['description'])) : ?>
508
+ <p class="description"><?php echo esc_html($args['description']); ?></p>
509
+ <?php endif; ?>
510
+ </div>
511
+ <?php else : ?>
512
+ <input name="<?php echo esc_attr($key); ?>"
513
+ id="<?php echo esc_attr($key); ?>"
514
+ type="<?php echo esc_attr($args['type']); ?>"
515
+ value="<?php echo esc_attr($args['value']); ?>"
516
+ <?php echo ($args['required'] ? 'required="true"' : '');?>
517
+ <?php echo (!$args['editable'] ? 'readonly="readonly"' : ''); ?>/>
518
+ <?php if (isset($args['description'])) : ?>
519
+ <p class="description"><?php echo esc_html($args['description']); ?></p>
520
+ <?php endif; ?>
521
  <?php endif; ?>
522
  </td>
523
  </tr>
554
  $current = $role_data;
555
  $role_copy = true;
556
  }
557
+
558
+ if ($current_role) {
559
+ //add role options
560
+ $role_option = get_option("pp_capabilities_{$current_role}_role_option", []);
561
+ if (is_array($role_option) && !empty($role_option)) {
562
+ $current = array_merge($role_option, $current);
563
+ }
564
+ //add role level
565
+ $current['role_level'] = (is_array($current) && isset($current['capabilities'])) ? ak_caps2level($current['capabilities']) : '0';
566
+ }
567
 
568
  $fields_tabs = apply_filters('pp_roles_fields_tabs', self::get_fields_tabs($current, $role_edit, $role_copy), $current, $role_edit, $role_copy);
569
  $fields = apply_filters('pp_roles_fields', self::get_fields($current, $role_edit, $role_copy), $current, $role_edit, $role_copy);
583
  <h1>
584
  <?php
585
  if ($role_edit) {
586
+ printf( esc_html__('Edit Role: %s', 'capsman-enhanced'), esc_html($current['name']));
587
  } elseif ($role_copy) {
588
  esc_html_e('Copy Role', 'capsman-enhanced');
589
  } else {
596
  </h1>
597
  <div class="wp-clearfix"></div>
598
 
599
+ <form method="post" action="" onkeydown="return event.key != 'Enter';">
600
  <input type="hidden" name="active_tab" class="ppc-roles-active-tab" value="<?php echo esc_attr($default_tab); ?>">
601
  <input type="hidden" name="role_action" value="<?php echo esc_attr($role_action); ?>">
602
  <input type="hidden" name="action" value="<?php echo ($role_action === 'edit' ? 'pp-roles-edit-role' : 'pp-roles-add-role'); ?>">
638
  $args['key'] = $key;
639
  $args['value'] = (is_array($current) && isset($current[$args['value_key']])) ? $current[$args['value_key']] : '';
640
 
641
+ self::get_rendered_role_partial($args, $current);
642
  }
643
  ?>
644
  </table>
657
  <div class="misc-pub-section misc-pub-section-last" style="margin:0;">
658
  <p>
659
  <input type="submit"
660
+ value="<?php echo esc_attr($save_button_text); ?>" class="submit-role-form button-primary" id="publish" name="publish">
661
  </p>
662
+ <p class="role-submit-response"></p>
663
  </div>
664
  </div>
665
 
675
  'capsman-enhanced'
676
  ),
677
  ($role_action === 'edit') ? '<a href="' . esc_url(add_query_arg(['page' => 'pp-capabilities', 'role' => esc_attr($current_role)], admin_url('admin.php'))) .'">' : '',
678
+ (esc_html($role_action) === 'edit') ? '</a>' : ''
679
  );
680
  ?>
681
  </p>
includes/roles/css/pp-roles-admin.css CHANGED
@@ -15,4 +15,175 @@
15
 
16
  span.pp-caps-action-note {
17
  color: #444;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  }
15
 
16
  span.pp-caps-action-note {
17
  color: #444;
18
+ }
19
+
20
+ .roles-capabilities-title {
21
+ font-weight: bold !important;
22
+ padding-left: 0 !important;
23
+ }
24
+ .pp-role-edit-wrap #publishing-action {
25
+ text-align: unset !important;
26
+ float: unset !important;
27
+ }
28
+
29
+ .pp-roles-delete-botton {
30
+ color: red !important;
31
+ border-color: red !important;
32
+ }
33
+
34
+ .ppc-roles-section {
35
+ min-height: 370px;
36
+ }
37
+
38
+ #poststuff .ppc-roles-section.postbox .inside {
39
+ margin-left: 0 !important;
40
+ margin-top: 0 !important;
41
+ padding-left: 0 !important;
42
+ }
43
+
44
+ .ppc-roles-section input[type=text],
45
+ .ppc-roles-section input[type=number],
46
+ .ppc-roles-section select {
47
+ width: 300px;
48
+ }
49
+
50
+ .ppc-roles-section #poststuff {
51
+ min-height: 600px;
52
+ }
53
+
54
+ ul.ppc-roles-tab {
55
+ margin: 0;
56
+ width: 20%;
57
+ float: left;
58
+ line-height: 1em;
59
+ padding: 0 0 10px;
60
+ position: relative;
61
+ background-color: #fafafa;
62
+ border-right: 1px solid #eee;
63
+ box-sizing: border-box;
64
+ min-height: 363px;
65
+ }
66
+ .ppc-roles-tab-content {
67
+ float: left;
68
+ width: 80%;
69
+ min-height: 275px;
70
+ box-sizing: border-box;
71
+ padding-left: 10px;
72
+ }
73
+ ul.ppc-roles-tab li {
74
+ margin: 0;
75
+ padding: 0;
76
+ display: block;
77
+ position: relative;
78
+ }
79
+ ul.ppc-roles-tab li a {
80
+ margin: 0;
81
+ padding: 10px;
82
+ display: block;
83
+ box-shadow: none;
84
+ text-decoration: none;
85
+ line-height: 20px!important;
86
+ border-bottom: 1px solid #eee;
87
+ }
88
+
89
+ ul.ppc-roles-tab li a span {
90
+ margin-right: .618em;
91
+ }
92
+
93
+ ul.ppc-roles-tab li a span.dashicons {
94
+ margin-left: 0;
95
+ font-size: 15px;
96
+ }
97
+ ul.ppc-roles-tab li.active a {
98
+ color: #555;
99
+ position: relative;
100
+ background-color: #eee;
101
+ }
102
+
103
+ .ppc-roles-sidebar ul.pp-roles-capabilities li {
104
+ margin-bottom: 0;
105
+ }
106
+
107
+ .ppc-roles-sidebar ul.pp-roles-capabilities li::before {
108
+ font-family: Dashicons;
109
+ font-weight: 400;
110
+ text-transform: none;
111
+ line-height: 1;
112
+ -webkit-font-smoothing: antialiased;
113
+ content: "\f12a";
114
+ font-variant: normal;
115
+ text-decoration: none;
116
+ color: green;
117
+ }
118
+ .roles-capabilities-load-more,
119
+ .roles-capabilities-load-less {
120
+ cursor: pointer;
121
+ color: #2271b1;
122
+ text-decoration: underline;
123
+ }
124
+
125
+ .ppc-roles-section .red-warning {
126
+ color: red;
127
+ font-weight: bold;
128
+ }
129
+
130
+ .role-submit-response {
131
+ color: red;
132
+ }
133
+
134
+ .ppc-roles-tab-content .login-redirect-option {
135
+ margin-bottom: 10px;
136
+ }
137
+
138
+ .ppc-roles-tab-content .custom-url-wrapper {
139
+ margin-top: 10px;
140
+ }
141
+
142
+ .pp-roles-internal-links-wrapper.activated {
143
+ display: flex;
144
+ }
145
+
146
+ .pp-roles-internal-links-wrapper.activated .base-input {
147
+ flex: 1 0 auto;
148
+ }
149
+
150
+ .pp-roles-internal-links-wrapper .base-input input[type=text] {
151
+ width: 95% !important;
152
+ }
153
+
154
+ .pp-roles-internal-links-wrapper.activated .base-url {
155
+ margin-top: 6px;
156
+ }
157
+
158
+ .pp-roles-internal-links-wrapper.activated .cancel-edit {
159
+ margin-right: 5px;
160
+ }
161
+
162
+ .pp-roles-internal-links-wrapper.activated .delete-entry {
163
+ color: red !important;
164
+ border-color: red !important;
165
+ }
166
+
167
+ .pp-roles-internal-links-wrapper:not(.activated) .base-url,
168
+ .pp-roles-internal-links-wrapper:not(.activated) .cancel-edit,
169
+ .pp-roles-internal-links-wrapper:not(.activated) .delete-entry {
170
+ display: none !important;
171
+ }
172
+
173
+ .role-editor-toggle-box {
174
+ margin-bottom: 10px;
175
+ }
176
+
177
+ @media only screen and (max-width: 1024px) {
178
+ .pp-roles-internal-links-wrapper.activated {
179
+ display: block;
180
+ }
181
+ .pp-roles-internal-links-wrapper.activated .base-input {
182
+ margin-bottom: 5px;
183
+ }
184
+
185
+ .ppc-roles-section .chosen-container.chosen-container-single,
186
+ .ppc-roles-section .chosen-container.chosen-container-multi {
187
+ max-width: 250px;
188
+ }
189
  }
includes/roles/js/pp-roles-admin.js CHANGED
@@ -111,4 +111,158 @@ jQuery(document).ready(function ($) {
111
  return false;
112
  });
113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  });
111
  return false;
112
  });
113
 
114
+
115
+ /**
116
+ * Capabilities role slug validation
117
+ */
118
+ $('.ppc-roles-tab-content input[name="role_slug"]').on('keyup', function (e) {
119
+ is_role_slug_exist();
120
+ });
121
+
122
+ if ($('#pp-role-slug-exists').length > 0) {
123
+ is_role_slug_exist();
124
+ }
125
+
126
+ /**
127
+ * Role active tab
128
+ */
129
+ $(document).on('click', 'ul.ppc-roles-tab li', function () {
130
+ $('.ppc-roles-active-tab').val($(this).attr('data-tab'));
131
+ });
132
+
133
+ /**
134
+ * Role screen select input
135
+ */
136
+ if ($('.pp-capabilities-role-choosen').length > 0) {
137
+ $('.pp-capabilities-role-choosen').chosen({
138
+ 'width': '25em'
139
+ });
140
+ }
141
+
142
+ /**
143
+ * Roles capabilities load less button
144
+ */
145
+ $(document).on('click', '.roles-capabilities-load-less', function (event) {
146
+ event.preventDefault();
147
+
148
+ $('.roles-capabilities-load-less').hide();
149
+
150
+ $('.roles-capabilities-load-more').show();
151
+
152
+ $('ul.pp-roles-capabilities li').hide();
153
+
154
+ $('ul.pp-roles-capabilities').children().slice(0, 6).show();
155
+
156
+ window.scrollTo({ top: 0, behavior: 'smooth' });
157
+ });
158
+
159
+ /**
160
+ * Roles login redirect options
161
+ */
162
+ $(document).on('change', '.login-redirect-option #referer_redirect', function () {
163
+ $('.login-redirect-option .custom-url-wrapper').hide();
164
+ $('.login-redirect-option #custom_redirect').prop('checked', false);
165
+ });
166
+
167
+ /**
168
+ * Roles login redirect options
169
+ */
170
+ $(document).on('change', '.login-redirect-option #custom_redirect', function (event) {
171
+ if ($(this).prop('checked')) {
172
+ $('.login-redirect-option .custom-url-wrapper').show();
173
+ } else {
174
+ $('.login-redirect-option .custom-url-wrapper').hide();
175
+ }
176
+ $('.login-redirect-option #referer_redirect').prop('checked', false);
177
+ });
178
+
179
+ /**
180
+ * Roles allowed editor manage toggle
181
+ */
182
+ $(document).on('change', '.allowed-editor-toggle', function () {
183
+ if ($(this).prop('checked')) {
184
+ $('.role-editor-select-box').show();
185
+ } else {
186
+ $('.role-editor-select-box').hide();
187
+ $('#role_editor-select option').prop('selected', false);
188
+ $('#role_editor-select').trigger('chosen:updated');
189
+ }
190
+ });
191
+
192
+ /**
193
+ * Role submit required field validation
194
+ */
195
+ $('.pp-capability-roles-wrapper .submit-role-form').on('click', function (e) {
196
+
197
+ let error_message = '';
198
+ let error_report = false;
199
+ $('.role-submit-response').html('');
200
+
201
+ //add required custom redirect link error message
202
+ if ($('#custom_redirect').prop('checked') && isEmptyOrSpaces($('#login_redirect').val())) {
203
+ error_report = true;
204
+ error_message += '- ' + $('#login_redirect').attr('data-required_message') + '<br />';
205
+ }
206
+
207
+ //add custom url validation warning
208
+ $('.pp-roles-internal-links-wrapper .base-input input').each(function () {
209
+ var base_url = $(this).attr('data-base');
210
+ if (!isEmptyOrSpaces(base_url) && base_url.includes('://')) {
211
+ error_report = true;
212
+ error_message += '- ' + $(this).attr('data-message') + '<br />';
213
+ }
214
+ });
215
+
216
+ //add allowed editor option validation
217
+ if ($('.allowed-editor-toggle').prop('checked') && $('#role_editor-select').val().length === 0) {
218
+ error_report = true;
219
+ error_message += '- ' + $('#role_editor-select').attr('data-message') + '<br />';
220
+ }
221
+
222
+ if (error_report) {
223
+ e.preventDefault();
224
+ $('.role-submit-response').html(error_message);
225
+ }
226
+
227
+ });
228
+
229
+ /**
230
+ * Role custom url change syc
231
+ */
232
+ $('.pp-roles-internal-links-wrapper .base-input input').on('keyup', function (e) {
233
+ var current_input = $(this);
234
+ var current_wrapper = current_input.closest('.pp-roles-internal-links-wrapper');
235
+ var current_entry = current_input.val();
236
+
237
+ current_wrapper.find('.base-input input')
238
+ .attr('data-base', current_entry)
239
+ .attr('data-entry', current_wrapper.find('.base-input input').attr('data-home_url') + current_entry);
240
+ });
241
+ /**
242
+ * Prevent click on custom url base link
243
+ */
244
+ $('.pp-roles-internal-links-wrapper .base-url a').on('click', function (e) {
245
+ e.preventDefault();
246
+ return false;
247
+ });
248
+
249
+ function isEmptyOrSpaces(str) {
250
+ return str === null || str.match(/^ *$/) !== null;
251
+ }
252
+
253
+
254
+ function is_role_slug_exist() {
255
+ if ($('.ppc-roles-tab-content input[name="role_slug"]').attr('readonly') !== 'readonly') {
256
+ var value = $('.ppc-roles-tab-content input[name="role_slug"]').val();
257
+ var slugexists = $('#pp-role-slug-exists')
258
+ var all_roles = $('.ppc-roles-all-roles').val();
259
+ var role_array = all_roles.split(',');
260
+ if (role_array.includes(value)) {
261
+ slugexists.show();
262
+ } else {
263
+ slugexists.hide();
264
+ }
265
+ }
266
+ }
267
+
268
  });
includes/roles/roles-functions.php CHANGED
@@ -27,9 +27,11 @@ function admin_roles_page_load()
27
 
28
  //enqueue scripts
29
  wp_enqueue_script($plugin_name . '_table_edit', plugin_dir_url(CME_FILE) . 'includes/roles/js/pp-roles-admin.js', ['jquery'], PUBLISHPRESS_CAPS_VERSION, false);
 
30
 
31
  //Localize
32
  wp_localize_script($plugin_name . '_table_edit', 'pp_roles_i18n', ['confirm_delete' => __('Are you sure you want to delete this role?', 'capsman-enhanced')]);
 
33
 
34
  //initialize table here to be able to register default WP_List_Table screen options
35
  pp_capabilities_roles()->admin->get_roles_list_table();
27
 
28
  //enqueue scripts
29
  wp_enqueue_script($plugin_name . '_table_edit', plugin_dir_url(CME_FILE) . 'includes/roles/js/pp-roles-admin.js', ['jquery'], PUBLISHPRESS_CAPS_VERSION, false);
30
+ wp_enqueue_script('pp-capabilities-chosen-js', plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.jquery.js', ['jquery'], PUBLISHPRESS_CAPS_VERSION);
31
 
32
  //Localize
33
  wp_localize_script($plugin_name . '_table_edit', 'pp_roles_i18n', ['confirm_delete' => __('Are you sure you want to delete this role?', 'capsman-enhanced')]);
34
+ wp_enqueue_style('pp-capabilities-chosen-css', plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.css', false, PUBLISHPRESS_CAPS_VERSION);
35
 
36
  //initialize table here to be able to register default WP_List_Table screen options
37
  pp_capabilities_roles()->admin->get_roles_list_table();
languages/capsman-enhanced-fr_FR.mo CHANGED
Binary file
languages/capsman-enhanced-fr_FR.po CHANGED
@@ -2,881 +2,714 @@
2
  # This file is distributed under the same license as the Plugins - PublishPress Capabilities &#8211; User Role Access, Editor Permissions, Admin Menus - Stable (latest release) package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Plugins - PublishPress Capabilities &#8211; User Role "
6
- "Access, Editor Permissions, Admin Menus - Stable (latest release)\n"
7
- "POT-Creation-Date: 2022-04-19 14:06-0400\n"
8
- "PO-Revision-Date: 2022-04-19 14:07-0400\n"
9
- "Last-Translator: Kevin Behrens <kevin@publishpress.com>\n"
10
  "Language-Team: Angelo Giammarresi - info@wocmultimedia.com\n"
11
  "Language: fr\n"
12
  "MIME-Version: 1.0\n"
13
  "Content-Type: text/plain; charset=UTF-8\n"
14
  "Content-Transfer-Encoding: 8bit\n"
15
  "Plural-Forms: nplurals=2; plural=n > 1;\n"
16
- "X-Generator: Poedit 2.4.3\n"
17
- "X-Poedit-KeywordsList: __;_e;_c;_n;_x;_ex;__ngettext;esc_html__;esc_html_e\n"
18
- "X-Poedit-Basepath: ..\n"
19
- "X-Poedit-SearchPath-0: .\n"
20
- "X-Poedit-SearchPath-1: classes\n"
21
- "X-Poedit-SearchPath-2: includes\n"
22
- "X-Poedit-SearchPath-3: includes-core\n"
23
-
24
- #: capsman-enhanced.php:40
25
- #, fuzzy, php-format
26
- #| msgid ""
27
- #| "<strong>Error:</strong> PublishPress Capabilities cannot function because "
28
- #| "another copy of Capability Manager is active."
29
- msgid ""
30
- "%1s Error: %2s PublishPress Capabilities cannot function because another "
31
- "copy of Capability Manager is active."
32
- msgstr ""
33
- "<strong>Erreur :</strong> PublishPress Capabilities ne peut être activée car "
34
- "un autre gestionnaire de permission est activé."
35
 
36
- #: capsman-enhanced.php:70
37
- #, fuzzy
38
- #| msgid "<strong>This plugin can be deleted.</strong>"
39
- msgid "This plugin can be deleted."
40
- msgstr "<strong>Cette extension peut être supprimée.</strong>"
41
 
42
- #: capsman-enhanced.php:97
43
- msgid "Warning:"
44
- msgstr "Avertissement :"
45
 
46
- #: capsman-enhanced.php:98
47
- #, php-format
48
- msgid "The active plugin %s is not compatible with your PHP version."
49
- msgstr "L’extension active %s n’est pas compatible avec votre version de PHP."
50
 
51
- #: capsman-enhanced.php:100
52
- #, php-format
53
- msgid "%s is required for this plugin."
54
- msgstr "%s est requis pour cette extension."
 
 
55
 
56
- #: framework/lib/formating.php:40
57
- msgid "Settings saved."
58
- msgstr "Réglages enregistrés."
 
59
 
60
- #: includes-core/CoreAdmin.php:62 includes/admin-load.php:311
61
- msgid "Admin Menus"
62
- msgstr "Menus d’administration"
63
 
64
- #: includes-core/CoreAdmin.php:63 includes/admin-load.php:312
65
- msgid "Nav Menus"
66
- msgstr "Menus de navigation"
67
 
68
- #: includes-core/admin-features-promo.php:74
69
- msgid ""
70
- "You can block pages by URL or hide Admin elements by entering a CSS class or "
71
- "ID. This feature is available in PublishPress Capabilities Pro."
72
- msgstr ""
73
- "Vous pouvez bloquer des pages par URL ou masquer des éléments de "
74
- "l’administration en saisissant une classe ou un ID CSS. Cette fonctionnalité "
75
- "est disponible dans PublishPress Capabilities Pro."
76
 
77
- #: includes-core/admin-features-promo.php:79
78
- #: includes-core/admin-menus-promo.php:62
79
- #: includes-core/editor-features-promo.php:91
80
- #: includes-core/nav-menus-promo.php:67 includes/admin-load.php:322
81
- #: includes/admin-load.php:323 includes/manager.php:388
82
- #: includes/manager.php:389
83
- msgid "Upgrade to Pro"
84
- msgstr "Mettre à niveau en Pro"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- #: includes-core/admin-menus-promo.php:29
87
- msgid "Admin Menu Restrictions"
88
- msgstr "Restrictions du menu d’administration"
89
 
90
- #: includes-core/admin-menus-promo.php:58
91
- msgid ""
92
- "You can restrict access to admin menu screens. This feature is available in "
93
- "PublishPress Capabilities Pro"
94
- msgstr ""
95
- "Vous pouvez restreindre l’accès aux écrans du menu d’administration. Cette "
96
- "fonctionnalité est disponible dans PublishPress Capabilities Pro"
97
 
98
- #: includes-core/editor-features-promo.php:24
99
- msgid "Metaboxes"
100
- msgstr "Boîtes méta"
101
 
102
- #: includes-core/editor-features-promo.php:32
103
- msgid "Checklist"
104
- msgstr "Liste de contrôle"
105
 
106
- #: includes-core/editor-features-promo.php:45
107
- msgid "Editorial Comments"
108
- msgstr "Commentaires éditoriaux"
109
 
110
- #: includes-core/editor-features-promo.php:58
111
- msgid "Notifications"
112
- msgstr "Notifications"
113
 
114
- #: includes-core/editor-features-promo.php:71
115
- msgid "TaxoPress - Settings"
116
- msgstr "TaxoPress - Réglages"
117
 
118
- #: includes-core/editor-features-promo.php:86
119
- msgid ""
120
- "You can hide plugin metaboxes. You can also hide specific items by entering "
121
- "their CSS class or ID. This feature is available in PublishPress "
122
- "Capabilities Pro."
123
- msgstr ""
124
- "Vous pouvez masquer les boîtes méta des extensions. Vous pouvez également "
125
- "masquer des éléments spécifiques en saisissant leur classe CSS ou leur ID. "
126
- "Cette fonctionnalité est disponible dans PublishPress Capabilities Pro."
127
 
128
- #: includes-core/editor-features-promo.php:101
129
- msgid "Custom Items"
130
- msgstr "Éléments personnalisés"
131
 
132
- #: includes-core/editor-features-promo.php:107
133
- msgid "Custom item one"
134
- msgstr "Élément personnalisé un"
135
 
136
- #: includes-core/editor-features-promo.php:108
137
- #: includes-core/editor-features-promo.php:122
138
- #: includes-core/editor-features-promo.php:135
139
- #: includes/features/admin-features.php:190
140
- #: includes/features/editor-features-classic.php:80
141
- #: includes/features/editor-features-gutenberg.php:79
142
- #: includes/roles/class/class-pp-roles-admin.php:116
143
- #: includes/roles/class/class-pp-roles-list-table.php:277
144
- #: includes/roles/class/class-pp-roles-list-table.php:414
145
- msgid "Delete"
146
- msgstr "Supprimer"
147
 
148
- #: includes-core/editor-features-promo.php:121
149
- msgid "Permalink: Descriptive Caption"
150
- msgstr "Permalien : Légende descriptive"
151
 
152
- #: includes-core/editor-features-promo.php:135
153
- msgid "Page Attributes: Order"
154
- msgstr "Attributs de la page : Tri"
155
 
156
- #: includes-core/nav-menus-promo.php:29
157
- msgid "Navigation Menu Restrictions"
158
- msgstr "Restrictions du menu de navigation"
159
 
160
- #: includes-core/nav-menus-promo.php:63
161
- msgid ""
162
- "You can restrict access to navigation menus. This feature is available in "
163
- "PublishPress Capabilities Pro"
164
- msgstr ""
165
- "Vous pouvez restreindre l’accès aux menus de navigation. Cette "
166
- "fonctionnalité est disponible dans PublishPress Capabilities Pro"
167
 
168
- #: includes/admin-load.php:286 includes/manager.php:339
169
- #: includes/roles/class/class-pp-roles-admin.php:416
170
- #: includes/roles/class/class-pp-roles-list-table.php:213
171
- msgid "Capabilities"
172
- msgstr "Permissions"
173
 
174
- #: includes/admin-load.php:308 includes/manager.php:361
175
- #: includes/roles/roles.php:8
176
- msgid "Roles"
177
- msgstr "Rôles"
178
 
179
- #: includes/admin-load.php:309 includes/manager.php:373
180
- msgid "Editor Features"
181
- msgstr "Fonctionnalités de l’éditeur"
182
 
183
- #: includes/admin-load.php:310 includes/manager.php:375
184
- msgid "Admin Features"
185
- msgstr "Fonctionnalités administratives"
186
 
187
- #: includes/admin-load.php:313 includes/backup.php:49 includes/manager.php:379
188
- msgid "Backup"
189
- msgstr "Sauvegarde"
190
 
191
- #: includes/admin-load.php:316
192
- #: includes/features/restrict-editor-features.php:309 includes/manager.php:382
193
- msgid "Settings"
194
- msgstr "Réglages"
195
 
196
- #: includes/admin.php:40
197
- #, php-format
198
- msgid ""
199
- "Warning: This role cannot access the dashboard without the read capability. "
200
- "%1$sClick here to fix this now%2$s."
201
- msgstr ""
202
- "Avertissement : ce rôle ne peut accéder au tableau de bord sans la "
203
- "permission de lecture. %1$sCliquez ici pour le corriger%2$s."
204
 
205
- #: includes/admin.php:59
206
- msgid "Role Capabilities"
207
- msgstr "Permissions du rôle"
208
 
209
- #: includes/admin.php:113 includes/admin.php:1348
210
- msgid "Save Changes"
211
- msgstr "Enregistrer les modifications"
212
 
213
- #: includes/admin.php:132
214
- #, php-format
215
- msgid ""
216
- "<strong>Note:</strong> Capability changes <strong>remain in the database</"
217
- "strong> after plugin deactivation. You can also configure this role as a "
218
- "%sPermission Group%s."
219
- msgstr ""
220
- "<strong>Note : </strong>Les changements de permission<strong> restent dans "
221
- "la base de données</strong> après la désactivation de l’extension. Vous "
222
- "pouvez également configurer ce rôle en tant que %sGroupe de droits%s."
223
 
224
- #: includes/admin.php:140
225
- msgid ""
226
- "<strong>Note:</strong> Capability changes <strong>remain in the database</"
227
- "strong> after plugin deactivation."
228
- msgstr ""
229
- "<strong>Note :</strong> Les changements de permission <strong>restent dans "
230
- "la base de données</strong> après la désactivation du plugin."
231
 
232
- #: includes/admin.php:221
233
- msgid "&nbsp;"
234
- msgstr "&nbsp;"
235
 
236
- #: includes/admin.php:222
237
- msgid "Reading"
238
- msgstr "Lecture"
239
 
240
- #: includes/admin.php:223
241
- msgid "Editing"
242
- msgstr "Édition"
243
 
244
- #: includes/admin.php:224
245
- msgid "Deletion"
246
- msgstr "Supression"
247
 
248
- #: includes/admin.php:316
249
- msgid "WordPress Core"
250
- msgstr "WordPress Core"
251
 
252
- #: includes/admin.php:490 includes/admin.php:978
253
- msgid "Invalid Capabilities"
254
- msgstr "Permissions invalides"
255
 
256
- #: includes/admin.php:495
257
- msgid "Additional"
258
- msgstr "Additionnel"
259
 
260
- #: includes/admin.php:539
261
- #, php-format
262
- msgid "Term %s Capabilities"
263
- msgstr "Permissions de le terme %s"
264
 
265
- #: includes/admin.php:539
266
- #, php-format
267
- msgid "Post %s Capabilities"
268
- msgstr "Permissions de la publication %s"
269
 
270
- #: includes/admin.php:545
271
- msgid "Filter by taxonomy"
272
- msgstr "Filtrer par taxonomie"
 
 
 
 
273
 
274
- #: includes/admin.php:545
275
- msgid "Filter by post type"
276
- msgstr "Filtrer par type de publication"
277
 
278
- #: includes/admin.php:548 includes/admin.php:736 includes/admin.php:874
279
- #: includes/admin.php:1080
280
- msgid "Clear"
281
- msgstr "Effacer"
282
 
283
- #: includes/admin.php:640 includes/admin.php:782 includes/admin.php:922
284
- #: includes/admin.php:1153
285
- #, php-format
286
- msgid "%s: assigned by Permission Group"
287
- msgstr "%s : attribué par le groupe de permission"
288
 
289
- #: includes/admin.php:652
290
- #, php-format
291
- msgid "shared capability: %s"
292
- msgstr "permission partagée : %s"
293
 
294
- #: includes/admin.php:732
295
- msgid "WordPress Core Capabilities"
296
- msgstr "Permissions de base de WordPress"
297
 
298
- #: includes/admin.php:738 includes/admin.php:876 includes/admin.php:1082
299
- msgid "No results found. Please try again with a different word."
300
- msgstr "Aucun résultat trouvé. Veuillez réessayer avec un autre mot."
301
 
302
- #: includes/admin.php:749 includes/admin.php:843 includes/admin.php:887
303
- #: includes/admin.php:960 includes/admin.php:1088 includes/admin.php:1205
304
- #, fuzzy
305
- #| msgid "Capabilities"
306
- msgid "Capability Name"
307
- msgstr "Permissions"
308
 
309
- #: includes/admin.php:801
310
- msgid ""
311
- "Lockout Prevention: To remove read capability, first remove WordPress "
312
- "admin / editing capabilities, or add \"dashboard_lockout_ok\" capability"
313
- msgstr ""
314
- "Prévention du verrouillage : pour supprimer la permission de lecture, "
315
- "supprimez d’abord les permissions d’administration/édition de WordPress ou "
316
- "ajoutez la permission « dashboard_lockout_ok »"
317
 
318
- #: includes/admin.php:870
319
- #, php-format
320
- msgid "Plugin Capabilities &ndash; %s"
321
- msgstr "Plugin Capabilities &ndash; %s"
322
 
323
- #: includes/admin.php:991
324
- msgid ""
325
- "The following entries have no effect. Please assign desired capabilities in "
326
- "the Read / Edit / Delete grid above."
327
- msgstr ""
328
- "Les entrées suivantes n’ont aucun effet. Veuillez attribuer les permisions "
329
- "souhaitées dans la grille lire/modifier/supprimer ci-dessus."
330
 
331
- #: includes/admin.php:1076
332
- msgid "Additional Capabilities"
333
- msgstr "Permissions supplémentaires"
334
 
335
- #: includes/admin.php:1237
336
- msgid ""
337
- "Automatically define type-specific capabilities for your custom post types "
338
- "and taxonomies"
339
- msgstr ""
340
- "Définissez automatiquement les permissions spécifiques à vos types de "
341
- "publication et taxonomies personnalisés"
342
 
343
- #: includes/admin.php:1241
344
- msgid "Assign standard WP roles supplementally for a specific post type"
345
- msgstr ""
346
- "Assignez des rôles WP standard de manière complémentaire pour un type de "
347
- "publication spécifique"
348
 
349
- #: includes/admin.php:1245
350
- msgid ""
351
- "Assign custom WP roles supplementally for a specific post type <em>(Pro)</em>"
352
- msgstr ""
353
- "Assignez des rôles WP personnalisés de manière complémentaire pour un type "
354
- "de publication spécifique <em> (Pro)</em>"
355
 
356
- #: includes/admin.php:1249
357
- msgid "Customize reading permissions per-category or per-post"
358
- msgstr "Personnalisez les droits de lecture par catégorie ou par article"
359
 
360
- #: includes/admin.php:1253
361
- msgid "Customize editing permissions per-category or per-post <em>(Pro)</em>"
362
- msgstr ""
363
- "Personnalisez les droits de modification par catégorie ou par publication "
364
- "<em> (Pro)</em>"
365
-
366
- #: includes/admin.php:1257
367
- msgid ""
368
- "Custom Post Visibility statuses, fully implemented throughout wp-admin "
369
- "<em>(Pro)</em>"
370
- msgstr ""
371
- "États de visibilité de publication personnalisés, entièrement mis en œuvre "
372
- "dans wp-admin. <em> (Pro)</em>"
373
 
374
- #: includes/admin.php:1261
375
- msgid ""
376
- "Custom Moderation statuses for access-controlled, multi-step publishing "
377
- "workflow <em>(Pro)</em>"
378
- msgstr ""
379
- "États de modération personnalisés pour un flux de publication à accès "
380
- "contrôlé et à plusieurs étapes <em> (Pro)</em>"
381
 
382
- #: includes/admin.php:1265
383
- msgid "Regulate permissions for Edit Flow post statuses <em>(Pro)</em>"
384
- msgstr ""
385
- "Réglementez les droits pour modifier les états de publication Edit Flow <em> "
386
- "(Pro)</em>"
387
 
388
- #: includes/admin.php:1269
389
- msgid ""
390
- "Customize the moderated editing of published content with Revisionary or "
391
- "Post Forking <em>(Pro)</em>"
392
- msgstr ""
393
- "Personnaliser la modification modérée de la publication publié avec "
394
- "Revisionary ou Post Forking <em> (Pro)</em>"
395
 
396
- #: includes/admin.php:1273
397
- msgid ""
398
- "Grant Spectator, Participant or Moderator access to specific bbPress forums "
399
- "<em>(Pro)</em>"
400
- msgstr ""
401
- "Autorisez les visiteurs, participants ou modérateurs à accéder aux forums "
402
- "bbPress <em> (Pro)</em>"
403
 
404
- #: includes/admin.php:1277
405
- msgid ""
406
- "Grant supplemental content permissions to a BuddyPress group <em>(Pro)</em>"
407
- msgstr ""
408
- "Autorisez les droits de contenu supplémentaire au groupe BuddyPress <em> "
409
- "(Pro)</em>"
410
 
411
- #: includes/admin.php:1281
412
- msgid "WPML integration to mirror permissions to translations <em>(Pro)</em>"
413
- msgstr ""
414
- "Intégration WPML pour refléter les droits dans les traductions <em> (Pro)</"
415
- "em>"
416
 
417
- #: includes/admin.php:1285
418
- msgid "Member support forum"
419
- msgstr "Forum dassistance aux membres"
420
 
421
- #: includes/admin.php:1292
422
- #, php-format
423
- msgid "%1$sgrab%2$s %3$s"
424
- msgstr "%1$sprendre%2$s %3$s"
425
 
426
- #: includes/admin.php:1294
427
- #, php-format
428
- msgid "%1$sbuy%2$s %3$s"
429
- msgstr "%1$sacheter%2$s %3$s"
430
 
431
- #: includes/admin.php:1328
432
- msgid "Level:"
433
- msgstr "Niveau :"
 
434
 
435
- #: includes/admin.php:1361
436
- #, fuzzy
437
- #| msgid "PublishPress Capabilities"
438
- msgid "PublishPress Capabilities is safe to use"
439
- msgstr "PublishPress Capabilities"
440
 
441
- #: includes/admin.php:1363
442
- #, fuzzy
443
- #| msgid ""
444
- #| "On this screen, you can restore an earlier version of your roles and "
445
- #| "capabilities."
446
- msgid ""
447
- "This plugin automatically creates a backup whenever you save changes. You "
448
- "can use these backups to\n"
449
- "restore an earlier version of your roles and capabilities."
450
- msgstr ""
451
- "Sur cet écran, vous pouvez restaurer une version antérieure de vos rôles et "
452
- "permissions."
453
 
454
- #: includes/admin.php:1367
455
- msgid "Go to the Backup feature"
456
- msgstr ""
 
457
 
458
- #: includes/admin.php:1372
459
- msgid "Add Capability"
460
- msgstr "Ajouter une permission"
 
461
 
462
- #: includes/admin.php:1411
463
- msgid "include in new sites"
464
- msgstr "inclure dans les nouveaux sites"
465
 
466
- #: includes/admin.php:1414
467
- msgid "sync role to all sites now"
468
- msgstr "synchroniser le rôle avec tous les sites maintenant"
469
 
470
- #: includes/admin.php:1417
471
- msgid "sync options to all sites now"
472
- msgstr "synchroniser les options sur tous les sites maintenant"
473
 
474
- #: includes/backup-handler.php:15 includes/manager.php:882
475
- msgid "You do not have permission to restore roles."
476
- msgstr "Vous n’avez pas la permission de restaurer les rôles."
477
 
478
- #: includes/backup-handler.php:73
479
- msgid "New backup saved."
480
- msgstr "Nouvelle sauvegarde enregistrée."
 
481
 
482
- #: includes/backup-handler.php:90
483
- msgid "Roles and Capabilities restored from initial backup."
484
- msgstr "Rôles et capacités restaurés à partir de la sauvegarde initiale."
485
 
486
- #: includes/backup-handler.php:92 includes/backup-handler.php:121
487
- #: includes/backup-handler.php:130
488
- msgid "Restore failed. No backup found."
489
- msgstr "Echec de la restauration. Aucune sauvegarde trouvée."
490
 
491
- #: includes/backup-handler.php:119
492
- #, fuzzy, php-format
493
- #| msgid "Roles and Capabilities restored from last backup."
494
- msgid "%s restored from last backup."
495
- msgstr "Rôles et permissions restaurés à partir de la dernière sauvegarde."
496
 
497
- #: includes/backup-handler.php:128
498
- msgid "Roles and Capabilities restored from selected auto-backup."
499
- msgstr ""
500
- "Rôles et capacités restaurés à partir de la sauvegarde automatique "
501
- "sélectionnée."
502
 
503
- #: includes/backup-handler.php:140
504
- msgid "Please upload a file to import"
505
- msgstr ""
506
 
507
- #: includes/backup-handler.php:145
508
- msgid "Please upload a valid .json file"
509
- msgstr ""
510
 
511
- #: includes/backup-handler.php:165
512
- msgid "Error importing settings! Please try again."
513
- msgstr ""
514
 
515
- #: includes/backup-handler.php:178
516
- msgid ""
517
- "Error importing settings! Please check that you uploaded a valid json file."
518
- msgstr ""
519
 
520
- #: includes/backup-handler.php:199
521
- #, php-format
522
- msgid "%s successfully imported from uploaded data."
523
- msgstr ""
 
524
 
525
- #: includes/backup-handler.php:283
526
- msgid "Needed function to create default roles not found!"
527
- msgstr "Fonction nécessaire à la création des rôles par défaut non trouvée !"
528
 
529
- #: includes/backup-handler.php:296
530
- msgid "Roles and Capabilities reset to WordPress defaults"
531
- msgstr ""
532
- "Rôles et permissions réinitialisées avec les valeurs par défaut de WordPress"
533
 
534
- #: includes/backup.php:39
535
- #, fuzzy
536
- #| msgid "Backup Tool for %1$sPublishPress Capabilities%2$s"
537
- msgid "Backup Tool for PublishPress Capabilities"
538
- msgstr "Outil de sauvegarde pour %1$sPublishPress Capabilities%2$s"
539
 
540
- #: includes/backup.php:48
541
- msgid "Restore"
542
- msgstr "Restaurer"
543
 
544
- #: includes/backup.php:50
545
- msgid "Reset Roles"
546
- msgstr "Réinitialiser les rôles"
547
 
548
- #: includes/backup.php:51 includes/backup.php:309
549
- msgid "Export / Import"
550
- msgstr ""
551
 
552
- #: includes/backup.php:60
553
- msgid "Backup Roles and Capabilities"
554
- msgstr "Sauvegarder les rôles et les permissions"
555
 
556
- #: includes/backup.php:65
557
- #, php-format
558
- msgid ""
559
- "PublishPress Capabilities automatically creates a backup on installation and "
560
- "whenever you save changes. The initial backup and last %d auto-backups are "
561
- "kept."
562
- msgstr ""
563
- "PublishPress Capabilities crée automatiquement une sauvegarde lors de "
564
- "l’installation et à chaque fois que vous enregistrez des modifications. La "
565
- "sauvegarde initiale et les dernières %d sauvegardes automatiques sont "
566
- "conservées."
567
 
568
- #: includes/backup.php:70
569
- msgid ""
570
- "A backup created on this screen replaces any previous manual backups, but is "
571
- "never automatically replaced."
572
- msgstr ""
573
- "Le sauvegarde créée sur cet écran remplace toutes les sauvegardes manuelles "
574
- "précédentes, mais n’est jamais remplacée automatiquement."
575
 
576
- #: includes/backup.php:85
577
- #, php-format
578
- msgid "Last Manual Backup - %s"
579
- msgstr "Dernière sauvegarde manuelle - %s"
580
 
581
- #: includes/backup.php:85
582
- msgid "Last Backup"
583
- msgstr "Dernière sauvegarde"
584
 
585
- #: includes/backup.php:89
586
- msgid "Restore Previous Roles and Capabilities"
587
- msgstr "Restaurer les rôles et permissions antérieurs"
588
 
589
- #: includes/backup.php:92
590
- msgid ""
591
- "PublishPress Capabilities automatically creates a backup on installation and "
592
- "whenever you save changes."
593
- msgstr ""
594
- "PublishPress Capabilities crée automatiquement une sauvegarde lors de "
595
- "l’installation et à chaque fois que vous enregistrez des modifications."
596
 
597
- #: includes/backup.php:96
598
- msgid ""
599
- "On this screen, you can restore an earlier version of your roles and "
600
- "capabilities."
601
- msgstr ""
602
- "Sur cet écran, vous pouvez restaurer une version antérieure de vos rôles et "
603
- "permissions."
604
 
605
- #: includes/backup.php:101
606
- msgid "Available Backups:"
607
- msgstr "Sauvegardes disponibles :"
608
 
609
- #: includes/backup.php:114
610
- #, fuzzy
611
- msgid "all roles"
612
- msgstr "Sauvegarde automatique de tous les rôles (%s)"
 
613
 
614
- #: includes/backup.php:119
615
- #, fuzzy, php-format
616
- #| msgid "Manual backup of all roles (%s)"
617
- msgid "Manual backup of %s (%s)"
618
- msgstr "Sauvegarde manuelle de tous les rôles (%s)"
619
 
620
- #: includes/backup.php:134
621
- #, php-format
622
- msgid "Auto-backup of all roles (%s)"
623
- msgstr "Sauvegarde automatique de tous les rôles (%s)"
624
 
625
- #: includes/backup.php:142
626
- msgid "Initial backup of all roles"
627
- msgstr "Sauvegarde initiale de tous les rôles"
628
 
629
- #: includes/backup.php:162
630
- msgid "Show changes from current roles only"
631
- msgstr "Afficher uniquement les changements par rapport aux rôles actuels"
632
 
633
- #: includes/backup.php:169
634
- #, php-format
635
- msgid "Initial Backup - %s"
636
- msgstr "Sauvegarde initiale - %s"
637
 
638
- #: includes/backup.php:169
639
- msgid "Initial Backup"
640
- msgstr "Sauvegarde initiale"
641
 
642
- #: includes/backup.php:196
643
- #, php-format
644
- msgid "%s (%s roles)"
645
- msgstr "%s (%s rôles)"
646
 
647
- #: includes/backup.php:203
648
- msgid "(this role will be removed if you restore backup)"
649
- msgstr "(ce rôle sera supprimé si vous restaurez la sauvegarde)"
650
 
651
- #: includes/backup.php:232
652
- #, php-format
653
- msgid "%s (level %s)"
654
- msgstr "%s (niveau %s)"
655
 
656
- #: includes/backup.php:272
657
- msgid "No changes"
658
- msgstr "Aucun changement"
659
 
660
- #: includes/backup.php:288
661
- msgid "Reset WordPress Defaults"
662
- msgstr "Réinitialiser avec les valeurs par défaut de WordPress"
663
 
664
- #: includes/backup.php:290 includes/backup.php:347
665
- msgid "WARNING:"
666
- msgstr "Avertissement :"
667
 
668
- #: includes/backup.php:290
669
- msgid ""
670
- "Reseting default Roles and Capabilities will set them to the WordPress "
671
- "install defaults."
672
- msgstr ""
673
- "La réinitialisation des rôles et des capacités par défaut les définira sur "
674
- "les valeurs d’installation par défaut de WordPress."
675
 
676
- #: includes/backup.php:294
677
- msgid ""
678
- "If you have installed any plugin that adds new roles or capabilities, these "
679
- "will be lost."
680
- msgstr ""
681
- "Si vous avez ajouté une extension pour créer de nouveaux rôles ou "
682
- "permissions, celles-ci seront perdues."
683
 
684
- #: includes/backup.php:296
685
- msgid "It is recommended to use this only as a last resource!"
686
- msgstr "Il est recommandé de ne l’utiliser qu’en dernier recours !"
687
 
688
- #: includes/backup.php:301
689
- msgid ""
690
- "You are about to reset Roles and Capabilities to WordPress defaults.\n"
691
- " 'Cancel' to stop, 'OK' to reset."
692
- msgstr ""
693
- "Vous êtes sur le point de réinitialiser les rôles et les permissions avec "
694
- "les valeurs par défaut de WordPress.\n"
695
- "« Annuler » pour arrêter et « OK » pour réinitialiser."
696
 
697
- #: includes/backup.php:301
698
- msgid "Reset to WordPress defaults"
699
- msgstr "Réinitialiser avec les valeurs par défaut de WordPress"
700
 
701
- #: includes/backup.php:314
702
- #, fuzzy
703
- #| msgid "Text settings"
704
- msgid "Export Settings"
705
- msgstr "Réglages du texte"
706
 
707
- #: includes/backup.php:316
708
- msgid ""
709
- "Export the plugin settings for this site as a .json file. This allows you to "
710
- "easily import the configuration into another site."
711
- msgstr ""
712
 
713
- #: includes/backup.php:321
714
- #, fuzzy
715
- #| msgid "Role Capabilities"
716
- msgid "Roles and Capabilities"
717
- msgstr ""
718
- "Réinitialiser les rôles et les permissions avec les valeurs par défaut de "
719
- "WordPress"
720
 
721
- #: includes/backup.php:345
722
- #, fuzzy
723
- #| msgid "Settings"
724
- msgid "Import Settings"
725
- msgstr "Réglages"
726
 
727
- #: includes/backup.php:347
728
- msgid ""
729
- "Please make a 'Manual Backup' in the backup tab to enable backup restore in "
730
- "case anything goes wrong."
731
- msgstr ""
732
 
733
- #: includes/backup.php:349
734
- msgid ""
735
- "Import the plugin settings from a .json file. This file can be obtained by "
736
- "exporting the settings on another site using the form above."
737
- msgstr ""
738
 
739
- #: includes/backup.php:351
740
- msgid ""
741
- "Before importing, we recommend using the \"Backup\" tab to create a backup "
742
- "of your current settings."
743
- msgstr ""
744
 
745
- #: includes/backup.php:381 includes/features/admin-features.php:228
746
- #: includes/features/editor-features.php:135
747
- msgid "Recommendations for you"
748
- msgstr "Des recommandations pour vous"
749
 
750
- #: includes/backup.php:382 includes/features/admin-features.php:229
751
- #: includes/features/editor-features.php:136
752
- msgid "Control permissions for individual posts and pages"
753
- msgstr ""
754
- "Contrôlez les autorisations pour les publications et les pages individuelles"
755
 
756
- #: includes/backup.php:384 includes/features/admin-features.php:231
757
- #: includes/features/editor-features.php:138
758
- msgid "Choose who can read and edit each post."
759
- msgstr "Choisissez qui peut lire et modifier chaque publication."
760
 
761
- #: includes/backup.php:385 includes/features/admin-features.php:232
762
- #: includes/features/editor-features.php:139
763
- msgid "Allow specific user roles or users to manage each post."
764
- msgstr ""
765
- "Autorisez des rôles d’utilisateur ou utilisatrices et des utilisateurs ou "
766
- "utilisatrices spécifiques à gérer chaque publication."
767
 
768
- #: includes/backup.php:386 includes/features/admin-features.php:233
769
- #: includes/features/editor-features.php:140
770
- #, fuzzy, php-format
771
- #| msgid "PublishPress Permissions is 100% free to install."
772
- msgid "PublishPress Permissions is 100% free to install."
773
- msgstr "PublishPress Permissions est 100% gratuit à installer."
774
 
775
- #: includes/backup.php:389 includes/features/admin-features.php:236
776
- #: includes/features/editor-features.php:143
777
- msgid "Click here to install PublishPress Permissions"
778
- msgstr "Cliquez ici pour installer PublishPress Permissions"
779
 
780
- #: includes/features/admin-features.php:37
781
- msgid "Admin Feature Restrictions"
782
- msgstr "Restrictions des fonctionnalités administratives"
783
 
784
- #: includes/features/admin-features.php:53
785
- msgid ""
786
- "Note: You are only restricting access to admin features screens. Some "
787
- "plugins may also add features to other areas of WordPress."
788
- msgstr ""
789
- "Note : Vous ne limitez l’accès qu’aux écrans des fonctionnalités "
790
- "d’administration. Certaines extensions peuvent également ajouter des "
791
- "fonctionnalités à d’autres zones de WordPress."
792
 
793
- #: includes/features/editor-features-classic.php:31
794
- msgid "Classic Editor Screen"
795
- msgstr "Écran éditeur classique"
796
 
797
- #: includes/features/editor-features-classic.php:36
798
- #: includes/features/editor-features-gutenberg.php:36
799
- #, php-format
800
- msgid "%s Restrict"
801
- msgstr "Restriction %s"
802
 
803
- #: includes/features/editor-features-gutenberg.php:31
804
- msgid "Gutenberg Screen"
805
- msgstr "Écran Gutenberg"
806
 
807
- #: includes/features/editor-features.php:32
808
- msgid "Editor Feature Restriction"
809
- msgstr "Restriction des fonctionnalités de l’éditeur"
 
810
 
811
- #: includes/features/editor-features.php:48
812
- msgid ""
813
- "Select editor features to remove. Note that this screen cannot be used to "
814
- "grant additional features to any role."
815
- msgstr ""
816
- "Sélectionnez les fonctions d’éditeur à supprimer. Notez que cet écran ne "
817
- "peut pas être utilisé pour accorder des fonctionnalités supplémentaires à un "
818
- "rôle."
819
 
820
- #: includes/features/editor-features.php:92
821
- msgid "Gutenberg"
822
- msgstr "Gutenberg"
823
 
824
- #: includes/features/editor-features.php:95
825
- msgid "Classic"
826
- msgstr "Classique"
827
 
828
- #: includes/features/restrict-admin-features.php:16
829
- msgid "Header and Footer"
830
- msgstr "En-tête et pied de page"
831
 
832
- #: includes/features/restrict-admin-features.php:19
833
- msgid "Admin Toolbar"
834
- msgstr "Barre d’outils de l’administration"
835
 
836
- #: includes/features/restrict-admin-features.php:22
837
- msgid "Dashboard widgets"
838
- msgstr "Widgets de tableau de bord"
839
 
840
- #: includes/features/restrict-admin-features.php:59
841
- msgid "Mobile Menu Toggle"
842
- msgstr "Ouvrir/fermer le menu mobile"
843
 
844
- #: includes/features/restrict-admin-features.php:60
845
- msgid "WordPress Logo"
846
- msgstr "Logo de WordPress"
847
 
848
- #: includes/features/restrict-admin-features.php:61
849
- msgid "WordPress External Links"
850
- msgstr "Liens externes de WordPress"
 
851
 
852
- #: includes/features/restrict-admin-features.php:62
853
- msgid "Updates"
854
- msgstr "Mises à jour"
 
855
 
856
- #: includes/features/restrict-admin-features.php:63
857
- msgid "Comments"
858
- msgstr "Commentaires"
 
859
 
860
- #: includes/features/restrict-admin-features.php:64
861
- msgid "Right bar"
862
- msgstr "Barre de droite"
863
 
864
- #: includes/features/restrict-admin-features.php:65
865
- msgid "User actions"
866
- msgstr "Actions de l’utilisateur ou utilisatrice"
867
 
868
- #: includes/features/restrict-admin-features.php:66
869
- #: includes/features/restrict-admin-features.php:67
870
- msgid "New"
871
- msgstr "Ajouter nouveau"
872
 
873
- #: includes/features/restrict-admin-features.php:68
874
- msgid "User Display Name"
875
- msgstr "Nom affiché de l’utilisateur/utilisatrice"
 
876
 
877
- #: includes/features/restrict-admin-features.php:69
878
- msgid "Yoast SEO"
879
- msgstr "Yoast SEO"
 
 
 
 
 
880
 
881
  #: includes/features/restrict-admin-features.php:81
882
  #: includes/features/restrict-editor-features.php:42
@@ -888,967 +721,836 @@ msgstr "Options de l’écran"
888
  msgid "Help"
889
  msgstr "Aide"
890
 
891
- #: includes/features/restrict-admin-features.php:83
892
- msgid "Thank you for creating with WordPress"
893
- msgstr "Merci de faire de WordPress votre outil de création"
894
-
895
- #: includes/features/restrict-admin-features.php:84
896
- #, php-format
897
- msgid "Version %s"
898
- msgstr "Version %s"
899
-
900
- #: includes/features/restrict-admin-features.php:133
901
- msgid "Welcome panel"
902
- msgstr "Panneau d’accueil"
903
-
904
  #: includes/features/restrict-editor-features.php:40
905
  msgid "Top Tabs"
906
  msgstr "Onglets supérieurs"
907
 
908
- #: includes/features/restrict-editor-features.php:45
909
- #: includes/features/restrict-editor-features.php:48
910
- msgid "Editor"
911
- msgstr "Éditeur"
912
-
913
- #: includes/features/restrict-editor-features.php:46
914
- #: includes/filters-woocommerce.php:33 includes/roles/roles.php:10
915
- msgid "Add New"
916
- msgstr "Ajouter"
917
-
918
- #: includes/features/restrict-editor-features.php:47
919
- msgid "Title"
920
- msgstr "Titre"
921
-
922
- #: includes/features/restrict-editor-features.php:49
923
- #: includes/features/restrict-editor-features.php:321
924
- msgid "Permalink"
925
- msgstr "Permalien"
926
-
927
- #: includes/features/restrict-editor-features.php:50
928
- msgid "Media Buttons (all)"
929
- msgstr "Boutons multimédia (tous)"
930
-
931
- #: includes/features/restrict-editor-features.php:51
932
- msgid "HTML Editor Button"
933
- msgstr "Bouton de l’éditeur HTML"
934
-
935
- #: includes/features/restrict-editor-features.php:52
936
- msgid "Word count"
937
- msgstr "Nombre de mots"
938
-
939
- #: includes/features/restrict-editor-features.php:55
940
- #: includes/features/restrict-editor-features.php:56
941
- msgid "Publish Box"
942
- msgstr "Boîte de publication"
943
 
944
- #: includes/features/restrict-editor-features.php:57
945
- #: includes/features/restrict-editor-features.php:305
946
- msgid "Save Draft"
947
- msgstr "Enregistrer le brouillon"
948
 
949
- #: includes/features/restrict-editor-features.php:58
950
- #: includes/features/restrict-editor-features.php:307
951
- msgid "Preview"
952
- msgstr "Aperçu"
953
 
954
- #: includes/features/restrict-editor-features.php:59
955
- msgid "Publish Status "
956
- msgstr "État de la publication "
957
 
958
- #: includes/features/restrict-editor-features.php:60
959
- msgid "Publish Visibility"
960
- msgstr "Visibilité de la publication"
961
 
962
- #: includes/features/restrict-editor-features.php:61
963
- msgid "Password Protect This Post"
964
- msgstr "Mot de passe pour protéger cette publication"
965
 
966
- #: includes/features/restrict-editor-features.php:62
967
- msgid "Publish Actions"
968
- msgstr "Actions de publication"
969
 
970
- #: includes/features/restrict-editor-features.php:63
971
- msgid "Publish Schedule"
972
- msgstr "Calendrier de publication"
973
 
974
- #: includes/features/restrict-editor-features.php:64
975
- msgid "Date"
976
- msgstr "Date"
977
 
978
- #: includes/features/restrict-editor-features.php:65
979
- msgid "Publish"
980
- msgstr "Publier"
981
 
982
- #: includes/features/restrict-editor-features.php:68
983
- msgid "Taxonomy Boxes"
984
- msgstr "Boîtes de taxonomie"
985
 
986
- #: includes/features/restrict-editor-features.php:69
987
- #: includes/features/restrict-editor-features.php:322
988
- msgid "Categories"
989
- msgstr "Catégories"
990
 
991
- #: includes/features/restrict-editor-features.php:70
992
- msgid "Add New Category"
993
- msgstr "Ajouter une nouvelle catégorie"
994
 
995
- #: includes/features/restrict-editor-features.php:71
996
- #: includes/features/restrict-editor-features.php:323
997
- msgid "Tags"
998
- msgstr "Étiquettes"
999
 
1000
- #: includes/features/restrict-editor-features.php:83
1001
- msgid "Page Boxes"
1002
- msgstr "Cadres de page"
1003
 
1004
- #: includes/features/restrict-editor-features.php:84
1005
- msgid "Page Attributes"
1006
- msgstr "Attributs de la page"
1007
 
1008
- #: includes/features/restrict-editor-features.php:85
1009
- msgid "Parent"
1010
- msgstr "Parent"
1011
 
1012
- #: includes/features/restrict-editor-features.php:86
1013
- msgid "Page Template"
1014
- msgstr "Modèle de page"
1015
 
1016
- #: includes/features/restrict-editor-features.php:87
1017
- msgid "Order"
1018
- msgstr "Tri"
1019
 
1020
- #: includes/features/restrict-editor-features.php:90
1021
- msgid "Other Boxes"
1022
- msgstr "Autres cases"
1023
 
1024
- #: includes/features/restrict-editor-features.php:91
1025
- msgid "Featured Image"
1026
- msgstr "Image mise en avant"
1027
 
1028
- #: includes/features/restrict-editor-features.php:92
1029
- msgid "Post Slug"
1030
- msgstr "Slug de publication"
1031
 
1032
- #: includes/features/restrict-editor-features.php:93
1033
- #: includes/features/restrict-editor-features.php:339
1034
- msgid "Discussion"
1035
- msgstr "Discussion"
1036
 
1037
- #: includes/features/restrict-editor-features.php:295
1038
- msgid "Top Bar - Left"
1039
- msgstr "Barre supérieure - Gauche"
1040
 
1041
- #: includes/features/restrict-editor-features.php:296
1042
- msgid "Add block"
1043
- msgstr "Ajouter un bloc"
 
1044
 
1045
- #: includes/features/restrict-editor-features.php:297
1046
- msgid "Modes"
1047
- msgstr "Modes"
1048
 
1049
- #: includes/features/restrict-editor-features.php:298
1050
- msgid "Undo"
1051
- msgstr "Annuler"
1052
 
1053
- #: includes/features/restrict-editor-features.php:299
1054
- msgid "Redo"
1055
- msgstr "Rétablir"
 
1056
 
1057
- #: includes/features/restrict-editor-features.php:300
1058
- msgid "Details"
1059
- msgstr "Détails"
 
1060
 
1061
- #: includes/features/restrict-editor-features.php:301
1062
- msgid "Outline"
1063
- msgstr "Contour"
1064
 
1065
- #: includes/features/restrict-editor-features.php:304
1066
- msgid "Top Bar - Right"
1067
- msgstr "Barre supérieure - Droite"
1068
 
1069
- #: includes/features/restrict-editor-features.php:306
1070
- msgid "Switch to draft"
1071
- msgstr "Passer en brouillon"
1072
 
1073
- #: includes/features/restrict-editor-features.php:308
1074
- msgid "Publish / Update"
1075
- msgstr "Publier/mettre à jour"
 
 
 
 
 
 
 
 
1076
 
1077
- #: includes/features/restrict-editor-features.php:310
1078
- msgid "Options"
1079
- msgstr "Options"
1080
 
1081
- #: includes/features/restrict-editor-features.php:313
1082
- msgid "Body"
1083
- msgstr "Corps"
1084
 
1085
- #: includes/features/restrict-editor-features.php:314
1086
- msgid "Edit title"
1087
- msgstr "Modifier le titre"
 
1088
 
1089
- #: includes/features/restrict-editor-features.php:315
1090
- msgid "Content"
1091
- msgstr "Contenu"
1092
 
1093
- #: includes/features/restrict-editor-features.php:318
1094
- msgid "Document Panel"
1095
- msgstr "Panneau de publication"
1096
 
1097
- #: includes/features/restrict-editor-features.php:319
1098
- msgid "Status & visibility"
1099
- msgstr "État et visibilité"
1100
 
1101
- #: includes/features/restrict-editor-features.php:320
1102
- #, fuzzy
1103
- #| msgid "Page Template"
1104
- msgid "Template"
1105
- msgstr "Modèle de page invalide."
1106
 
1107
- #: includes/features/restrict-editor-features.php:337
1108
- msgid "Featured image"
1109
- msgstr "Image mise en avant"
1110
 
1111
- #: includes/features/restrict-editor-features.php:338
1112
- msgid "Excerpt"
1113
- msgstr "Extrait"
1114
 
1115
- #: includes/features/restrict-editor-features.php:340
1116
- msgid "Post Attributes"
1117
- msgstr "Attributs d’articles"
1118
 
1119
- #: includes/features/restrict-editor-features.php:343
1120
- #: includes/features/restrict-editor-features.php:344
1121
- msgid "Block Panel"
1122
- msgstr "Panneau de blocs"
1123
 
1124
- #: includes/features/restrict-editor-features.php:345
1125
- msgid "Paragraph"
1126
- msgstr "Paragraphe"
 
 
 
 
1127
 
1128
- #: includes/features/restrict-editor-features.php:346
1129
- msgid "Typography"
1130
- msgstr "Typographie"
 
 
 
1131
 
1132
- #: includes/features/restrict-editor-features.php:347
1133
- msgid "Color settings"
1134
- msgstr "Réglages de couleur"
1135
 
1136
- #: includes/features/restrict-editor-features.php:348
1137
- msgid "Text settings"
1138
- msgstr "Réglages du texte"
 
1139
 
1140
- #: includes/filters-woocommerce.php:32
1141
- #, php-format
1142
- msgid "All %s"
1143
- msgstr "Tous les %s"
1144
 
1145
- #: includes/filters.php:254
1146
- msgid "Edit Roles"
1147
- msgstr "Modifier les Rôles"
1148
 
1149
- #: includes/functions-admin.php:201
1150
- #, fuzzy
1151
- #| msgid "Editor Features"
1152
- msgid "Editor Feature"
1153
- msgstr "Fonctionnalités de l’éditeur"
1154
 
1155
- #: includes/functions-admin.php:212
1156
- #, fuzzy
1157
- #| msgid "Admin Features"
1158
- msgid "Admin Feature"
1159
- msgstr "Fonctionnalités administratives"
1160
 
1161
- #: includes/handler.php:45
1162
- msgid "New role created."
1163
- msgstr "Nouveau rôle créé."
1164
 
1165
- #: includes/handler.php:51
1166
- msgid "Error: Failed creating the new role."
1167
- msgstr "Erreur : Échec de la création du nouveau rôle."
1168
 
1169
- #: includes/handler.php:61 includes/handler.php:89 includes/manager.php:739
1170
- msgid "The selected role is not editable."
1171
- msgstr "Le rôle sélectionné n’est pas modifiable."
1172
 
1173
- #: includes/handler.php:119
1174
- msgid "Incorrect capability name."
1175
- msgstr "Nom de permission incorrect."
1176
 
1177
- #: includes/handler.php:124
1178
- msgid "Type / Taxonomy settings saved."
1179
- msgstr "Réglages de type/taxonomie sauvegardés."
 
1180
 
1181
- #: includes/handler.php:127
1182
- msgid "Bad form received."
1183
- msgstr "Formulaire reçu incorrect."
 
 
 
1184
 
1185
- #: includes/handler.php:250
1186
- msgid "You cannot remove Manage Capabilities from Administrators"
1187
- msgstr "Vous ne pouvez pas supprimer Gérer les permissions des administrateurs"
1188
 
1189
- #: includes/manager.php:201
1190
- msgid "Explicity negate this capability by storing as disabled"
1191
- msgstr "Annulez explicitement cette permission en la stockant comme désactivée"
1192
 
1193
- #: includes/manager.php:202
1194
- msgid "Explicitly negate these capabilities by storing as disabled"
1195
- msgstr ""
1196
- "Annulez explicitement ces permissions en les stockant comme désactivées"
1197
 
1198
- #: includes/manager.php:203
1199
- msgid "Post type registration does not define this capability distinctly"
1200
- msgstr ""
1201
- "L’enregistrement du type de publication ne définit pas cette permission de "
1202
- "manière distincte"
1203
 
1204
- #: includes/manager.php:204
1205
- msgid "This capability is explicitly negated. Click to add/remove normally."
1206
- msgstr ""
1207
- "Cette permission est explicitement niée. Cliquer pour l’ajouter/supprimer "
1208
- "normalement."
1209
 
1210
- #: includes/manager.php:205
1211
- msgid "Add or remove this capability from the WordPress role"
1212
- msgstr "Ajouter ou supprimer une permission au rôle WordPress"
1213
 
1214
- #: includes/manager.php:206
1215
- msgid "Add or remove capability from the role normally"
1216
- msgstr "Ajouter ou supprimer une permission du rôle normalement"
1217
 
1218
- #: includes/manager.php:207
1219
- msgid "Are you sure you want to delete this item ?"
1220
- msgstr "Confirmez-vous vouloir supprimer cet élément ?"
 
 
 
 
 
1221
 
1222
- #: includes/manager.php:208
1223
- msgid "Add or clear custom item entry before saving changes."
1224
- msgstr ""
1225
- "Ajoutez ou effacez une entrée d’élément personnalisé avant d’enregistrer les "
1226
- "modifications."
1227
 
1228
- #: includes/manager.php:406
1229
- msgid "Name"
1230
- msgstr "Nom du rôle"
1231
 
1232
- #: includes/manager.php:407
1233
- #: includes/roles/class/class-pp-roles-list-table.php:165
1234
- msgid "Role"
1235
- msgstr "Rôle"
1236
 
1237
- #: includes/manager.php:408
1238
- #: includes/roles/class/class-pp-roles-list-table.php:166
1239
- msgid "Users"
1240
- msgstr "Utilisateurs"
1241
 
1242
- #: includes/manager.php:435
1243
- msgid "You do not have permission to manage roles."
1244
- msgstr "Vous n’êtes pas autorisé à gérer les rôles."
1245
 
1246
- #: includes/manager.php:458 includes/manager.php:480
1247
- msgid "You do not have permission to manage editor features."
1248
- msgstr "Vous n’êtes pas autorisé à gérer les fonctionnalités de l’éditeur."
1249
 
1250
- #: includes/manager.php:502 includes/manager.php:556
1251
- msgid "Settings updated."
1252
- msgstr "Réglages mis à jour."
1253
 
1254
- #: includes/manager.php:518 includes/manager.php:540
1255
- msgid "You do not have permission to manage admin features."
1256
- msgstr ""
1257
- "Vous n’avez pas le droit de gérer les fonctionnalités d’administration."
1258
 
1259
- #: includes/manager.php:661 includes/manager.php:695 includes/manager.php:713
1260
- msgid "You do not have permission to manage capabilities."
1261
- msgstr "Vous n’avez pas le droit de gérer les permissions."
1262
 
1263
- #: includes/manager.php:727
1264
- msgid "New capability added to role."
1265
- msgstr "Nouvelle permission ajouté au rôle."
1266
 
1267
- #: includes/manager.php:768
1268
- msgid "Bad form Received"
1269
- msgstr "Formulaire reçu incorrect"
1270
 
1271
- #: includes/manager.php:920
1272
- #, fuzzy
1273
- #| msgid "You do not have sufficient permissions to perform this action."
1274
- msgid "You do not have permission to perform this action."
1275
- msgstr "Vous n’avez pas les droits suffisants pour effectuer cette action."
1276
 
1277
- #: includes/manager.php:975
1278
- #, php-format
1279
- msgid "If you like %s, please leave us a %s rating. Thank you!"
1280
- msgstr "Si vous appréciez %s, veuillez nous laisser une note de %s. Merci !"
1281
 
1282
- #: includes/manager.php:986
1283
- msgid "About"
1284
- msgstr "À propos"
1285
 
1286
- #: includes/manager.php:988
1287
- msgid "Documentation"
1288
- msgstr "Documentation"
1289
 
1290
- #: includes/manager.php:990
1291
- msgid "Contact"
1292
- msgstr "Contact"
 
1293
 
1294
- #: includes/pp-ui.php:58
1295
- #, php-format
1296
- msgid "see %1$sRole Usage%2$s: \"Pattern Roles\""
1297
- msgstr "voir %1$sUtilisation des rôles%2$s : « Modèle de rôle »."
1298
 
1299
- #: includes/pp-ui.php:60
1300
- #, php-format
1301
- msgid "activate %1$sAdvanced settings%2$s, see Role Usage"
1302
- msgstr "activer %1$sRéglages avancées%2$s, voir Utilisation des rôles"
1303
 
1304
- #: includes/pp-ui.php:65
1305
- #, php-format
1306
- msgid ""
1307
- "\"Posts\" capabilities selected here also define type-specific role "
1308
- "assignment for Permission Groups%s."
1309
- msgstr ""
1310
- "Les permissions de « publications » sélectionnées ici définissent également "
1311
- "l’attribution de rôles spécifiques au type pour les groupes de permissions%s."
1312
 
1313
- #: includes/pp-ui.php:67
1314
- #, php-format
1315
- msgid ""
1316
- "\"Posts\" capabilities selected here also define type-specific role "
1317
- "assignment for Permit Groups%s."
1318
- msgstr ""
1319
- "Les permissions de « publications » sélectionnées ici définissent également "
1320
- "l’attribution de rôles spécifiques au type pour les groupes de permissions%s."
1321
 
1322
- #: includes/pp-ui.php:75
1323
- #, php-format
1324
- msgid ""
1325
- "Capabilities for custom statuses can be manually added here. (See "
1326
- "%sPermissions > Post Statuses%s for applicable names). %sSupplemental status-"
1327
- "specific roles%s are usually more convenient, though."
1328
- msgstr ""
1329
- "Les permissions pour les états personnalisés peuvent être ajoutées "
1330
- "manuellement ici. (Voir %sPermissions > Afficher les états%s pour les noms "
1331
- "applicables). Cependant, les %sRôles supplémentaires spécifiques aux "
1332
- "états %s sont généralement plus pratiques, cependant."
1333
 
1334
- #: includes/pp-ui.php:77
1335
- msgid ""
1336
- "Capabilities for custom statuses can be manually added here. Or activate the "
1337
- "PP Custom Post Statuses extension to assign status-specific supplemental "
1338
- "roles."
1339
- msgstr ""
1340
- "Les permissions pour les états personnalisés peuvent être ajoutées "
1341
- "manuellement ici. Ou activez l’extension PP Custom Post Statuses pour "
1342
- "affecter des rôles supplémentaires spécifiques à l’état."
1343
 
1344
- #: includes/pp-ui.php:80
1345
- msgid ""
1346
- "Capabilities for custom statuses can be manually added to a role here (see "
1347
- "Conditions > Status > Capability Mapping for applicable names). However, it "
1348
- "is usually more convenient to use Permit Groups to assign a supplemental "
1349
- "status-specific role."
1350
- msgstr ""
1351
- "Les permissions pour les états personnalisés peuvent être ajoutées "
1352
- "manuellement à un rôle ici (voir Conditions > États > Mappage des "
1353
- "permissions pour les noms applicables). Toutefois, il est généralement plus "
1354
- "pratique d’utiliser les groupes de permissions pour attribuer un rôle "
1355
- "supplémentaire spécifique à l’etat."
1356
 
1357
- #: includes/pp-ui.php:93
1358
- msgid "Type-Specific Capabilities"
1359
- msgstr "Permissions spécifiques par type"
1360
 
1361
- #: includes/pp-ui.php:96
1362
- msgid "Ensure permissions can be controlled separately from other post types."
1363
- msgstr ""
1364
- "Assurez-vous que les droits peuvent être contrôlés séparément des autres "
1365
- "types de publication."
1366
 
1367
- #: includes/pp-ui.php:159
1368
- msgid "Use create_posts capability"
1369
- msgstr "Utilisez la permission create_posts"
1370
 
1371
- #: includes/pp-ui.php:177
1372
- msgid "Taxonomy-Specific Capabilities"
1373
- msgstr "Taxonomies spécifiques aux permissions"
1374
 
1375
- #: includes/pp-ui.php:180
1376
- msgid "Ensure permissions can be controlled separately from other taxonomies."
1377
- msgstr ""
1378
- "Cela vous garantit que les droits peuvent être contrôlés séparément des "
1379
- "autres taxonomies."
1380
 
1381
- #: includes/pp-ui.php:236
1382
- msgid "Detailed Taxonomy Capabilities"
1383
- msgstr "Permissions détaillées de la taxonomie"
1384
 
1385
- #: includes/pp-ui.php:239
1386
- msgid ""
1387
- "Enforce Edit, Delete and Assign capabilities separately from Management "
1388
- "capability."
1389
- msgstr ""
1390
- "Appliquez les permissions de modification, de suppression et d’attribution "
1391
- "séparément de la gestion des permissions."
1392
 
1393
- #: includes/roles/class/class-pp-roles-actions.php:148
1394
- msgid "You do not have sufficient permissions to perform this action."
1395
- msgstr "Vous n’avez pas les droits suffisants pour effectuer cette action."
1396
 
1397
- #: includes/roles/class/class-pp-roles-actions.php:162
1398
- #: includes/roles/class/class-pp-roles-actions.php:180
1399
- #: includes/roles/class/class-pp-roles-actions.php:288
1400
- #: includes/roles/class/class-pp-roles-actions.php:385
1401
- msgid "Your link has expired, refresh the page and try again."
1402
- msgstr "Votre lien a expiré, rafraîchissez la page et réessayez."
1403
 
1404
- #: includes/roles/class/class-pp-roles-actions.php:184
1405
- #: includes/roles/class/class-pp-roles-actions.php:292
1406
- #: includes/roles/class/class-pp-roles-actions.php:409
1407
- #: includes/roles/class/class-pp-roles-actions.php:534
1408
- #: includes/roles/class/class-pp-roles-actions.php:595
1409
- msgid "Missing parameters, refresh the page and try again."
1410
- msgstr "Il y a des paramètres manquants, rafraîchissez la page et réessayez."
1411
 
1412
- #: includes/roles/class/class-pp-roles-actions.php:211
1413
- #, php-format
1414
- msgid "Invalid role name entry: %s"
1415
- msgstr "Entrée de nom de rôle invalide : %s"
1416
 
1417
- #: includes/roles/class/class-pp-roles-actions.php:223
1418
- #, php-format
1419
- msgid "The role \"%s\" already exists. Please choose a different name."
1420
- msgstr "Le rôle « %s » existe déjà. Veuillez choisir un autre nom."
1421
 
1422
- #: includes/roles/class/class-pp-roles-actions.php:247
1423
- msgid ""
1424
- "Something went wrong, the system wasn't able to create the role, refresh the "
1425
- "page and try again."
1426
- msgstr ""
1427
- "Quelque chose s’est mal passé, le système n’a pas été en mesure de créer le "
1428
- "rôle, rafraîchissez la page et réessayez."
1429
 
1430
- #: includes/roles/class/class-pp-roles-actions.php:255
1431
- #, php-format
1432
- msgid "The new role %s was created successfully."
1433
- msgstr "Le nouveau rôle %s a été créé avec succès."
1434
 
1435
- #: includes/roles/class/class-pp-roles-actions.php:344
1436
- #, fuzzy, php-format
1437
- #| msgid "The new role %s was created successfully."
1438
- msgid "%s role updated successfully."
1439
- msgstr "Le nouveau rôle %s a été créé avec succès."
1440
 
1441
- #: includes/roles/class/class-pp-roles-actions.php:417
1442
- #, php-format
1443
- msgid ""
1444
- "Cannot delete default role. You <a href=\"%s\">have to change it first</a>."
1445
- msgstr ""
1446
- "Vous ne pouvez pas modifier le rôle par defaut. Vous devez d’abord <a href="
1447
- "\"%s\">le modifier</a>."
1448
 
1449
- #: includes/roles/class/class-pp-roles-actions.php:436
1450
- msgid "Deleting a system role is not allowed."
1451
- msgstr "La suppression d’un rôle système n’est pas autorisée."
1452
 
1453
- #: includes/roles/class/class-pp-roles-actions.php:458
1454
- #, php-format
1455
- msgid "%1$d users moved to default role %2$s."
1456
- msgstr "%1$d utilisateurs déplacés vers le rôle par défaut %2$s."
1457
 
1458
- #: includes/roles/class/class-pp-roles-actions.php:463
1459
- #, php-format
1460
- msgid "The role %1$s was successfully deleted. %2$s"
1461
- msgstr "Le rôle %1$s a été supprimé avec succès. %2$s"
1462
 
1463
- #: includes/roles/class/class-pp-roles-actions.php:469
1464
- #, php-format
1465
- msgid "The selected %1$s roles were successfully deleted. %2$s"
1466
- msgstr "Les rôles %1$s sélectionnés ont été supprimés avec succès. %2$s"
1467
 
1468
- #: includes/roles/class/class-pp-roles-actions.php:491
1469
- msgid "The role could not be deleted."
1470
- msgstr "Le rôle na pas pu être supprimé."
1471
 
1472
- #: includes/roles/class/class-pp-roles-actions.php:545
1473
- #, php-format
1474
- msgid "The role %1$s was successfully hidden."
1475
- msgstr "Le rôle %1$s a été masqué avec succès."
1476
 
1477
- #: includes/roles/class/class-pp-roles-actions.php:605
1478
- #, php-format
1479
- msgid "The role %1$s was successfully unhidden."
1480
- msgstr "Le rôle %1$s a été affiché avec succès."
1481
 
1482
- #: includes/roles/class/class-pp-roles-admin.php:105
1483
- msgid "General"
1484
- msgstr ""
1485
 
1486
- #: includes/roles/class/class-pp-roles-admin.php:109
1487
- msgid "Advanced"
1488
- msgstr ""
1489
 
1490
- #: includes/roles/class/class-pp-roles-admin.php:145
1491
- #: includes/roles/class/class-pp-roles-list-table.php:164
1492
- msgid "Role Name"
1493
- msgstr "Nom du rôle"
1494
 
1495
- #: includes/roles/class/class-pp-roles-admin.php:153
1496
- #, fuzzy
1497
- #| msgid "Post Slug"
1498
- msgid "Role Slug"
1499
- msgstr "Slug de publication"
1500
 
1501
- #: includes/roles/class/class-pp-roles-admin.php:154
1502
- msgid ""
1503
- "The \"slug\" is the URL-friendly version of the role. It is usually all "
1504
- "lowercase and contains only letters, numbers and underscores."
1505
- msgstr ""
1506
 
1507
- #: includes/roles/class/class-pp-roles-admin.php:162
1508
- #, fuzzy
1509
- #| msgid "Role Name"
1510
- msgid "Role Level"
1511
- msgstr "Nom du rôle"
1512
 
1513
- #: includes/roles/class/class-pp-roles-admin.php:183
1514
- #, fuzzy
1515
- #| msgid "Delete Role"
1516
- msgid "Delete role"
1517
- msgstr "Supprimer le rôle"
1518
 
1519
- #: includes/roles/class/class-pp-roles-admin.php:184
1520
- msgid ""
1521
- "Deleting this role will completely remove it from database and is "
1522
- "irrecoverable."
1523
- msgstr ""
1524
 
1525
- #: includes/roles/class/class-pp-roles-admin.php:240
1526
- msgid "Slug already exists"
1527
- msgstr ""
1528
 
1529
- #: includes/roles/class/class-pp-roles-admin.php:320
1530
- #, php-format
1531
  msgid ""
1532
- "%s role copied to editor. Please click the \"Create Role\" button to create "
1533
- "this new role."
1534
  msgstr ""
 
 
1535
 
1536
- #: includes/roles/class/class-pp-roles-admin.php:326
1537
- #, fuzzy
1538
- #| msgid "Update"
1539
- msgid "Update Role"
1540
- msgstr "Mettre à jour"
1541
 
1542
- #: includes/roles/class/class-pp-roles-admin.php:326
1543
- #, fuzzy
1544
- #| msgid "Delete Role"
1545
- msgid "Create Role"
1546
- msgstr "Supprimer le rôle"
1547
 
1548
- #: includes/roles/class/class-pp-roles-admin.php:334
1549
- #, fuzzy
1550
- #| msgid "Edit Roles"
1551
- msgid "Edit Role"
1552
- msgstr "Modifier les Rôles"
1553
 
1554
- #: includes/roles/class/class-pp-roles-admin.php:336
1555
- #, fuzzy
1556
- #| msgid "Your Role"
1557
- msgid "Copy Role"
1558
- msgstr "Ton rôle"
1559
 
1560
- #: includes/roles/class/class-pp-roles-admin.php:338
1561
- #, fuzzy
1562
- #| msgid "Add New Role"
1563
- msgid "Create New Role"
1564
- msgstr "Ajouter un nouveau rôle"
1565
 
1566
- #: includes/roles/class/class-pp-roles-admin.php:342
1567
- #, fuzzy
1568
- #| msgid "Roles"
1569
- msgid "All Roles"
1570
- msgstr "Sauvegarde automatique de tous les rôles (%s)"
1571
 
1572
- #: includes/roles/class/class-pp-roles-admin.php:421
1573
- #, php-format
1574
- msgid "These can be edited on the %1s Capabilities screen %2s"
1575
- msgstr ""
1576
 
1577
- #: includes/roles/class/class-pp-roles-admin.php:448
1578
- msgid "Load More"
1579
- msgstr ""
1580
 
1581
- #: includes/roles/class/class-pp-roles-admin.php:451
1582
- msgid "Load Less"
1583
- msgstr ""
1584
 
1585
- #: includes/roles/class/class-pp-roles-list-table.php:225
1586
- #, fuzzy
1587
- #| msgid "Editor"
1588
- msgid "Edit"
1589
- msgstr "Modifier"
1590
 
1591
- #: includes/roles/class/class-pp-roles-list-table.php:236
1592
- msgid "Copy"
1593
- msgstr "Copier"
1594
 
1595
- #: includes/roles/class/class-pp-roles-list-table.php:241
1596
- msgid "(non-editable role)"
1597
- msgstr "(rôle non modifiable)"
1598
 
1599
- #: includes/roles/class/class-pp-roles-list-table.php:259
1600
- msgid "Unhide"
1601
- msgstr "Afficher"
1602
 
1603
- #: includes/roles/class/class-pp-roles-list-table.php:296
1604
- msgid "Hide"
1605
- msgstr "Masquer"
1606
 
1607
- #: includes/roles/class/class-pp-roles-list-table.php:347
1608
- msgid "Default Role"
1609
- msgstr "Rôle par défaut"
1610
 
1611
- #: includes/roles/class/class-pp-roles-list-table.php:352
1612
- msgid "Your Role"
1613
- msgstr "Ton rôle"
1614
 
1615
- #: includes/roles/roles-functions.php:32
1616
- msgid "Are you sure you want to delete this role?"
1617
- msgstr "Confirmez-vous la suppression de ce rôle ?"
1618
 
1619
- #: includes/roles/roles.php:15
1620
- #, php-format
1621
- msgid "Search results for &#8220;%s&#8221;"
1622
- msgstr "Résultats de la recherche pour &#171; %s &#187;"
1623
 
1624
- #: includes/roles/roles.php:26
1625
- msgid "Search Roles"
1626
- msgstr "Recherche de rôles"
1627
 
1628
- #: includes/roles/roles.php:34
1629
- msgid "Description here."
1630
- msgstr "Description ici."
1631
 
1632
- #: includes/settings.php:14
1633
- msgid "Capabilities Settings"
1634
- msgstr "Réglages des permissions"
1635
 
1636
- #: includes/settings.php:24
1637
- msgid "Related Permissions Plugins"
1638
- msgstr "Extensions de droits similaires"
1639
 
1640
- #: includes/settings.php:29
1641
- msgid "PublishPress"
1642
- msgstr "PublishPress"
 
 
 
1643
 
1644
- #: includes/settings.php:34
1645
- msgid "PublishPress Authors"
1646
- msgstr "PublishPress Authors"
1647
 
1648
- #: includes/settings.php:40
1649
- msgid "PublishPress Permissions"
1650
- msgstr "PublishPress Permissions"
1651
 
1652
- #: includes/settings.php:46
1653
- msgid "PublishPress Revisions"
1654
- msgstr "PublishPress Revisions"
 
1655
 
1656
- #: includes/settings.php:48
1657
- msgid "Help / Contact Form"
1658
- msgstr "Aide/Formulaire de contact"
 
1659
 
1660
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:332
1661
- #, php-format
1662
- msgid ""
1663
- "Hey, you've been using %1$s for %2$s on your site. We hope the plugin has "
1664
- "been useful. Please could you quickly leave a 5-star rating on WordPress."
1665
- "org? It really does help to keep %1$s growing."
1666
- msgstr ""
1667
 
1668
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:342
1669
- msgid "1 week"
1670
- msgstr ""
 
1671
 
1672
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:350
1673
- msgid "1 month"
1674
- msgstr ""
1675
 
1676
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:361
1677
- msgid "3 months"
1678
- msgstr ""
1679
 
1680
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:615
1681
- #, php-format
1682
- msgid "Click here to add your rating for %s"
1683
- msgstr ""
1684
 
1685
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:621
1686
- msgid "Maybe later"
1687
- msgstr ""
1688
 
1689
- #: vendor/publishpress/wordpress-reviews/ReviewsController.php:626
1690
- msgid "I already did"
1691
- msgstr ""
1692
 
1693
- #: vendor/publishpress/wordpress-version-notices/src/Module/MenuLink/Module.php:129
1694
- msgid "Amazing! We are redirecting you to our site..."
1695
- msgstr ""
 
 
 
 
1696
 
1697
- #~ msgid "Filter by capability"
1698
- #~ msgstr "Filtrer par permission"
 
1699
 
1700
- #~ msgid "Toggle all"
1701
- #~ msgstr "Tout masquer/afficher"
 
1702
 
1703
- #~ msgid "Copy option settings to all sites now"
1704
- #~ msgstr "Copiez les réglages des options sur tous les sites maintenant"
 
1705
 
1706
- #~ msgid "Rename"
1707
- #~ msgstr "Renommer"
 
1708
 
1709
- #~ msgid "New Role Name"
1710
- #~ msgstr "Nom du nouveau rôle"
 
1711
 
1712
- #~ msgid "Rename Role"
1713
- #~ msgstr "Renommer le rôle"
 
1714
 
1715
- #~ msgid "Restore Selected Roles"
1716
- #~ msgstr "Restaurer les rôles sélectionnés"
 
1717
 
1718
- #~ msgid "Manual Backup"
1719
- #~ msgstr "Sauvegarde manuelle"
 
1720
 
1721
- #~ msgid "Add"
1722
- #~ msgstr "Ajouter"
 
1723
 
1724
- #~ msgid "The name is how it appears on your site."
1725
- #~ msgstr "Le nom tel qu’il apparaîtra sur votre site."
 
1726
 
1727
- #~ msgid "Contact the PublishPress team"
1728
- #~ msgstr "Contact de l’équipe de PublishPress"
 
1729
 
1730
- #~ msgid "Capabilites Documentation"
1731
- #~ msgstr "Documentation de Capabilities"
 
1732
 
1733
- #~ msgid "About PublishPress Capabilities"
1734
- #~ msgstr "À propos de PublishPress Capabilities"
 
1735
 
1736
- #~ msgid ""
1737
- #~ "Make selected post types require a different capability to add new posts."
1738
- #~ msgstr ""
1739
- #~ "Faire en sorte que les types de publication sélectionnés nécessitent une "
1740
- #~ "permission différente pour ajouter de nouvelles publications."
1741
 
1742
- #~ msgid ""
1743
- #~ "Role level is mostly deprecated. However, it still determines eligibility "
1744
- #~ "for Post Author assignment and limits the application of user editing "
1745
- #~ "capabilities."
1746
- #~ msgstr ""
1747
- #~ "Le niveau de rôle est généralement obsolète. Cependant, il détermine "
1748
- #~ "toujours l’éligibilité à l’affectation d’auteur de publication et limite "
1749
- #~ "l’application des permissions de modification par l’utilisateur."
1750
 
1751
- #~ msgid "https://publishpress.com/"
1752
- #~ msgstr "https://publishpress.com/"
 
1753
 
1754
- #~ msgid "https://publishpress.com/capability-manager/"
1755
- #~ msgstr "https://publishpress.com/capability-manager/"
 
1756
 
1757
- #~ msgid ""
1758
- #~ "Manage WordPress role definitions, per-site or network-wide. Organizes "
1759
- #~ "post capabilities by post type and operation."
1760
- #~ msgstr ""
1761
- #~ "Gérez les définitions de rôles WordPress, par site ou à l’échelle du "
1762
- #~ "réseau. Organisez les permissions par type de publication."
1763
 
1764
- #~ msgid "Reset Roles and Capabilities to WordPress defaults"
1765
- #~ msgstr ""
1766
- #~ "Réinitialiser les rôles et les permissions avec les valeurs par défaut de "
1767
- #~ "WordPress"
1768
 
1769
- #~ msgid "Copy / update this role definition to all sites now"
1770
- #~ msgstr ""
1771
- #~ "Copiez/mettez à jour cette définition de rôle sur tous les sites "
1772
- #~ "maintenant"
1773
 
1774
- #~ msgid "Create this role definition in new (future) sites"
1775
- #~ msgstr "Créer cette définition de rôle dans les nouveaux (futurs) sites"
 
1776
 
1777
- #~ msgid "Add to role"
1778
- #~ msgstr "Ajouter au rôle"
 
1779
 
1780
- #~ msgid "Copy this role to"
1781
- #~ msgstr "Copier ce rôle vers"
 
1782
 
1783
- #~ msgid "hidden"
1784
- #~ msgstr "masqué"
 
1785
 
1786
- #~ msgid ""
1787
- #~ "Make role available for supplemental assignment to Permission Groups only"
1788
- #~ msgstr "Rendre ce rôle uniquement disponible aux Permissions de groupe"
1789
 
1790
- #~ msgid ""
1791
- #~ "You are about to delete the %s role.\n"
1792
- #~ "\n"
1793
- #~ " 'Cancel' to stop, 'OK' to delete."
1794
- #~ msgstr ""
1795
- #~ "Vous allez supprimer le rôle %s.\n"
1796
- #~ "\n"
1797
- #~ " « Annuler » pour arrêter, « OK » pour supprimer."
1798
 
1799
- #~ msgid "Delete this role"
1800
- #~ msgstr "Supprimer ce rôle"
 
1801
 
1802
- #~ msgid "negate none (add/remove all capabilities normally)"
1803
- #~ msgstr "ne rien nier (ajouter/supprimer les permissions normalement)"
 
1804
 
1805
- #~ msgid "negate all (storing as disabled capabilities)"
1806
- #~ msgstr "nier tout (stockage en tant que permissions désactivées)"
 
1807
 
1808
- #~ msgid "check / uncheck all"
1809
- #~ msgstr "sélectionner/désélectionner tout"
 
1810
 
1811
- #~ msgid ""
1812
- #~ "can delete posts which are currently published with private visibility"
1813
- #~ msgstr "peut supprimer les publications publiées avec une visibilité privée"
1814
 
1815
- #~ msgid "can delete posts which are currently published"
1816
- #~ msgstr "peut supprimer les publications publiées"
 
 
 
1817
 
1818
- #~ msgid "can delete posts which were created by other users"
1819
- #~ msgstr "peut supprimer les publications créés par d’autres utilisateurs"
 
1820
 
1821
- #~ msgid ""
1822
- #~ "has basic deletion capability (but may need other capabilities based on "
1823
- #~ "post status and ownership)"
1824
- #~ msgstr ""
1825
- #~ "possède la permission de supprimer de base (mais peut nécessiter d’autres "
1826
- #~ "permissions basées sur le état ou la propriété de la publication)"
1827
-
1828
- #~ msgid "can make a post publicly visible"
1829
- #~ msgstr "peut modifier la visibilité d’une publication"
1830
-
1831
- #~ msgid "can edit posts which are currently published with private visibility"
1832
- #~ msgstr "peut modifier les articles publiés avec la visibilité privée"
1833
-
1834
- #~ msgid "can edit posts which are currently published"
1835
- #~ msgstr "peut modifier les articles publiés"
1836
-
1837
- #~ msgid "can edit posts which were created by other users"
1838
- #~ msgstr "peut modifier les articles créés par d’autres utilisateurs"
1839
-
1840
- #~ msgid ""
1841
- #~ "has basic editing capability (but may need other capabilities based on "
1842
- #~ "post status and ownership)"
1843
- #~ msgstr ""
1844
- #~ "possède la permission de modifier de base (mais peut nécessiter d’autres "
1845
- #~ "permissions basées sur le état ou la propriété de la publication)"
1846
 
1847
- #~ msgid "can read posts which are currently published with private visibility"
1848
- #~ msgstr "peut lire les articles publiés avec la visibilité privée"
 
1849
 
1850
- #~ msgid "%s info/purchase"
1851
- #~ msgstr "%s infos/achat"
 
1852
 
1853
- #~ msgid "%s (free install)"
1854
- #~ msgstr "%s (installation gratuite)"
 
2
  # This file is distributed under the same license as the Plugins - PublishPress Capabilities &#8211; User Role Access, Editor Permissions, Admin Menus - Stable (latest release) package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Plugins - PublishPress Capabilities &#8211; User Role Access, Editor Permissions, Admin Menus - Stable (latest release)\n"
6
+ "POT-Creation-Date: \n"
7
+ "PO-Revision-Date: 2022-05-16 16:03+0200\n"
8
+ "Last-Translator: \n"
 
9
  "Language-Team: Angelo Giammarresi - info@wocmultimedia.com\n"
10
  "Language: fr\n"
11
  "MIME-Version: 1.0\n"
12
  "Content-Type: text/plain; charset=UTF-8\n"
13
  "Content-Transfer-Encoding: 8bit\n"
14
  "Plural-Forms: nplurals=2; plural=n > 1;\n"
15
+ "X-Generator: Poedit 3.0.1\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ #: includes/roles/class/class-pp-roles-admin.php:264
18
+ msgid "Read more on Role Level."
19
+ msgstr "Lire la suite sur le niveau de rôle."
 
 
20
 
21
+ #: includes/roles/class/class-pp-roles-admin.php:163
22
+ msgid "Each user role has a level from 0 to 10. The Subscriber role defaults to the lowest level (0). The Administrator role defaults to level 10."
23
+ msgstr "Chaque rôle d’utilisateur/utilisatrice a un niveau de 0 à 10. Le rôle d’abonné/abonnée a par défaut le niveau le plus bas (0). Le rôle d’administrateur/administratrice a le niveau 10 par défaut."
24
 
25
+ #: includes/features/editor-features.php:171
26
+ msgid "Restricted:"
27
+ msgstr "Limité :"
 
28
 
29
+ #: includes/features/editor-features.php:111
30
+ #: includes/features/editor-features.php:113
31
+ #: includes/features/editor-features.php:215
32
+ #: includes/features/editor-features.php:217
33
+ msgid "Save %s Restrictions"
34
+ msgstr "Enregistrer %s restrictions"
35
 
36
+ #: includes/features/editor-features.php:107
37
+ #: includes/features/editor-features.php:211
38
+ msgid "Save for all Post Types"
39
+ msgstr "Enregistrer pour tous les types de publication"
40
 
41
+ #: includes/features/editor-features-gutenberg.php:1
42
+ msgid "Gutenberg Editor %s Restriction"
43
+ msgstr "Restriction %s de l’éditeur Gutenberg"
44
 
45
+ #: includes/features/editor-features-classic.php:1
46
+ msgid "Classic Editor %s Restriction"
47
+ msgstr "Restriction %s de l’éditeur classique"
48
 
49
+ #: includes/roles/class/class-pp-roles-list-table.php:229
50
+ msgid "Edit"
51
+ msgstr "Modifier"
 
 
 
 
 
52
 
53
+ #: includes/roles/class/class-pp-roles-list-table.php:92
54
+ msgid "System %s"
55
+ msgid_plural "System %s"
56
+ msgstr[0] "Système %s"
57
+ msgstr[1] "Systèmes %s"
58
+
59
+ #: includes/roles/class/class-pp-roles-list-table.php:91
60
+ msgid "Uneditable %s"
61
+ msgid_plural "Uneditable %s"
62
+ msgstr[0] "Non modifiable %s"
63
+ msgstr[1] "Non modifiables %s"
64
+
65
+ #: includes/roles/class/class-pp-roles-list-table.php:90
66
+ msgid "Editable %s"
67
+ msgid_plural "Editable %s"
68
+ msgstr[0] "Modifiable %s"
69
+ msgstr[1] "Modifiables %s"
70
+
71
+ #: includes/roles/class/class-pp-roles-list-table.php:89
72
+ msgid "No Users %s"
73
+ msgid_plural "No Users %s"
74
+ msgstr[0] "Aucun utilisateur/utilisatrice %s"
75
+ msgstr[1] "Aucun utilisateurs/utilisatrices %s"
76
+
77
+ #: includes/roles/class/class-pp-roles-list-table.php:88
78
+ msgid "Has Users %s"
79
+ msgid_plural "Has Users %s"
80
+ msgstr[0] "A un utilisateur/utilisatrice %s"
81
+ msgstr[1] "A des utilisateurs/utilisatrices %s"
82
+
83
+ #: includes/roles/class/class-pp-roles-list-table.php:87
84
+ msgid "Mine %s"
85
+ msgid_plural "Mine %s"
86
+ msgstr[0] "Mon %s"
87
+ msgstr[1] "Mis %s"
88
+
89
+ #: includes/roles/class/class-pp-roles-admin.php:462
90
+ msgid "Load Less"
91
+ msgstr "Charger moins"
92
 
93
+ #: includes/roles/class/class-pp-roles-admin.php:459
94
+ msgid "Load More"
95
+ msgstr "Charger plus"
96
 
97
+ #: includes/roles/class/class-pp-roles-admin.php:431
98
+ msgid "These can be edited on the %1s Capabilities screen %2s"
99
+ msgstr "Elles peuvent être modifiées sur l’écran %1s Permissions %2s"
 
 
 
 
100
 
101
+ #: includes/roles/class/class-pp-roles-admin.php:353
102
+ msgid "All Roles"
103
+ msgstr "Tous les rôles"
104
 
105
+ #: includes/roles/class/class-pp-roles-admin.php:347
106
+ msgid "Copy Role"
107
+ msgstr "Copier le rôle"
108
 
109
+ #: includes/roles/class/class-pp-roles-admin.php:345
110
+ msgid "Edit Role"
111
+ msgstr "Modifier le rôle"
112
 
113
+ #: includes/roles/class/class-pp-roles-admin.php:337
114
+ msgid "Create Role"
115
+ msgstr "Créer le rôle"
116
 
117
+ #: includes/roles/class/class-pp-roles-admin.php:337
118
+ msgid "Update Role"
119
+ msgstr "Mettre à jour le rôle"
120
 
121
+ #: includes/roles/class/class-pp-roles-admin.php:331
122
+ msgid "%s role copied to editor. Please click the \"Create Role\" button to create this new role."
123
+ msgstr "Le rôle %s a été copié dans l’éditeur. Veuillez cliquer sur le bouton « Créer un rôle » pour créer ce nouveau rôle."
 
 
 
 
 
 
124
 
125
+ #: includes/roles/class/class-pp-roles-admin.php:241
126
+ msgid "Slug already exists"
127
+ msgstr "Ce slug existe déjà"
128
 
129
+ #: includes/roles/class/class-pp-roles-admin.php:185
130
+ msgid "Deleting this role will completely remove it from database and is irrecoverable."
131
+ msgstr "En supprimant ce rôle, il sera complètement supprimé de la base de données et sera irrécupérable."
132
 
133
+ #: includes/roles/class/class-pp-roles-admin.php:154
134
+ msgid "The \"slug\" is the URL-friendly version of the role. It is usually all lowercase and contains only letters, numbers and underscores."
135
+ msgstr "Le « slug » est la version du rôle adaptée à l’URL. Il est généralement tout en minuscules et ne contient que des lettres, des chiffres et des tirets bas."
 
 
 
 
 
 
 
 
136
 
137
+ #: includes/roles/class/class-pp-roles-admin.php:153
138
+ msgid "Role Slug"
139
+ msgstr "Slug du rôle"
140
 
141
+ #: includes/roles/class/class-pp-roles-admin.php:109
142
+ msgid "Advanced"
143
+ msgstr "Avancé"
144
 
145
+ #: includes/roles/class/class-pp-roles-admin.php:105
146
+ msgid "General"
147
+ msgstr "Général"
148
 
149
+ #: includes/roles/class/class-pp-roles-actions.php:388
150
+ msgid "%s role updated successfully."
151
+ msgstr "Le rôle de %s a bien été mis à jour."
 
 
 
 
152
 
153
+ #: includes/manager.php:939
154
+ msgid "You do not have permission to perform this action."
155
+ msgstr "Vous n’avez pas les droits nécessaires pour effectuer cette action."
 
 
156
 
157
+ #: includes/features/restrict-editor-features.php:320
158
+ msgid "Template"
159
+ msgstr "Modèle"
 
160
 
161
+ #: includes/backup.php:360
162
+ msgid "Import"
163
+ msgstr "Importer"
164
 
165
+ #: includes/backup.php:351
166
+ msgid "Before importing, we recommend using the \"Backup\" tab to create a backup of your current settings."
167
+ msgstr "Avant d’importer, nous vous recommandons d’utiliser l’onglet « Sauvegarde » pour créer une sauvegarde de vos paramètres actuels."
168
 
169
+ #: includes/backup.php:349
170
+ msgid "Import the plugin settings from a .json file. This file can be obtained by exporting the settings on another site using the form above."
171
+ msgstr "Importez les réglages de l’extension à partir d’un fichier .json. Ce fichier peut être obtenu en exportant les réglages sur un autre site à l’aide du formulaire ci-dessus."
172
 
173
+ #: includes/backup.php:347
174
+ msgid "Please make a 'Manual Backup' in the backup tab to enable backup restore in case anything goes wrong."
175
+ msgstr "Veuillez effectuer une « sauvegarde manuelle » dans l’onglet « Sauvegarde » pour permettre la restauration de la sauvegarde en cas de problème."
 
176
 
177
+ #: includes/backup.php:345
178
+ msgid "Import Settings"
179
+ msgstr "Importer les réglages"
 
 
 
 
 
180
 
181
+ #: includes/backup.php:338
182
+ msgid "Export"
183
+ msgstr "Exporter"
184
 
185
+ #: includes/backup.php:316
186
+ msgid "Export the plugin settings for this site as a .json file. This allows you to easily import the configuration into another site."
187
+ msgstr "Exportez les réglages de l’extension de ce site au format .json. Cela vous permet d’importer facilement les réglages de votre configuration sur un autre site."
188
 
189
+ #: includes/backup.php:314
190
+ msgid "Export Settings"
191
+ msgstr "Exporter les réglages"
 
 
 
 
 
 
 
192
 
193
+ #: includes/backup.php:119
194
+ msgid "Manual backup of %s (%s)"
195
+ msgstr "Sauvegarde manuelle de %s (%s)"
 
 
 
 
196
 
197
+ #: includes/backup.php:114
198
+ msgid "all roles"
199
+ msgstr "tous les rôles"
200
 
201
+ #: includes/backup.php:51 includes/backup.php:309
202
+ msgid "Export / Import"
203
+ msgstr "Exporter/importer"
204
 
205
+ #: includes/backup-handler.php:199
206
+ msgid "%s successfully imported from uploaded data."
207
+ msgstr "%s a bien été importé à partir des données téléversées."
208
 
209
+ #: includes/backup-handler.php:178
210
+ msgid "Error importing settings! Please check that you uploaded a valid json file."
211
+ msgstr "Erreur d’importation des réglages ! Veuillez vérifier que vous avez téléversé un fichier json valide."
212
 
213
+ #: includes/backup-handler.php:165
214
+ msgid "Error importing settings! Please try again."
215
+ msgstr "Erreur d’importation des réglages ! Veuillez réessayer."
216
 
217
+ #: includes/backup-handler.php:145
218
+ msgid "Please upload a valid .json file"
219
+ msgstr "Veuillez téléverser un fichier json valide"
220
 
221
+ #: includes/backup-handler.php:140
222
+ msgid "Please upload a file to import"
223
+ msgstr "Veuillez téléverser un fichier à importer"
224
 
225
+ #: includes/backup-handler.php:119
226
+ msgid "%s restored from last backup."
227
+ msgstr "%s restauré à partir de la dernière sauvegarde."
 
228
 
229
+ #: includes/admin.php:1367
230
+ msgid "Go to the Backup feature"
231
+ msgstr "Accédez à la fonctionnalité de sauvegarde"
 
232
 
233
+ #: includes/admin.php:1363
234
+ msgid ""
235
+ "This plugin automatically creates a backup whenever you save changes. You can use these backups to\n"
236
+ "restore an earlier version of your roles and capabilities."
237
+ msgstr ""
238
+ "Cette extension crée automatiquement une sauvegarde à chaque fois que vous enregistrez des modifications. Vous pouvez utiliser ces sauvegardes pour\n"
239
+ "restaurer une version antérieure de vos rôles et permissions."
240
 
241
+ #: includes/admin.php:1361
242
+ msgid "PublishPress Capabilities is safe to use"
243
+ msgstr "PublishPress Capabilities est sûr à utiliser"
244
 
245
+ #: capsman-enhanced.php:85
246
+ msgid "This plugin can be deleted."
247
+ msgstr "Cette extension peut être supprimée."
 
248
 
249
+ #: includes/roles/class/class-pp-roles-actions.php:299
250
+ msgid "The new role %s was created successfully."
251
+ msgstr "Le nouveau rôle %s a été créé avec succès."
 
 
252
 
253
+ #: includes/roles/class/class-pp-roles-actions.php:223
254
+ msgid "The role \"%s\" already exists. Please choose a different name."
255
+ msgstr "Le rôle « %s » existe déjà. Veuillez choisir un autre nom."
 
256
 
257
+ #: includes/roles/class/class-pp-roles-actions.php:211
258
+ msgid "Invalid role name entry: %s"
259
+ msgstr "Entrée de nom de rôle invalide : %s"
260
 
261
+ #: includes/manager.php:537 includes/manager.php:559
262
+ msgid "You do not have permission to manage admin features."
263
+ msgstr "Vous n’avez pas le droit de gérer les fonctionnalités d’administration."
264
 
265
+ #: includes/features/restrict-admin-features.php:133
266
+ msgid "Welcome panel"
267
+ msgstr "Panneau d’accueil"
 
 
 
268
 
269
+ #: includes/features/restrict-admin-features.php:84
270
+ msgid "Version %s"
271
+ msgstr "Version %s"
 
 
 
 
 
272
 
273
+ #: includes/features/restrict-admin-features.php:83
274
+ msgid "Thank you for creating with WordPress"
275
+ msgstr "Merci de faire de WordPress votre outil de création"
 
276
 
277
+ #: includes/features/restrict-admin-features.php:69
278
+ msgid "Yoast SEO"
279
+ msgstr "Yoast SEO"
 
 
 
 
280
 
281
+ #: includes/features/restrict-admin-features.php:68
282
+ msgid "User Display Name"
283
+ msgstr "Nom affiché de l’utilisateur/utilisatrice"
284
 
285
+ #: includes/features/restrict-admin-features.php:66
286
+ #: includes/features/restrict-admin-features.php:67
287
+ msgid "New"
288
+ msgstr "Nouveau"
 
 
 
289
 
290
+ #: includes/features/restrict-admin-features.php:65
291
+ msgid "User actions"
292
+ msgstr "Actions de l’internaute"
 
 
293
 
294
+ #: includes/features/restrict-admin-features.php:64
295
+ msgid "Right bar"
296
+ msgstr "Barre de droite"
 
 
 
297
 
298
+ #: includes/features/restrict-admin-features.php:63
299
+ msgid "Comments"
300
+ msgstr "Commentaires"
301
 
302
+ #: includes/features/restrict-admin-features.php:62
303
+ msgid "Updates"
304
+ msgstr "Mises à jour"
 
 
 
 
 
 
 
 
 
 
305
 
306
+ #: includes/features/restrict-admin-features.php:61
307
+ msgid "WordPress External Links"
308
+ msgstr "Liens externes de WordPress"
 
 
 
 
309
 
310
+ #: includes/features/restrict-admin-features.php:60
311
+ msgid "WordPress Logo"
312
+ msgstr "Logo de WordPress"
 
 
313
 
314
+ #: includes/features/restrict-admin-features.php:59
315
+ msgid "Mobile Menu Toggle"
316
+ msgstr "Ouvrir/fermer le menu mobile"
 
 
 
 
317
 
318
+ #: includes/features/restrict-admin-features.php:22
319
+ msgid "Dashboard widgets"
320
+ msgstr "Widgets de tableau de bord"
 
 
 
 
321
 
322
+ #: includes/features/restrict-admin-features.php:19
323
+ msgid "Admin Toolbar"
324
+ msgstr "Barre d’outils de l’administration"
 
 
 
325
 
326
+ #: includes/features/restrict-admin-features.php:16
327
+ msgid "Header and Footer"
328
+ msgstr "En-tête et pied de page"
 
 
329
 
330
+ #: includes/features/admin-features.php:53
331
+ msgid "Note: You are only restricting access to admin features screens. Some plugins may also add features to other areas of WordPress."
332
+ msgstr "Note : Vous ne limitez laccès qu’aux écrans des fonctionnalités d’administration. Certaines extensions peuvent également ajouter des fonctionnalités à d’autres zones de WordPress."
333
 
334
+ #: includes/features/admin-features.php:37
335
+ msgid "Admin Feature Restrictions"
336
+ msgstr "Restrictions des fonctionnalités administratives"
 
337
 
338
+ #: includes/backup.php:389 includes/features/admin-features.php:236
339
+ #: includes/features/editor-features.php:236
340
+ msgid "Click here to install PublishPress Permissions"
341
+ msgstr "Cliquez ici pour installer PublishPress Permissions"
342
 
343
+ #: includes/backup.php:386 includes/features/admin-features.php:233
344
+ #: includes/features/editor-features.php:233
345
+ msgid "PublishPress Permissions is 100% free to install."
346
+ msgstr "PublishPress Permissions est 100% gratuit à installer."
347
 
348
+ #: includes/backup.php:385 includes/features/admin-features.php:232
349
+ #: includes/features/editor-features.php:232
350
+ msgid "Allow specific user roles or users to manage each post."
351
+ msgstr "Autorisez des rôles de comptes spécifiques à gérer chaque publication."
 
352
 
353
+ #: includes/backup.php:384 includes/features/admin-features.php:231
354
+ #: includes/features/editor-features.php:231
355
+ msgid "Choose who can read and edit each post."
356
+ msgstr "Choisissez qui peut lire et modifier chaque publication."
 
 
 
 
 
 
 
 
357
 
358
+ #: includes/backup.php:382 includes/features/admin-features.php:229
359
+ #: includes/features/editor-features.php:229
360
+ msgid "Control permissions for individual posts and pages"
361
+ msgstr "Contrôlez les autorisations pour les publications et les pages individuelles"
362
 
363
+ #: includes/backup.php:381 includes/features/admin-features.php:228
364
+ #: includes/features/editor-features.php:228
365
+ msgid "Recommendations for you"
366
+ msgstr "Des recommandations pour vous"
367
 
368
+ #: includes/admin.php:870
369
+ msgid "Plugin Capabilities &ndash; %s"
370
+ msgstr "Extension Permissions &ndash; %s"
371
 
372
+ #: includes/admin.php:738 includes/admin.php:876 includes/admin.php:1082
373
+ msgid "No results found. Please try again with a different word."
374
+ msgstr "Aucun résultat trouvé. Veuillez réessayer avec un autre mot."
375
 
376
+ #: includes/admin.php:735 includes/admin.php:873 includes/admin.php:1079
377
+ msgid "Filter by capability"
378
+ msgstr "Filtrer par permission"
379
 
380
+ #: includes/admin.php:732
381
+ msgid "WordPress Core Capabilities"
382
+ msgstr "Permissions natives de WordPress"
383
 
384
+ #: includes/admin.php:548 includes/admin.php:736 includes/admin.php:874
385
+ #: includes/admin.php:1080
386
+ msgid "Clear"
387
+ msgstr "Effacer"
388
 
389
+ #: includes/admin.php:545
390
+ msgid "Filter by post type"
391
+ msgstr "Filtrer par type de publication"
392
 
393
+ #: includes/admin.php:545
394
+ msgid "Filter by taxonomy"
395
+ msgstr "Filtrer par taxonomie"
 
396
 
397
+ #: includes/admin.php:539
398
+ msgid "Post %s Capabilities"
399
+ msgstr "Permissions de la publication %s"
 
 
400
 
401
+ #: includes/admin.php:539
402
+ msgid "Term %s Capabilities"
403
+ msgstr "Permissions de le terme %s"
 
 
404
 
405
+ #: includes/admin.php:495
406
+ msgid "Additional"
407
+ msgstr "Additionnel"
408
 
409
+ #: includes/admin.php:316
410
+ msgid "WordPress Core"
411
+ msgstr "Cœur de WordPress"
412
 
413
+ #: includes/admin.php:224
414
+ msgid "Deletion"
415
+ msgstr "Suppression"
416
 
417
+ #: includes/admin.php:223
418
+ msgid "Editing"
419
+ msgstr "Édition"
 
420
 
421
+ #: includes/admin-load.php:333 includes/functions-admin.php:212
422
+ #: includes/manager.php:377 includes/manager.php:412
423
+ #: includes/roles/class/class-pp-roles-list-table.php:174
424
+ msgid "Admin Features"
425
+ msgstr "Fonctionnalités administratives"
426
 
427
+ #: includes-core/admin-features-promo.php:74
428
+ msgid "You can block pages by URL or hide Admin elements by entering a CSS class or ID. This feature is available in PublishPress Capabilities Pro."
429
+ msgstr "Vous pouvez bloquer des pages par URL ou masquer des éléments de l’administration en saisissant une classe ou un ID CSS. Cette fonctionnalité est disponible dans PublishPress Capabilities Pro."
430
 
431
+ #: includes/manager.php:208
432
+ msgid "Add or clear custom item entry before saving changes."
433
+ msgstr "Ajoutez ou effacez une entrée d’élément personnalisé avant d’enregistrer les modifications."
 
434
 
435
+ #: includes/manager.php:207
436
+ msgid "Are you sure you want to delete this item ?"
437
+ msgstr "Confirmez-vous vouloir supprimer cet élément ?"
 
 
438
 
439
+ #: includes-core/editor-features-promo.php:117
440
+ msgid "Page Attributes: Order"
441
+ msgstr "Attributs de la page : Tri"
442
 
443
+ #: includes-core/editor-features-promo.php:106
444
+ msgid "Permalink: Descriptive Caption"
445
+ msgstr "Permalien : Légende descriptive"
446
 
447
+ #: includes-core/editor-features-promo.php:95
448
+ msgid "Custom item one"
449
+ msgstr "Élément personnalisé un"
450
 
451
+ #: includes-core/editor-features-promo.php:89
452
+ msgid "Custom Items"
453
+ msgstr "Éléments personnalisés"
454
 
455
+ #: includes-core/editor-features-promo.php:74
456
+ msgid "You can hide plugin metaboxes. You can also hide specific items by entering their CSS class or ID. This feature is available in PublishPress Capabilities Pro."
457
+ msgstr "Vous pouvez masquer les boîtes méta des extensions. Vous pouvez également masquer des éléments spécifiques en saisissant leur classe CSS ou leur ID. Cette fonctionnalité est disponible dans PublishPress Capabilities Pro."
 
 
 
 
 
 
 
 
458
 
459
+ #: includes-core/editor-features-promo.php:62
460
+ msgid "TaxoPress - Settings"
461
+ msgstr "TaxoPress - Réglages"
 
 
 
 
462
 
463
+ #: includes-core/editor-features-promo.php:52
464
+ msgid "Notifications"
465
+ msgstr "Notifications"
 
466
 
467
+ #: includes-core/editor-features-promo.php:42
468
+ msgid "Editorial Comments"
469
+ msgstr "Commentaires éditoriaux"
470
 
471
+ #: includes-core/editor-features-promo.php:32
472
+ msgid "Checklist"
473
+ msgstr "Liste de contrôle"
474
 
475
+ #: includes-core/editor-features-promo.php:24
476
+ msgid "Metaboxes"
477
+ msgstr "Boîtes méta"
 
 
 
 
478
 
479
+ #: includes/manager.php:521 includes/manager.php:575
480
+ msgid "Settings updated."
481
+ msgstr "Réglages mis à jour."
 
 
 
 
482
 
483
+ #: includes/manager.php:464 includes/manager.php:486
484
+ msgid "You do not have permission to manage editor features."
485
+ msgstr "Vous n’êtes pas autorisé à gérer les fonctionnalités de l’éditeur."
486
 
487
+ #: includes/admin-load.php:332 includes/functions-admin.php:201
488
+ #: includes/manager.php:375 includes/manager.php:411
489
+ #: includes/roles/class/class-pp-roles-list-table.php:173
490
+ msgid "Editor Features"
491
+ msgstr "Fonctionnalités de l’éditeur"
492
 
493
+ #: includes/features/restrict-editor-features.php:348
494
+ msgid "Text settings"
495
+ msgstr "Réglages du texte"
 
 
496
 
497
+ #: includes/features/restrict-editor-features.php:347
498
+ msgid "Color settings"
499
+ msgstr "Réglages de couleur"
 
500
 
501
+ #: includes/features/restrict-editor-features.php:346
502
+ msgid "Typography"
503
+ msgstr "Typographie"
504
 
505
+ #: includes/features/restrict-editor-features.php:345
506
+ msgid "Paragraph"
507
+ msgstr "Paragraphe"
508
 
509
+ #: includes/features/restrict-editor-features.php:343
510
+ #: includes/features/restrict-editor-features.php:344
511
+ msgid "Block Panel"
512
+ msgstr "Panneau de blocs"
513
 
514
+ #: includes/features/restrict-editor-features.php:340
515
+ msgid "Post Attributes"
516
+ msgstr "Attributs d’articles"
517
 
518
+ #: includes/features/restrict-editor-features.php:338
519
+ msgid "Excerpt"
520
+ msgstr "Extrait"
 
521
 
522
+ #: includes/features/restrict-editor-features.php:337
523
+ msgid "Featured image"
524
+ msgstr "Image mise en avant"
525
 
526
+ #: includes/features/restrict-editor-features.php:319
527
+ msgid "Status & visibility"
528
+ msgstr "État et visibilité"
 
529
 
530
+ #: includes/features/restrict-editor-features.php:318
531
+ msgid "Document Panel"
532
+ msgstr "Panneau de publication"
533
 
534
+ #: includes/features/restrict-editor-features.php:315
535
+ msgid "Content"
536
+ msgstr "Contenu"
537
 
538
+ #: includes/features/restrict-editor-features.php:314
539
+ msgid "Edit title"
540
+ msgstr "Modifier le titre"
541
 
542
+ #: includes/features/restrict-editor-features.php:313
543
+ msgid "Body"
544
+ msgstr "Corps"
 
 
 
 
545
 
546
+ #: includes/features/restrict-editor-features.php:310
547
+ msgid "Options"
548
+ msgstr "Options"
 
 
 
 
549
 
550
+ #: includes/features/restrict-editor-features.php:308
551
+ msgid "Publish / Update"
552
+ msgstr "Publier/mettre à jour"
553
 
554
+ #: includes/features/restrict-editor-features.php:306
555
+ msgid "Switch to draft"
556
+ msgstr "Passer en brouillon"
 
 
 
 
 
557
 
558
+ #: includes/features/restrict-editor-features.php:304
559
+ msgid "Top Bar - Right"
560
+ msgstr "Barre supérieure - Droite"
561
 
562
+ #: includes/features/restrict-editor-features.php:301
563
+ msgid "Outline"
564
+ msgstr "Contour"
 
 
565
 
566
+ #: includes/features/restrict-editor-features.php:300
567
+ msgid "Details"
568
+ msgstr "Détails"
 
 
569
 
570
+ #: includes/features/restrict-editor-features.php:299
571
+ msgid "Redo"
572
+ msgstr "Rétablir"
 
 
 
 
573
 
574
+ #: includes/features/restrict-editor-features.php:298
575
+ msgid "Undo"
576
+ msgstr "Annuler"
 
 
577
 
578
+ #: includes/features/restrict-editor-features.php:297
579
+ msgid "Modes"
580
+ msgstr "Modes"
 
 
581
 
582
+ #: includes/features/restrict-editor-features.php:296
583
+ msgid "Add block"
584
+ msgstr "Ajouter un bloc"
 
 
585
 
586
+ #: includes/features/restrict-editor-features.php:295
587
+ msgid "Top Bar - Left"
588
+ msgstr "Barre supérieure - Gauche"
 
 
589
 
590
+ #: includes/features/restrict-editor-features.php:93
591
+ #: includes/features/restrict-editor-features.php:339
592
+ msgid "Discussion"
593
+ msgstr "Discussion"
594
 
595
+ #: includes/features/restrict-editor-features.php:92
596
+ msgid "Post Slug"
597
+ msgstr "Slug de publication"
 
 
598
 
599
+ #: includes/features/restrict-editor-features.php:91
600
+ msgid "Featured Image"
601
+ msgstr "Image mise en avant"
 
602
 
603
+ #: includes/features/restrict-editor-features.php:90
604
+ msgid "Other Boxes"
605
+ msgstr "Autres cases"
 
 
 
606
 
607
+ #: includes/features/restrict-editor-features.php:87
608
+ msgid "Order"
609
+ msgstr "Tri"
 
 
 
610
 
611
+ #: includes/features/restrict-editor-features.php:86
612
+ msgid "Page Template"
613
+ msgstr "Modèle de page"
 
614
 
615
+ #: includes/features/restrict-editor-features.php:85
616
+ msgid "Parent"
617
+ msgstr "Parent"
618
 
619
+ #: includes/features/restrict-editor-features.php:84
620
+ msgid "Page Attributes"
621
+ msgstr "Attributs de la page"
 
 
 
 
 
622
 
623
+ #: includes/features/restrict-editor-features.php:83
624
+ msgid "Page Boxes"
625
+ msgstr "Cadres de page"
626
 
627
+ #: includes/features/restrict-editor-features.php:71
628
+ #: includes/features/restrict-editor-features.php:323
629
+ msgid "Tags"
630
+ msgstr "Étiquettes"
 
631
 
632
+ #: includes/features/restrict-editor-features.php:70
633
+ msgid "Add New Category"
634
+ msgstr "Ajouter une nouvelle catégorie"
635
 
636
+ #: includes/features/restrict-editor-features.php:69
637
+ #: includes/features/restrict-editor-features.php:322
638
+ msgid "Categories"
639
+ msgstr "Catégories"
640
 
641
+ #: includes/features/restrict-editor-features.php:68
642
+ msgid "Taxonomy Boxes"
643
+ msgstr "Boîtes de taxonomie"
 
 
 
 
 
644
 
645
+ #: includes/features/restrict-editor-features.php:65
646
+ msgid "Publish"
647
+ msgstr "Publier"
648
 
649
+ #: includes/features/restrict-editor-features.php:64
650
+ msgid "Date"
651
+ msgstr "Date"
652
 
653
+ #: includes/features/restrict-editor-features.php:63
654
+ msgid "Publish Schedule"
655
+ msgstr "Calendrier de publication"
656
 
657
+ #: includes/features/restrict-editor-features.php:62
658
+ msgid "Publish Actions"
659
+ msgstr "Actions de publication"
660
 
661
+ #: includes/features/restrict-editor-features.php:61
662
+ msgid "Password Protect This Post"
663
+ msgstr "Mot de passe pour protéger cette publication"
664
 
665
+ #: includes/features/restrict-editor-features.php:60
666
+ msgid "Publish Visibility"
667
+ msgstr "Visibilité de la publication"
668
 
669
+ #: includes/features/restrict-editor-features.php:59
670
+ msgid "Publish Status "
671
+ msgstr "État de la publication "
672
 
673
+ #: includes/features/restrict-editor-features.php:58
674
+ #: includes/features/restrict-editor-features.php:307
675
+ msgid "Preview"
676
+ msgstr "Aperçu"
677
 
678
+ #: includes/features/restrict-editor-features.php:57
679
+ #: includes/features/restrict-editor-features.php:305
680
+ msgid "Save Draft"
681
+ msgstr "Enregistrer le brouillon"
682
 
683
+ #: includes/features/restrict-editor-features.php:55
684
+ #: includes/features/restrict-editor-features.php:56
685
+ msgid "Publish Box"
686
+ msgstr "Boîte de publication"
687
 
688
+ #: includes/features/restrict-editor-features.php:52
689
+ msgid "Word count"
690
+ msgstr "Nombre de mots"
691
 
692
+ #: includes/features/restrict-editor-features.php:51
693
+ msgid "HTML Editor Button"
694
+ msgstr "Bouton de l’éditeur HTML"
695
 
696
+ #: includes/features/restrict-editor-features.php:50
697
+ msgid "Media Buttons (all)"
698
+ msgstr "Boutons multimédia (tous)"
 
699
 
700
+ #: includes/features/restrict-editor-features.php:49
701
+ #: includes/features/restrict-editor-features.php:321
702
+ msgid "Permalink"
703
+ msgstr "Permalien"
704
 
705
+ #: includes/features/restrict-editor-features.php:47
706
+ msgid "Title"
707
+ msgstr "Titre"
708
+
709
+ #: includes/features/restrict-editor-features.php:45
710
+ #: includes/features/restrict-editor-features.php:48
711
+ msgid "Editor"
712
+ msgstr "Éditeur"
713
 
714
  #: includes/features/restrict-admin-features.php:81
715
  #: includes/features/restrict-editor-features.php:42
721
  msgid "Help"
722
  msgstr "Aide"
723
 
 
 
 
 
 
 
 
 
 
 
 
 
 
724
  #: includes/features/restrict-editor-features.php:40
725
  msgid "Top Tabs"
726
  msgstr "Onglets supérieurs"
727
 
728
+ #: includes/features/editor-features.php:138
729
+ msgid "Classic"
730
+ msgstr "Classique"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
731
 
732
+ #: includes/features/editor-features.php:135
733
+ msgid "Gutenberg"
734
+ msgstr "Gutenberg"
 
735
 
736
+ #: includes/features/editor-features.php:85
737
+ msgid "Select editor features to remove. Note that this screen cannot be used to grant additional features to any role."
738
+ msgstr "Sélectionnez les fonctions d’éditeur à supprimer. Notez que cet écran ne peut pas être utilisé pour accorder des fonctionnalités supplémentaires à un rôle."
 
739
 
740
+ #: includes/features/editor-features.php:69
741
+ msgid "Editor Feature Restriction"
742
+ msgstr "Restriction des fonctionnalités de l’éditeur"
743
 
744
+ #: includes/admin.php:1417
745
+ msgid "sync options to all sites now"
746
+ msgstr "synchroniser les options sur tous les sites maintenant"
747
 
748
+ #: includes/admin.php:1417
749
+ msgid "Copy option settings to all sites now"
750
+ msgstr "Copiez les réglages des options sur tous les sites maintenant"
751
 
752
+ #: includes/admin.php:991
753
+ msgid "The following entries have no effect. Please assign desired capabilities in the Read / Edit / Delete grid above."
754
+ msgstr "Les entrées suivantes n’ont aucun effet. Veuillez attribuer les permisions souhaitées dans la grille lire/modifier/supprimer ci-dessus."
755
 
756
+ #: includes/handler.php:61 includes/handler.php:89 includes/manager.php:758
757
+ msgid "The selected role is not editable."
758
+ msgstr "Le rôle sélectionné n’est pas modifiable."
759
 
760
+ #: includes/manager.php:441
761
+ msgid "You do not have permission to manage roles."
762
+ msgstr "Vous n’êtes pas autorisé à gérer les rôles."
763
 
764
+ #: includes/backup.php:272
765
+ msgid "No changes"
766
+ msgstr "Aucun changement"
767
 
768
+ #: includes/backup.php:203
769
+ msgid "(this role will be removed if you restore backup)"
770
+ msgstr "(ce rôle sera supprimé si vous restaurez la sauvegarde)"
771
 
772
+ #: includes/backup.php:162
773
+ msgid "Show changes from current roles only"
774
+ msgstr "Afficher uniquement les changements par rapport aux rôles actuels"
 
775
 
776
+ #: includes/backup.php:151
777
+ msgid "Restore Selected Roles"
778
+ msgstr "Restaurer les rôles sélectionnés"
779
 
780
+ #: includes/backup.php:142
781
+ msgid "Initial backup of all roles"
782
+ msgstr "Sauvegarde initiale de tous les rôles"
 
783
 
784
+ #: includes/backup.php:134
785
+ msgid "Auto-backup of all roles (%s)"
786
+ msgstr "Sauvegarde automatique de tous les rôles (%s)"
787
 
788
+ #: includes/backup.php:101
789
+ msgid "Available Backups:"
790
+ msgstr "Sauvegardes disponibles :"
791
 
792
+ #: includes/backup.php:96
793
+ msgid "On this screen, you can restore an earlier version of your roles and capabilities."
794
+ msgstr "Sur cet écran, vous pouvez restaurer une version antérieure de vos rôles et permissions."
795
 
796
+ #: includes/backup.php:92
797
+ msgid "PublishPress Capabilities automatically creates a backup on installation and whenever you save changes."
798
+ msgstr "PublishPress Capabilities crée automatiquement une sauvegarde lors de l’installation et à chaque fois que vous enregistrez des modifications."
799
 
800
+ #: includes/backup.php:89
801
+ msgid "Restore Previous Roles and Capabilities"
802
+ msgstr "Restaurer les rôles et permissions antérieurs"
803
 
804
+ #: includes/backup.php:75
805
+ msgid "Manual Backup"
806
+ msgstr "Sauvegarde manuelle"
807
 
808
+ #: includes/backup.php:70
809
+ msgid "A backup created on this screen replaces any previous manual backups, but is never automatically replaced."
810
+ msgstr "Le sauvegarde créée sur cet écran remplace toutes les sauvegardes manuelles précédentes, mais n’est jamais remplacée automatiquement."
811
 
812
+ #: includes/backup.php:65
813
+ msgid "PublishPress Capabilities automatically creates a backup on installation and whenever you save changes. The initial backup and last %d auto-backups are kept."
814
+ msgstr "PublishPress Capabilities crée automatiquement une sauvegarde lors de l’installation et à chaque fois que vous enregistrez des modifications. La sauvegarde initiale et les dernières %d sauvegardes automatiques sont conservées."
815
 
816
+ #: includes/backup.php:50
817
+ msgid "Reset Roles"
818
+ msgstr "Réinitialiser les rôles"
 
819
 
820
+ #: includes/backup.php:48
821
+ msgid "Restore"
822
+ msgstr "Restaurer"
823
 
824
+ #: includes/admin-load.php:339
825
+ #: includes/features/restrict-editor-features.php:309 includes/manager.php:384
826
+ msgid "Settings"
827
+ msgstr "Réglages"
828
 
829
+ #: includes/roles/roles.php:34
830
+ msgid "Description here."
831
+ msgstr "Description ici."
832
 
833
+ #: includes/roles/roles.php:26
834
+ msgid "Search Roles"
835
+ msgstr "Recherche de rôles"
836
 
837
+ #. translators: %s: search keywords
838
+ #: includes/roles/roles.php:15
839
+ msgid "Search results for &#8220;%s&#8221;"
840
+ msgstr "Résultats de la recherche pour &#171; %s &#187;"
841
 
842
+ #: includes/admin-load.php:330 includes/manager.php:361
843
+ #: includes/roles/roles.php:8
844
+ msgid "Roles"
845
+ msgstr "Rôles"
846
 
847
+ #: includes/roles/class/class-pp-roles-list-table.php:356
848
+ msgid "Your Role"
849
+ msgstr "Ton rôle"
850
 
851
+ #: includes/roles/class/class-pp-roles-list-table.php:351
852
+ msgid "Default Role"
853
+ msgstr "Rôle par défaut"
854
 
855
+ #: includes/roles/class/class-pp-roles-list-table.php:300
856
+ msgid "Hide"
857
+ msgstr "Masquer"
858
 
859
+ #: includes-core/editor-features-promo.php:96
860
+ #: includes-core/editor-features-promo.php:107
861
+ #: includes-core/editor-features-promo.php:117
862
+ #: includes/features/admin-features.php:190
863
+ #: includes/features/editor-features-classic.php:51
864
+ #: includes/features/editor-features-gutenberg.php:50
865
+ #: includes/roles/class/class-pp-roles-admin.php:116
866
+ #: includes/roles/class/class-pp-roles-list-table.php:281
867
+ #: includes/roles/class/class-pp-roles-list-table.php:540
868
+ msgid "Delete"
869
+ msgstr "Supprimer"
870
 
871
+ #: includes/roles/class/class-pp-roles-list-table.php:263
872
+ msgid "Unhide"
873
+ msgstr "Afficher"
874
 
875
+ #: includes/roles/class/class-pp-roles-list-table.php:245
876
+ msgid "(non-editable role)"
877
+ msgstr "(rôle non modifiable)"
878
 
879
+ #: includes/manager.php:409
880
+ #: includes/roles/class/class-pp-roles-list-table.php:171
881
+ msgid "Users"
882
+ msgstr "Utilisateurs"
883
 
884
+ #: includes/roles/class/class-pp-roles-actions.php:649
885
+ msgid "The role %1$s was successfully unhidden."
886
+ msgstr "Le rôle %1$s a été affiché avec succès."
887
 
888
+ #: includes/roles/class/class-pp-roles-actions.php:589
889
+ msgid "The role %1$s was successfully hidden."
890
+ msgstr "Le rôle %1$s a été masqué avec succès."
891
 
892
+ #: includes/roles/class/class-pp-roles-actions.php:535
893
+ msgid "The role could not be deleted."
894
+ msgstr "Le rôle n’a pas pu être supprimé."
895
 
896
+ #: includes/roles/class/class-pp-roles-actions.php:513
897
+ msgid "The selected %1$s roles were successfully deleted. %2$s"
898
+ msgstr "Les rôles %1$s sélectionnés ont été supprimés avec succès. %2$s"
 
 
899
 
900
+ #: includes/roles/class/class-pp-roles-actions.php:507
901
+ msgid "The role %1$s was successfully deleted. %2$s"
902
+ msgstr "Le rôle %1$s a été supprimé avec succès. %2$s"
903
 
904
+ #: includes/roles/class/class-pp-roles-actions.php:502
905
+ msgid "%1$d users moved to default role %2$s."
906
+ msgstr "%1$d utilisateurs/utilisatrices déplacés vers le rôle par défaut %2$s."
907
 
908
+ #: includes/roles/class/class-pp-roles-actions.php:480
909
+ msgid "Deleting a system role is not allowed."
910
+ msgstr "La suppression d’un rôle système n’est pas autorisée."
911
 
912
+ #: includes/roles/class/class-pp-roles-actions.php:250
913
+ msgid "Something went wrong, the system wasn't able to create the role, refresh the page and try again."
914
+ msgstr "Quelque chose s’est mal passé, le système n’a pas été en mesure de créer le rôle, rafraîchissez la page et réessayez."
 
915
 
916
+ #: includes/roles/class/class-pp-roles-actions.php:184
917
+ #: includes/roles/class/class-pp-roles-actions.php:336
918
+ #: includes/roles/class/class-pp-roles-actions.php:453
919
+ #: includes/roles/class/class-pp-roles-actions.php:578
920
+ #: includes/roles/class/class-pp-roles-actions.php:639
921
+ msgid "Missing parameters, refresh the page and try again."
922
+ msgstr "Il y a des paramètres manquants, rafraîchissez la page et réessayez."
923
 
924
+ #: includes/roles/class/class-pp-roles-actions.php:162
925
+ #: includes/roles/class/class-pp-roles-actions.php:180
926
+ #: includes/roles/class/class-pp-roles-actions.php:332
927
+ #: includes/roles/class/class-pp-roles-actions.php:429
928
+ msgid "Your link has expired, refresh the page and try again."
929
+ msgstr "Votre lien a expiré, rafraîchissez la page et réessayez."
930
 
931
+ #: includes/roles/class/class-pp-roles-actions.php:148
932
+ msgid "You do not have sufficient permissions to perform this action."
933
+ msgstr "Vous n’avez pas les droits suffisants pour effectuer cette action."
934
 
935
+ #: includes/roles/class/class-pp-roles-admin.php:276
936
+ #: includes/roles/roles-functions.php:32
937
+ msgid "Are you sure you want to delete this role?"
938
+ msgstr "Confirmez-vous la suppression de ce rôle ?"
939
 
940
+ #: includes/settings.php:34
941
+ msgid "PublishPress Authors"
942
+ msgstr "PublishPress Authors"
 
943
 
944
+ #: includes/settings.php:14
945
+ msgid "Capabilities Settings"
946
+ msgstr "Réglages des permissions"
947
 
948
+ #: includes-core/CoreAdmin.php:63 includes/admin-load.php:335
949
+ #: includes/manager.php:414
950
+ #: includes/roles/class/class-pp-roles-list-table.php:176
951
+ msgid "Nav Menus"
952
+ msgstr "Menus de navigation"
953
 
954
+ #: includes-core/CoreAdmin.php:62 includes/admin-load.php:334
955
+ #: includes/manager.php:413
956
+ #: includes/roles/class/class-pp-roles-list-table.php:175
957
+ msgid "Admin Menus"
958
+ msgstr "Menus d’administration"
959
 
960
+ #: includes-core/admin-menus-promo.php:58
961
+ msgid "You can restrict access to admin menu screens. This feature is available in PublishPress Capabilities Pro"
962
+ msgstr "Vous pouvez restreindre l’accès aux écrans du menu d’administration. Cette fonctionnalité est disponible dans PublishPress Capabilities Pro"
963
 
964
+ #: includes-core/admin-menus-promo.php:29
965
+ msgid "Admin Menu Restrictions"
966
+ msgstr "Restrictions du menu d’administration"
967
 
968
+ #: includes-core/nav-menus-promo.php:63
969
+ msgid "You can restrict access to navigation menus. This feature is available in PublishPress Capabilities Pro"
970
+ msgstr "Vous pouvez restreindre laccès aux menus de navigation. Cette fonctionnalité est disponible dans PublishPress Capabilities Pro"
971
 
972
+ #: includes-core/nav-menus-promo.php:29
973
+ msgid "Navigation Menu Restrictions"
974
+ msgstr "Restrictions du menu de navigation"
975
 
976
+ #: includes/features/restrict-editor-features.php:46
977
+ #: includes/filters-woocommerce.php:33 includes/roles/roles.php:10
978
+ msgid "Add New"
979
+ msgstr "Ajouter"
980
 
981
+ #: includes/filters-woocommerce.php:32
982
+ #: includes/roles/class/class-pp-roles-list-table.php:86
983
+ msgid "All %s"
984
+ msgid_plural "All %s"
985
+ msgstr[0] "Tous les %s"
986
+ msgstr[1] "Tous les %s"
987
 
988
+ #: includes/manager.php:1009
989
+ msgid "Contact"
990
+ msgstr "Contact"
991
 
992
+ #: includes/manager.php:1009
993
+ msgid "Contact the PublishPress team"
994
+ msgstr "Contact de l’équipe de PublishPress"
995
 
996
+ #: includes/manager.php:1007
997
+ msgid "Capabilites Documentation"
998
+ msgstr "Documentation de Capabilities"
 
999
 
1000
+ #: includes/manager.php:1005
1001
+ msgid "About"
1002
+ msgstr "À propos"
 
 
1003
 
1004
+ #: includes/manager.php:1005
1005
+ msgid "About PublishPress Capabilities"
1006
+ msgstr "À propos de PublishPress Capabilities"
 
 
1007
 
1008
+ #: includes/manager.php:994
1009
+ msgid "If you like %s, please leave us a %s rating. Thank you!"
1010
+ msgstr "Si vous appréciez %s, veuillez nous laisser une note de %s. Merci !"
1011
 
1012
+ #: includes/manager.php:680 includes/manager.php:714 includes/manager.php:732
1013
+ msgid "You do not have permission to manage capabilities."
1014
+ msgstr "Vous n’avez pas le droit de gérer les permissions."
1015
 
1016
+ #: includes-core/admin-features-promo.php:79
1017
+ #: includes-core/admin-menus-promo.php:62
1018
+ #: includes-core/editor-features-promo.php:79
1019
+ #: includes-core/nav-menus-promo.php:67 includes/admin-load.php:345
1020
+ #: includes/admin-load.php:346 includes/manager.php:390
1021
+ #: includes/manager.php:391
1022
+ msgid "Upgrade to Pro"
1023
+ msgstr "Mettre à niveau en Pro"
1024
 
1025
+ #: includes/admin-load.php:336 includes/backup.php:49 includes/manager.php:381
1026
+ msgid "Backup"
1027
+ msgstr "Sauvegarde"
 
 
1028
 
1029
+ #: includes/handler.php:124
1030
+ msgid "Type / Taxonomy settings saved."
1031
+ msgstr "Réglages de type/taxonomie sauvegardés."
1032
 
1033
+ #: includes/backup-handler.php:128
1034
+ msgid "Roles and Capabilities restored from selected auto-backup."
1035
+ msgstr "Rôles et capacités restaurés à partir de la sauvegarde automatique sélectionnée."
 
1036
 
1037
+ #: includes/backup-handler.php:90
1038
+ msgid "Roles and Capabilities restored from initial backup."
1039
+ msgstr "Rôles et capacités restaurés à partir de la sauvegarde initiale."
 
1040
 
1041
+ #: includes/pp-ui.php:239
1042
+ msgid "Enforce Edit, Delete and Assign capabilities separately from Management capability."
1043
+ msgstr "Appliquez les permissions de modification, de suppression et d’attribution séparément de la gestion des permissions."
1044
 
1045
+ #: includes/pp-ui.php:236
1046
+ msgid "Detailed Taxonomy Capabilities"
1047
+ msgstr "Permissions détaillées de la taxonomie"
1048
 
1049
+ #: includes/pp-ui.php:180
1050
+ msgid "Ensure permissions can be controlled separately from other taxonomies."
1051
+ msgstr "Cela vous garantit que les droits peuvent être contrôlés séparément des autres taxonomies."
1052
 
1053
+ #: includes/pp-ui.php:177
1054
+ msgid "Taxonomy-Specific Capabilities"
1055
+ msgstr "Taxonomies spécifiques aux permissions"
 
1056
 
1057
+ #: includes/pp-ui.php:159
1058
+ msgid "Make selected post types require a different capability to add new posts."
1059
+ msgstr "Faire en sorte que les types de publication sélectionnés nécessitent une permission différente pour ajouter de nouvelles publications."
1060
 
1061
+ #: includes/pp-ui.php:96
1062
+ msgid "Ensure permissions can be controlled separately from other post types."
1063
+ msgstr "Assurez-vous que les droits peuvent être contrôlés séparément des autres types de publication."
1064
 
1065
+ #: includes/pp-ui.php:93
1066
+ msgid "Type-Specific Capabilities"
1067
+ msgstr "Permissions spécifiques par type"
1068
 
1069
+ #: includes/pp-ui.php:75
1070
+ msgid "Capabilities for custom statuses can be manually added here. (See %sPermissions > Post Statuses%s for applicable names). %sSupplemental status-specific roles%s are usually more convenient, though."
1071
+ msgstr "Les permissions pour les états personnalisés peuvent être ajoutées manuellement ici. (Voir %sPermissions > Afficher les états%s pour les noms applicables). Cependant, les %sRôles supplémentaires spécifiques aux états %s sont généralement plus pratiques, cependant."
 
 
1072
 
1073
+ #: includes/settings.php:48
1074
+ msgid "Help / Contact Form"
1075
+ msgstr "Aide/Formulaire de contact"
 
1076
 
1077
+ #: includes/settings.php:46
1078
+ msgid "PublishPress Revisions"
1079
+ msgstr "PublishPress Revisions"
1080
 
1081
+ #: includes/settings.php:24
1082
+ msgid "Related Permissions Plugins"
1083
+ msgstr "Extensions de droits similaires"
1084
 
1085
+ #: includes/manager.php:408 includes/roles/class/class-pp-roles-admin.php:145
1086
+ #: includes/roles/class/class-pp-roles-list-table.php:170
1087
+ msgid "Role Name"
1088
+ msgstr "Nom du rôle"
1089
 
1090
+ #: includes/roles/class/class-pp-roles-admin.php:162
1091
+ msgid "Role Level"
1092
+ msgstr "Niveau du rôle"
 
1093
 
1094
+ #: includes/admin.php:1326
1095
+ msgid "Role level is mostly deprecated. However, it still determines eligibility for Post Author assignment and limits the application of user editing capabilities."
1096
+ msgstr "Le niveau de rôle est généralement obsolète. Cependant, il détermine toujours l’éligibilité à l’affectation d’auteur de publication et limite l’application des permissions de modification par l’utilisateur/utilisatrice."
 
1097
 
1098
+ #: includes/admin.php:490 includes/admin.php:978
1099
+ msgid "Invalid Capabilities"
1100
+ msgstr "Permissions invalides"
 
 
 
 
 
1101
 
1102
+ #: includes/admin.php:801
1103
+ msgid "Lockout Prevention: To remove read capability, first remove WordPress admin / editing capabilities, or add \"dashboard_lockout_ok\" capability"
1104
+ msgstr "Prévention du verrouillage : pour supprimer la permission de lecture, supprimez d’abord les permissions d’administration/édition de WordPress ou ajoutez la permission « dashboard_lockout_ok »"
 
 
 
 
 
1105
 
1106
+ #: includes/admin.php:652
1107
+ msgid "shared capability: %s"
1108
+ msgstr "permission partagée : %s"
 
 
 
 
 
 
 
 
1109
 
1110
+ #: includes/admin.php:1235 includes/settings.php:40
1111
+ msgid "PublishPress Permissions"
1112
+ msgstr "PublishPress Permissions"
 
 
 
 
 
 
1113
 
1114
+ #: includes/admin.php:132
1115
+ msgid "<strong>Note:</strong> Capability changes <strong>remain in the database</strong> after plugin deactivation. You can also configure this role as a %sPermission Group%s."
1116
+ msgstr "<strong>Note : </strong>Les changements de permission<strong> restent dans la base de données</strong> après la désactivation de l’extension. Vous pouvez également configurer ce rôle en tant que %sGroupe de droits%s."
 
 
 
 
 
 
 
 
 
1117
 
1118
+ #: includes/admin.php:140
1119
+ msgid "<strong>Note:</strong> Capability changes <strong>remain in the database</strong> after plugin deactivation."
1120
+ msgstr "<strong>Note :</strong> Les modifications des permissions <strong>restent dans la base de données</strong> après la désactivation de l’extension."
1121
 
1122
+ #: includes/admin.php:40
1123
+ msgid "Warning: This role cannot access the dashboard without the read capability. %1$sClick here to fix this now%2$s."
1124
+ msgstr "Avertissement : ce rôle ne peut accéder au tableau de bord sans la permission de lecture. %1$sCliquez ici pour le corriger%2$s."
 
 
1125
 
1126
+ #: includes/filters.php:254
1127
+ msgid "Edit Roles"
1128
+ msgstr "Modifier les Rôles"
1129
 
1130
+ #: includes/backup.php:232
1131
+ msgid "%s (level %s)"
1132
+ msgstr "%s (niveau %s)"
1133
 
1134
+ #: includes/backup.php:196
1135
+ msgid "%s (%s roles)"
1136
+ msgstr "%s (%s rôles)"
 
 
1137
 
1138
+ #: includes/backup.php:85
1139
+ msgid "Last Backup"
1140
+ msgstr "Dernière sauvegarde"
1141
 
1142
+ #: includes/backup.php:85
1143
+ msgid "Last Manual Backup - %s"
1144
+ msgstr "Dernière sauvegarde manuelle - %s"
 
 
 
 
1145
 
1146
+ #: includes/backup.php:169
1147
+ msgid "Initial Backup"
1148
+ msgstr "Sauvegarde initiale"
1149
 
1150
+ #: includes/backup.php:169
1151
+ msgid "Initial Backup - %s"
1152
+ msgstr "Sauvegarde initiale - %s"
 
 
 
1153
 
1154
+ #: includes/backup.php:39
1155
+ msgid "Backup Tool for PublishPress Capabilities"
1156
+ msgstr "Outil de sauvegarde de PublishPress Capabilities"
 
 
 
 
1157
 
1158
+ #. Author URI of the plugin
1159
+ msgid "https://publishpress.com/"
1160
+ msgstr "https://publishpress.com/"
 
1161
 
1162
+ #. Author of the plugin
1163
+ #: includes/settings.php:29
1164
+ msgid "PublishPress"
1165
+ msgstr "PublishPress"
1166
 
1167
+ #. Plugin URI of the plugin
1168
+ msgid "https://publishpress.com/capability-manager/"
1169
+ msgstr "https://publishpress.com/capability-manager/"
 
 
 
 
1170
 
1171
+ #. Plugin Name of the plugin
1172
+ msgid "PublishPress Capabilities"
1173
+ msgstr "PublishPress Capabilities"
 
1174
 
1175
+ #. Description of the plugin
1176
+ msgid "Manage WordPress role definitions, per-site or network-wide. Organizes post capabilities by post type and operation."
1177
+ msgstr "Gérez les définitions de rôles WordPress, par site ou à l’échelle du réseau. Organisez les permissions par type de publication."
 
 
1178
 
1179
+ #: includes/pp-ui.php:167 includes/pp-ui.php:231 includes/pp-ui.php:288
1180
+ msgid "Update"
1181
+ msgstr "Mettre à jour"
 
 
 
 
1182
 
1183
+ #: includes/pp-ui.php:159
1184
+ msgid "Use create_posts capability"
1185
+ msgstr "Utilisez la permission create_posts"
1186
 
1187
+ #: includes/pp-ui.php:80
1188
+ msgid "Capabilities for custom statuses can be manually added to a role here (see Conditions > Status > Capability Mapping for applicable names). However, it is usually more convenient to use Permit Groups to assign a supplemental status-specific role."
1189
+ msgstr "Les permissions pour les états personnalisés peuvent être ajoutées manuellement à un rôle ici (voir Conditions > États > Mappage des permissions pour les noms applicables). Toutefois, il est généralement plus pratique d’utiliser les groupes de permissions pour attribuer un rôle supplémentaire spécifique à l’etat."
 
1190
 
1191
+ #: includes/pp-ui.php:77
1192
+ msgid "Capabilities for custom statuses can be manually added here. Or activate the PP Custom Post Statuses extension to assign status-specific supplemental roles."
1193
+ msgstr "Les permissions pour les états personnalisés peuvent être ajoutées manuellement ici. Ou activez l’extension PP Custom Post Statuses pour affecter des rôles supplémentaires spécifiques à l’état."
 
1194
 
1195
+ #: includes/pp-ui.php:67
1196
+ msgid "\"Posts\" capabilities selected here also define type-specific role assignment for Permit Groups%s."
1197
+ msgstr "Les permissions de « publications » sélectionnées ici définissent également l’attribution de rôles spécifiques au type pour les groupes de permissions%s."
 
1198
 
1199
+ #: includes/pp-ui.php:65
1200
+ msgid "\"Posts\" capabilities selected here also define type-specific role assignment for Permission Groups%s."
1201
+ msgstr "Les permissions de « publications » sélectionnées ici définissent également lattribution de rôles spécifiques au type pour les groupes de permissions%s."
1202
 
1203
+ #: includes/pp-ui.php:60
1204
+ msgid "activate %1$sAdvanced settings%2$s, see Role Usage"
1205
+ msgstr "activer %1$sRéglages avancées%2$s, voir Utilisation des rôles"
 
1206
 
1207
+ #: includes/pp-ui.php:58
1208
+ msgid "see %1$sRole Usage%2$s: \"Pattern Roles\""
1209
+ msgstr "voir %1$sUtilisation des rôles%2$s : « Modèle de rôle »."
 
1210
 
1211
+ #: includes/manager.php:787
1212
+ msgid "Bad form Received"
1213
+ msgstr "Formulaire reçu incorrect"
1214
 
1215
+ #: includes/roles/class/class-pp-roles-actions.php:461
1216
+ msgid "Cannot delete default role. You <a href=\"%s\">have to change it first</a>."
1217
+ msgstr "Vous ne pouvez pas modifier le rôle par defaut. Vous devez d’abord <a href=\"%s\">le modifier</a>."
1218
 
1219
+ #: includes/handler.php:250
1220
+ msgid "You cannot remove Manage Capabilities from Administrators"
1221
+ msgstr "Vous ne pouvez pas supprimer Gérer les permissions des administrateurs"
 
1222
 
1223
+ #: includes/handler.php:127
1224
+ msgid "Bad form received."
1225
+ msgstr "Formulaire reçu incorrect."
 
 
1226
 
1227
+ #: includes/handler.php:119
1228
+ msgid "Incorrect capability name."
1229
+ msgstr "Nom de permission incorrect."
 
 
1230
 
1231
+ #: includes/manager.php:746
1232
+ msgid "New capability added to role."
1233
+ msgstr "Nouvelle permission ajouté au rôle."
 
 
1234
 
1235
+ #: includes/handler.php:51
1236
+ msgid "Error: Failed creating the new role."
1237
+ msgstr "Erreur : Échec de la création du nouveau rôle."
 
 
1238
 
1239
+ #: includes/handler.php:45
1240
+ msgid "New role created."
1241
+ msgstr "Nouveau rôle créé."
 
 
1242
 
1243
+ #: includes/backup.php:301
1244
+ msgid "Reset to WordPress defaults"
1245
+ msgstr "Réinitialiser avec les valeurs par défaut de WordPress"
1246
 
1247
+ #: includes/backup.php:301
 
1248
  msgid ""
1249
+ "You are about to reset Roles and Capabilities to WordPress defaults.\n"
1250
+ " 'Cancel' to stop, 'OK' to reset."
1251
  msgstr ""
1252
+ "Vous êtes sur le point de réinitialiser les rôles et les permissions avec les valeurs par défaut de WordPress.\n"
1253
+ "« Annuler » pour arrêter et « OK » pour réinitialiser."
1254
 
1255
+ #: includes/backup.php:299
1256
+ msgid "Reset Roles and Capabilities to WordPress defaults"
1257
+ msgstr "Réinitialiser les rôles et les permissions avec les valeurs par défaut de WordPress"
 
 
1258
 
1259
+ #: includes/backup.php:296
1260
+ msgid "It is recommended to use this only as a last resource!"
1261
+ msgstr "Il est recommandé de ne l’utiliser qu’en dernier recours !"
 
 
1262
 
1263
+ #: includes/backup.php:294
1264
+ msgid "If you have installed any plugin that adds new roles or capabilities, these will be lost."
1265
+ msgstr "Si vous avez ajouté une extension pour créer de nouveaux rôles ou permissions, celles-ci seront perdues."
 
 
1266
 
1267
+ #: includes/backup.php:290
1268
+ msgid "Reseting default Roles and Capabilities will set them to the WordPress install defaults."
1269
+ msgstr "La réinitialisation des rôles et des capacités par défaut les définira sur les valeurs d’installation par défaut de WordPress."
 
 
1270
 
1271
+ #: includes/backup.php:290 includes/backup.php:347
1272
+ msgid "WARNING:"
1273
+ msgstr "Avertissement :"
 
 
1274
 
1275
+ #: includes/backup.php:288
1276
+ msgid "Reset WordPress Defaults"
1277
+ msgstr "Réinitialiser avec les valeurs par défaut de WordPress"
 
 
1278
 
1279
+ #: includes/backup.php:60
1280
+ msgid "Backup Roles and Capabilities"
1281
+ msgstr "Sauvegarder les rôles et les permissions"
 
1282
 
1283
+ #: includes/backup-handler.php:296
1284
+ msgid "Roles and Capabilities reset to WordPress defaults"
1285
+ msgstr "Rôles et permissions réinitialisées avec les valeurs par défaut de WordPress"
1286
 
1287
+ #: includes/backup-handler.php:283
1288
+ msgid "Needed function to create default roles not found!"
1289
+ msgstr "Fonction nécessaire à la création des rôles par défaut non trouvée !"
1290
 
1291
+ #: includes/backup-handler.php:92 includes/backup-handler.php:121
1292
+ #: includes/backup-handler.php:130
1293
+ msgid "Restore failed. No backup found."
1294
+ msgstr "Echec de la restauration. Aucune sauvegarde trouvée."
 
1295
 
1296
+ #: includes/backup-handler.php:73
1297
+ msgid "New backup saved."
1298
+ msgstr "Nouvelle sauvegarde enregistrée."
1299
 
1300
+ #: includes/backup-handler.php:15 includes/manager.php:901
1301
+ msgid "You do not have permission to restore roles."
1302
+ msgstr "Vous n’avez pas la permission de restaurer les rôles."
1303
 
1304
+ #: includes/admin.php:1414
1305
+ msgid "sync role to all sites now"
1306
+ msgstr "synchroniser le rôle avec tous les sites maintenant"
1307
 
1308
+ #: includes/admin.php:1414
1309
+ msgid "Copy / update this role definition to all sites now"
1310
+ msgstr "Copiez/mettez à jour cette définition de rôle sur tous les sites maintenant"
1311
 
1312
+ #: includes/admin.php:1411
1313
+ msgid "include in new sites"
1314
+ msgstr "inclure dans les nouveaux sites"
1315
 
1316
+ #: includes/admin.php:1411
1317
+ msgid "Create this role definition in new (future) sites"
1318
+ msgstr "Créer cette définition de rôle dans les nouveaux (futurs) sites"
1319
 
1320
+ #: includes/admin.php:1375
1321
+ msgid "Add to role"
1322
+ msgstr "Ajouter au rôle"
1323
 
1324
+ #: includes/admin.php:749 includes/admin.php:843 includes/admin.php:887
1325
+ #: includes/admin.php:960 includes/admin.php:1088 includes/admin.php:1205
1326
+ msgid "Capability Name"
1327
+ msgstr "Nom de la permission"
1328
 
1329
+ #: includes/admin.php:1372
1330
+ msgid "Add Capability"
1331
+ msgstr "Ajouter une permission"
1332
 
1333
+ #: includes/roles/class/class-pp-roles-list-table.php:240
1334
+ msgid "Copy"
1335
+ msgstr "Copier"
1336
 
1337
+ #: includes/roles/class/class-pp-roles-admin.php:349
1338
+ msgid "Create New Role"
1339
+ msgstr "Créer un nouveau rôle"
1340
 
1341
+ #: includes/roles/class/class-pp-roles-admin.php:184
1342
+ msgid "Delete role"
1343
+ msgstr "Supprimer le rôle"
1344
 
1345
+ #: includes-core/admin-menus-promo.php:48 includes-core/nav-menus-promo.php:52
1346
+ #: includes/admin.php:113 includes/admin.php:1348
1347
+ #: includes/features/admin-features.php:76
1348
+ #: includes/features/admin-features.php:215 includes/settings.php:56
1349
+ msgid "Save Changes"
1350
+ msgstr "Enregistrer les modifications"
1351
 
1352
+ #: includes/admin.php:1328
1353
+ msgid "Level:"
1354
+ msgstr "Niveau :"
1355
 
1356
+ #: includes/admin.php:1076
1357
+ msgid "Additional Capabilities"
1358
+ msgstr "Permissions supplémentaires"
1359
 
1360
+ #: includes/admin.php:751 includes/admin.php:845 includes/admin.php:889
1361
+ #: includes/admin.php:962 includes/admin.php:1090 includes/admin.php:1207
1362
+ msgid "negate none (add/remove all capabilities normally)"
1363
+ msgstr "ne rien nier (ajouter/supprimer les permissions normalement)"
1364
 
1365
+ #: includes/admin.php:751 includes/admin.php:845 includes/admin.php:889
1366
+ #: includes/admin.php:962 includes/admin.php:1090 includes/admin.php:1207
1367
+ msgid "negate all (storing as disabled capabilities)"
1368
+ msgstr "nier tout (stockage en tant que permissions désactivées)"
1369
 
1370
+ #: includes/admin.php:749 includes/admin.php:843 includes/admin.php:887
1371
+ #: includes/admin.php:960 includes/admin.php:1088 includes/admin.php:1205
1372
+ msgid "check / uncheck all"
1373
+ msgstr "tout cocher/décocher"
 
 
 
1374
 
1375
+ #: includes/admin.php:640 includes/admin.php:782 includes/admin.php:922
1376
+ #: includes/admin.php:1153
1377
+ msgid "%s: assigned by Permission Group"
1378
+ msgstr "%s : attribué par le groupe de permission"
1379
 
1380
+ #: includes/admin.php:237
1381
+ msgid "can delete posts which are currently published with private visibility"
1382
+ msgstr "peut supprimer les publications publiées avec une visibilité privée"
1383
 
1384
+ #: includes/admin.php:236
1385
+ msgid "can delete posts which are currently published"
1386
+ msgstr "peut supprimer les publications publiées"
1387
 
1388
+ #: includes/admin.php:235
1389
+ msgid "can delete posts which were created by other users"
1390
+ msgstr "peut supprimer les publications créés par d’autres utilisateurs/utilisatrices"
 
1391
 
1392
+ #: includes/admin.php:234
1393
+ msgid "has basic deletion capability (but may need other capabilities based on post status and ownership)"
1394
+ msgstr "possède la permission de supprimer de base (mais peut nécessiter d’autres permissions basées sur le état ou la propriété de la publication)"
1395
 
1396
+ #: includes/admin.php:233
1397
+ msgid "can make a post publicly visible"
1398
+ msgstr "peut modifier la visibilité d’une publication"
1399
 
1400
+ #: includes/admin.php:232
1401
+ msgid "can edit posts which are currently published with private visibility"
1402
+ msgstr "peut modifier les publications publiés avec la visibilité privée"
1403
+
1404
+ #: includes/admin.php:231
1405
+ msgid "can edit posts which are currently published"
1406
+ msgstr "peut modifier les articles publiés"
1407
 
1408
+ #: includes/admin.php:230
1409
+ msgid "can edit posts which were created by other users"
1410
+ msgstr "peut modifier les articles créés par d’autres utilisateurs/utilisatrices"
1411
 
1412
+ #: includes/admin.php:229
1413
+ msgid "has basic editing capability (but may need other capabilities based on post status and ownership)"
1414
+ msgstr "possède la permission de modifier de base (mais peut nécessiter d’autres permissions basées sur le état ou la propriété de la publication)"
1415
 
1416
+ #: includes/admin.php:228
1417
+ msgid "can read posts which are currently published with private visibility"
1418
+ msgstr "peut lire les articles publiés avec la visibilité privée"
1419
 
1420
+ #: includes/admin.php:222
1421
+ msgid "Reading"
1422
+ msgstr "Lecture"
1423
 
1424
+ #: includes/admin.php:221
1425
+ msgid "&nbsp;"
1426
+ msgstr "&nbsp;"
1427
 
1428
+ #: includes/admin.php:1294
1429
+ msgid "%s info/purchase"
1430
+ msgstr "%s infos/achat"
1431
 
1432
+ #: includes/admin.php:1294
1433
+ msgid "%1$sbuy%2$s %3$s"
1434
+ msgstr "%1$sacheter%2$s %3$s"
1435
 
1436
+ #: includes/admin.php:1292
1437
+ msgid "%s (free install)"
1438
+ msgstr "%s (installation gratuite)"
1439
 
1440
+ #: includes/admin.php:1292
1441
+ msgid "%1$sgrab%2$s %3$s"
1442
+ msgstr "%1$sprendre%2$s %3$s"
1443
 
1444
+ #: includes/admin.php:1285
1445
+ msgid "Member support forum"
1446
+ msgstr "Forum d’assistance aux membres"
1447
 
1448
+ #: includes/admin.php:1281
1449
+ msgid "WPML integration to mirror permissions to translations <em>(Pro)</em>"
1450
+ msgstr "Intégration WPML pour refléter les droits dans les traductions <em> (Pro)</em>"
1451
 
1452
+ #: includes/admin.php:1277
1453
+ msgid "Grant supplemental content permissions to a BuddyPress group <em>(Pro)</em>"
1454
+ msgstr "Autorisez les droits de contenu supplémentaire au groupe BuddyPress <em> (Pro)</em>"
1455
 
1456
+ #: includes/admin.php:1273
1457
+ msgid "Grant Spectator, Participant or Moderator access to specific bbPress forums <em>(Pro)</em>"
1458
+ msgstr "Autorisez les visiteurs, participants ou modérateurs à accéder aux forums bbPress <em> (Pro)</em>"
1459
 
1460
+ #: includes/admin.php:1269
1461
+ msgid "Customize the moderated editing of published content with Revisionary or Post Forking <em>(Pro)</em>"
1462
+ msgstr "Personnaliser la modification modérée de la publication publié avec Revisionary ou Post Forking <em> (Pro)</em>"
 
 
1463
 
1464
+ #: includes/admin.php:1265
1465
+ msgid "Regulate permissions for Edit Flow post statuses <em>(Pro)</em>"
1466
+ msgstr "Réglementez les droits pour modifier les états de publication Edit Flow <em> (Pro)</em>"
 
 
 
 
 
1467
 
1468
+ #: includes/admin.php:1261
1469
+ msgid "Custom Moderation statuses for access-controlled, multi-step publishing workflow <em>(Pro)</em>"
1470
+ msgstr "États de modération personnalisés pour un flux de publication à accès contrôlé et à plusieurs étapes <em> (Pro)</em>"
1471
 
1472
+ #: includes/admin.php:1257
1473
+ msgid "Custom Post Visibility statuses, fully implemented throughout wp-admin <em>(Pro)</em>"
1474
+ msgstr "États de visibilité de publication personnalisés, entièrement mis en œuvre dans wp-admin. <em> (Pro)</em>"
1475
 
1476
+ #: includes/admin.php:1253
1477
+ msgid "Customize editing permissions per-category or per-post <em>(Pro)</em>"
1478
+ msgstr "Personnalisez les droits de modification par catégorie ou par publication <em> (Pro)</em>"
 
 
 
1479
 
1480
+ #: includes/admin.php:1249
1481
+ msgid "Customize reading permissions per-category or per-post"
1482
+ msgstr "Personnalisez les droits de lecture par catégorie ou par article"
 
1483
 
1484
+ #: includes/admin.php:1245
1485
+ msgid "Assign custom WP roles supplementally for a specific post type <em>(Pro)</em>"
1486
+ msgstr "Assignez des rôles WP personnalisés de manière complémentaire pour un type de publication spécifique <em> (Pro)</em>"
 
1487
 
1488
+ #: includes/admin.php:1241
1489
+ msgid "Assign standard WP roles supplementally for a specific post type"
1490
+ msgstr "Assignez des rôles WP standard de manière complémentaire pour un type de publication spécifique"
1491
 
1492
+ #: includes/admin.php:1237
1493
+ msgid "Automatically define type-specific capabilities for your custom post types and taxonomies"
1494
+ msgstr "Définissez automatiquement les permissions spécifiques à vos types de publication et taxonomies personnalisés"
1495
 
1496
+ #: includes/backup.php:321
1497
+ msgid "Roles and Capabilities"
1498
+ msgstr "Rôles et capacités"
1499
 
1500
+ #: includes/manager.php:1007
1501
+ msgid "Documentation"
1502
+ msgstr "Documentation"
1503
 
1504
+ #: framework/lib/formating.php:40
1505
+ msgid "Settings saved."
1506
+ msgstr "Réglages enregistrés."
1507
 
1508
+ #: includes/manager.php:206
1509
+ msgid "Add or remove capability from the role normally"
1510
+ msgstr "Ajouter ou supprimer une permission du rôle normalement"
 
 
 
 
 
1511
 
1512
+ #: includes/manager.php:205
1513
+ msgid "Add or remove this capability from the WordPress role"
1514
+ msgstr "Ajouter ou supprimer une permission au rôle WordPress"
1515
 
1516
+ #: includes/manager.php:204
1517
+ msgid "This capability is explicitly negated. Click to add/remove normally."
1518
+ msgstr "Cette permission est explicitement niée. Cliquer pour l’ajouter/supprimer normalement."
1519
 
1520
+ #: includes/manager.php:203
1521
+ msgid "Post type registration does not define this capability distinctly"
1522
+ msgstr "L’enregistrement du type de publication ne définit pas cette permission de manière distincte"
1523
 
1524
+ #: includes/manager.php:202
1525
+ msgid "Explicitly negate these capabilities by storing as disabled"
1526
+ msgstr "Annulez explicitement ces permissions en les stockant comme désactivées"
1527
 
1528
+ #: includes/manager.php:201
1529
+ msgid "Explicity negate this capability by storing as disabled"
1530
+ msgstr "Annulez explicitement cette permission en la stockant comme désactivée"
1531
 
1532
+ #: includes/admin-load.php:308 includes/manager.php:339
1533
+ #: includes/manager.php:410 includes/roles/class/class-pp-roles-admin.php:427
1534
+ #: includes/roles/class/class-pp-roles-list-table.php:172
1535
+ msgid "Capabilities"
1536
+ msgstr "Permissions"
1537
 
1538
+ #: includes/admin.php:59
1539
+ msgid "Role Capabilities"
1540
+ msgstr "Permissions du rôle"
1541
 
1542
+ #: capsman-enhanced.php:115
1543
+ msgid "%s is required for this plugin."
1544
+ msgstr "%s est requis pour cette extension."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1545
 
1546
+ #: capsman-enhanced.php:113
1547
+ msgid "The active plugin %s is not compatible with your PHP version."
1548
+ msgstr "L’extension active %s n’est pas compatible avec votre version de PHP."
1549
 
1550
+ #: capsman-enhanced.php:112
1551
+ msgid "Warning:"
1552
+ msgstr "Avertissement :"
1553
 
1554
+ #: capsman-enhanced.php:55
1555
+ msgid "%1s Error: %2s PublishPress Capabilities cannot function because another copy of Capability Manager is active."
1556
+ msgstr "%1s Erreur : %2s PublishPress Capabilities ne peut pas fonctionner car une autre copie de Capability Manager est active."
languages/capsman-enhanced-it_IT.mo CHANGED
Binary file
languages/capsman-enhanced-it_IT.po CHANGED
@@ -4,8 +4,8 @@ msgid ""
4
  msgstr ""
5
  "Project-Id-Version: Plugins - PublishPress Capabilities &#8211; User Role Access, Editor Permissions, Admin Menus - Stable (latest release)\n"
6
  "POT-Creation-Date: \n"
7
- "PO-Revision-Date: 2022-04-21 11:09-0400\n"
8
- "Last-Translator: Kevin Behrens <kevin@publishpress.com>\n"
9
  "Language-Team: Angelo Giammarresi - info@wocmultimedia.com\n"
10
  "Language: it\n"
11
  "MIME-Version: 1.0\n"
@@ -14,19 +14,251 @@ msgstr ""
14
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
15
  "X-Generator: Poedit 3.0.1\n"
16
 
17
- #: includes/roles/class/class-pp-roles-actions.php:248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  msgid "The new role %s was created successfully."
19
- msgstr "Il nuovo ruolo è stato creato con successo."
20
 
21
- #: includes/roles/class/class-pp-roles-actions.php:204
22
  msgid "The role \"%s\" already exists. Please choose a different name."
23
  msgstr "Il ruolo \"%s\" esiste già, scegli un nome diverso."
24
 
25
- #: includes/roles/class/class-pp-roles-actions.php:192
26
  msgid "Invalid role name entry: %s"
27
  msgstr "Nome di ruolo inserito non valido: %s"
28
 
29
- #: includes/manager.php:508 includes/manager.php:530
30
  msgid "You do not have permission to manage admin features."
31
  msgstr "Non hai le autorizzazioni adatte per gestire le caratteristiche amministrative."
32
 
@@ -103,90 +335,92 @@ msgstr "Nota: stai solo limitando l'accesso alle schermate delle funzioni di amm
103
  msgid "Admin Feature Restrictions"
104
  msgstr "Restrizioni caratteristiche di amministrazione"
105
 
106
- #: includes/backup.php:320 includes/features/admin-features.php:236
107
- #: includes/features/editor-features.php:143
108
  msgid "Click here to install PublishPress Permissions"
109
  msgstr "Fai clic qui per installare PublishPress Permissions"
110
 
111
- #: includes/backup.php:317 includes/features/admin-features.php:233
112
- #: includes/features/editor-features.php:140
113
  msgid "PublishPress Permissions is 100% free to install."
114
  msgstr "PublishPress Permissions è al 100% gratuito da installare."
115
 
116
- #: includes/backup.php:316 includes/features/admin-features.php:232
117
- #: includes/features/editor-features.php:139
118
  msgid "Allow specific user roles or users to manage each post."
119
  msgstr "Consenti a ruoli o utenti specifici di gestire ogni singolo articolo."
120
 
121
- #: includes/backup.php:315 includes/features/admin-features.php:231
122
- #: includes/features/editor-features.php:138
123
  msgid "Choose who can read and edit each post."
124
  msgstr "Scegli chi può leggere e modificare ogni singolo articolo."
125
 
126
- #: includes/backup.php:313 includes/features/admin-features.php:229
127
- #: includes/features/editor-features.php:136
128
  msgid "Control permissions for individual posts and pages"
129
  msgstr "Controlli le autorizzazioni per ogni singolo articolo e pagina"
130
 
131
- #: includes/backup.php:312 includes/features/admin-features.php:228
132
- #: includes/features/editor-features.php:135
133
  msgid "Recommendations for you"
134
  msgstr "Raccomandazioni per te"
135
 
136
- #: includes/admin.php:848
137
  msgid "Plugin Capabilities &ndash; %s"
138
  msgstr "Plugin Capabilities &ndash; %s"
139
 
140
- #: includes/admin.php:729 includes/admin.php:854 includes/admin.php:1048
141
  msgid "No results found. Please try again with a different word."
142
  msgstr "Nessun risultato trovato, riprova con una parola differente."
143
 
144
- #: includes/admin.php:726 includes/admin.php:851 includes/admin.php:1045
145
  msgid "Filter by capability"
146
  msgstr "Filtra per capacità"
147
 
148
- #: includes/admin.php:723
149
  msgid "WordPress Core Capabilities"
150
  msgstr "Capacità di base di WordPress"
151
 
152
- #: includes/admin.php:539 includes/admin.php:727 includes/admin.php:852
153
- #: includes/admin.php:1046
154
  msgid "Clear"
155
  msgstr "Pulisci"
156
 
157
- #: includes/admin.php:536
158
  msgid "Filter by post type"
159
  msgstr "Filtra per tipo di contenuto"
160
 
161
- #: includes/admin.php:536
162
  msgid "Filter by taxonomy"
163
  msgstr "Filtra per tassonomia"
164
 
165
- #: includes/admin.php:530
166
  msgid "Post %s Capabilities"
167
  msgstr "Capacità dell'articolo %s"
168
 
169
- #: includes/admin.php:530
170
  msgid "Term %s Capabilities"
171
  msgstr "Capacità del termine %s"
172
 
173
- #: includes/admin.php:486
174
  msgid "Additional"
175
  msgstr "Aggiuntivi"
176
 
177
- #: includes/admin.php:307
178
  msgid "WordPress Core"
179
  msgstr "WordPress core"
180
 
181
- #: includes/admin.php:220
182
  msgid "Deletion"
183
  msgstr "Cancellazione"
184
 
185
- #: includes/admin.php:219
186
  msgid "Editing"
187
  msgstr "Modifica"
188
 
189
- #: includes/admin-load.php:306 includes/manager.php:365
 
 
190
  msgid "Admin Features"
191
  msgstr "Caratteristiche amministrative"
192
 
@@ -194,43 +428,43 @@ msgstr "Caratteristiche amministrative"
194
  msgid "You can block pages by URL or hide Admin elements by entering a CSS class or ID. This feature is available in PublishPress Capabilities Pro."
195
  msgstr "Puoi bloccare le pagine per URL, nascondere gli elementi di amministrazione inserendo una classe CSS o un ID. Questa caratteristiche sono disponibili con PublishPress Capabilities Pro."
196
 
197
- #: includes/manager.php:199
198
  msgid "Add or clear custom item entry before saving changes."
199
  msgstr "Aggiungi o cancella la voce personalizzata prima di salvare le modifiche."
200
 
201
- #: includes/manager.php:198
202
  msgid "Are you sure you want to delete this item ?"
203
  msgstr "Sei sicuro di voler cancellare questo elemento?"
204
 
205
- #: includes-core/editor-features-promo.php:135
206
  msgid "Page Attributes: Order"
207
  msgstr "Pagina attributi: Ordini"
208
 
209
- #: includes-core/editor-features-promo.php:121
210
  msgid "Permalink: Descriptive Caption"
211
  msgstr "Permalink: Didascalia descrittiva"
212
 
213
- #: includes-core/editor-features-promo.php:107
214
  msgid "Custom item one"
215
  msgstr "Elemento personalizzato uno"
216
 
217
- #: includes-core/editor-features-promo.php:101
218
  msgid "Custom Items"
219
  msgstr "Elementi personalizzati"
220
 
221
- #: includes-core/editor-features-promo.php:86
222
  msgid "You can hide plugin metaboxes. You can also hide specific items by entering their CSS class or ID. This feature is available in PublishPress Capabilities Pro."
223
  msgstr "Puoi nascondere le metabox dei plugin. Puoi anche nascondere elementi specifici inserendo la loro classe CSS o il loro ID. Questa funzione è disponibile in PublishPress Capabilities Pro."
224
 
225
- #: includes-core/editor-features-promo.php:71
226
  msgid "TaxoPress - Settings"
227
  msgstr "TaxoPress - Impostazioni"
228
 
229
- #: includes-core/editor-features-promo.php:58
230
  msgid "Notifications"
231
  msgstr "Notifiche"
232
 
233
- #: includes-core/editor-features-promo.php:45
234
  msgid "Editorial Comments"
235
  msgstr "Commenti editoriali"
236
 
@@ -242,117 +476,119 @@ msgstr "Elenco di controllo"
242
  msgid "Metaboxes"
243
  msgstr "Metaboxes"
244
 
245
- #: includes/manager.php:492 includes/manager.php:546
246
  msgid "Settings updated."
247
  msgstr "Impostazioni aggiornate."
248
 
249
- #: includes/manager.php:448 includes/manager.php:470
250
  msgid "You do not have permission to manage editor features."
251
  msgstr "Non hai i permessi per gestire le funzionalità dell'editor."
252
 
253
- #: includes/admin-load.php:305 includes/manager.php:363
 
 
254
  msgid "Editor Features"
255
  msgstr "Funzioni dell'editor"
256
 
257
- #: includes/features/restrict-editor-features.php:345
258
  msgid "Text settings"
259
  msgstr "Impostazioni del testo"
260
 
261
- #: includes/features/restrict-editor-features.php:344
262
  msgid "Color settings"
263
  msgstr "Impostazioni colore"
264
 
265
- #: includes/features/restrict-editor-features.php:343
266
  msgid "Typography"
267
  msgstr "Tipografia"
268
 
269
- #: includes/features/restrict-editor-features.php:342
270
  msgid "Paragraph"
271
  msgstr "Paragrafo"
272
 
273
- #: includes/features/restrict-editor-features.php:340
274
- #: includes/features/restrict-editor-features.php:341
275
  msgid "Block Panel"
276
  msgstr "Pannello del blocco"
277
 
278
- #: includes/features/restrict-editor-features.php:337
279
  msgid "Post Attributes"
280
  msgstr "Attributi articolo"
281
 
282
- #: includes/features/restrict-editor-features.php:335
283
  msgid "Excerpt"
284
  msgstr "Riassunto"
285
 
286
- #: includes/features/restrict-editor-features.php:334
287
  msgid "Featured image"
288
  msgstr "Immagine in evidenza"
289
 
290
- #: includes/features/restrict-editor-features.php:317
291
  msgid "Status & visibility"
292
  msgstr "Stato e visibilità"
293
 
294
- #: includes/features/restrict-editor-features.php:316
295
  msgid "Document Panel"
296
  msgstr "Pannello documenti"
297
 
298
- #: includes/features/restrict-editor-features.php:313
299
  msgid "Content"
300
  msgstr "Contenuti"
301
 
302
- #: includes/features/restrict-editor-features.php:312
303
  msgid "Edit title"
304
  msgstr "Modifica titolo"
305
 
306
- #: includes/features/restrict-editor-features.php:311
307
  msgid "Body"
308
  msgstr "Contenuto"
309
 
310
- #: includes/features/restrict-editor-features.php:308
311
  msgid "Options"
312
  msgstr "Opzioni"
313
 
314
- #: includes/features/restrict-editor-features.php:306
315
  msgid "Publish / Update"
316
  msgstr "Pubblica/Aggiorna"
317
 
318
- #: includes/features/restrict-editor-features.php:304
319
  msgid "Switch to draft"
320
  msgstr "Passa alla bozza"
321
 
322
- #: includes/features/restrict-editor-features.php:302
323
  msgid "Top Bar - Right"
324
  msgstr "Barra in alto - Destra"
325
 
326
- #: includes/features/restrict-editor-features.php:299
327
  msgid "Outline"
328
  msgstr "Contorno"
329
 
330
- #: includes/features/restrict-editor-features.php:298
331
  msgid "Details"
332
  msgstr "Dettagli"
333
 
334
- #: includes/features/restrict-editor-features.php:297
335
  msgid "Redo"
336
  msgstr "Ripeti"
337
 
338
- #: includes/features/restrict-editor-features.php:296
339
  msgid "Undo"
340
  msgstr "Annulla"
341
 
342
- #: includes/features/restrict-editor-features.php:295
343
  msgid "Modes"
344
  msgstr "Modalità"
345
 
346
- #: includes/features/restrict-editor-features.php:294
347
  msgid "Add block"
348
  msgstr "Aggiungi blocco"
349
 
350
- #: includes/features/restrict-editor-features.php:293
351
  msgid "Top Bar - Left"
352
  msgstr "Barra in alto - Sinistra"
353
 
354
  #: includes/features/restrict-editor-features.php:93
355
- #: includes/features/restrict-editor-features.php:336
356
  msgid "Discussion"
357
  msgstr "Discussione"
358
 
@@ -389,7 +625,7 @@ msgid "Page Boxes"
389
  msgstr "Riquadri pagina"
390
 
391
  #: includes/features/restrict-editor-features.php:71
392
- #: includes/features/restrict-editor-features.php:320
393
  msgid "Tags"
394
  msgstr "Tag"
395
 
@@ -398,7 +634,7 @@ msgid "Add New Category"
398
  msgstr "Aggiungi una nuova categoria"
399
 
400
  #: includes/features/restrict-editor-features.php:69
401
- #: includes/features/restrict-editor-features.php:319
402
  msgid "Categories"
403
  msgstr "Categorie"
404
 
@@ -435,12 +671,12 @@ msgid "Publish Status "
435
  msgstr "Stato pubblicazione "
436
 
437
  #: includes/features/restrict-editor-features.php:58
438
- #: includes/features/restrict-editor-features.php:305
439
  msgid "Preview"
440
  msgstr "Anteprima"
441
 
442
  #: includes/features/restrict-editor-features.php:57
443
- #: includes/features/restrict-editor-features.php:303
444
  msgid "Save Draft"
445
  msgstr "Salva bozza"
446
 
@@ -462,7 +698,7 @@ msgid "Media Buttons (all)"
462
  msgstr "Pulsanti Media (tutti)"
463
 
464
  #: includes/features/restrict-editor-features.php:49
465
- #: includes/features/restrict-editor-features.php:318
466
  msgid "Permalink"
467
  msgstr "Permalink"
468
 
@@ -489,126 +725,91 @@ msgstr "Aiuto"
489
  msgid "Top Tabs"
490
  msgstr "Schede in alto"
491
 
492
- #: includes/features/editor-features.php:95
493
  msgid "Classic"
494
  msgstr "Classico"
495
 
496
- #: includes/features/editor-features.php:92
497
  msgid "Gutenberg"
498
  msgstr "Gutenberg"
499
 
500
- #: includes/features/editor-features.php:48
501
  msgid "Select editor features to remove. Note that this screen cannot be used to grant additional features to any role."
502
  msgstr "Seleziona le caratteristiche dell'editor da rimuovere. Sappi che questa schermata non può essere usata per attribuire funzionalità aggiuntive ai vari ruoli."
503
 
504
- #: includes/features/editor-features.php:32
505
  msgid "Editor Feature Restriction"
506
  msgstr "Limitazione delle funzioni dell'editor"
507
 
508
- #: includes/features/editor-features-gutenberg.php:29
509
- msgid "Gutenberg Screen"
510
- msgstr "Schermata Gutenberg"
511
-
512
- #: includes/features/editor-features-classic.php:35
513
- #: includes/features/editor-features-gutenberg.php:35
514
- msgid "Toggle all"
515
- msgstr "Commuta tutti"
516
-
517
- #: includes/features/editor-features-classic.php:34
518
- #: includes/features/editor-features-gutenberg.php:34
519
- msgid "%s Restrict"
520
- msgstr "Limitazione %s"
521
-
522
- #: includes/features/editor-features-classic.php:29
523
- msgid "Classic Editor Screen"
524
- msgstr "Schermata dell'editor classico"
525
-
526
- #: includes/admin.php:1387
527
  msgid "sync options to all sites now"
528
  msgstr "sincronizza le opzioni su tutti i siti adesso"
529
 
530
- #: includes/admin.php:1387
531
  msgid "Copy option settings to all sites now"
532
  msgstr "Copia le impostazioni delle opzioni su tutti i siti adesso"
533
 
534
- #: includes/admin.php:1352
535
- msgid "Rename"
536
- msgstr "Rinomina"
537
-
538
- #: includes/admin.php:1349
539
- msgid "New Role Name"
540
- msgstr "Nome del nuovo ruolo"
541
-
542
- #: includes/admin.php:1347
543
- msgid "Rename Role"
544
- msgstr "Rinomina il ruolo"
545
-
546
- #: includes/admin.php:957
547
  msgid "The following entries have no effect. Please assign desired capabilities in the Read / Edit / Delete grid above."
548
  msgstr "Le voci seguenti non hanno effetto. Assegna le funzionalità desiderate nella griglia Leggi/Modifica/Elimina sopra."
549
 
550
- #: includes/handler.php:90 includes/handler.php:118 includes/handler.php:420
551
- #: includes/manager.php:735
552
  msgid "The selected role is not editable."
553
  msgstr "Il ruolo selezionato non è modificabile."
554
 
555
- #: includes/manager.php:425
556
  msgid "You do not have permission to manage roles."
557
  msgstr "Non hai le autorizzazioni per gestire i ruoli."
558
 
559
- #: includes/backup.php:267
560
  msgid "No changes"
561
  msgstr "Nessuna modifica"
562
 
563
- #: includes/backup.php:198
564
  msgid "(this role will be removed if you restore backup)"
565
  msgstr "(questo ruolo sarà rimosso se ripristini il backup)"
566
 
567
- #: includes/backup.php:157
568
  msgid "Show changes from current roles only"
569
  msgstr "Mostra le modifiche solo dai ruoli attuali"
570
 
571
- #: includes/backup.php:146
572
  msgid "Restore Selected Roles"
573
  msgstr "Ripristina i ruoli selezionati"
574
 
575
- #: includes/backup.php:137
576
  msgid "Initial backup of all roles"
577
  msgstr "Backup iniziali di tutti i ruoli"
578
 
579
- #: includes/backup.php:129
580
  msgid "Auto-backup of all roles (%s)"
581
  msgstr "Backup automatico di tutti i ruoli (%s)"
582
 
583
- #: includes/backup.php:114
584
- msgid "Manual backup of all roles (%s)"
585
- msgstr "Backup manuale di tutti i ruoli (%s)"
586
-
587
- #: includes/backup.php:100
588
  msgid "Available Backups:"
589
  msgstr "Backup disponibili:"
590
 
591
- #: includes/backup.php:95
592
  msgid "On this screen, you can restore an earlier version of your roles and capabilities."
593
  msgstr "In questa schermata puoi ripristinare una versione precedente dei tuoi ruoli e delle capacità."
594
 
595
- #: includes/backup.php:91
596
  msgid "PublishPress Capabilities automatically creates a backup on installation and whenever you save changes."
597
  msgstr "PublishPress Capabilities crea automaticamente un backup durante l'installazione e ogni volta che salvi le modifiche."
598
 
599
- #: includes/backup.php:88
600
  msgid "Restore Previous Roles and Capabilities"
601
  msgstr "Ripristina ruoli e capacità precedenti"
602
 
603
- #: includes/backup.php:74
604
  msgid "Manual Backup"
605
  msgstr "Backup manuale"
606
 
607
- #: includes/backup.php:69
608
  msgid "A backup created on this screen replaces any previous manual backups, but is never automatically replaced."
609
  msgstr "Un backup creato in questa schermata sostituirà qualsiasi backup manuale precedente, ma non viene sostituito automaticamente."
610
 
611
- #: includes/backup.php:64
612
  msgid "PublishPress Capabilities automatically creates a backup on installation and whenever you save changes. The initial backup and last %d auto-backups are kept."
613
  msgstr "PublishPress Capabilities crea automaticamente un backup durante l'installazione e ogni volta che salvi le modifiche. Il backup iniziale e gli ultimi %d backup automatici vengono mantenuti."
614
 
@@ -620,133 +821,118 @@ msgstr "Ripristina ruoli"
620
  msgid "Restore"
621
  msgstr "Ripristina"
622
 
623
- #: includes/admin-load.php:312
624
- #: includes/features/restrict-editor-features.php:307 includes/manager.php:372
625
  msgid "Settings"
626
  msgstr "Impostazioni"
627
 
628
- #: includes/roles/roles.php:52
629
  msgid "Description here."
630
  msgstr "La descrizione qui."
631
 
632
- #: includes/roles/roles.php:40
633
- msgid "Add"
634
- msgstr "Aggiungi"
635
-
636
- #: includes/roles/roles.php:35
637
- msgid "The name is how it appears on your site."
638
- msgstr "Il nome come apparirà sul tuo sito."
639
-
640
- #: includes/manager.php:396 includes/roles/roles.php:33
641
- msgid "Name"
642
- msgstr "Nome"
643
-
644
- #: includes/roles/roles.php:25
645
- msgid "Add New Role"
646
- msgstr "Aggiungi un nuovo ruolo"
647
-
648
- #: includes/roles/roles.php:19
649
  msgid "Search Roles"
650
  msgstr "Cerca ruoli"
651
 
652
  #. translators: %s: search keywords
653
- #: includes/roles/roles.php:8
654
  msgid "Search results for &#8220;%s&#8221;"
655
  msgstr "Risultati di ricerca per &#8220;%s&#8221;"
656
 
657
- #: includes/admin-load.php:304 includes/manager.php:351
658
- #: includes/roles/roles.php:4
659
  msgid "Roles"
660
  msgstr "Ruoli"
661
 
662
- #: includes/roles/class/class-pp-roles-list-table.php:239
663
  msgid "Your Role"
664
  msgstr "Il tuo ruolo"
665
 
666
- #: includes/roles/class/class-pp-roles-list-table.php:234
667
  msgid "Default Role"
668
  msgstr "Ruolo predefinito"
669
 
670
- #: includes/roles/class/class-pp-roles-list-table.php:183
671
  msgid "Hide"
672
  msgstr "Nascondi"
673
 
674
- #: includes-core/editor-features-promo.php:108
675
- #: includes-core/editor-features-promo.php:122
676
- #: includes-core/editor-features-promo.php:135
677
  #: includes/features/admin-features.php:190
678
- #: includes/features/editor-features-classic.php:78
679
- #: includes/features/editor-features-gutenberg.php:77
680
- #: includes/roles/class/class-pp-roles-list-table.php:164
681
- #: includes/roles/class/class-pp-roles-list-table.php:301
 
682
  msgid "Delete"
683
  msgstr "Elimina"
684
 
685
- #: includes/roles/class/class-pp-roles-list-table.php:146
686
  msgid "Unhide"
687
  msgstr "Mostra"
688
 
689
- #: includes/roles/class/class-pp-roles-list-table.php:128
690
  msgid "(non-editable role)"
691
  msgstr "(ruolo non modificabile)"
692
 
693
- #: includes/manager.php:398
694
- #: includes/roles/class/class-pp-roles-list-table.php:78
695
  msgid "Users"
696
  msgstr "Utenti"
697
 
698
- #: includes/manager.php:397
699
- #: includes/roles/class/class-pp-roles-list-table.php:77
700
- msgid "Role"
701
- msgstr "Ruolo"
702
-
703
- #: includes/roles/class/class-pp-roles-actions.php:491
704
  msgid "The role %1$s was successfully unhidden."
705
  msgstr "Il ruolo %1$s è stato reso visibile con successo."
706
 
707
- #: includes/roles/class/class-pp-roles-actions.php:431
708
  msgid "The role %1$s was successfully hidden."
709
  msgstr "Il ruolo %1$s è stato nascosto con successo."
710
 
711
- #: includes/roles/class/class-pp-roles-actions.php:377
712
  msgid "The role could not be deleted."
713
  msgstr "Il ruolo non può essere eliminato."
714
 
715
- #: includes/roles/class/class-pp-roles-actions.php:364
716
  msgid "The selected %1$s roles were successfully deleted. %2$s"
717
  msgstr "I ruoli %1$s selezionati sono stati eliminati con successo. %2$s"
718
 
719
- #: includes/roles/class/class-pp-roles-actions.php:358
720
  msgid "The role %1$s was successfully deleted. %2$s"
721
  msgstr "Il ruolo %1$s è stato eliminato con successo. %2$s"
722
 
723
- #: includes/roles/class/class-pp-roles-actions.php:353
724
  msgid "%1$d users moved to default role %2$s."
725
  msgstr "%1$d utenti sono passati al ruolo predefinito %2$s."
726
 
727
- #: includes/roles/class/class-pp-roles-actions.php:331
728
  msgid "Deleting a system role is not allowed."
729
  msgstr "Non è consentito eliminare un ruolo di sistema."
730
 
731
- #: includes/roles/class/class-pp-roles-actions.php:217
732
  msgid "Something went wrong, the system wasn't able to create the role, refresh the page and try again."
733
  msgstr "Qualcosa è andato storto, il sistema non è riuscito a creare il ruolo, ricarica la pagina e prova ancora."
734
 
735
- #: includes/roles/class/class-pp-roles-actions.php:177
736
- #: includes/roles/class/class-pp-roles-actions.php:304
737
- #: includes/roles/class/class-pp-roles-actions.php:420
738
- #: includes/roles/class/class-pp-roles-actions.php:481
 
739
  msgid "Missing parameters, refresh the page and try again."
740
  msgstr "Ci sono dei parametri mancanti, ricarica la pagina e prova ancora."
741
 
742
- #: includes/roles/class/class-pp-roles-actions.php:157
 
 
 
743
  msgid "Your link has expired, refresh the page and try again."
744
  msgstr "Il tuo link è scaduto, ricarica la pagina e prova ancora."
745
 
746
- #: includes/roles/class/class-pp-roles-actions.php:142
747
  msgid "You do not have sufficient permissions to perform this action."
748
  msgstr "Non hai i permessi necessari per compiere quest'azione."
749
 
 
750
  #: includes/roles/roles-functions.php:32
751
  msgid "Are you sure you want to delete this role?"
752
  msgstr "Sei certo di voler eliminare questo ruolo?"
@@ -759,11 +945,15 @@ msgstr "PublishPress Authors"
759
  msgid "Capabilities Settings"
760
  msgstr "Impostazioni di capacità"
761
 
762
- #: includes-core/CoreAdmin.php:63 includes/admin-load.php:308
 
 
763
  msgid "Nav Menus"
764
  msgstr "Menu navigazione"
765
 
766
- #: includes-core/CoreAdmin.php:62 includes/admin-load.php:307
 
 
767
  msgid "Admin Menus"
768
  msgstr "Menu amministrazione"
769
 
@@ -784,64 +974,67 @@ msgid "Navigation Menu Restrictions"
784
  msgstr "Limitazioni menu di navigazione"
785
 
786
  #: includes/features/restrict-editor-features.php:46
787
- #: includes/filters-woocommerce.php:33
788
  msgid "Add New"
789
  msgstr "Aggiungi nuovo"
790
 
791
  #: includes/filters-woocommerce.php:32
 
792
  msgid "All %s"
793
- msgstr "Tutti %s"
 
 
794
 
795
- #: includes/manager.php:923
796
  msgid "Contact"
797
  msgstr "Contatto"
798
 
799
- #: includes/manager.php:923
800
  msgid "Contact the PublishPress team"
801
  msgstr "Contatta il team di PublishPress"
802
 
803
- #: includes/manager.php:921
804
  msgid "Capabilites Documentation"
805
  msgstr "Documentazione di Capabilites"
806
 
807
- #: includes/manager.php:919
808
  msgid "About"
809
  msgstr "Chi siamo"
810
 
811
- #: includes/manager.php:919
812
  msgid "About PublishPress Capabilities"
813
  msgstr "Informazioni su PublishPress Capabilities"
814
 
815
- #: includes/manager.php:908
816
  msgid "If you like %s, please leave us a %s rating. Thank you!"
817
  msgstr "Se sei soddisfatto di %s, lasciaci una valutazione di %s!"
818
 
819
- #: includes/manager.php:651 includes/manager.php:685 includes/manager.php:703
820
  msgid "You do not have permission to manage capabilities."
821
  msgstr "Non hai le autorizzazioni per gestire le capacità."
822
 
823
  #: includes-core/admin-features-promo.php:79
824
  #: includes-core/admin-menus-promo.php:62
825
- #: includes-core/editor-features-promo.php:91
826
- #: includes-core/nav-menus-promo.php:67 includes/admin-load.php:318
827
- #: includes/admin-load.php:319 includes/manager.php:378
828
- #: includes/manager.php:379
829
  msgid "Upgrade to Pro"
830
  msgstr "Aggiorna a Pro"
831
 
832
- #: includes/admin-load.php:309 includes/backup.php:49 includes/manager.php:369
833
  msgid "Backup"
834
  msgstr "Backup"
835
 
836
- #: includes/handler.php:153
837
  msgid "Type / Taxonomy settings saved."
838
  msgstr "Impostazioni tipo/tassonomia salvate."
839
 
840
- #: includes/backup-handler.php:82
841
  msgid "Roles and Capabilities restored from selected auto-backup."
842
  msgstr "Ruoli e capacità sono stati ripristinati dal backup automatico selezionato."
843
 
844
- #: includes/backup-handler.php:64
845
  msgid "Roles and Capabilities restored from initial backup."
846
  msgstr "Ruoli e capacità sono stati ripristinati dal backup iniziale."
847
 
@@ -889,36 +1082,40 @@ msgstr "PublishPress Revisions"
889
  msgid "Related Permissions Plugins"
890
  msgstr "Plugin di autorizzazioni correlati"
891
 
892
- #: includes/admin.php:1334
893
- #: includes/roles/class/class-pp-roles-list-table.php:76
894
  msgid "Role Name"
895
  msgstr "Nome del ruolo"
896
 
897
- #: includes/admin.php:1280
 
 
 
 
898
  msgid "Role level is mostly deprecated. However, it still determines eligibility for Post Author assignment and limits the application of user editing capabilities."
899
  msgstr "Il livello di ruolo è per lo più deprecato. Tuttavia, determina comunque l'idoneità per l'assegnazione di autore articolo e limita l'applicazione delle capacità di modifica dell'utente."
900
 
901
- #: includes/admin.php:481 includes/admin.php:944
902
  msgid "Invalid Capabilities"
903
  msgstr "Capacità non valide"
904
 
905
- #: includes/admin.php:781
906
  msgid "Lockout Prevention: To remove read capability, first remove WordPress admin / editing capabilities, or add \"dashboard_lockout_ok\" capability"
907
  msgstr "Prevenzione blocco: Per rimuovere la capacità di lettura bisogna prima rimuovere le capacità di gestione/modifica di WordPress oppure aggiungere la capacità \"dashboard_lockout_ok\""
908
 
909
- #: includes/admin.php:643
910
  msgid "shared capability: %s"
911
  msgstr "capacità condivise: %s"
912
 
913
- #: includes/admin.php:1189 includes/settings.php:40
914
  msgid "PublishPress Permissions"
915
  msgstr "PublishPress Permissions"
916
 
917
- #: includes/admin.php:128
918
  msgid "<strong>Note:</strong> Capability changes <strong>remain in the database</strong> after plugin deactivation. You can also configure this role as a %sPermission Group%s."
919
  msgstr "<strong>Nota:</strong> Le modifiche della capacità <strong>rimangono nel database</strong> anche dopo la disattivazione del plugin. Puoi anche configurare questo ruolo come una %sautorizzazione di gruppo%s."
920
 
921
- #: includes/admin.php:136
922
  msgid "<strong>Note:</strong> Capability changes <strong>remain in the database</strong> after plugin deactivation."
923
  msgstr "<strong>Nota:</strong> Le modifiche della capacità <strong>rimangono nel database</strong> anche dopo la disattivazione del plugin."
924
 
@@ -926,42 +1123,38 @@ msgstr "<strong>Nota:</strong> Le modifiche della capacità <strong>rimangono ne
926
  msgid "Warning: This role cannot access the dashboard without the read capability. %1$sClick here to fix this now%2$s."
927
  msgstr "Attenzione: Questo ruolo non può accedere alla bacheca senza le capacità di lettura. %1$sFai clic qui per risolvere ora%2$s."
928
 
929
- #: includes/filters.php:263
930
  msgid "Edit Roles"
931
  msgstr "Modifica ruoli"
932
 
933
- #: includes/backup.php:227
934
  msgid "%s (level %s)"
935
  msgstr "%s (livello %s)"
936
 
937
- #: includes/backup.php:191
938
  msgid "%s (%s roles)"
939
  msgstr "%s (%s ruoli)"
940
 
941
- #: includes/backup.php:84
942
  msgid "Last Backup"
943
  msgstr "Ultimo backup"
944
 
945
- #: includes/backup.php:84
946
  msgid "Last Manual Backup - %s"
947
  msgstr "Ultimo backup manuale - %s"
948
 
949
- #: includes/backup.php:164
950
  msgid "Initial Backup"
951
  msgstr "Backup iniziale"
952
 
953
- #: includes/backup.php:164
954
  msgid "Initial Backup - %s"
955
  msgstr "Backup iniziale - %s"
956
 
957
  #: includes/backup.php:39
958
- msgid "Backup Tool for %1$sPublishPress Capabilities%2$s"
959
  msgstr "Strumento di backup per %1$sPublishPress Capabilities%2$s"
960
 
961
- #: capsman-enhanced.php:70
962
- msgid "<strong>This plugin can be deleted.</strong>"
963
- msgstr "<strong>Questo plugin può essere eliminato.</strong>"
964
-
965
  #. Author URI of the plugin
966
  msgid "https://publishpress.com/"
967
  msgstr "https://publishpress.com/"
@@ -1015,43 +1208,43 @@ msgstr "attiva %1$sImpostazioni avanzate%2$s, vedi utilizzo dei ruoli"
1015
  msgid "see %1$sRole Usage%2$s: \"Pattern Roles\""
1016
  msgstr "vedi %1$sUtilizzo dei ruoli%2$s: \"Modelli di ruolo\""
1017
 
1018
- #: includes/manager.php:764
1019
  msgid "Bad form Received"
1020
  msgstr "E' stato ricevuto un modulo errato"
1021
 
1022
- #: includes/roles/class/class-pp-roles-actions.php:312
1023
  msgid "Cannot delete default role. You <a href=\"%s\">have to change it first</a>."
1024
  msgstr "Non é possibile cancellare il ruolo predefinito. Bisogna che prima effettui questa <a href=\"%s\">modifica</a>."
1025
 
1026
- #: includes/handler.php:279
1027
  msgid "You cannot remove Manage Capabilities from Administrators"
1028
  msgstr "Non puoi rimuovere la gestione delle capacità per gli amministratori"
1029
 
1030
- #: includes/handler.php:156
1031
  msgid "Bad form received."
1032
  msgstr "E' stato ricevuto un modulo errato."
1033
 
1034
- #: includes/handler.php:148
1035
  msgid "Incorrect capability name."
1036
  msgstr "Nome non valido per la capacità."
1037
 
1038
- #: includes/manager.php:717
1039
  msgid "New capability added to role."
1040
  msgstr "La nuova capacità é stata aggiunta al ruolo."
1041
 
1042
- #: includes/handler.php:51 includes/handler.php:80
1043
  msgid "Error: Failed creating the new role."
1044
  msgstr "Errore: non é stato possibile creare il nuovo ruolo."
1045
 
1046
- #: includes/handler.php:45 includes/handler.php:74
1047
  msgid "New role created."
1048
  msgstr "Il nuovo ruolo é stato creato."
1049
 
1050
- #: includes/backup.php:296
1051
  msgid "Reset to WordPress defaults"
1052
  msgstr "Ripristina ai predefiniti di WordPress"
1053
 
1054
- #: includes/backup.php:296
1055
  msgid ""
1056
  "You are about to reset Roles and Capabilities to WordPress defaults.\n"
1057
  " 'Cancel' to stop, 'OK' to reset."
@@ -1059,268 +1252,252 @@ msgstr ""
1059
  "Stai per ripristinare i Ruoli e le Capacità ai valori predefiniti di WordPress.\n"
1060
  " 'Annulla' per fermarti, 'OK' per procedere."
1061
 
1062
- #: includes/backup.php:294
1063
  msgid "Reset Roles and Capabilities to WordPress defaults"
1064
  msgstr "Ripristina i Ruoli e le Capacità ai valori predefiniti di WordPress"
1065
 
1066
- #: includes/backup.php:291
1067
  msgid "It is recommended to use this only as a last resource!"
1068
  msgstr "Da utilizzarsi solamente come ultima risorsa!"
1069
 
1070
- #: includes/backup.php:289
1071
  msgid "If you have installed any plugin that adds new roles or capabilities, these will be lost."
1072
  msgstr "I ruoli e le capacità propri di ogni plugin installato saranno persi."
1073
 
1074
- #: includes/backup.php:285
1075
  msgid "Reseting default Roles and Capabilities will set them to the WordPress install defaults."
1076
- msgstr "Il riipristino dei valori predefiniti per i Ruoli e le Capacità li riporterà ai valori predefiniti di WordPress."
1077
 
1078
- #: includes/backup.php:285
1079
  msgid "WARNING:"
1080
  msgstr "Attenzione:"
1081
 
1082
- #: includes/backup.php:283
1083
  msgid "Reset WordPress Defaults"
1084
  msgstr "Ripristina ai valori predefiniti di WordPress"
1085
 
1086
- #: includes/backup.php:59
1087
  msgid "Backup Roles and Capabilities"
1088
  msgstr "Backup ruoli e capacità"
1089
 
1090
- #: includes/backup-handler.php:115
1091
  msgid "Roles and Capabilities reset to WordPress defaults"
1092
  msgstr "I ruoli e le capacità sono stati ripristinati ai valori predefiniti di WordPress"
1093
 
1094
- #: includes/backup-handler.php:102
1095
  msgid "Needed function to create default roles not found!"
1096
  msgstr "La funzione necessaria per la creazione dei ruoli predefiniti non é stata trovata!"
1097
 
1098
- #: includes/backup-handler.php:66 includes/backup-handler.php:75
1099
- #: includes/backup-handler.php:84
1100
  msgid "Restore failed. No backup found."
1101
  msgstr "Non é stato possibile effettuare il ripristino. Non é stato trovato alcun file di backup."
1102
 
1103
  #: includes/backup-handler.php:73
1104
- msgid "Roles and Capabilities restored from last backup."
1105
- msgstr "I ruoli e le capacità sono stati ripristinati all'ultimo backup."
1106
-
1107
- #: includes/backup-handler.php:49
1108
  msgid "New backup saved."
1109
  msgstr "Il nuovo backup é stato salvato."
1110
 
1111
- #: includes/backup-handler.php:15 includes/manager.php:878
1112
  msgid "You do not have permission to restore roles."
1113
  msgstr "Non hai le autorizzazioni per il ripristino dei ruoli."
1114
 
1115
- #: includes/admin.php:1384
1116
  msgid "sync role to all sites now"
1117
  msgstr "sincronizza i ruoli su tutti i siti adesso"
1118
 
1119
- #: includes/admin.php:1384
1120
  msgid "Copy / update this role definition to all sites now"
1121
  msgstr "Copia/aggiorna la definizione di questo ruolo su tutti i siti adesso"
1122
 
1123
- #: includes/admin.php:1381
1124
  msgid "include in new sites"
1125
  msgstr "includi nei nuovi siti"
1126
 
1127
- #: includes/admin.php:1381
1128
  msgid "Create this role definition in new (future) sites"
1129
  msgstr "Crea la definizione di questo ruolo nei nuovi (futuri) siti"
1130
 
1131
- #: includes/admin.php:1319
1132
  msgid "Add to role"
1133
  msgstr "Aggiungi al ruolo"
1134
 
1135
- #: includes/admin.php:1316
 
 
 
 
 
1136
  msgid "Add Capability"
1137
  msgstr "Aggiungi capacità"
1138
 
1139
- #: includes/admin.php:1341
1140
  msgid "Copy"
1141
  msgstr "Copia"
1142
 
1143
- #: includes/admin.php:1331
1144
- msgid "Copy this role to"
1145
- msgstr "Copia questo ruolo per"
1146
-
1147
- #: includes/admin.php:1337
1148
- msgid "hidden"
1149
- msgstr "nascosto"
1150
-
1151
- #: includes/admin.php:1337
1152
- msgid "Make role available for supplemental assignment to Permission Groups only"
1153
- msgstr "Rendi il ruolo disponibile per assegnazioni supplementari solo per i gruppi di autorizzazione"
1154
 
1155
- #: includes/admin.php:1307
1156
- msgid "Delete Role"
1157
  msgstr "Elimina il ruolo"
1158
 
1159
- #: includes/admin.php:1307
1160
- msgid ""
1161
- "You are about to delete the %s role.\n"
1162
- "\n"
1163
- " 'Cancel' to stop, 'OK' to delete."
1164
- msgstr ""
1165
- "Stai per eliminare il ruolo %s.\n"
1166
- "\n"
1167
- " 'Annulla' per fermarti, 'OK' per eliminare."
1168
-
1169
- #: includes/admin.php:1307
1170
- msgid "Delete this role"
1171
- msgstr "Elimina questo ruolo"
1172
-
1173
  #: includes-core/admin-menus-promo.php:48 includes-core/nav-menus-promo.php:52
1174
- #: includes/admin.php:109 includes/admin.php:1302
1175
  #: includes/features/admin-features.php:76
1176
- #: includes/features/admin-features.php:215
1177
- #: includes/features/editor-features.php:69
1178
- #: includes/features/editor-features.php:122 includes/settings.php:56
1179
  msgid "Save Changes"
1180
  msgstr "Salva modifiche"
1181
 
1182
- #: includes/admin.php:1282
1183
  msgid "Level:"
1184
  msgstr "Livello:"
1185
 
1186
- #: includes/admin.php:1042
1187
  msgid "Additional Capabilities"
1188
  msgstr "Capacità aggiuntive"
1189
 
1190
- #: includes/admin.php:824 includes/admin.php:929 includes/admin.php:1162
 
1191
  msgid "negate none (add/remove all capabilities normally)"
1192
  msgstr "nessuna negazione (aggiungere/rimuovere tutte le funzionalità normalmente)"
1193
 
1194
- #: includes/admin.php:824 includes/admin.php:929 includes/admin.php:1162
 
1195
  msgid "negate all (storing as disabled capabilities)"
1196
  msgstr "negare tutto (memorizzare come capacità disabilitate)"
1197
 
1198
- #: includes/admin.php:824 includes/admin.php:929 includes/admin.php:1162
1199
- msgid "check/uncheck all"
 
1200
  msgstr "seleziona/deseleziona tutto"
1201
 
1202
- #: includes/admin.php:631 includes/admin.php:762 includes/admin.php:890
1203
- #: includes/admin.php:1109
1204
  msgid "%s: assigned by Permission Group"
1205
  msgstr "%s: assegnato dal Gruppo autorizzazione"
1206
 
1207
- #: includes/admin.php:233
1208
  msgid "can delete posts which are currently published with private visibility"
1209
  msgstr "può eliminare gli articoli che sono attualmente pubblicati con visibilità privata"
1210
 
1211
- #: includes/admin.php:232
1212
  msgid "can delete posts which are currently published"
1213
  msgstr "può eliminare gli articoli che sono attualmente pubblicati"
1214
 
1215
- #: includes/admin.php:231
1216
  msgid "can delete posts which were created by other users"
1217
  msgstr "può eliminare gli articoli che sono stati creati da altri utenti"
1218
 
1219
- #: includes/admin.php:230
1220
  msgid "has basic deletion capability (but may need other capabilities based on post status and ownership)"
1221
  msgstr "ha una capacità di cancellazione di base (ma può necessitare di altre capacità basate sullo stato e la proprietà degli articoli)"
1222
 
1223
- #: includes/admin.php:229
1224
  msgid "can make a post publicly visible"
1225
  msgstr "può rendere un articolo visibile pubblicamente"
1226
 
1227
- #: includes/admin.php:228
1228
  msgid "can edit posts which are currently published with private visibility"
1229
  msgstr "può modificare gli articoli che sono attualmente pubblicati con visibilità privata"
1230
 
1231
- #: includes/admin.php:227
1232
  msgid "can edit posts which are currently published"
1233
  msgstr "può modificare gli articoli che sono attualmente pubblicati"
1234
 
1235
- #: includes/admin.php:226
1236
  msgid "can edit posts which were created by other users"
1237
  msgstr "può modificare gli articoli che sono stati creati da altri utenti"
1238
 
1239
- #: includes/admin.php:225
1240
  msgid "has basic editing capability (but may need other capabilities based on post status and ownership)"
1241
  msgstr "ha la capacità di modificazione di base (ma può necessitare di altre capacità basate sullo stato e la proprietà degli articoli)"
1242
 
1243
- #: includes/admin.php:224
1244
  msgid "can read posts which are currently published with private visibility"
1245
  msgstr "può leggere gli articoli che sono attualmente pubblicati con visibilità privata"
1246
 
1247
- #: includes/admin.php:218
1248
  msgid "Reading"
1249
  msgstr "Lettura"
1250
 
1251
- #: includes/admin.php:217
1252
  msgid "&nbsp;"
1253
  msgstr "&nbsp;"
1254
 
1255
- #: includes/admin.php:1248
1256
  msgid "%s info/purchase"
1257
  msgstr "%s info/acquisto"
1258
 
1259
- #: includes/admin.php:1248
1260
  msgid "%1$sbuy%2$s %3$s"
1261
  msgstr "%1$scompra%2$s %3$s"
1262
 
1263
- #: includes/admin.php:1246
1264
  msgid "%s (free install)"
1265
  msgstr "%s (installazione gratuita)"
1266
 
1267
- #: includes/admin.php:1246
1268
  msgid "%1$sgrab%2$s %3$s"
1269
  msgstr "%1$scattura%2$s %3$s"
1270
 
1271
- #: includes/admin.php:1239
1272
  msgid "Member support forum"
1273
  msgstr "Forum di support membri"
1274
 
1275
- #: includes/admin.php:1235
1276
  msgid "WPML integration to mirror permissions to translations <em>(Pro)</em>"
1277
  msgstr "Integrazione con WPML per trasmettere le autorizzazioni alle traduzioni <em>(Pro)</em>"
1278
 
1279
- #: includes/admin.php:1231
1280
  msgid "Grant supplemental content permissions to a BuddyPress group <em>(Pro)</em>"
1281
  msgstr "Concede autorizzazioni di contenuto supplementari a un gruppo BuddyPress <em>(Pro)</em>"
1282
 
1283
- #: includes/admin.php:1227
1284
  msgid "Grant Spectator, Participant or Moderator access to specific bbPress forums <em>(Pro)</em>"
1285
  msgstr "Concedi a Spettatore, Partecipante o Moderatore l'accesso a specifici forum bbPress <em>(Pro)</em>"
1286
 
1287
- #: includes/admin.php:1223
1288
  msgid "Customize the moderated editing of published content with Revisionary or Post Forking <em>(Pro)</em>"
1289
  msgstr "Personalizza la modifica moderata dei contenuti pubblicati con Revisionary o Post Forking <em>(Pro)</em>"
1290
 
1291
- #: includes/admin.php:1219
1292
  msgid "Regulate permissions for Edit Flow post statuses <em>(Pro)</em>"
1293
  msgstr "Regola le autorizzazioni per gli stati dell'articolo in Edit Flow <em>(Pro)</em>"
1294
 
1295
- #: includes/admin.php:1215
1296
  msgid "Custom Moderation statuses for access-controlled, multi-step publishing workflow <em>(Pro)</em>"
1297
  msgstr "Stati di moderazione personalizzati per gli accessi controllati, flusso di lavoro di pubblicazione in più fasi <em>(Pro)</em>"
1298
 
1299
- #: includes/admin.php:1211
1300
  msgid "Custom Post Visibility statuses, fully implemented throughout wp-admin <em>(Pro)</em>"
1301
  msgstr "Stati di visibilità degli articoli personalizzati, completamente implementati in wp-admin <em>(Pro)</em>"
1302
 
1303
- #: includes/admin.php:1207
1304
  msgid "Customize editing permissions per-category or per-post <em>(Pro)</em>"
1305
  msgstr "Personalizza le modifiche delle autorizzazioni per categoria o per articolo <em>(Pro)</em>"
1306
 
1307
- #: includes/admin.php:1203
1308
  msgid "Customize reading permissions per-category or per-post"
1309
  msgstr "Personalizza le autorizzazioni di lettura per categoria o per articolo"
1310
 
1311
- #: includes/admin.php:1199
1312
  msgid "Assign custom WP roles supplementally for a specific post type <em>(Pro)</em>"
1313
  msgstr "Assegna ruoli WP personalizzati in aggiunta a un tipo di articolo specifico <em>(Pro)</em>"
1314
 
1315
- #: includes/admin.php:1195
1316
  msgid "Assign standard WP roles supplementally for a specific post type"
1317
  msgstr "Assegna ruoli WP standard in aggiunta a un tipo di articolo specifico"
1318
 
1319
- #: includes/admin.php:1191
1320
  msgid "Automatically define type-specific capabilities for your custom post types and taxonomies"
1321
  msgstr "Definisci automaticamente le capacità specifiche del tipo per i tuoi tipi di articoli e tassonomie personalizzate"
1322
 
1323
- #: includes/manager.php:921
 
 
 
 
1324
  msgid "Documentation"
1325
  msgstr "Documentazione"
1326
 
@@ -1328,32 +1505,33 @@ msgstr "Documentazione"
1328
  msgid "Settings saved."
1329
  msgstr "Impostazioni salvate."
1330
 
1331
- #: includes/manager.php:197
1332
  msgid "Add or remove capability from the role normally"
1333
  msgstr "Aggiungi o rimuovi capacità dal ruolo normalmente"
1334
 
1335
- #: includes/manager.php:196
1336
  msgid "Add or remove this capability from the WordPress role"
1337
  msgstr "Aggiungi o rimuovi questa capacità dal ruolo di WordPress"
1338
 
1339
- #: includes/manager.php:195
1340
  msgid "This capability is explicitly negated. Click to add/remove normally."
1341
  msgstr "Questa capacità è esplicitamente negata. Fai clic per aggiungere/rimuovere normalmente."
1342
 
1343
- #: includes/manager.php:194
1344
  msgid "Post type registration does not define this capability distinctly"
1345
  msgstr "La registrazione del tipo di articolo non definisce chiaramente questa capacità"
1346
 
1347
- #: includes/manager.php:193
1348
  msgid "Explicitly negate these capabilities by storing as disabled"
1349
  msgstr "Nega esplicitamente queste capacità memorizzandole come disabilitate"
1350
 
1351
- #: includes/manager.php:192
1352
  msgid "Explicity negate this capability by storing as disabled"
1353
  msgstr "Nega esplicitamente questa capacità memorizzandola come disabilitata"
1354
 
1355
- #: includes/admin-load.php:282 includes/manager.php:329
1356
- #: includes/roles/class/class-pp-roles-list-table.php:123
 
1357
  msgid "Capabilities"
1358
  msgstr "Capacità"
1359
 
@@ -1361,18 +1539,18 @@ msgstr "Capacità"
1361
  msgid "Role Capabilities"
1362
  msgstr "Capacità di ruolo"
1363
 
1364
- #: capsman-enhanced.php:100
1365
  msgid "%s is required for this plugin."
1366
  msgstr "E' necessario %s per l'utilizzo di questo plugin."
1367
 
1368
- #: capsman-enhanced.php:98
1369
  msgid "The active plugin %s is not compatible with your PHP version."
1370
  msgstr "Il plugin %s non é compatibile con la tua versione PHP."
1371
 
1372
- #: capsman-enhanced.php:97
1373
  msgid "Warning:"
1374
  msgstr "Attenzione:"
1375
 
1376
- #: capsman-enhanced.php:40
1377
- msgid "<strong>Error:</strong> PublishPress Capabilities cannot function because another copy of Capability Manager is active."
1378
  msgstr "<strong>Errore:</strong> PublishPress Capabilities non può funzionare perché è attiva un'altra copia di Capability Manager."
4
  msgstr ""
5
  "Project-Id-Version: Plugins - PublishPress Capabilities &#8211; User Role Access, Editor Permissions, Admin Menus - Stable (latest release)\n"
6
  "POT-Creation-Date: \n"
7
+ "PO-Revision-Date: 2022-05-16 13:09+0200\n"
8
+ "Last-Translator: \n"
9
  "Language-Team: Angelo Giammarresi - info@wocmultimedia.com\n"
10
  "Language: it\n"
11
  "MIME-Version: 1.0\n"
14
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
15
  "X-Generator: Poedit 3.0.1\n"
16
 
17
+ #: includes/roles/class/class-pp-roles-admin.php:264
18
+ msgid "Read more on Role Level."
19
+ msgstr "Leggi tutto sui livelli di ruolo."
20
+
21
+ #: includes/roles/class/class-pp-roles-admin.php:163
22
+ msgid "Each user role has a level from 0 to 10. The Subscriber role defaults to the lowest level (0). The Administrator role defaults to level 10."
23
+ msgstr "Ciascun ruolo utente ha un livello da 0 a 10. Il ruolo di sottoscrittore ha come impostazione predefinita il livello più basso (0). Il ruolo amministratore ha come impostazione predefinita il livello 10."
24
+
25
+ #: includes/features/editor-features.php:171
26
+ msgid "Restricted:"
27
+ msgstr "Limitato:"
28
+
29
+ #: includes/features/editor-features.php:111
30
+ #: includes/features/editor-features.php:113
31
+ #: includes/features/editor-features.php:215
32
+ #: includes/features/editor-features.php:217
33
+ msgid "Save %s Restrictions"
34
+ msgstr "Salva le limitazioni di %s"
35
+
36
+ #: includes/features/editor-features.php:107
37
+ #: includes/features/editor-features.php:211
38
+ msgid "Save for all Post Types"
39
+ msgstr "Salva per tutti i tipi di contenuto"
40
+
41
+ #: includes/features/editor-features-gutenberg.php:1
42
+ msgid "Gutenberg Editor %s Restriction"
43
+ msgstr "Salva le limitazioni %s dell'editor Gutenberg"
44
+
45
+ #: includes/features/editor-features-classic.php:1
46
+ msgid "Classic Editor %s Restriction"
47
+ msgstr "Salva le limitazioni %s dell'editor classico"
48
+
49
+ #: includes/roles/class/class-pp-roles-list-table.php:229
50
+ msgid "Edit"
51
+ msgstr "Modifica"
52
+
53
+ #: includes/roles/class/class-pp-roles-list-table.php:92
54
+ msgid "System %s"
55
+ msgid_plural "System %s"
56
+ msgstr[0] "Sistema %s"
57
+ msgstr[1] "Sistemi %s"
58
+
59
+ #: includes/roles/class/class-pp-roles-list-table.php:91
60
+ msgid "Uneditable %s"
61
+ msgid_plural "Uneditable %s"
62
+ msgstr[0] "Non modificabile %s"
63
+ msgstr[1] "Non modificabili %s"
64
+
65
+ #: includes/roles/class/class-pp-roles-list-table.php:90
66
+ msgid "Editable %s"
67
+ msgid_plural "Editable %s"
68
+ msgstr[0] "Modificabile %s"
69
+ msgstr[1] "Modificabili %s"
70
+
71
+ #: includes/roles/class/class-pp-roles-list-table.php:89
72
+ msgid "No Users %s"
73
+ msgid_plural "No Users %s"
74
+ msgstr[0] "Senza utente %s"
75
+ msgstr[1] "Senza utenti %s"
76
+
77
+ #: includes/roles/class/class-pp-roles-list-table.php:88
78
+ msgid "Has Users %s"
79
+ msgid_plural "Has Users %s"
80
+ msgstr[0] "Ha utenti %s"
81
+ msgstr[1] "Hanno utenti %s"
82
+
83
+ #: includes/roles/class/class-pp-roles-list-table.php:87
84
+ msgid "Mine %s"
85
+ msgid_plural "Mine %s"
86
+ msgstr[0] "Mio %s"
87
+ msgstr[1] "Miei %s"
88
+
89
+ #: includes/roles/class/class-pp-roles-admin.php:462
90
+ msgid "Load Less"
91
+ msgstr "Carica meno"
92
+
93
+ #: includes/roles/class/class-pp-roles-admin.php:459
94
+ msgid "Load More"
95
+ msgstr "Carica altro"
96
+
97
+ #: includes/roles/class/class-pp-roles-admin.php:431
98
+ msgid "These can be edited on the %1s Capabilities screen %2s"
99
+ msgstr "Queste possono essere modificate nella schermata %1s Capacità %2s"
100
+
101
+ #: includes/roles/class/class-pp-roles-admin.php:353
102
+ msgid "All Roles"
103
+ msgstr "Tutti i ruoli"
104
+
105
+ #: includes/roles/class/class-pp-roles-admin.php:347
106
+ msgid "Copy Role"
107
+ msgstr "Copia ruolo"
108
+
109
+ #: includes/roles/class/class-pp-roles-admin.php:345
110
+ msgid "Edit Role"
111
+ msgstr "Modifica ruolo"
112
+
113
+ #: includes/roles/class/class-pp-roles-admin.php:337
114
+ msgid "Create Role"
115
+ msgstr "Crea ruolo"
116
+
117
+ #: includes/roles/class/class-pp-roles-admin.php:337
118
+ msgid "Update Role"
119
+ msgstr "Aggiorna ruolo"
120
+
121
+ #: includes/roles/class/class-pp-roles-admin.php:331
122
+ msgid "%s role copied to editor. Please click the \"Create Role\" button to create this new role."
123
+ msgstr "Il ruolo %s è stato copiato nell'editor. Fare clic sul pulsante \"Crea ruolo\" per creare questo nuovo ruolo."
124
+
125
+ #: includes/roles/class/class-pp-roles-admin.php:241
126
+ msgid "Slug already exists"
127
+ msgstr "Questo slug esiste già"
128
+
129
+ #: includes/roles/class/class-pp-roles-admin.php:185
130
+ msgid "Deleting this role will completely remove it from database and is irrecoverable."
131
+ msgstr "L'eliminazione di questo ruolo lo rimuoverà completamente dal database e sarà irrecuperabile."
132
+
133
+ #: includes/roles/class/class-pp-roles-admin.php:154
134
+ msgid "The \"slug\" is the URL-friendly version of the role. It is usually all lowercase and contains only letters, numbers and underscores."
135
+ msgstr "Lo \"slug\" è la versione URL-friendly del ruolo. Di solito è tutto minuscolo e contiene solo lettere, numeri e trattini bassi."
136
+
137
+ #: includes/roles/class/class-pp-roles-admin.php:153
138
+ msgid "Role Slug"
139
+ msgstr "Slug del ruolo"
140
+
141
+ #: includes/roles/class/class-pp-roles-admin.php:109
142
+ msgid "Advanced"
143
+ msgstr "Avanzate"
144
+
145
+ #: includes/roles/class/class-pp-roles-admin.php:105
146
+ msgid "General"
147
+ msgstr "Generale"
148
+
149
+ #: includes/roles/class/class-pp-roles-actions.php:388
150
+ msgid "%s role updated successfully."
151
+ msgstr "Ruolo %s aggiornato correttamente."
152
+
153
+ #: includes/manager.php:939
154
+ msgid "You do not have permission to perform this action."
155
+ msgstr "Non hai i permessi per effettuare questa azione."
156
+
157
+ #: includes/features/restrict-editor-features.php:320
158
+ msgid "Template"
159
+ msgstr "Template"
160
+
161
+ #: includes/backup.php:360
162
+ msgid "Import"
163
+ msgstr "Importa"
164
+
165
+ #: includes/backup.php:351
166
+ msgid "Before importing, we recommend using the \"Backup\" tab to create a backup of your current settings."
167
+ msgstr "Prima di importare, ti consigliamo di utilizzare la scheda \"Backup\" per creare una copia di sicurezza delle impostazioni correnti."
168
+
169
+ #: includes/backup.php:349
170
+ msgid "Import the plugin settings from a .json file. This file can be obtained by exporting the settings on another site using the form above."
171
+ msgstr "Importare le impostazioni del plugin da un file .json. Questo file può essere ottenuto esportando le impostazioni di un altro sito tramite il modulo precedente."
172
+
173
+ #: includes/backup.php:347
174
+ msgid "Please make a 'Manual Backup' in the backup tab to enable backup restore in case anything goes wrong."
175
+ msgstr "Fai un \"backup manuale\" nella scheda di backup per consentire il ripristino del backup nel caso in cui qualcosa vada storto."
176
+
177
+ #: includes/backup.php:345
178
+ msgid "Import Settings"
179
+ msgstr "Importa impostazioni"
180
+
181
+ #: includes/backup.php:338
182
+ msgid "Export"
183
+ msgstr "Esporta"
184
+
185
+ #: includes/backup.php:316
186
+ msgid "Export the plugin settings for this site as a .json file. This allows you to easily import the configuration into another site."
187
+ msgstr "Esporta le impostazioni del plugin per questo sito in un file .json. Ciò consente di importare facilmente la configurazione in un altro sito."
188
+
189
+ #: includes/backup.php:314
190
+ msgid "Export Settings"
191
+ msgstr "Esporta impostazioni"
192
+
193
+ #: includes/backup.php:119
194
+ msgid "Manual backup of %s (%s)"
195
+ msgstr "Backup manuale di %s (%s)"
196
+
197
+ #: includes/backup.php:114
198
+ msgid "all roles"
199
+ msgstr "tutti i ruoli"
200
+
201
+ #: includes/backup.php:51 includes/backup.php:309
202
+ msgid "Export / Import"
203
+ msgstr "Esporta/importa"
204
+
205
+ #: includes/backup-handler.php:199
206
+ msgid "%s successfully imported from uploaded data."
207
+ msgstr "%s importato correttamente dai dati caricati."
208
+
209
+ #: includes/backup-handler.php:178
210
+ msgid "Error importing settings! Please check that you uploaded a valid json file."
211
+ msgstr "Errore nell'importazione delle impostazioni! Verifica di aver caricato un file json valido."
212
+
213
+ #: includes/backup-handler.php:165
214
+ msgid "Error importing settings! Please try again."
215
+ msgstr "Errore nell'importazione delle impostazioni! Riprova."
216
+
217
+ #: includes/backup-handler.php:145
218
+ msgid "Please upload a valid .json file"
219
+ msgstr "Carica un file json valido"
220
+
221
+ #: includes/backup-handler.php:140
222
+ msgid "Please upload a file to import"
223
+ msgstr "Carica un file da importare"
224
+
225
+ #: includes/backup-handler.php:119
226
+ msgid "%s restored from last backup."
227
+ msgstr "%s ripristinato dall'ultimo backup."
228
+
229
+ #: includes/admin.php:1367
230
+ msgid "Go to the Backup feature"
231
+ msgstr "Vai alle caratteristiche del backup"
232
+
233
+ #: includes/admin.php:1363
234
+ msgid ""
235
+ "This plugin automatically creates a backup whenever you save changes. You can use these backups to\n"
236
+ "restore an earlier version of your roles and capabilities."
237
+ msgstr ""
238
+ "Questo plugin crea automaticamente un backup ogni volta che salvi delle modifiche. È possibile utilizzare questi backup per\n"
239
+ "ripristinare una versione precedente dei ruoli e delle capacità."
240
+
241
+ #: includes/admin.php:1361
242
+ msgid "PublishPress Capabilities is safe to use"
243
+ msgstr "PublishPress Capabilities è sicuro da usare"
244
+
245
+ #: capsman-enhanced.php:85
246
+ msgid "This plugin can be deleted."
247
+ msgstr "Questo plugin può essere eliminato."
248
+
249
+ #: includes/roles/class/class-pp-roles-actions.php:299
250
  msgid "The new role %s was created successfully."
251
+ msgstr "Il nuovo ruolo %s è stato creato con successo."
252
 
253
+ #: includes/roles/class/class-pp-roles-actions.php:223
254
  msgid "The role \"%s\" already exists. Please choose a different name."
255
  msgstr "Il ruolo \"%s\" esiste già, scegli un nome diverso."
256
 
257
+ #: includes/roles/class/class-pp-roles-actions.php:211
258
  msgid "Invalid role name entry: %s"
259
  msgstr "Nome di ruolo inserito non valido: %s"
260
 
261
+ #: includes/manager.php:537 includes/manager.php:559
262
  msgid "You do not have permission to manage admin features."
263
  msgstr "Non hai le autorizzazioni adatte per gestire le caratteristiche amministrative."
264
 
335
  msgid "Admin Feature Restrictions"
336
  msgstr "Restrizioni caratteristiche di amministrazione"
337
 
338
+ #: includes/backup.php:389 includes/features/admin-features.php:236
339
+ #: includes/features/editor-features.php:236
340
  msgid "Click here to install PublishPress Permissions"
341
  msgstr "Fai clic qui per installare PublishPress Permissions"
342
 
343
+ #: includes/backup.php:386 includes/features/admin-features.php:233
344
+ #: includes/features/editor-features.php:233
345
  msgid "PublishPress Permissions is 100% free to install."
346
  msgstr "PublishPress Permissions è al 100% gratuito da installare."
347
 
348
+ #: includes/backup.php:385 includes/features/admin-features.php:232
349
+ #: includes/features/editor-features.php:232
350
  msgid "Allow specific user roles or users to manage each post."
351
  msgstr "Consenti a ruoli o utenti specifici di gestire ogni singolo articolo."
352
 
353
+ #: includes/backup.php:384 includes/features/admin-features.php:231
354
+ #: includes/features/editor-features.php:231
355
  msgid "Choose who can read and edit each post."
356
  msgstr "Scegli chi può leggere e modificare ogni singolo articolo."
357
 
358
+ #: includes/backup.php:382 includes/features/admin-features.php:229
359
+ #: includes/features/editor-features.php:229
360
  msgid "Control permissions for individual posts and pages"
361
  msgstr "Controlli le autorizzazioni per ogni singolo articolo e pagina"
362
 
363
+ #: includes/backup.php:381 includes/features/admin-features.php:228
364
+ #: includes/features/editor-features.php:228
365
  msgid "Recommendations for you"
366
  msgstr "Raccomandazioni per te"
367
 
368
+ #: includes/admin.php:870
369
  msgid "Plugin Capabilities &ndash; %s"
370
  msgstr "Plugin Capabilities &ndash; %s"
371
 
372
+ #: includes/admin.php:738 includes/admin.php:876 includes/admin.php:1082
373
  msgid "No results found. Please try again with a different word."
374
  msgstr "Nessun risultato trovato, riprova con una parola differente."
375
 
376
+ #: includes/admin.php:735 includes/admin.php:873 includes/admin.php:1079
377
  msgid "Filter by capability"
378
  msgstr "Filtra per capacità"
379
 
380
+ #: includes/admin.php:732
381
  msgid "WordPress Core Capabilities"
382
  msgstr "Capacità di base di WordPress"
383
 
384
+ #: includes/admin.php:548 includes/admin.php:736 includes/admin.php:874
385
+ #: includes/admin.php:1080
386
  msgid "Clear"
387
  msgstr "Pulisci"
388
 
389
+ #: includes/admin.php:545
390
  msgid "Filter by post type"
391
  msgstr "Filtra per tipo di contenuto"
392
 
393
+ #: includes/admin.php:545
394
  msgid "Filter by taxonomy"
395
  msgstr "Filtra per tassonomia"
396
 
397
+ #: includes/admin.php:539
398
  msgid "Post %s Capabilities"
399
  msgstr "Capacità dell'articolo %s"
400
 
401
+ #: includes/admin.php:539
402
  msgid "Term %s Capabilities"
403
  msgstr "Capacità del termine %s"
404
 
405
+ #: includes/admin.php:495
406
  msgid "Additional"
407
  msgstr "Aggiuntivi"
408
 
409
+ #: includes/admin.php:316
410
  msgid "WordPress Core"
411
  msgstr "WordPress core"
412
 
413
+ #: includes/admin.php:224
414
  msgid "Deletion"
415
  msgstr "Cancellazione"
416
 
417
+ #: includes/admin.php:223
418
  msgid "Editing"
419
  msgstr "Modifica"
420
 
421
+ #: includes/admin-load.php:333 includes/functions-admin.php:212
422
+ #: includes/manager.php:377 includes/manager.php:412
423
+ #: includes/roles/class/class-pp-roles-list-table.php:174
424
  msgid "Admin Features"
425
  msgstr "Caratteristiche amministrative"
426
 
428
  msgid "You can block pages by URL or hide Admin elements by entering a CSS class or ID. This feature is available in PublishPress Capabilities Pro."
429
  msgstr "Puoi bloccare le pagine per URL, nascondere gli elementi di amministrazione inserendo una classe CSS o un ID. Questa caratteristiche sono disponibili con PublishPress Capabilities Pro."
430
 
431
+ #: includes/manager.php:208
432
  msgid "Add or clear custom item entry before saving changes."
433
  msgstr "Aggiungi o cancella la voce personalizzata prima di salvare le modifiche."
434
 
435
+ #: includes/manager.php:207
436
  msgid "Are you sure you want to delete this item ?"
437
  msgstr "Sei sicuro di voler cancellare questo elemento?"
438
 
439
+ #: includes-core/editor-features-promo.php:117
440
  msgid "Page Attributes: Order"
441
  msgstr "Pagina attributi: Ordini"
442
 
443
+ #: includes-core/editor-features-promo.php:106
444
  msgid "Permalink: Descriptive Caption"
445
  msgstr "Permalink: Didascalia descrittiva"
446
 
447
+ #: includes-core/editor-features-promo.php:95
448
  msgid "Custom item one"
449
  msgstr "Elemento personalizzato uno"
450
 
451
+ #: includes-core/editor-features-promo.php:89
452
  msgid "Custom Items"
453
  msgstr "Elementi personalizzati"
454
 
455
+ #: includes-core/editor-features-promo.php:74
456
  msgid "You can hide plugin metaboxes. You can also hide specific items by entering their CSS class or ID. This feature is available in PublishPress Capabilities Pro."
457
  msgstr "Puoi nascondere le metabox dei plugin. Puoi anche nascondere elementi specifici inserendo la loro classe CSS o il loro ID. Questa funzione è disponibile in PublishPress Capabilities Pro."
458
 
459
+ #: includes-core/editor-features-promo.php:62
460
  msgid "TaxoPress - Settings"
461
  msgstr "TaxoPress - Impostazioni"
462
 
463
+ #: includes-core/editor-features-promo.php:52
464
  msgid "Notifications"
465
  msgstr "Notifiche"
466
 
467
+ #: includes-core/editor-features-promo.php:42
468
  msgid "Editorial Comments"
469
  msgstr "Commenti editoriali"
470
 
476
  msgid "Metaboxes"
477
  msgstr "Metaboxes"
478
 
479
+ #: includes/manager.php:521 includes/manager.php:575
480
  msgid "Settings updated."
481
  msgstr "Impostazioni aggiornate."
482
 
483
+ #: includes/manager.php:464 includes/manager.php:486
484
  msgid "You do not have permission to manage editor features."
485
  msgstr "Non hai i permessi per gestire le funzionalità dell'editor."
486
 
487
+ #: includes/admin-load.php:332 includes/functions-admin.php:201
488
+ #: includes/manager.php:375 includes/manager.php:411
489
+ #: includes/roles/class/class-pp-roles-list-table.php:173
490
  msgid "Editor Features"
491
  msgstr "Funzioni dell'editor"
492
 
493
+ #: includes/features/restrict-editor-features.php:348
494
  msgid "Text settings"
495
  msgstr "Impostazioni del testo"
496
 
497
+ #: includes/features/restrict-editor-features.php:347
498
  msgid "Color settings"
499
  msgstr "Impostazioni colore"
500
 
501
+ #: includes/features/restrict-editor-features.php:346
502
  msgid "Typography"
503
  msgstr "Tipografia"
504
 
505
+ #: includes/features/restrict-editor-features.php:345
506
  msgid "Paragraph"
507
  msgstr "Paragrafo"
508
 
509
+ #: includes/features/restrict-editor-features.php:343
510
+ #: includes/features/restrict-editor-features.php:344
511
  msgid "Block Panel"
512
  msgstr "Pannello del blocco"
513
 
514
+ #: includes/features/restrict-editor-features.php:340
515
  msgid "Post Attributes"
516
  msgstr "Attributi articolo"
517
 
518
+ #: includes/features/restrict-editor-features.php:338
519
  msgid "Excerpt"
520
  msgstr "Riassunto"
521
 
522
+ #: includes/features/restrict-editor-features.php:337
523
  msgid "Featured image"
524
  msgstr "Immagine in evidenza"
525
 
526
+ #: includes/features/restrict-editor-features.php:319
527
  msgid "Status & visibility"
528
  msgstr "Stato e visibilità"
529
 
530
+ #: includes/features/restrict-editor-features.php:318
531
  msgid "Document Panel"
532
  msgstr "Pannello documenti"
533
 
534
+ #: includes/features/restrict-editor-features.php:315
535
  msgid "Content"
536
  msgstr "Contenuti"
537
 
538
+ #: includes/features/restrict-editor-features.php:314
539
  msgid "Edit title"
540
  msgstr "Modifica titolo"
541
 
542
+ #: includes/features/restrict-editor-features.php:313
543
  msgid "Body"
544
  msgstr "Contenuto"
545
 
546
+ #: includes/features/restrict-editor-features.php:310
547
  msgid "Options"
548
  msgstr "Opzioni"
549
 
550
+ #: includes/features/restrict-editor-features.php:308
551
  msgid "Publish / Update"
552
  msgstr "Pubblica/Aggiorna"
553
 
554
+ #: includes/features/restrict-editor-features.php:306
555
  msgid "Switch to draft"
556
  msgstr "Passa alla bozza"
557
 
558
+ #: includes/features/restrict-editor-features.php:304
559
  msgid "Top Bar - Right"
560
  msgstr "Barra in alto - Destra"
561
 
562
+ #: includes/features/restrict-editor-features.php:301
563
  msgid "Outline"
564
  msgstr "Contorno"
565
 
566
+ #: includes/features/restrict-editor-features.php:300
567
  msgid "Details"
568
  msgstr "Dettagli"
569
 
570
+ #: includes/features/restrict-editor-features.php:299
571
  msgid "Redo"
572
  msgstr "Ripeti"
573
 
574
+ #: includes/features/restrict-editor-features.php:298
575
  msgid "Undo"
576
  msgstr "Annulla"
577
 
578
+ #: includes/features/restrict-editor-features.php:297
579
  msgid "Modes"
580
  msgstr "Modalità"
581
 
582
+ #: includes/features/restrict-editor-features.php:296
583
  msgid "Add block"
584
  msgstr "Aggiungi blocco"
585
 
586
+ #: includes/features/restrict-editor-features.php:295
587
  msgid "Top Bar - Left"
588
  msgstr "Barra in alto - Sinistra"
589
 
590
  #: includes/features/restrict-editor-features.php:93
591
+ #: includes/features/restrict-editor-features.php:339
592
  msgid "Discussion"
593
  msgstr "Discussione"
594
 
625
  msgstr "Riquadri pagina"
626
 
627
  #: includes/features/restrict-editor-features.php:71
628
+ #: includes/features/restrict-editor-features.php:323
629
  msgid "Tags"
630
  msgstr "Tag"
631
 
634
  msgstr "Aggiungi una nuova categoria"
635
 
636
  #: includes/features/restrict-editor-features.php:69
637
+ #: includes/features/restrict-editor-features.php:322
638
  msgid "Categories"
639
  msgstr "Categorie"
640
 
671
  msgstr "Stato pubblicazione "
672
 
673
  #: includes/features/restrict-editor-features.php:58
674
+ #: includes/features/restrict-editor-features.php:307
675
  msgid "Preview"
676
  msgstr "Anteprima"
677
 
678
  #: includes/features/restrict-editor-features.php:57
679
+ #: includes/features/restrict-editor-features.php:305
680
  msgid "Save Draft"
681
  msgstr "Salva bozza"
682
 
698
  msgstr "Pulsanti Media (tutti)"
699
 
700
  #: includes/features/restrict-editor-features.php:49
701
+ #: includes/features/restrict-editor-features.php:321
702
  msgid "Permalink"
703
  msgstr "Permalink"
704
 
725
  msgid "Top Tabs"
726
  msgstr "Schede in alto"
727
 
728
+ #: includes/features/editor-features.php:138
729
  msgid "Classic"
730
  msgstr "Classico"
731
 
732
+ #: includes/features/editor-features.php:135
733
  msgid "Gutenberg"
734
  msgstr "Gutenberg"
735
 
736
+ #: includes/features/editor-features.php:85
737
  msgid "Select editor features to remove. Note that this screen cannot be used to grant additional features to any role."
738
  msgstr "Seleziona le caratteristiche dell'editor da rimuovere. Sappi che questa schermata non può essere usata per attribuire funzionalità aggiuntive ai vari ruoli."
739
 
740
+ #: includes/features/editor-features.php:69
741
  msgid "Editor Feature Restriction"
742
  msgstr "Limitazione delle funzioni dell'editor"
743
 
744
+ #: includes/admin.php:1417
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
  msgid "sync options to all sites now"
746
  msgstr "sincronizza le opzioni su tutti i siti adesso"
747
 
748
+ #: includes/admin.php:1417
749
  msgid "Copy option settings to all sites now"
750
  msgstr "Copia le impostazioni delle opzioni su tutti i siti adesso"
751
 
752
+ #: includes/admin.php:991
 
 
 
 
 
 
 
 
 
 
 
 
753
  msgid "The following entries have no effect. Please assign desired capabilities in the Read / Edit / Delete grid above."
754
  msgstr "Le voci seguenti non hanno effetto. Assegna le funzionalità desiderate nella griglia Leggi/Modifica/Elimina sopra."
755
 
756
+ #: includes/handler.php:61 includes/handler.php:89 includes/manager.php:758
 
757
  msgid "The selected role is not editable."
758
  msgstr "Il ruolo selezionato non è modificabile."
759
 
760
+ #: includes/manager.php:441
761
  msgid "You do not have permission to manage roles."
762
  msgstr "Non hai le autorizzazioni per gestire i ruoli."
763
 
764
+ #: includes/backup.php:272
765
  msgid "No changes"
766
  msgstr "Nessuna modifica"
767
 
768
+ #: includes/backup.php:203
769
  msgid "(this role will be removed if you restore backup)"
770
  msgstr "(questo ruolo sarà rimosso se ripristini il backup)"
771
 
772
+ #: includes/backup.php:162
773
  msgid "Show changes from current roles only"
774
  msgstr "Mostra le modifiche solo dai ruoli attuali"
775
 
776
+ #: includes/backup.php:151
777
  msgid "Restore Selected Roles"
778
  msgstr "Ripristina i ruoli selezionati"
779
 
780
+ #: includes/backup.php:142
781
  msgid "Initial backup of all roles"
782
  msgstr "Backup iniziali di tutti i ruoli"
783
 
784
+ #: includes/backup.php:134
785
  msgid "Auto-backup of all roles (%s)"
786
  msgstr "Backup automatico di tutti i ruoli (%s)"
787
 
788
+ #: includes/backup.php:101
 
 
 
 
789
  msgid "Available Backups:"
790
  msgstr "Backup disponibili:"
791
 
792
+ #: includes/backup.php:96
793
  msgid "On this screen, you can restore an earlier version of your roles and capabilities."
794
  msgstr "In questa schermata puoi ripristinare una versione precedente dei tuoi ruoli e delle capacità."
795
 
796
+ #: includes/backup.php:92
797
  msgid "PublishPress Capabilities automatically creates a backup on installation and whenever you save changes."
798
  msgstr "PublishPress Capabilities crea automaticamente un backup durante l'installazione e ogni volta che salvi le modifiche."
799
 
800
+ #: includes/backup.php:89
801
  msgid "Restore Previous Roles and Capabilities"
802
  msgstr "Ripristina ruoli e capacità precedenti"
803
 
804
+ #: includes/backup.php:75
805
  msgid "Manual Backup"
806
  msgstr "Backup manuale"
807
 
808
+ #: includes/backup.php:70
809
  msgid "A backup created on this screen replaces any previous manual backups, but is never automatically replaced."
810
  msgstr "Un backup creato in questa schermata sostituirà qualsiasi backup manuale precedente, ma non viene sostituito automaticamente."
811
 
812
+ #: includes/backup.php:65
813
  msgid "PublishPress Capabilities automatically creates a backup on installation and whenever you save changes. The initial backup and last %d auto-backups are kept."
814
  msgstr "PublishPress Capabilities crea automaticamente un backup durante l'installazione e ogni volta che salvi le modifiche. Il backup iniziale e gli ultimi %d backup automatici vengono mantenuti."
815
 
821
  msgid "Restore"
822
  msgstr "Ripristina"
823
 
824
+ #: includes/admin-load.php:339
825
+ #: includes/features/restrict-editor-features.php:309 includes/manager.php:384
826
  msgid "Settings"
827
  msgstr "Impostazioni"
828
 
829
+ #: includes/roles/roles.php:34
830
  msgid "Description here."
831
  msgstr "La descrizione qui."
832
 
833
+ #: includes/roles/roles.php:26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
834
  msgid "Search Roles"
835
  msgstr "Cerca ruoli"
836
 
837
  #. translators: %s: search keywords
838
+ #: includes/roles/roles.php:15
839
  msgid "Search results for &#8220;%s&#8221;"
840
  msgstr "Risultati di ricerca per &#8220;%s&#8221;"
841
 
842
+ #: includes/admin-load.php:330 includes/manager.php:361
843
+ #: includes/roles/roles.php:8
844
  msgid "Roles"
845
  msgstr "Ruoli"
846
 
847
+ #: includes/roles/class/class-pp-roles-list-table.php:356
848
  msgid "Your Role"
849
  msgstr "Il tuo ruolo"
850
 
851
+ #: includes/roles/class/class-pp-roles-list-table.php:351
852
  msgid "Default Role"
853
  msgstr "Ruolo predefinito"
854
 
855
+ #: includes/roles/class/class-pp-roles-list-table.php:300
856
  msgid "Hide"
857
  msgstr "Nascondi"
858
 
859
+ #: includes-core/editor-features-promo.php:96
860
+ #: includes-core/editor-features-promo.php:107
861
+ #: includes-core/editor-features-promo.php:117
862
  #: includes/features/admin-features.php:190
863
+ #: includes/features/editor-features-classic.php:51
864
+ #: includes/features/editor-features-gutenberg.php:50
865
+ #: includes/roles/class/class-pp-roles-admin.php:116
866
+ #: includes/roles/class/class-pp-roles-list-table.php:281
867
+ #: includes/roles/class/class-pp-roles-list-table.php:540
868
  msgid "Delete"
869
  msgstr "Elimina"
870
 
871
+ #: includes/roles/class/class-pp-roles-list-table.php:263
872
  msgid "Unhide"
873
  msgstr "Mostra"
874
 
875
+ #: includes/roles/class/class-pp-roles-list-table.php:245
876
  msgid "(non-editable role)"
877
  msgstr "(ruolo non modificabile)"
878
 
879
+ #: includes/manager.php:409
880
+ #: includes/roles/class/class-pp-roles-list-table.php:171
881
  msgid "Users"
882
  msgstr "Utenti"
883
 
884
+ #: includes/roles/class/class-pp-roles-actions.php:649
 
 
 
 
 
885
  msgid "The role %1$s was successfully unhidden."
886
  msgstr "Il ruolo %1$s è stato reso visibile con successo."
887
 
888
+ #: includes/roles/class/class-pp-roles-actions.php:589
889
  msgid "The role %1$s was successfully hidden."
890
  msgstr "Il ruolo %1$s è stato nascosto con successo."
891
 
892
+ #: includes/roles/class/class-pp-roles-actions.php:535
893
  msgid "The role could not be deleted."
894
  msgstr "Il ruolo non può essere eliminato."
895
 
896
+ #: includes/roles/class/class-pp-roles-actions.php:513
897
  msgid "The selected %1$s roles were successfully deleted. %2$s"
898
  msgstr "I ruoli %1$s selezionati sono stati eliminati con successo. %2$s"
899
 
900
+ #: includes/roles/class/class-pp-roles-actions.php:507
901
  msgid "The role %1$s was successfully deleted. %2$s"
902
  msgstr "Il ruolo %1$s è stato eliminato con successo. %2$s"
903
 
904
+ #: includes/roles/class/class-pp-roles-actions.php:502
905
  msgid "%1$d users moved to default role %2$s."
906
  msgstr "%1$d utenti sono passati al ruolo predefinito %2$s."
907
 
908
+ #: includes/roles/class/class-pp-roles-actions.php:480
909
  msgid "Deleting a system role is not allowed."
910
  msgstr "Non è consentito eliminare un ruolo di sistema."
911
 
912
+ #: includes/roles/class/class-pp-roles-actions.php:250
913
  msgid "Something went wrong, the system wasn't able to create the role, refresh the page and try again."
914
  msgstr "Qualcosa è andato storto, il sistema non è riuscito a creare il ruolo, ricarica la pagina e prova ancora."
915
 
916
+ #: includes/roles/class/class-pp-roles-actions.php:184
917
+ #: includes/roles/class/class-pp-roles-actions.php:336
918
+ #: includes/roles/class/class-pp-roles-actions.php:453
919
+ #: includes/roles/class/class-pp-roles-actions.php:578
920
+ #: includes/roles/class/class-pp-roles-actions.php:639
921
  msgid "Missing parameters, refresh the page and try again."
922
  msgstr "Ci sono dei parametri mancanti, ricarica la pagina e prova ancora."
923
 
924
+ #: includes/roles/class/class-pp-roles-actions.php:162
925
+ #: includes/roles/class/class-pp-roles-actions.php:180
926
+ #: includes/roles/class/class-pp-roles-actions.php:332
927
+ #: includes/roles/class/class-pp-roles-actions.php:429
928
  msgid "Your link has expired, refresh the page and try again."
929
  msgstr "Il tuo link è scaduto, ricarica la pagina e prova ancora."
930
 
931
+ #: includes/roles/class/class-pp-roles-actions.php:148
932
  msgid "You do not have sufficient permissions to perform this action."
933
  msgstr "Non hai i permessi necessari per compiere quest'azione."
934
 
935
+ #: includes/roles/class/class-pp-roles-admin.php:276
936
  #: includes/roles/roles-functions.php:32
937
  msgid "Are you sure you want to delete this role?"
938
  msgstr "Sei certo di voler eliminare questo ruolo?"
945
  msgid "Capabilities Settings"
946
  msgstr "Impostazioni di capacità"
947
 
948
+ #: includes-core/CoreAdmin.php:63 includes/admin-load.php:335
949
+ #: includes/manager.php:414
950
+ #: includes/roles/class/class-pp-roles-list-table.php:176
951
  msgid "Nav Menus"
952
  msgstr "Menu navigazione"
953
 
954
+ #: includes-core/CoreAdmin.php:62 includes/admin-load.php:334
955
+ #: includes/manager.php:413
956
+ #: includes/roles/class/class-pp-roles-list-table.php:175
957
  msgid "Admin Menus"
958
  msgstr "Menu amministrazione"
959
 
974
  msgstr "Limitazioni menu di navigazione"
975
 
976
  #: includes/features/restrict-editor-features.php:46
977
+ #: includes/filters-woocommerce.php:33 includes/roles/roles.php:10
978
  msgid "Add New"
979
  msgstr "Aggiungi nuovo"
980
 
981
  #: includes/filters-woocommerce.php:32
982
+ #: includes/roles/class/class-pp-roles-list-table.php:86
983
  msgid "All %s"
984
+ msgid_plural "All %s"
985
+ msgstr[0] "Tutto %s"
986
+ msgstr[1] "Tutti %s"
987
 
988
+ #: includes/manager.php:1009
989
  msgid "Contact"
990
  msgstr "Contatto"
991
 
992
+ #: includes/manager.php:1009
993
  msgid "Contact the PublishPress team"
994
  msgstr "Contatta il team di PublishPress"
995
 
996
+ #: includes/manager.php:1007
997
  msgid "Capabilites Documentation"
998
  msgstr "Documentazione di Capabilites"
999
 
1000
+ #: includes/manager.php:1005
1001
  msgid "About"
1002
  msgstr "Chi siamo"
1003
 
1004
+ #: includes/manager.php:1005
1005
  msgid "About PublishPress Capabilities"
1006
  msgstr "Informazioni su PublishPress Capabilities"
1007
 
1008
+ #: includes/manager.php:994
1009
  msgid "If you like %s, please leave us a %s rating. Thank you!"
1010
  msgstr "Se sei soddisfatto di %s, lasciaci una valutazione di %s!"
1011
 
1012
+ #: includes/manager.php:680 includes/manager.php:714 includes/manager.php:732
1013
  msgid "You do not have permission to manage capabilities."
1014
  msgstr "Non hai le autorizzazioni per gestire le capacità."
1015
 
1016
  #: includes-core/admin-features-promo.php:79
1017
  #: includes-core/admin-menus-promo.php:62
1018
+ #: includes-core/editor-features-promo.php:79
1019
+ #: includes-core/nav-menus-promo.php:67 includes/admin-load.php:345
1020
+ #: includes/admin-load.php:346 includes/manager.php:390
1021
+ #: includes/manager.php:391
1022
  msgid "Upgrade to Pro"
1023
  msgstr "Aggiorna a Pro"
1024
 
1025
+ #: includes/admin-load.php:336 includes/backup.php:49 includes/manager.php:381
1026
  msgid "Backup"
1027
  msgstr "Backup"
1028
 
1029
+ #: includes/handler.php:124
1030
  msgid "Type / Taxonomy settings saved."
1031
  msgstr "Impostazioni tipo/tassonomia salvate."
1032
 
1033
+ #: includes/backup-handler.php:128
1034
  msgid "Roles and Capabilities restored from selected auto-backup."
1035
  msgstr "Ruoli e capacità sono stati ripristinati dal backup automatico selezionato."
1036
 
1037
+ #: includes/backup-handler.php:90
1038
  msgid "Roles and Capabilities restored from initial backup."
1039
  msgstr "Ruoli e capacità sono stati ripristinati dal backup iniziale."
1040
 
1082
  msgid "Related Permissions Plugins"
1083
  msgstr "Plugin di autorizzazioni correlati"
1084
 
1085
+ #: includes/manager.php:408 includes/roles/class/class-pp-roles-admin.php:145
1086
+ #: includes/roles/class/class-pp-roles-list-table.php:170
1087
  msgid "Role Name"
1088
  msgstr "Nome del ruolo"
1089
 
1090
+ #: includes/roles/class/class-pp-roles-admin.php:162
1091
+ msgid "Role Level"
1092
+ msgstr "Livello del ruolo"
1093
+
1094
+ #: includes/admin.php:1326
1095
  msgid "Role level is mostly deprecated. However, it still determines eligibility for Post Author assignment and limits the application of user editing capabilities."
1096
  msgstr "Il livello di ruolo è per lo più deprecato. Tuttavia, determina comunque l'idoneità per l'assegnazione di autore articolo e limita l'applicazione delle capacità di modifica dell'utente."
1097
 
1098
+ #: includes/admin.php:490 includes/admin.php:978
1099
  msgid "Invalid Capabilities"
1100
  msgstr "Capacità non valide"
1101
 
1102
+ #: includes/admin.php:801
1103
  msgid "Lockout Prevention: To remove read capability, first remove WordPress admin / editing capabilities, or add \"dashboard_lockout_ok\" capability"
1104
  msgstr "Prevenzione blocco: Per rimuovere la capacità di lettura bisogna prima rimuovere le capacità di gestione/modifica di WordPress oppure aggiungere la capacità \"dashboard_lockout_ok\""
1105
 
1106
+ #: includes/admin.php:652
1107
  msgid "shared capability: %s"
1108
  msgstr "capacità condivise: %s"
1109
 
1110
+ #: includes/admin.php:1235 includes/settings.php:40
1111
  msgid "PublishPress Permissions"
1112
  msgstr "PublishPress Permissions"
1113
 
1114
+ #: includes/admin.php:132
1115
  msgid "<strong>Note:</strong> Capability changes <strong>remain in the database</strong> after plugin deactivation. You can also configure this role as a %sPermission Group%s."
1116
  msgstr "<strong>Nota:</strong> Le modifiche della capacità <strong>rimangono nel database</strong> anche dopo la disattivazione del plugin. Puoi anche configurare questo ruolo come una %sautorizzazione di gruppo%s."
1117
 
1118
+ #: includes/admin.php:140
1119
  msgid "<strong>Note:</strong> Capability changes <strong>remain in the database</strong> after plugin deactivation."
1120
  msgstr "<strong>Nota:</strong> Le modifiche della capacità <strong>rimangono nel database</strong> anche dopo la disattivazione del plugin."
1121
 
1123
  msgid "Warning: This role cannot access the dashboard without the read capability. %1$sClick here to fix this now%2$s."
1124
  msgstr "Attenzione: Questo ruolo non può accedere alla bacheca senza le capacità di lettura. %1$sFai clic qui per risolvere ora%2$s."
1125
 
1126
+ #: includes/filters.php:254
1127
  msgid "Edit Roles"
1128
  msgstr "Modifica ruoli"
1129
 
1130
+ #: includes/backup.php:232
1131
  msgid "%s (level %s)"
1132
  msgstr "%s (livello %s)"
1133
 
1134
+ #: includes/backup.php:196
1135
  msgid "%s (%s roles)"
1136
  msgstr "%s (%s ruoli)"
1137
 
1138
+ #: includes/backup.php:85
1139
  msgid "Last Backup"
1140
  msgstr "Ultimo backup"
1141
 
1142
+ #: includes/backup.php:85
1143
  msgid "Last Manual Backup - %s"
1144
  msgstr "Ultimo backup manuale - %s"
1145
 
1146
+ #: includes/backup.php:169
1147
  msgid "Initial Backup"
1148
  msgstr "Backup iniziale"
1149
 
1150
+ #: includes/backup.php:169
1151
  msgid "Initial Backup - %s"
1152
  msgstr "Backup iniziale - %s"
1153
 
1154
  #: includes/backup.php:39
1155
+ msgid "Backup Tool for PublishPress Capabilities"
1156
  msgstr "Strumento di backup per %1$sPublishPress Capabilities%2$s"
1157
 
 
 
 
 
1158
  #. Author URI of the plugin
1159
  msgid "https://publishpress.com/"
1160
  msgstr "https://publishpress.com/"
1208
  msgid "see %1$sRole Usage%2$s: \"Pattern Roles\""
1209
  msgstr "vedi %1$sUtilizzo dei ruoli%2$s: \"Modelli di ruolo\""
1210
 
1211
+ #: includes/manager.php:787
1212
  msgid "Bad form Received"
1213
  msgstr "E' stato ricevuto un modulo errato"
1214
 
1215
+ #: includes/roles/class/class-pp-roles-actions.php:461
1216
  msgid "Cannot delete default role. You <a href=\"%s\">have to change it first</a>."
1217
  msgstr "Non é possibile cancellare il ruolo predefinito. Bisogna che prima effettui questa <a href=\"%s\">modifica</a>."
1218
 
1219
+ #: includes/handler.php:250
1220
  msgid "You cannot remove Manage Capabilities from Administrators"
1221
  msgstr "Non puoi rimuovere la gestione delle capacità per gli amministratori"
1222
 
1223
+ #: includes/handler.php:127
1224
  msgid "Bad form received."
1225
  msgstr "E' stato ricevuto un modulo errato."
1226
 
1227
+ #: includes/handler.php:119
1228
  msgid "Incorrect capability name."
1229
  msgstr "Nome non valido per la capacità."
1230
 
1231
+ #: includes/manager.php:746
1232
  msgid "New capability added to role."
1233
  msgstr "La nuova capacità é stata aggiunta al ruolo."
1234
 
1235
+ #: includes/handler.php:51
1236
  msgid "Error: Failed creating the new role."
1237
  msgstr "Errore: non é stato possibile creare il nuovo ruolo."
1238
 
1239
+ #: includes/handler.php:45
1240
  msgid "New role created."
1241
  msgstr "Il nuovo ruolo é stato creato."
1242
 
1243
+ #: includes/backup.php:301
1244
  msgid "Reset to WordPress defaults"
1245
  msgstr "Ripristina ai predefiniti di WordPress"
1246
 
1247
+ #: includes/backup.php:301
1248
  msgid ""
1249
  "You are about to reset Roles and Capabilities to WordPress defaults.\n"
1250
  " 'Cancel' to stop, 'OK' to reset."
1252
  "Stai per ripristinare i Ruoli e le Capacità ai valori predefiniti di WordPress.\n"
1253
  " 'Annulla' per fermarti, 'OK' per procedere."
1254
 
1255
+ #: includes/backup.php:299
1256
  msgid "Reset Roles and Capabilities to WordPress defaults"
1257
  msgstr "Ripristina i Ruoli e le Capacità ai valori predefiniti di WordPress"
1258
 
1259
+ #: includes/backup.php:296
1260
  msgid "It is recommended to use this only as a last resource!"
1261
  msgstr "Da utilizzarsi solamente come ultima risorsa!"
1262
 
1263
+ #: includes/backup.php:294
1264
  msgid "If you have installed any plugin that adds new roles or capabilities, these will be lost."
1265
  msgstr "I ruoli e le capacità propri di ogni plugin installato saranno persi."
1266
 
1267
+ #: includes/backup.php:290
1268
  msgid "Reseting default Roles and Capabilities will set them to the WordPress install defaults."
1269
+ msgstr "Il ripristino dei valori predefiniti per i Ruoli e le Capacità li riporterà ai valori predefiniti di WordPress."
1270
 
1271
+ #: includes/backup.php:290 includes/backup.php:347
1272
  msgid "WARNING:"
1273
  msgstr "Attenzione:"
1274
 
1275
+ #: includes/backup.php:288
1276
  msgid "Reset WordPress Defaults"
1277
  msgstr "Ripristina ai valori predefiniti di WordPress"
1278
 
1279
+ #: includes/backup.php:60
1280
  msgid "Backup Roles and Capabilities"
1281
  msgstr "Backup ruoli e capacità"
1282
 
1283
+ #: includes/backup-handler.php:296
1284
  msgid "Roles and Capabilities reset to WordPress defaults"
1285
  msgstr "I ruoli e le capacità sono stati ripristinati ai valori predefiniti di WordPress"
1286
 
1287
+ #: includes/backup-handler.php:283
1288
  msgid "Needed function to create default roles not found!"
1289
  msgstr "La funzione necessaria per la creazione dei ruoli predefiniti non é stata trovata!"
1290
 
1291
+ #: includes/backup-handler.php:92 includes/backup-handler.php:121
1292
+ #: includes/backup-handler.php:130
1293
  msgid "Restore failed. No backup found."
1294
  msgstr "Non é stato possibile effettuare il ripristino. Non é stato trovato alcun file di backup."
1295
 
1296
  #: includes/backup-handler.php:73
 
 
 
 
1297
  msgid "New backup saved."
1298
  msgstr "Il nuovo backup é stato salvato."
1299
 
1300
+ #: includes/backup-handler.php:15 includes/manager.php:901
1301
  msgid "You do not have permission to restore roles."
1302
  msgstr "Non hai le autorizzazioni per il ripristino dei ruoli."
1303
 
1304
+ #: includes/admin.php:1414
1305
  msgid "sync role to all sites now"
1306
  msgstr "sincronizza i ruoli su tutti i siti adesso"
1307
 
1308
+ #: includes/admin.php:1414
1309
  msgid "Copy / update this role definition to all sites now"
1310
  msgstr "Copia/aggiorna la definizione di questo ruolo su tutti i siti adesso"
1311
 
1312
+ #: includes/admin.php:1411
1313
  msgid "include in new sites"
1314
  msgstr "includi nei nuovi siti"
1315
 
1316
+ #: includes/admin.php:1411
1317
  msgid "Create this role definition in new (future) sites"
1318
  msgstr "Crea la definizione di questo ruolo nei nuovi (futuri) siti"
1319
 
1320
+ #: includes/admin.php:1375
1321
  msgid "Add to role"
1322
  msgstr "Aggiungi al ruolo"
1323
 
1324
+ #: includes/admin.php:749 includes/admin.php:843 includes/admin.php:887
1325
+ #: includes/admin.php:960 includes/admin.php:1088 includes/admin.php:1205
1326
+ msgid "Capability Name"
1327
+ msgstr "Nome della capacità"
1328
+
1329
+ #: includes/admin.php:1372
1330
  msgid "Add Capability"
1331
  msgstr "Aggiungi capacità"
1332
 
1333
+ #: includes/roles/class/class-pp-roles-list-table.php:240
1334
  msgid "Copy"
1335
  msgstr "Copia"
1336
 
1337
+ #: includes/roles/class/class-pp-roles-admin.php:349
1338
+ msgid "Create New Role"
1339
+ msgstr "Crea un nuovo ruolo"
 
 
 
 
 
 
 
 
1340
 
1341
+ #: includes/roles/class/class-pp-roles-admin.php:184
1342
+ msgid "Delete role"
1343
  msgstr "Elimina il ruolo"
1344
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1345
  #: includes-core/admin-menus-promo.php:48 includes-core/nav-menus-promo.php:52
1346
+ #: includes/admin.php:113 includes/admin.php:1348
1347
  #: includes/features/admin-features.php:76
1348
+ #: includes/features/admin-features.php:215 includes/settings.php:56
 
 
1349
  msgid "Save Changes"
1350
  msgstr "Salva modifiche"
1351
 
1352
+ #: includes/admin.php:1328
1353
  msgid "Level:"
1354
  msgstr "Livello:"
1355
 
1356
+ #: includes/admin.php:1076
1357
  msgid "Additional Capabilities"
1358
  msgstr "Capacità aggiuntive"
1359
 
1360
+ #: includes/admin.php:751 includes/admin.php:845 includes/admin.php:889
1361
+ #: includes/admin.php:962 includes/admin.php:1090 includes/admin.php:1207
1362
  msgid "negate none (add/remove all capabilities normally)"
1363
  msgstr "nessuna negazione (aggiungere/rimuovere tutte le funzionalità normalmente)"
1364
 
1365
+ #: includes/admin.php:751 includes/admin.php:845 includes/admin.php:889
1366
+ #: includes/admin.php:962 includes/admin.php:1090 includes/admin.php:1207
1367
  msgid "negate all (storing as disabled capabilities)"
1368
  msgstr "negare tutto (memorizzare come capacità disabilitate)"
1369
 
1370
+ #: includes/admin.php:749 includes/admin.php:843 includes/admin.php:887
1371
+ #: includes/admin.php:960 includes/admin.php:1088 includes/admin.php:1205
1372
+ msgid "check / uncheck all"
1373
  msgstr "seleziona/deseleziona tutto"
1374
 
1375
+ #: includes/admin.php:640 includes/admin.php:782 includes/admin.php:922
1376
+ #: includes/admin.php:1153
1377
  msgid "%s: assigned by Permission Group"
1378
  msgstr "%s: assegnato dal Gruppo autorizzazione"
1379
 
1380
+ #: includes/admin.php:237
1381
  msgid "can delete posts which are currently published with private visibility"
1382
  msgstr "può eliminare gli articoli che sono attualmente pubblicati con visibilità privata"
1383
 
1384
+ #: includes/admin.php:236
1385
  msgid "can delete posts which are currently published"
1386
  msgstr "può eliminare gli articoli che sono attualmente pubblicati"
1387
 
1388
+ #: includes/admin.php:235
1389
  msgid "can delete posts which were created by other users"
1390
  msgstr "può eliminare gli articoli che sono stati creati da altri utenti"
1391
 
1392
+ #: includes/admin.php:234
1393
  msgid "has basic deletion capability (but may need other capabilities based on post status and ownership)"
1394
  msgstr "ha una capacità di cancellazione di base (ma può necessitare di altre capacità basate sullo stato e la proprietà degli articoli)"
1395
 
1396
+ #: includes/admin.php:233
1397
  msgid "can make a post publicly visible"
1398
  msgstr "può rendere un articolo visibile pubblicamente"
1399
 
1400
+ #: includes/admin.php:232
1401
  msgid "can edit posts which are currently published with private visibility"
1402
  msgstr "può modificare gli articoli che sono attualmente pubblicati con visibilità privata"
1403
 
1404
+ #: includes/admin.php:231
1405
  msgid "can edit posts which are currently published"
1406
  msgstr "può modificare gli articoli che sono attualmente pubblicati"
1407
 
1408
+ #: includes/admin.php:230
1409
  msgid "can edit posts which were created by other users"
1410
  msgstr "può modificare gli articoli che sono stati creati da altri utenti"
1411
 
1412
+ #: includes/admin.php:229
1413
  msgid "has basic editing capability (but may need other capabilities based on post status and ownership)"
1414
  msgstr "ha la capacità di modificazione di base (ma può necessitare di altre capacità basate sullo stato e la proprietà degli articoli)"
1415
 
1416
+ #: includes/admin.php:228
1417
  msgid "can read posts which are currently published with private visibility"
1418
  msgstr "può leggere gli articoli che sono attualmente pubblicati con visibilità privata"
1419
 
1420
+ #: includes/admin.php:222
1421
  msgid "Reading"
1422
  msgstr "Lettura"
1423
 
1424
+ #: includes/admin.php:221
1425
  msgid "&nbsp;"
1426
  msgstr "&nbsp;"
1427
 
1428
+ #: includes/admin.php:1294
1429
  msgid "%s info/purchase"
1430
  msgstr "%s info/acquisto"
1431
 
1432
+ #: includes/admin.php:1294
1433
  msgid "%1$sbuy%2$s %3$s"
1434
  msgstr "%1$scompra%2$s %3$s"
1435
 
1436
+ #: includes/admin.php:1292
1437
  msgid "%s (free install)"
1438
  msgstr "%s (installazione gratuita)"
1439
 
1440
+ #: includes/admin.php:1292
1441
  msgid "%1$sgrab%2$s %3$s"
1442
  msgstr "%1$scattura%2$s %3$s"
1443
 
1444
+ #: includes/admin.php:1285
1445
  msgid "Member support forum"
1446
  msgstr "Forum di support membri"
1447
 
1448
+ #: includes/admin.php:1281
1449
  msgid "WPML integration to mirror permissions to translations <em>(Pro)</em>"
1450
  msgstr "Integrazione con WPML per trasmettere le autorizzazioni alle traduzioni <em>(Pro)</em>"
1451
 
1452
+ #: includes/admin.php:1277
1453
  msgid "Grant supplemental content permissions to a BuddyPress group <em>(Pro)</em>"
1454
  msgstr "Concede autorizzazioni di contenuto supplementari a un gruppo BuddyPress <em>(Pro)</em>"
1455
 
1456
+ #: includes/admin.php:1273
1457
  msgid "Grant Spectator, Participant or Moderator access to specific bbPress forums <em>(Pro)</em>"
1458
  msgstr "Concedi a Spettatore, Partecipante o Moderatore l'accesso a specifici forum bbPress <em>(Pro)</em>"
1459
 
1460
+ #: includes/admin.php:1269
1461
  msgid "Customize the moderated editing of published content with Revisionary or Post Forking <em>(Pro)</em>"
1462
  msgstr "Personalizza la modifica moderata dei contenuti pubblicati con Revisionary o Post Forking <em>(Pro)</em>"
1463
 
1464
+ #: includes/admin.php:1265
1465
  msgid "Regulate permissions for Edit Flow post statuses <em>(Pro)</em>"
1466
  msgstr "Regola le autorizzazioni per gli stati dell'articolo in Edit Flow <em>(Pro)</em>"
1467
 
1468
+ #: includes/admin.php:1261
1469
  msgid "Custom Moderation statuses for access-controlled, multi-step publishing workflow <em>(Pro)</em>"
1470
  msgstr "Stati di moderazione personalizzati per gli accessi controllati, flusso di lavoro di pubblicazione in più fasi <em>(Pro)</em>"
1471
 
1472
+ #: includes/admin.php:1257
1473
  msgid "Custom Post Visibility statuses, fully implemented throughout wp-admin <em>(Pro)</em>"
1474
  msgstr "Stati di visibilità degli articoli personalizzati, completamente implementati in wp-admin <em>(Pro)</em>"
1475
 
1476
+ #: includes/admin.php:1253
1477
  msgid "Customize editing permissions per-category or per-post <em>(Pro)</em>"
1478
  msgstr "Personalizza le modifiche delle autorizzazioni per categoria o per articolo <em>(Pro)</em>"
1479
 
1480
+ #: includes/admin.php:1249
1481
  msgid "Customize reading permissions per-category or per-post"
1482
  msgstr "Personalizza le autorizzazioni di lettura per categoria o per articolo"
1483
 
1484
+ #: includes/admin.php:1245
1485
  msgid "Assign custom WP roles supplementally for a specific post type <em>(Pro)</em>"
1486
  msgstr "Assegna ruoli WP personalizzati in aggiunta a un tipo di articolo specifico <em>(Pro)</em>"
1487
 
1488
+ #: includes/admin.php:1241
1489
  msgid "Assign standard WP roles supplementally for a specific post type"
1490
  msgstr "Assegna ruoli WP standard in aggiunta a un tipo di articolo specifico"
1491
 
1492
+ #: includes/admin.php:1237
1493
  msgid "Automatically define type-specific capabilities for your custom post types and taxonomies"
1494
  msgstr "Definisci automaticamente le capacità specifiche del tipo per i tuoi tipi di articoli e tassonomie personalizzate"
1495
 
1496
+ #: includes/backup.php:321
1497
+ msgid "Roles and Capabilities"
1498
+ msgstr "Ruoli e capacità"
1499
+
1500
+ #: includes/manager.php:1007
1501
  msgid "Documentation"
1502
  msgstr "Documentazione"
1503
 
1505
  msgid "Settings saved."
1506
  msgstr "Impostazioni salvate."
1507
 
1508
+ #: includes/manager.php:206
1509
  msgid "Add or remove capability from the role normally"
1510
  msgstr "Aggiungi o rimuovi capacità dal ruolo normalmente"
1511
 
1512
+ #: includes/manager.php:205
1513
  msgid "Add or remove this capability from the WordPress role"
1514
  msgstr "Aggiungi o rimuovi questa capacità dal ruolo di WordPress"
1515
 
1516
+ #: includes/manager.php:204
1517
  msgid "This capability is explicitly negated. Click to add/remove normally."
1518
  msgstr "Questa capacità è esplicitamente negata. Fai clic per aggiungere/rimuovere normalmente."
1519
 
1520
+ #: includes/manager.php:203
1521
  msgid "Post type registration does not define this capability distinctly"
1522
  msgstr "La registrazione del tipo di articolo non definisce chiaramente questa capacità"
1523
 
1524
+ #: includes/manager.php:202
1525
  msgid "Explicitly negate these capabilities by storing as disabled"
1526
  msgstr "Nega esplicitamente queste capacità memorizzandole come disabilitate"
1527
 
1528
+ #: includes/manager.php:201
1529
  msgid "Explicity negate this capability by storing as disabled"
1530
  msgstr "Nega esplicitamente questa capacità memorizzandola come disabilitata"
1531
 
1532
+ #: includes/admin-load.php:308 includes/manager.php:339
1533
+ #: includes/manager.php:410 includes/roles/class/class-pp-roles-admin.php:427
1534
+ #: includes/roles/class/class-pp-roles-list-table.php:172
1535
  msgid "Capabilities"
1536
  msgstr "Capacità"
1537
 
1539
  msgid "Role Capabilities"
1540
  msgstr "Capacità di ruolo"
1541
 
1542
+ #: capsman-enhanced.php:115
1543
  msgid "%s is required for this plugin."
1544
  msgstr "E' necessario %s per l'utilizzo di questo plugin."
1545
 
1546
+ #: capsman-enhanced.php:113
1547
  msgid "The active plugin %s is not compatible with your PHP version."
1548
  msgstr "Il plugin %s non é compatibile con la tua versione PHP."
1549
 
1550
+ #: capsman-enhanced.php:112
1551
  msgid "Warning:"
1552
  msgstr "Attenzione:"
1553
 
1554
+ #: capsman-enhanced.php:55
1555
+ msgid "%1s Error: %2s PublishPress Capabilities cannot function because another copy of Capability Manager is active."
1556
  msgstr "<strong>Errore:</strong> PublishPress Capabilities non può funzionare perché è attiva un'altra copia di Capability Manager."
loco.xml DELETED
@@ -1,19 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <bundle name="PublishPress Capabilities">
3
- <domain name="capsman-enhanced">
4
- <project name="PublishPress Capabilities" slug="capsman-enhanced">
5
- <source>
6
- <directory>.</directory>
7
- </source>
8
- <target>
9
- <directory>languages</directory>
10
- </target>
11
- <template>
12
- <file>languages/capsman-enhanced.pot</file>
13
- </template>
14
- </project>
15
- </domain>
16
- <exclude>
17
- <directory>vendor</directory>
18
- </exclude>
19
- </bundle>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -7,7 +7,7 @@ Tags: user roles, capabilities, permissions, admin menus, post editing, post typ
7
  Requires at least: 4.9.7
8
  Tested up to: 6.0
9
  Requires PHP: 5.6.20
10
- Stable tag: 2.4.1
11
  License: GPLv3
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
@@ -409,6 +409,37 @@ Fixed : Security issue. Please update.
409
 
410
  == Changelog ==
411
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
  = 2.4.1 - 09 May 2022 =
413
  * Fixed : Small bug with Capabilities search #340
414
  * Update : Add sorting for more table columns in "Roles" #388
7
  Requires at least: 4.9.7
8
  Tested up to: 6.0
9
  Requires PHP: 5.6.20
10
+ Stable tag: 2.4.3
11
  License: GPLv3
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
409
 
410
  == Changelog ==
411
 
412
+ = 2.4.3 - 12 Jul 2022 =
413
+ * Fixed : Capabilities conflict with Advanced Custom Fields #494
414
+ * Fixed : Issue with editor features when options is not array #495
415
+ * Update : Add checkbox for the "Allowed Editors" feature #498
416
+ * Update : Add support for TaxoPress on the Capabilities screen #500
417
+ * Update : Use 3 clicks approach for all boxes in Capabilities #497
418
+ * Fixed : Uncaught TypeError: in_array(): Argument #2 ($haystack) must be of type array, null given. #513
419
+ * Fixed : Hide Invalid Capabilities if empty #490
420
+
421
+ = 2.4.2 - 14 Jun 2022 =
422
+ * Fixed : Correct match of post types and Editor Features boxes #427
423
+ * Update : Changes to user role selection UI and make role draggable for re-ordering #443
424
+ * Added : Two new role tabs (Redirects and Editing) #403
425
+ * Added : Redirect users to original page after login to role editor #301
426
+ * Added : Redirect on login and logout to role editor #11
427
+ * Fixed : Admin Menus issue with JetPack #381
428
+ * Added : Hide the "add new block" button to editor feature #436
429
+ * Added : Hide the Revisions box in Editor Features #428
430
+ * Update : UI clean up for Backup screens #322
431
+ * Update : Move the Taxonomy area to it's own tab #425
432
+ * Added : Support for WPML capabilities #411
433
+ * Added : Support for WS Form #305
434
+ * Added : Support Gravity Forms support #306
435
+ * Added : Add a new setting to disable Code Editor in Posts to role editor #298
436
+ * Update : Remember last tab after updating role settings #445
437
+ * Update : Add toggle all checkmarks options on the Capabilities screen #419
438
+ * Update : More categorization for capabilities #303
439
+ * Update : Force user roles to use specific editors in role settings #276
440
+ * Added : Add a setting to show private taxonomies on the "Capabilities" screen #314
441
+ * Added: Extend admin features "hide by css" to include plugin list #488
442
+
443
  = 2.4.1 - 09 May 2022 =
444
  * Fixed : Small bug with Capabilities search #340
445
  * Update : Add sorting for more table columns in "Roles" #388
vendor/composer/InstalledVersions.php CHANGED
@@ -21,8 +21,6 @@ use Composer\Semver\VersionParser;
21
  * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
22
  *
23
  * To require its presence, you can require `composer-runtime-api ^2.0`
24
- *
25
- * @final
26
  */
27
  class InstalledVersions
28
  {
21
  * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
22
  *
23
  * To require its presence, you can require `composer-runtime-api ^2.0`
 
 
24
  */
25
  class InstalledVersions
26
  {
vendor/composer/autoload_classmap.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_classmap.php @generated by Composer
4
 
5
- $vendorDir = dirname(__DIR__);
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
2
 
3
  // autoload_classmap.php @generated by Composer
4
 
5
+ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
vendor/composer/autoload_files.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_files.php @generated by Composer
4
 
5
- $vendorDir = dirname(__DIR__);
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
2
 
3
  // autoload_files.php @generated by Composer
4
 
5
+ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
vendor/composer/autoload_namespaces.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_namespaces.php @generated by Composer
4
 
5
- $vendorDir = dirname(__DIR__);
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
2
 
3
  // autoload_namespaces.php @generated by Composer
4
 
5
+ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
vendor/composer/autoload_psr4.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_psr4.php @generated by Composer
4
 
5
- $vendorDir = dirname(__DIR__);
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
2
 
3
  // autoload_psr4.php @generated by Composer
4
 
5
+ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
vendor/composer/autoload_real.php CHANGED
@@ -25,15 +25,38 @@ class ComposerAutoloaderInit94bd22b5e0f1f0f3ce6feebfa626e892
25
  require __DIR__ . '/platform_check.php';
26
 
27
  spl_autoload_register(array('ComposerAutoloaderInit94bd22b5e0f1f0f3ce6feebfa626e892', 'loadClassLoader'), true, true);
28
- self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
29
  spl_autoload_unregister(array('ComposerAutoloaderInit94bd22b5e0f1f0f3ce6feebfa626e892', 'loadClassLoader'));
30
 
31
- require __DIR__ . '/autoload_static.php';
32
- \Composer\Autoload\ComposerStaticInit94bd22b5e0f1f0f3ce6feebfa626e892::getInitializer($loader)();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  $loader->register(true);
35
 
36
- $includeFiles = \Composer\Autoload\ComposerStaticInit94bd22b5e0f1f0f3ce6feebfa626e892::$files;
 
 
 
 
37
  foreach ($includeFiles as $fileIdentifier => $file) {
38
  composerRequire94bd22b5e0f1f0f3ce6feebfa626e892($fileIdentifier, $file);
39
  }
25
  require __DIR__ . '/platform_check.php';
26
 
27
  spl_autoload_register(array('ComposerAutoloaderInit94bd22b5e0f1f0f3ce6feebfa626e892', 'loadClassLoader'), true, true);
28
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
29
  spl_autoload_unregister(array('ComposerAutoloaderInit94bd22b5e0f1f0f3ce6feebfa626e892', 'loadClassLoader'));
30
 
31
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
32
+ if ($useStaticLoader) {
33
+ require __DIR__ . '/autoload_static.php';
34
+
35
+ call_user_func(\Composer\Autoload\ComposerStaticInit94bd22b5e0f1f0f3ce6feebfa626e892::getInitializer($loader));
36
+ } else {
37
+ $map = require __DIR__ . '/autoload_namespaces.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->set($namespace, $path);
40
+ }
41
+
42
+ $map = require __DIR__ . '/autoload_psr4.php';
43
+ foreach ($map as $namespace => $path) {
44
+ $loader->setPsr4($namespace, $path);
45
+ }
46
+
47
+ $classMap = require __DIR__ . '/autoload_classmap.php';
48
+ if ($classMap) {
49
+ $loader->addClassMap($classMap);
50
+ }
51
+ }
52
 
53
  $loader->register(true);
54
 
55
+ if ($useStaticLoader) {
56
+ $includeFiles = Composer\Autoload\ComposerStaticInit94bd22b5e0f1f0f3ce6feebfa626e892::$files;
57
+ } else {
58
+ $includeFiles = require __DIR__ . '/autoload_files.php';
59
+ }
60
  foreach ($includeFiles as $fileIdentifier => $file) {
61
  composerRequire94bd22b5e0f1f0f3ce6feebfa626e892($fileIdentifier, $file);
62
  }
vendor/composer/installed.json CHANGED
@@ -115,17 +115,17 @@
115
  },
116
  {
117
  "name": "publishpress/publishpress-instance-protection",
118
- "version": "v1.0.1",
119
- "version_normalized": "1.0.1.0",
120
  "source": {
121
  "type": "git",
122
  "url": "https://github.com/publishpress/publishpress-instance-protection",
123
- "reference": "ddfa4b1e07f77b41b26e46223626584a85800073"
124
  },
125
  "require": {
126
  "php": ">=5.6.20"
127
  },
128
- "time": "2022-05-03T13:25:31+00:00",
129
  "type": "library",
130
  "installation-source": "source",
131
  "license": [
@@ -146,23 +146,23 @@
146
  },
147
  {
148
  "name": "publishpress/wordpress-banners",
149
- "version": "v1.2.8",
150
- "version_normalized": "1.2.8.0",
151
  "source": {
152
  "type": "git",
153
  "url": "https://github.com/publishpress/wordpress-banners.git",
154
- "reference": "79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c"
155
  },
156
  "dist": {
157
  "type": "zip",
158
- "url": "https://api.github.com/repos/publishpress/wordpress-banners/zipball/79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c",
159
- "reference": "79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c",
160
  "shasum": ""
161
  },
162
  "require": {
163
  "php": ">=5.6.20"
164
  },
165
- "time": "2022-03-18T14:49:29+00:00",
166
  "type": "library",
167
  "installation-source": "dist",
168
  "autoload": {
@@ -184,23 +184,23 @@
184
  "homepage": "http://publishpress.com/",
185
  "support": {
186
  "issues": "https://github.com/publishpress/wordpress-banners/issues",
187
- "source": "https://github.com/publishpress/wordpress-banners/tree/v1.2.8"
188
  },
189
  "install-path": "../publishpress/wordpress-banners"
190
  },
191
  {
192
  "name": "publishpress/wordpress-reviews",
193
- "version": "v1.1.18",
194
- "version_normalized": "1.1.18.0",
195
  "source": {
196
  "type": "git",
197
  "url": "https://github.com/publishpress/wordpress-reviews.git",
198
- "reference": "0020705b8f6a7177fc393c6c42c82171bf9e2fbd"
199
  },
200
  "dist": {
201
  "type": "zip",
202
- "url": "https://api.github.com/repos/publishpress/wordpress-reviews/zipball/0020705b8f6a7177fc393c6c42c82171bf9e2fbd",
203
- "reference": "0020705b8f6a7177fc393c6c42c82171bf9e2fbd",
204
  "shasum": ""
205
  },
206
  "require": {
@@ -224,7 +224,7 @@
224
  "wp-cli/i18n-command": "^2.2",
225
  "wp-cli/wp-cli": "^2.5"
226
  },
227
- "time": "2021-12-15T00:03:53+00:00",
228
  "type": "library",
229
  "installation-source": "dist",
230
  "autoload": {
@@ -255,33 +255,44 @@
255
  ],
256
  "support": {
257
  "issues": "https://github.com/publishpress/wordpress-reviews/issues",
258
- "source": "https://github.com/publishpress/wordpress-reviews/tree/v1.1.18"
259
  },
260
  "install-path": "../publishpress/wordpress-reviews"
261
  },
262
  {
263
  "name": "publishpress/wordpress-version-notices",
264
- "version": "1.1.3",
265
- "version_normalized": "1.1.3.0",
266
  "source": {
267
  "type": "git",
268
  "url": "https://github.com/publishpress/WordPress-Version-Notices.git",
269
- "reference": "57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3"
270
  },
271
  "dist": {
272
  "type": "zip",
273
- "url": "https://api.github.com/repos/publishpress/WordPress-Version-Notices/zipball/57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3",
274
- "reference": "57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3",
275
  "shasum": ""
276
  },
277
  "require": {
278
  "php": ">=5.6.20",
279
- "pimple/pimple": "^3"
 
280
  },
281
  "require-dev": {
282
- "lucatume/wp-browser": "^2.4"
 
 
 
 
 
 
 
 
 
 
283
  },
284
- "time": "2021-07-14T16:15:47+00:00",
285
  "type": "library",
286
  "installation-source": "dist",
287
  "autoload": {
@@ -304,7 +315,7 @@
304
  "description": "Library for displaying version notices for Pro plugins in WordPress.",
305
  "support": {
306
  "issues": "https://github.com/publishpress/WordPress-Version-Notices/issues",
307
- "source": "https://github.com/publishpress/WordPress-Version-Notices/tree/1.1.3"
308
  },
309
  "install-path": "../publishpress/wordpress-version-notices"
310
  }
115
  },
116
  {
117
  "name": "publishpress/publishpress-instance-protection",
118
+ "version": "v1.0.2",
119
+ "version_normalized": "1.0.2.0",
120
  "source": {
121
  "type": "git",
122
  "url": "https://github.com/publishpress/publishpress-instance-protection",
123
+ "reference": "ef1a631a41b723ce2e856f534ff4befbe914e964"
124
  },
125
  "require": {
126
  "php": ">=5.6.20"
127
  },
128
+ "time": "2022-06-03T17:41:36+00:00",
129
  "type": "library",
130
  "installation-source": "source",
131
  "license": [
146
  },
147
  {
148
  "name": "publishpress/wordpress-banners",
149
+ "version": "v1.3.0",
150
+ "version_normalized": "1.3.0.0",
151
  "source": {
152
  "type": "git",
153
  "url": "https://github.com/publishpress/wordpress-banners.git",
154
+ "reference": "08e20b98320367bdbc59105095c72e7ccbf968f1"
155
  },
156
  "dist": {
157
  "type": "zip",
158
+ "url": "https://api.github.com/repos/publishpress/wordpress-banners/zipball/08e20b98320367bdbc59105095c72e7ccbf968f1",
159
+ "reference": "08e20b98320367bdbc59105095c72e7ccbf968f1",
160
  "shasum": ""
161
  },
162
  "require": {
163
  "php": ">=5.6.20"
164
  },
165
+ "time": "2022-06-03T15:45:27+00:00",
166
  "type": "library",
167
  "installation-source": "dist",
168
  "autoload": {
184
  "homepage": "http://publishpress.com/",
185
  "support": {
186
  "issues": "https://github.com/publishpress/wordpress-banners/issues",
187
+ "source": "https://github.com/publishpress/wordpress-banners/tree/v1.3.0"
188
  },
189
  "install-path": "../publishpress/wordpress-banners"
190
  },
191
  {
192
  "name": "publishpress/wordpress-reviews",
193
+ "version": "v1.1.19",
194
+ "version_normalized": "1.1.19.0",
195
  "source": {
196
  "type": "git",
197
  "url": "https://github.com/publishpress/wordpress-reviews.git",
198
+ "reference": "028e573eb7c5da2455a7a823cabbbe5e3f89ca9c"
199
  },
200
  "dist": {
201
  "type": "zip",
202
+ "url": "https://api.github.com/repos/publishpress/wordpress-reviews/zipball/028e573eb7c5da2455a7a823cabbbe5e3f89ca9c",
203
+ "reference": "028e573eb7c5da2455a7a823cabbbe5e3f89ca9c",
204
  "shasum": ""
205
  },
206
  "require": {
224
  "wp-cli/i18n-command": "^2.2",
225
  "wp-cli/wp-cli": "^2.5"
226
  },
227
+ "time": "2022-06-03T13:38:53+00:00",
228
  "type": "library",
229
  "installation-source": "dist",
230
  "autoload": {
255
  ],
256
  "support": {
257
  "issues": "https://github.com/publishpress/wordpress-reviews/issues",
258
+ "source": "https://github.com/publishpress/wordpress-reviews/tree/v1.1.19"
259
  },
260
  "install-path": "../publishpress/wordpress-reviews"
261
  },
262
  {
263
  "name": "publishpress/wordpress-version-notices",
264
+ "version": "1.1.4",
265
+ "version_normalized": "1.1.4.0",
266
  "source": {
267
  "type": "git",
268
  "url": "https://github.com/publishpress/WordPress-Version-Notices.git",
269
+ "reference": "a46b552ac4cbec26d743307611e5dd8d56f80a57"
270
  },
271
  "dist": {
272
  "type": "zip",
273
+ "url": "https://api.github.com/repos/publishpress/WordPress-Version-Notices/zipball/a46b552ac4cbec26d743307611e5dd8d56f80a57",
274
+ "reference": "a46b552ac4cbec26d743307611e5dd8d56f80a57",
275
  "shasum": ""
276
  },
277
  "require": {
278
  "php": ">=5.6.20",
279
+ "pimple/pimple": "~3.2.0",
280
+ "psr/container": "~1.0.0"
281
  },
282
  "require-dev": {
283
+ "codeception/module-asserts": "^1.0",
284
+ "codeception/module-cli": "^1.0",
285
+ "codeception/module-db": "^1.0",
286
+ "codeception/module-filesystem": "^1.0",
287
+ "codeception/module-phpbrowser": "^1.0",
288
+ "codeception/module-rest": "^1.3",
289
+ "codeception/module-webdriver": "^1.0",
290
+ "codeception/util-universalframework": "^1.0",
291
+ "composer/composer": "2.2.12",
292
+ "lucatume/wp-browser": "^3",
293
+ "overtrue/phplint": "^2.1"
294
  },
295
+ "time": "2022-06-06T15:45:54+00:00",
296
  "type": "library",
297
  "installation-source": "dist",
298
  "autoload": {
315
  "description": "Library for displaying version notices for Pro plugins in WordPress.",
316
  "support": {
317
  "issues": "https://github.com/publishpress/WordPress-Version-Notices/issues",
318
+ "source": "https://github.com/publishpress/WordPress-Version-Notices/tree/1.1.4"
319
  },
320
  "install-path": "../publishpress/wordpress-version-notices"
321
  }
vendor/composer/installed.php CHANGED
@@ -5,8 +5,8 @@
5
  'type' => 'wordpress-plugin',
6
  'install_path' => __DIR__ . '/../../',
7
  'aliases' => array(),
8
- 'reference' => '784077e5717a7054508951d171ef415535cf860f',
9
- 'name' => 'publishpress/publishpress-capabilities',
10
  'dev' => false,
11
  ),
12
  'versions' => array(
@@ -28,49 +28,49 @@
28
  'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
29
  'dev_requirement' => false,
30
  ),
31
- 'publishpress/publishpress-capabilities' => array(
32
  'pretty_version' => 'dev-master',
33
  'version' => 'dev-master',
34
  'type' => 'wordpress-plugin',
35
  'install_path' => __DIR__ . '/../../',
36
  'aliases' => array(),
37
- 'reference' => '784077e5717a7054508951d171ef415535cf860f',
38
  'dev_requirement' => false,
39
  ),
40
  'publishpress/publishpress-instance-protection' => array(
41
- 'pretty_version' => 'v1.0.1',
42
- 'version' => '1.0.1.0',
43
  'type' => 'library',
44
  'install_path' => __DIR__ . '/../publishpress/publishpress-instance-protection',
45
  'aliases' => array(),
46
- 'reference' => 'ddfa4b1e07f77b41b26e46223626584a85800073',
47
  'dev_requirement' => false,
48
  ),
49
  'publishpress/wordpress-banners' => array(
50
- 'pretty_version' => 'v1.2.8',
51
- 'version' => '1.2.8.0',
52
  'type' => 'library',
53
  'install_path' => __DIR__ . '/../publishpress/wordpress-banners',
54
  'aliases' => array(),
55
- 'reference' => '79a02716f89b93daec5b2dc0e8c1bc4d1cf9967c',
56
  'dev_requirement' => false,
57
  ),
58
  'publishpress/wordpress-reviews' => array(
59
- 'pretty_version' => 'v1.1.18',
60
- 'version' => '1.1.18.0',
61
  'type' => 'library',
62
  'install_path' => __DIR__ . '/../publishpress/wordpress-reviews',
63
  'aliases' => array(),
64
- 'reference' => '0020705b8f6a7177fc393c6c42c82171bf9e2fbd',
65
  'dev_requirement' => false,
66
  ),
67
  'publishpress/wordpress-version-notices' => array(
68
- 'pretty_version' => '1.1.3',
69
- 'version' => '1.1.3.0',
70
  'type' => 'library',
71
  'install_path' => __DIR__ . '/../publishpress/wordpress-version-notices',
72
  'aliases' => array(),
73
- 'reference' => '57e7cbb3e9b9ac366ddd3fd0a80c2e2eabf75ea3',
74
  'dev_requirement' => false,
75
  ),
76
  ),
5
  'type' => 'wordpress-plugin',
6
  'install_path' => __DIR__ . '/../../',
7
  'aliases' => array(),
8
+ 'reference' => 'cf9718efbc16014918ecd70207cad9214af894f1',
9
+ 'name' => 'publishpress/capability-manager-enhanced',
10
  'dev' => false,
11
  ),
12
  'versions' => array(
28
  'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
29
  'dev_requirement' => false,
30
  ),
31
+ 'publishpress/capability-manager-enhanced' => array(
32
  'pretty_version' => 'dev-master',
33
  'version' => 'dev-master',
34
  'type' => 'wordpress-plugin',
35
  'install_path' => __DIR__ . '/../../',
36
  'aliases' => array(),
37
+ 'reference' => 'cf9718efbc16014918ecd70207cad9214af894f1',
38
  'dev_requirement' => false,
39
  ),
40
  'publishpress/publishpress-instance-protection' => array(
41
+ 'pretty_version' => 'v1.0.2',
42
+ 'version' => '1.0.2.0',
43
  'type' => 'library',
44
  'install_path' => __DIR__ . '/../publishpress/publishpress-instance-protection',
45
  'aliases' => array(),
46
+ 'reference' => 'ef1a631a41b723ce2e856f534ff4befbe914e964',
47
  'dev_requirement' => false,
48
  ),
49
  'publishpress/wordpress-banners' => array(
50
+ 'pretty_version' => 'v1.3.0',
51
+ 'version' => '1.3.0.0',
52
  'type' => 'library',
53
  'install_path' => __DIR__ . '/../publishpress/wordpress-banners',
54
  'aliases' => array(),
55
+ 'reference' => '08e20b98320367bdbc59105095c72e7ccbf968f1',
56
  'dev_requirement' => false,
57
  ),
58
  'publishpress/wordpress-reviews' => array(
59
+ 'pretty_version' => 'v1.1.19',
60
+ 'version' => '1.1.19.0',
61
  'type' => 'library',
62
  'install_path' => __DIR__ . '/../publishpress/wordpress-reviews',
63
  'aliases' => array(),
64
+ 'reference' => '028e573eb7c5da2455a7a823cabbbe5e3f89ca9c',
65
  'dev_requirement' => false,
66
  ),
67
  'publishpress/wordpress-version-notices' => array(
68
+ 'pretty_version' => '1.1.4',
69
+ 'version' => '1.1.4.0',
70
  'type' => 'library',
71
  'install_path' => __DIR__ . '/../publishpress/wordpress-version-notices',
72
  'aliases' => array(),
73
+ 'reference' => 'a46b552ac4cbec26d743307611e5dd8d56f80a57',
74
  'dev_requirement' => false,
75
  ),
76
  ),
vendor/pimple/pimple/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- phpunit.xml
2
- composer.lock
3
- /vendor/
 
 
 
vendor/pimple/pimple/CHANGELOG DELETED
@@ -1,59 +0,0 @@
1
- * 3.2.3 (2017-XX-XX)
2
-
3
- * n/a
4
-
5
- * 3.2.2 (2017-07-23)
6
-
7
- * reverted extending a protected closure throws an exception (deprecated it instead)
8
-
9
- * 3.2.1 (2017-07-17)
10
-
11
- * fixed PHP error
12
-
13
- * 3.2.0 (2017-07-17)
14
-
15
- * added a PSR-11 service locator
16
- * added a PSR-11 wrapper
17
- * added ServiceIterator
18
- * fixed extending a protected closure (now throws InvalidServiceIdentifierException)
19
-
20
- * 3.1.0 (2017-07-03)
21
-
22
- * deprecated the C extension
23
- * added support for PSR-11 exceptions
24
-
25
- * 3.0.2 (2015-09-11)
26
-
27
- * refactored the C extension
28
- * minor non-significant changes
29
-
30
- * 3.0.1 (2015-07-30)
31
-
32
- * simplified some code
33
- * fixed a segfault in the C extension
34
-
35
- * 3.0.0 (2014-07-24)
36
-
37
- * removed the Pimple class alias (use Pimple\Container instead)
38
-
39
- * 2.1.1 (2014-07-24)
40
-
41
- * fixed compiler warnings for the C extension
42
- * fixed code when dealing with circular references
43
-
44
- * 2.1.0 (2014-06-24)
45
-
46
- * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a
47
- deprecated alias which will be removed in Pimple 3.0)
48
- * added Pimple\ServiceProviderInterface (and Pimple::register())
49
-
50
- * 2.0.0 (2014-02-10)
51
-
52
- * changed extend to automatically re-assign the extended service and keep it as shared or factory
53
- (to keep BC, extend still returns the extended service)
54
- * changed services to be shared by default (use factory() for factory
55
- services)
56
-
57
- * 1.0.0
58
-
59
- * initial version
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/pimple/pimple/README.rst DELETED
@@ -1,326 +0,0 @@
1
- Pimple
2
- ======
3
-
4
- .. caution::
5
-
6
- This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read
7
- the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good
8
- way to learn more about how to create a simple Dependency Injection
9
- Container (recent versions of Pimple are more focused on performance).
10
-
11
- Pimple is a small Dependency Injection Container for PHP.
12
-
13
- Installation
14
- ------------
15
-
16
- Before using Pimple in your project, add it to your ``composer.json`` file:
17
-
18
- .. code-block:: bash
19
-
20
- $ ./composer.phar require pimple/pimple "^3.0"
21
-
22
- Usage
23
- -----
24
-
25
- Creating a container is a matter of creating a ``Container`` instance:
26
-
27
- .. code-block:: php
28
-
29
- use Pimple\Container;
30
-
31
- $container = new Container();
32
-
33
- As many other dependency injection containers, Pimple manages two different
34
- kind of data: **services** and **parameters**.
35
-
36
- Defining Services
37
- ~~~~~~~~~~~~~~~~~
38
-
39
- A service is an object that does something as part of a larger system. Examples
40
- of services: a database connection, a templating engine, or a mailer. Almost
41
- any **global** object can be a service.
42
-
43
- Services are defined by **anonymous functions** that return an instance of an
44
- object:
45
-
46
- .. code-block:: php
47
-
48
- // define some services
49
- $container['session_storage'] = function ($c) {
50
- return new SessionStorage('SESSION_ID');
51
- };
52
-
53
- $container['session'] = function ($c) {
54
- return new Session($c['session_storage']);
55
- };
56
-
57
- Notice that the anonymous function has access to the current container
58
- instance, allowing references to other services or parameters.
59
-
60
- As objects are only created when you get them, the order of the definitions
61
- does not matter.
62
-
63
- Using the defined services is also very easy:
64
-
65
- .. code-block:: php
66
-
67
- // get the session object
68
- $session = $container['session'];
69
-
70
- // the above call is roughly equivalent to the following code:
71
- // $storage = new SessionStorage('SESSION_ID');
72
- // $session = new Session($storage);
73
-
74
- Defining Factory Services
75
- ~~~~~~~~~~~~~~~~~~~~~~~~~
76
-
77
- By default, each time you get a service, Pimple returns the **same instance**
78
- of it. If you want a different instance to be returned for all calls, wrap your
79
- anonymous function with the ``factory()`` method
80
-
81
- .. code-block:: php
82
-
83
- $container['session'] = $container->factory(function ($c) {
84
- return new Session($c['session_storage']);
85
- });
86
-
87
- Now, each call to ``$container['session']`` returns a new instance of the
88
- session.
89
-
90
- Defining Parameters
91
- ~~~~~~~~~~~~~~~~~~~
92
-
93
- Defining a parameter allows to ease the configuration of your container from
94
- the outside and to store global values:
95
-
96
- .. code-block:: php
97
-
98
- // define some parameters
99
- $container['cookie_name'] = 'SESSION_ID';
100
- $container['session_storage_class'] = 'SessionStorage';
101
-
102
- If you change the ``session_storage`` service definition like below:
103
-
104
- .. code-block:: php
105
-
106
- $container['session_storage'] = function ($c) {
107
- return new $c['session_storage_class']($c['cookie_name']);
108
- };
109
-
110
- You can now easily change the cookie name by overriding the
111
- ``cookie_name`` parameter instead of redefining the service
112
- definition.
113
-
114
- Protecting Parameters
115
- ~~~~~~~~~~~~~~~~~~~~~
116
-
117
- Because Pimple sees anonymous functions as service definitions, you need to
118
- wrap anonymous functions with the ``protect()`` method to store them as
119
- parameters:
120
-
121
- .. code-block:: php
122
-
123
- $container['random_func'] = $container->protect(function () {
124
- return rand();
125
- });
126
-
127
- Modifying Services after Definition
128
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
129
-
130
- In some cases you may want to modify a service definition after it has been
131
- defined. You can use the ``extend()`` method to define additional code to be
132
- run on your service just after it is created:
133
-
134
- .. code-block:: php
135
-
136
- $container['session_storage'] = function ($c) {
137
- return new $c['session_storage_class']($c['cookie_name']);
138
- };
139
-
140
- $container->extend('session_storage', function ($storage, $c) {
141
- $storage->...();
142
-
143
- return $storage;
144
- });
145
-
146
- The first argument is the name of the service to extend, the second a function
147
- that gets access to the object instance and the container.
148
-
149
- Extending a Container
150
- ~~~~~~~~~~~~~~~~~~~~~
151
-
152
- If you use the same libraries over and over, you might want to reuse some
153
- services from one project to the next one; package your services into a
154
- **provider** by implementing ``Pimple\ServiceProviderInterface``:
155
-
156
- .. code-block:: php
157
-
158
- use Pimple\Container;
159
-
160
- class FooProvider implements Pimple\ServiceProviderInterface
161
- {
162
- public function register(Container $pimple)
163
- {
164
- // register some services and parameters
165
- // on $pimple
166
- }
167
- }
168
-
169
- Then, register the provider on a Container:
170
-
171
- .. code-block:: php
172
-
173
- $pimple->register(new FooProvider());
174
-
175
- Fetching the Service Creation Function
176
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177
-
178
- When you access an object, Pimple automatically calls the anonymous function
179
- that you defined, which creates the service object for you. If you want to get
180
- raw access to this function, you can use the ``raw()`` method:
181
-
182
- .. code-block:: php
183
-
184
- $container['session'] = function ($c) {
185
- return new Session($c['session_storage']);
186
- };
187
-
188
- $sessionFunction = $container->raw('session');
189
-
190
- PSR-11 compatibility
191
- --------------------
192
-
193
- For historical reasons, the ``Container`` class does not implement the PSR-11
194
- ``ContainerInterface``. However, Pimple provides a helper class that will let
195
- you decouple your code from the Pimple container class.
196
-
197
- The PSR-11 container class
198
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
199
-
200
- The ``Pimple\Psr11\Container`` class lets you access the content of an
201
- underlying Pimple container using ``Psr\Container\ContainerInterface``
202
- methods:
203
-
204
- .. code-block:: php
205
-
206
- use Pimple\Container;
207
- use Pimple\Psr11\Container as PsrContainer;
208
-
209
- $container = new Container();
210
- $container['service'] = function ($c) {
211
- return new Service();
212
- };
213
- $psr11 = new PsrContainer($container);
214
-
215
- $controller = function (PsrContainer $container) {
216
- $service = $container->get('service');
217
- };
218
- $controller($psr11);
219
-
220
- Using the PSR-11 ServiceLocator
221
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
222
-
223
- Sometimes, a service needs access to several other services without being sure
224
- that all of them will actually be used. In those cases, you may want the
225
- instantiation of the services to be lazy.
226
-
227
- The traditional solution is to inject the entire service container to get only
228
- the services really needed. However, this is not recommended because it gives
229
- services a too broad access to the rest of the application and it hides their
230
- actual dependencies.
231
-
232
- The ``ServiceLocator`` is intended to solve this problem by giving access to a
233
- set of predefined services while instantiating them only when actually needed.
234
-
235
- It also allows you to make your services available under a different name than
236
- the one used to register them. For instance, you may want to use an object
237
- that expects an instance of ``EventDispatcherInterface`` to be available under
238
- the name ``event_dispatcher`` while your event dispatcher has been
239
- registered under the name ``dispatcher``:
240
-
241
- .. code-block:: php
242
-
243
- use Monolog\Logger;
244
- use Pimple\Psr11\ServiceLocator;
245
- use Psr\Container\ContainerInterface;
246
- use Symfony\Component\EventDispatcher\EventDispatcher;
247
-
248
- class MyService
249
- {
250
- /**
251
- * "logger" must be an instance of Psr\Log\LoggerInterface
252
- * "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface
253
- */
254
- private $services;
255
-
256
- public function __construct(ContainerInterface $services)
257
- {
258
- $this->services = $services;
259
- }
260
- }
261
-
262
- $container['logger'] = function ($c) {
263
- return new Monolog\Logger();
264
- };
265
- $container['dispatcher'] = function () {
266
- return new EventDispatcher();
267
- };
268
-
269
- $container['service'] = function ($c) {
270
- $locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher'));
271
-
272
- return new MyService($locator);
273
- };
274
-
275
- Referencing a Collection of Services Lazily
276
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
277
-
278
- Passing a collection of services instances in an array may prove inefficient
279
- if the class that consumes the collection only needs to iterate over it at a
280
- later stage, when one of its method is called. It can also lead to problems
281
- if there is a circular dependency between one of the services stored in the
282
- collection and the class that consumes it.
283
-
284
- The ``ServiceIterator`` class helps you solve these issues. It receives a
285
- list of service names during instantiation and will retrieve the services
286
- when iterated over:
287
-
288
- .. code-block:: php
289
-
290
- use Pimple\Container;
291
- use Pimple\ServiceIterator;
292
-
293
- class AuthorizationService
294
- {
295
- private $voters;
296
-
297
- public function __construct($voters)
298
- {
299
- $this->voters = $voters;
300
- }
301
-
302
- public function canAccess($resource)
303
- {
304
- foreach ($this->voters as $voter) {
305
- if (true === $voter->canAccess($resource) {
306
- return true;
307
- }
308
- }
309
-
310
- return false;
311
- }
312
- }
313
-
314
- $container = new Container();
315
-
316
- $container['voter1'] = function ($c) {
317
- return new SomeVoter();
318
- }
319
- $container['voter2'] = function ($c) {
320
- return new SomeOtherVoter($c['auth']);
321
- }
322
- $container['auth'] = function ($c) {
323
- return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2'));
324
- }
325
-
326
- .. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/pimple/pimple/composer.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "name": "pimple/pimple",
3
- "type": "library",
4
- "description": "Pimple, a simple Dependency Injection Container",
5
- "keywords": ["dependency injection", "container"],
6
- "homepage": "http://pimple.sensiolabs.org",
7
- "license": "MIT",
8
- "authors": [
9
- {
10
- "name": "Fabien Potencier",
11
- "email": "fabien@symfony.com"
12
- }
13
- ],
14
- "require": {
15
- "php": ">=5.3.0",
16
- "psr/container": "^1.0"
17
- },
18
- "require-dev": {
19
- "symfony/phpunit-bridge": "^3.2"
20
- },
21
- "autoload": {
22
- "psr-0": { "Pimple": "src/" }
23
- },
24
- "extra": {
25
- "branch-alias": {
26
- "dev-master": "3.2.x-dev"
27
- }
28
- }
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/pimple/pimple/phpunit.xml.dist DELETED
@@ -1,14 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
-
3
- <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
- xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
5
- backupGlobals="false"
6
- colors="true"
7
- bootstrap="vendor/autoload.php"
8
- >
9
- <testsuites>
10
- <testsuite name="Pimple Test Suite">
11
- <directory>./src/Pimple/Tests</directory>
12
- </testsuite>
13
- </testsuites>
14
- </phpunit>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/psr/container/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- composer.lock
2
- composer.phar
3
- /vendor/
 
 
 
vendor/psr/container/README.md DELETED
@@ -1,5 +0,0 @@
1
- # PSR Container
2
-
3
- This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
4
-
5
- Note that this is not a container implementation of its own. See the specification for more details.
 
 
 
 
 
vendor/psr/container/composer.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "name": "psr/container",
3
- "type": "library",
4
- "description": "Common Container Interface (PHP FIG PSR-11)",
5
- "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
6
- "homepage": "https://github.com/php-fig/container",
7
- "license": "MIT",
8
- "authors": [
9
- {
10
- "name": "PHP-FIG",
11
- "homepage": "http://www.php-fig.org/"
12
- }
13
- ],
14
- "require": {
15
- "php": ">=5.3.0"
16
- },
17
- "autoload": {
18
- "psr-4": {
19
- "Psr\\Container\\": "src/"
20
- }
21
- },
22
- "extra": {
23
- "branch-alias": {
24
- "dev-master": "1.0.x-dev"
25
- }
26
- }
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/publishpress/publishpress-instance-protection/.gitattributes ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .babelrc export-ignore
2
+ .distignore export-ignore
3
+ .DS_Store export-ignore
4
+ .editorconfig export-ignore
5
+ .git export-ignore
6
+ .gitattributes export-ignore
7
+ .github export-ignore
8
+ .gitignore export-ignore
9
+ .gitlab-ci.yml export-ignore
10
+ .phplint.yml export-ignore
11
+ .travis.yml export-ignore
12
+ .vscode export-ignore
13
+ *.bash export-ignore
14
+ *.cache export-ignore
15
+ *.code-workspace export-ignore
16
+ *.dist export-ignore
17
+ *.dist.yml export-ignore
18
+ *.exe export-ignore
19
+ *.sh export-ignore
20
+ *.sql export-ignore
21
+ *.tar.gz export-ignore
22
+ *.testing export-ignore
23
+ *.zip export-ignore
24
+ /dist export-ignore
25
+ /screenshot-*.png export-ignore
26
+ /tests export-ignore
27
+ behat.yml export-ignore
28
+ bin export-ignore
29
+ builder.yml export-ignore
30
+ circle.yml export-ignore
31
+ codeception.yml export-ignore
32
+ composer.json export-ignore
33
+ composer.lock export-ignore
34
+ docker-compose.yml export-ignore
35
+ Gruntfile.js export-ignore
36
+ Gruntfile.js export-ignore
37
+ jsconfig.json export-ignore
38
+ multisite.xml export-ignore
39
+ multisite.xml.dist export-ignore
40
+ node_modules export-ignore
41
+ package-lock.json export-ignore
42
+ package.json export-ignore
43
+ phpcs.ruleset.xml export-ignore
44
+ phpcs.xml export-ignore
45
+ phpcs.xml.dist export-ignore
46
+ phpmd.xml export-ignore
47
+ phpunit.xml export-ignore
48
+ phpunit.xml.dist export-ignore
49
+ psalm.xml export-ignore
50
+ README.md export-ignore
51
+ RoboFile.php export-ignore
52
+ Thumbs.db export-ignore
53
+ webpack.config.js export-ignore
54
+ wp-cli.local.yml export-ignore
vendor/publishpress/publishpress-instance-protection/README.md CHANGED
@@ -100,6 +100,7 @@ if (class_exists('PublishPressInstanceProtection\\Config')) {
100
  $pluginCheckerConfig = new PublishPressInstanceProtection\Config();
101
  $pluginCheckerConfig->pluginSlug = 'publishpress-authors';
102
  $pluginCheckerConfig->pluginName = 'PublishPress Authors';
 
103
 
104
  $pluginChecker = new PublishPressInstanceProtection\InstanceChecker($pluginCheckerConfig);
105
  }
@@ -120,6 +121,7 @@ if (class_exists('PublishPressInstanceProtection\\Config')) {
120
  $pluginCheckerConfig = new PublishPressInstanceProtection\Config();
121
  $pluginCheckerConfig->pluginSlug = 'publishpress-authors-pro';
122
  $pluginCheckerConfig->pluginName = 'PublishPress Authors Pro';
 
123
  $pluginCheckerConfig->isProPlugin = true;
124
  $pluginCheckerConfig->freePluginName = 'PublishPress Authors';
125
 
100
  $pluginCheckerConfig = new PublishPressInstanceProtection\Config();
101
  $pluginCheckerConfig->pluginSlug = 'publishpress-authors';
102
  $pluginCheckerConfig->pluginName = 'PublishPress Authors';
103
+ $pluginCheckerConfig->pluginFolder = 'publishpress-authors'; // Only required if the folder is different from the slug.
104
 
105
  $pluginChecker = new PublishPressInstanceProtection\InstanceChecker($pluginCheckerConfig);
106
  }
121
  $pluginCheckerConfig = new PublishPressInstanceProtection\Config();
122
  $pluginCheckerConfig->pluginSlug = 'publishpress-authors-pro';
123
  $pluginCheckerConfig->pluginName = 'PublishPress Authors Pro';
124
+ $pluginCheckerConfig->pluginFolder = 'publishpress-authors-pro'; // Only required if the folder is different from the slug.
125
  $pluginCheckerConfig->isProPlugin = true;
126
  $pluginCheckerConfig->freePluginName = 'PublishPress Authors';
127
 
vendor/publishpress/publishpress-instance-protection/core/InstanceChecker.php CHANGED
@@ -57,7 +57,7 @@ class InstanceChecker
57
 
58
  public function getVersion()
59
  {
60
- return '1.0.1';
61
  }
62
 
63
  public function init()
57
 
58
  public function getVersion()
59
  {
60
+ return '1.0.2';
61
  }
62
 
63
  public function init()
vendor/publishpress/wordpress-banners/BannersMain.php CHANGED
@@ -3,7 +3,7 @@
3
  * @package PublishPress
4
  * @author PublishPress
5
  *
6
- * Copyright (c) 2021 PublishPress
7
  *
8
  * WordPressBanners is free software: you can redistribute it and/or modify
9
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ namespace PublishPress\WordPressBanners;
25
  use Exception;
26
 
27
  if (! defined('PP_WP_BANNERS_VERSION')) {
28
- define('PP_WP_BANNERS_VERSION', '1.2.8');
29
  }
30
 
31
  if (! class_exists('\\PublishPress\\WordPressBanners\\BannersMain')) {
@@ -41,6 +41,7 @@ if (! class_exists('\\PublishPress\\WordPressBanners\\BannersMain')) {
41
  * @param string $link Link to apply to button and image
42
  * @param string $link_title Link title
43
  * @param string $image A filename from assets/images/ folder; disabled if blank
 
44
  *
45
  * @return void
46
  */
@@ -50,7 +51,8 @@ if (! class_exists('\\PublishPress\\WordPressBanners\\BannersMain')) {
50
  $contents = array(),
51
  $link = '',
52
  $link_title = '',
53
- $image = ''
 
54
  ) {
55
  if (! empty($heading)) {
56
  ?>
@@ -94,7 +96,7 @@ if (! class_exists('\\PublishPress\\WordPressBanners\\BannersMain')) {
94
  ?>
95
 
96
  <p>
97
- <a class="button button-primary" href="<?php echo $link ?>">
98
  <?php echo $link_title ?>
99
  </a>
100
  </p>
3
  * @package PublishPress
4
  * @author PublishPress
5
  *
6
+ * Copyright (c) 2022 PublishPress
7
  *
8
  * WordPressBanners is free software: you can redistribute it and/or modify
9
  * it under the terms of the GNU General Public License as published by
25
  use Exception;
26
 
27
  if (! defined('PP_WP_BANNERS_VERSION')) {
28
+ define('PP_WP_BANNERS_VERSION', '1.3.0');
29
  }
30
 
31
  if (! class_exists('\\PublishPress\\WordPressBanners\\BannersMain')) {
41
  * @param string $link Link to apply to button and image
42
  * @param string $link_title Link title
43
  * @param string $image A filename from assets/images/ folder; disabled if blank
44
+ * @param string $link_class Link class. e.g. 'button button-secondary'
45
  *
46
  * @return void
47
  */
51
  $contents = array(),
52
  $link = '',
53
  $link_title = '',
54
+ $image = '',
55
+ $link_class = 'button pp-button-yellow'
56
  ) {
57
  if (! empty($heading)) {
58
  ?>
96
  ?>
97
 
98
  <p>
99
+ <a class="<?php echo $link_class ?>" href="<?php echo $link ?>">
100
  <?php echo $link_title ?>
101
  </a>
102
  </p>
vendor/publishpress/wordpress-banners/assets/css/style.css CHANGED
@@ -58,6 +58,27 @@
58
  padding: 4px 10px !important;
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  .pp-sidebar-box .pp-box-banner-image {
62
  background: #655997;
63
  text-align: center;
58
  padding: 4px 10px !important;
59
  }
60
 
61
+ .pp-sidebar-box .button.pp-button-yellow {
62
+ background-color: #FFB300;
63
+ border-color: #C58C07;
64
+ color: #754D26;
65
+
66
+ text-shadow: none;
67
+ }
68
+
69
+ .pp-sidebar-box .button.pp-button-yellow:hover,
70
+ .pp-sidebar-box .button.pp-button-yellow:active,
71
+ .pp-sidebar-box .button.pp-button-yellow:focus {
72
+ background-color: #F3AC04;
73
+ border-color: #C58C07;
74
+ color: #333;
75
+ outline: none;
76
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
77
+ -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
78
+ -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
79
+ -o-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
80
+ }
81
+
82
  .pp-sidebar-box .pp-box-banner-image {
83
  background: #655997;
84
  text-align: center;
vendor/publishpress/wordpress-reviews/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- .phplint-cache
2
-
3
- .idea/
4
- vendor/
 
 
 
 
vendor/publishpress/wordpress-reviews/README.md DELETED
@@ -1,197 +0,0 @@
1
- # PublishPress WordPress Reviews Library
2
-
3
- The PublishPress WordPress Reviews is a library for displaying a banner to users asking for a five-star review.
4
-
5
- ## Installation
6
-
7
- We do recommend using composer for adding this library as a requirement:
8
-
9
- ```shell
10
- $ composer require publishpress/wordpress-reviews
11
- ```
12
-
13
- ## How to use it
14
-
15
- If your plugin does not load the composer's autoloader yet, you need to add the following code:
16
-
17
- ```php
18
- <?php
19
-
20
- require_once 'vendor/autoload.php';
21
- ```
22
-
23
- **Only free plugins should initialize this library**.
24
-
25
- It can be instantiated and initialized in the method that loads the main WordPress hooks.
26
-
27
- When instantiating this library, you have to pass three params:
28
-
29
- * the plugin slug (the same one used in the URL of the WordPress repository)
30
- * the plugin's name
31
- * the URL for the logo (optional)
32
-
33
- ### Configuring the criteria to display the banner in the Free plugin
34
-
35
- It by default displays the banner when the following conditional is true:
36
-
37
- ```php
38
- is_admin() && current_user_can('edit_posts')
39
- ```
40
-
41
- But you can specify custom criteria to display the banner hooking into the filter `<plugin_slug>_wp_reviews_allow_display_notice`.
42
-
43
- ```php
44
- <?php
45
-
46
- use PublishPress\WordPressReviews\ReviewsController;
47
-
48
- class MyPlugin
49
- {
50
- /**
51
- * @var ReviewsController
52
- */
53
- private $reviewController;
54
-
55
- public function __construct()
56
- {
57
- $this->reviewController = new ReviewsController(
58
- 'my-plugin',
59
- 'My Plugin',
60
- MY_PLUGIN_URL . '/assets/img/logo.png'
61
- );
62
- }
63
-
64
- public function init()
65
- {
66
- // .......
67
- add_filter('my-plugin_wp_reviews_allow_display_notice', [$this, 'shouldDisplayBanner']);
68
-
69
- $this->reviewController->init();
70
- }
71
-
72
- public function shouldDisplayBanner($shouldDisplay)
73
- {
74
- global $pagenow;
75
-
76
- if (! is_admin() || ! current_user_can('edit_posts')) {
77
- return false;
78
- }
79
-
80
- if ($pagenow === 'admin.php' && isset($_GET['page'])) {
81
- if ($_GET['page'] === 'pp-page1') {
82
- return true;
83
- }
84
-
85
- if ($_GET['page'] === 'pp-page2') {
86
- return true;
87
- }
88
- }
89
-
90
- if ($pagenow === 'edit.php' && isset($_GET['post_type'])) {
91
- if ($_GET['post_type'] === 'pp_custom_post_type') {
92
- return true;
93
- }
94
- }
95
-
96
- return false;
97
- }
98
-
99
- // .......
100
- }
101
- ```
102
-
103
- ### Configuring the criteria to display the banner in the Pro plugin
104
-
105
- In case the Pro plugin has additional pages where you want to display the banner, feel free to use the same filter as
106
- in the free plugin but with a higher priority. You can choose to override the conditions used in the Free plugin
107
- or to append more conditions, for different pages.
108
-
109
- ```php
110
- add_filter('my-plugin_wp_reviews_allow_display_notice', [$this, 'shouldDisplayBanner'], 20);
111
- ```
112
-
113
- ```php
114
- /**
115
- * @param $shouldDisplay
116
- * @return bool|null
117
- */
118
- public function shouldDisplayBanner($shouldDisplay)
119
- {
120
- global $pagenow;
121
-
122
- if ($shouldDisplay) {
123
- return true;
124
- }
125
-
126
- if ($pagenow === 'edit.php' && isset($_GET['post_type'])) {
127
- if ($_GET['post_type'] === 'custom-posttype') {
128
- return true;
129
- }
130
- }
131
-
132
- return $shouldDisplay;
133
- }
134
- ```
135
-
136
- ### Backward compatibility with older versions
137
-
138
- By default, the library will use the plugin's slug as a prefix for the actions, metadata, and options:
139
-
140
- ```php
141
- [
142
- 'action_ajax_handler' => $this->pluginSlug . '_action',
143
- 'option_installed_on' => $this->pluginSlug . '_wp_reviews_installed_on',
144
- 'nonce_action' => $this->pluginSlug . '_wp_reviews_action',
145
- 'user_meta_dismissed_triggers' => '_' . $this->pluginSlug . '_wp_reviews_dismissed_triggers',
146
- 'user_meta_last_dismissed' => '_' . $this->pluginSlug . '_wp_reviews_last_dismissed',
147
- 'user_meta_already_did' => '_' . $this->pluginSlug . '_wp_reviews_already_did',
148
- 'filter_triggers' => $this->pluginSlug . '_wp_reviews_triggers',
149
- ]
150
- ```
151
-
152
- If you already use the original library in your plugin and want to keep compatibility with current sites data, you can customize the
153
- hooks and keys for the data stored in the DB using the filter `<plugin_slug>_wp_reviews_meta_map`:
154
-
155
- ```php
156
- <?php
157
-
158
- add_filter('my-plugin_wp_reviews_meta_map', 'my_plugin_wp_reviews_meta_map');
159
-
160
- function my_plugin_wp_reviews_meta_map($metaMap)
161
- {
162
- // You can override all the array, or specific keys.
163
- $metaMap = [
164
- 'action_ajax_handler' => 'legacy_slug_ajax_action',
165
- 'option_installed_on' => 'legacy_slug_wp_reviews_installed_on',
166
- 'nonce_action' => 'legacy_slug_wp_reviews_action',
167
- 'user_meta_dismissed_triggers' => '_legacy_slug_wp_reviews_dismissed_triggers',
168
- 'user_meta_last_dismissed' => '_legacy_slug_wp_reviews_last_dismissed',
169
- 'user_meta_already_did' => '_legacy_slug_wp_reviews_already_did',
170
- 'filter_triggers' => 'legacy_slug_wp_reviews_triggers',
171
- ];
172
-
173
- return $metaMap;
174
- }
175
- ```
176
-
177
- ## Common questions
178
-
179
- ### Should I use this library on Pro plugins?
180
-
181
- Pro plugins that embed the free plugin code **should not instantiate or initialize this library** otherwise, users will
182
- probably see duplicated admin notices or will be asked for a review twice.
183
-
184
- Keeping the library activated only by the free plugin allows both versions, free and pro,
185
- to share the same options and metadata stored in the database, avoiding duplicated banners or review requests.
186
-
187
- Please, **only initialize this library in the Free plugin** and do not disable or block it in the Pro version. We want to keep it enabled
188
- for both free and pro users.
189
-
190
-
191
- ## Testing
192
-
193
- You can test the banner in the WordPress admin by changing the option `<plugin-slug>_wp_reviews_installed_on` in the options table. Set it for older data to make sure the time difference is bigger than the selected trigger
194
-
195
- ## Copyright
196
-
197
- Based on the [library](https://github.com/danieliser/WP-Product-In-Dash-Review-Requests) created by [Daniel Iser](https://danieliser.com).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/publishpress/wordpress-reviews/composer.json DELETED
@@ -1,46 +0,0 @@
1
- {
2
- "name": "publishpress/wordpress-reviews",
3
- "type": "library",
4
- "license": "GPL-3.0-or-later",
5
- "description": "Library for showing a five-star review banner.",
6
- "keywords": ["reviews", "review", "wordpress plugin"],
7
- "homepage": "http://publishpress.com/",
8
- "authors": [
9
- {
10
- "name": "PublishPress",
11
- "email": "help@publishpress.com"
12
- },
13
- {
14
- "name": "Daniel Iser",
15
- "homepage": "https://github.com/danieliser/WP-Product-In-Dash-Review-Requests"
16
- }
17
- ],
18
- "minimum-stability": "dev",
19
- "prefer-stable": true,
20
- "autoload": {
21
- "files": [
22
- "ReviewsController.php"
23
- ]
24
- },
25
- "require": {
26
- "php": ">=5.6.20"
27
- },
28
- "require-dev": {
29
- "lucatume/wp-browser": "^3",
30
- "codeception/module-asserts": "^1.0",
31
- "codeception/module-phpbrowser": "^1.0",
32
- "codeception/module-webdriver": "^1.0",
33
- "codeception/module-db": "^1.0",
34
- "codeception/module-filesystem": "^1.0",
35
- "codeception/module-cli": "^1.0",
36
- "codeception/util-universalframework": "^1.0",
37
- "codeception/module-rest": "^1.3",
38
- "publishpress/publishpress-plugin-builder": "^1.2",
39
- "phpmd/phpmd": "^2.8",
40
- "squizlabs/php_codesniffer": "^3.5",
41
- "sebastian/phpcpd": "^5.0",
42
- "overtrue/phplint": "^2.1",
43
- "wp-cli/wp-cli": "^2.5",
44
- "wp-cli/i18n-command": "^2.2"
45
- }
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/publishpress/wordpress-reviews/composer.lock DELETED
@@ -1,8265 +0,0 @@
1
- {
2
- "_readme": [
3
- "This file locks the dependencies of your project to a known state",
4
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
- "This file is @generated automatically"
6
- ],
7
- "content-hash": "1f9719013ecdfb6c278cc0c5c976b141",
8
- "packages": [],
9
- "packages-dev": [
10
- {
11
- "name": "antecedent/patchwork",
12
- "version": "2.1.17",
13
- "source": {
14
- "type": "git",
15
- "url": "https://github.com/antecedent/patchwork.git",
16
- "reference": "df5aba175a44c2996ced4edf8ec9f9081b5348c0"
17
- },
18
- "dist": {
19
- "type": "zip",
20
- "url": "https://api.github.com/repos/antecedent/patchwork/zipball/df5aba175a44c2996ced4edf8ec9f9081b5348c0",
21
- "reference": "df5aba175a44c2996ced4edf8ec9f9081b5348c0",
22
- "shasum": ""
23
- },
24
- "require": {
25
- "php": ">=5.4.0"
26
- },
27
- "require-dev": {
28
- "phpunit/phpunit": ">=4"
29
- },
30
- "type": "library",
31
- "notification-url": "https://packagist.org/downloads/",
32
- "license": [
33
- "MIT"
34
- ],
35
- "authors": [
36
- {
37
- "name": "Ignas Rudaitis",
38
- "email": "ignas.rudaitis@gmail.com"
39
- }
40
- ],
41
- "description": "Method redefinition (monkey-patching) functionality for PHP.",
42
- "homepage": "http://patchwork2.org/",
43
- "keywords": [
44
- "aop",
45
- "aspect",
46
- "interception",
47
- "monkeypatching",
48
- "redefinition",
49
- "runkit",
50
- "testing"
51
- ],
52
- "support": {
53
- "issues": "https://github.com/antecedent/patchwork/issues",
54
- "source": "https://github.com/antecedent/patchwork/tree/2.1.17"
55
- },
56
- "time": "2021-10-21T14:22:43+00:00"
57
- },
58
- {
59
- "name": "behat/gherkin",
60
- "version": "v4.9.0",
61
- "source": {
62
- "type": "git",
63
- "url": "https://github.com/Behat/Gherkin.git",
64
- "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4"
65
- },
66
- "dist": {
67
- "type": "zip",
68
- "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4",
69
- "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4",
70
- "shasum": ""
71
- },
72
- "require": {
73
- "php": "~7.2|~8.0"
74
- },
75
- "require-dev": {
76
- "cucumber/cucumber": "dev-gherkin-22.0.0",
77
- "phpunit/phpunit": "~8|~9",
78
- "symfony/yaml": "~3|~4|~5"
79
- },
80
- "suggest": {
81
- "symfony/yaml": "If you want to parse features, represented in YAML files"
82
- },
83
- "type": "library",
84
- "extra": {
85
- "branch-alias": {
86
- "dev-master": "4.x-dev"
87
- }
88
- },
89
- "autoload": {
90
- "psr-0": {
91
- "Behat\\Gherkin": "src/"
92
- }
93
- },
94
- "notification-url": "https://packagist.org/downloads/",
95
- "license": [
96
- "MIT"
97
- ],
98
- "authors": [
99
- {
100
- "name": "Konstantin Kudryashov",
101
- "email": "ever.zet@gmail.com",
102
- "homepage": "http://everzet.com"
103
- }
104
- ],
105
- "description": "Gherkin DSL parser for PHP",
106
- "homepage": "http://behat.org/",
107
- "keywords": [
108
- "BDD",
109
- "Behat",
110
- "Cucumber",
111
- "DSL",
112
- "gherkin",
113
- "parser"
114
- ],
115
- "support": {
116
- "issues": "https://github.com/Behat/Gherkin/issues",
117
- "source": "https://github.com/Behat/Gherkin/tree/v4.9.0"
118
- },
119
- "time": "2021-10-12T13:05:09+00:00"
120
- },
121
- {
122
- "name": "bordoni/phpass",
123
- "version": "0.3.5",
124
- "source": {
125
- "type": "git",
126
- "url": "https://github.com/bordoni/phpass.git",
127
- "reference": "fd57c109213e95150b7de1dc8908c55605cd8e55"
128
- },
129
- "dist": {
130
- "type": "zip",
131
- "url": "https://api.github.com/repos/bordoni/phpass/zipball/fd57c109213e95150b7de1dc8908c55605cd8e55",
132
- "reference": "fd57c109213e95150b7de1dc8908c55605cd8e55",
133
- "shasum": ""
134
- },
135
- "require": {
136
- "php": ">=5.3.3"
137
- },
138
- "replace": {
139
- "hautelook/phpass": "0.3.*"
140
- },
141
- "type": "library",
142
- "autoload": {
143
- "psr-0": {
144
- "Hautelook": "src/"
145
- }
146
- },
147
- "notification-url": "https://packagist.org/downloads/",
148
- "license": [
149
- "Public Domain"
150
- ],
151
- "authors": [
152
- {
153
- "name": "Solar Designer",
154
- "email": "solar@openwall.com",
155
- "homepage": "http://openwall.com/phpass/"
156
- },
157
- {
158
- "name": "Gustavo Bordoni",
159
- "email": "gustavo@bordoni.me",
160
- "homepage": "https://bordoni.me"
161
- }
162
- ],
163
- "description": "Portable PHP password hashing framework",
164
- "homepage": "http://github.com/hautelook/phpass/",
165
- "keywords": [
166
- "blowfish",
167
- "crypt",
168
- "password",
169
- "security"
170
- ],
171
- "support": {
172
- "issues": "https://github.com/bordoni/phpass/issues",
173
- "source": "https://github.com/bordoni/phpass/tree/0.3.5"
174
- },
175
- "time": "2012-08-31T00:00:00+00:00"
176
- },
177
- {
178
- "name": "codeception/codeception",
179
- "version": "4.1.22",
180
- "source": {
181
- "type": "git",
182
- "url": "https://github.com/Codeception/Codeception.git",
183
- "reference": "9777ec3690ceedc4bce2ed13af7af4ca4ee3088f"
184
- },
185
- "dist": {
186
- "type": "zip",
187
- "url": "https://api.github.com/repos/Codeception/Codeception/zipball/9777ec3690ceedc4bce2ed13af7af4ca4ee3088f",
188
- "reference": "9777ec3690ceedc4bce2ed13af7af4ca4ee3088f",
189
- "shasum": ""
190
- },
191
- "require": {
192
- "behat/gherkin": "^4.4.0",
193
- "codeception/lib-asserts": "^1.0",
194
- "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.1.1 | ^9.0",
195
- "codeception/stub": "^2.0 | ^3.0",
196
- "ext-curl": "*",
197
- "ext-json": "*",
198
- "ext-mbstring": "*",
199
- "guzzlehttp/psr7": "^1.4 | ^2.0",
200
- "php": ">=5.6.0 <9.0",
201
- "symfony/console": ">=2.7 <6.0",
202
- "symfony/css-selector": ">=2.7 <6.0",
203
- "symfony/event-dispatcher": ">=2.7 <6.0",
204
- "symfony/finder": ">=2.7 <6.0",
205
- "symfony/yaml": ">=2.7 <6.0"
206
- },
207
- "require-dev": {
208
- "codeception/module-asserts": "1.*@dev",
209
- "codeception/module-cli": "1.*@dev",
210
- "codeception/module-db": "1.*@dev",
211
- "codeception/module-filesystem": "1.*@dev",
212
- "codeception/module-phpbrowser": "1.*@dev",
213
- "codeception/specify": "~0.3",
214
- "codeception/util-universalframework": "*@dev",
215
- "monolog/monolog": "~1.8",
216
- "squizlabs/php_codesniffer": "~2.0",
217
- "symfony/process": ">=2.7 <6.0",
218
- "vlucas/phpdotenv": "^2.0 | ^3.0 | ^4.0 | ^5.0"
219
- },
220
- "suggest": {
221
- "codeception/specify": "BDD-style code blocks",
222
- "codeception/verify": "BDD-style assertions",
223
- "hoa/console": "For interactive console functionality",
224
- "stecman/symfony-console-completion": "For BASH autocompletion",
225
- "symfony/phpunit-bridge": "For phpunit-bridge support"
226
- },
227
- "bin": [
228
- "codecept"
229
- ],
230
- "type": "library",
231
- "extra": {
232
- "branch-alias": []
233
- },
234
- "autoload": {
235
- "psr-4": {
236
- "Codeception\\": "src/Codeception",
237
- "Codeception\\Extension\\": "ext"
238
- }
239
- },
240
- "notification-url": "https://packagist.org/downloads/",
241
- "license": [
242
- "MIT"
243
- ],
244
- "authors": [
245
- {
246
- "name": "Michael Bodnarchuk",
247
- "email": "davert@mail.ua",
248
- "homepage": "http://codegyre.com"
249
- }
250
- ],
251
- "description": "BDD-style testing framework",
252
- "homepage": "http://codeception.com/",
253
- "keywords": [
254
- "BDD",
255
- "TDD",
256
- "acceptance testing",
257
- "functional testing",
258
- "unit testing"
259
- ],
260
- "support": {
261
- "issues": "https://github.com/Codeception/Codeception/issues",
262
- "source": "https://github.com/Codeception/Codeception/tree/4.1.22"
263
- },
264
- "funding": [
265
- {
266
- "url": "https://opencollective.com/codeception",
267
- "type": "open_collective"
268
- }
269
- ],
270
- "time": "2021-08-06T17:15:34+00:00"
271
- },
272
- {
273
- "name": "codeception/lib-asserts",
274
- "version": "1.13.2",
275
- "source": {
276
- "type": "git",
277
- "url": "https://github.com/Codeception/lib-asserts.git",
278
- "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6"
279
- },
280
- "dist": {
281
- "type": "zip",
282
- "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/184231d5eab66bc69afd6b9429344d80c67a33b6",
283
- "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6",
284
- "shasum": ""
285
- },
286
- "require": {
287
- "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3 | ^9.0",
288
- "ext-dom": "*",
289
- "php": ">=5.6.0 <9.0"
290
- },
291
- "type": "library",
292
- "autoload": {
293
- "classmap": [
294
- "src/"
295
- ]
296
- },
297
- "notification-url": "https://packagist.org/downloads/",
298
- "license": [
299
- "MIT"
300
- ],
301
- "authors": [
302
- {
303
- "name": "Michael Bodnarchuk",
304
- "email": "davert@mail.ua",
305
- "homepage": "http://codegyre.com"
306
- },
307
- {
308
- "name": "Gintautas Miselis"
309
- },
310
- {
311
- "name": "Gustavo Nieves",
312
- "homepage": "https://medium.com/@ganieves"
313
- }
314
- ],
315
- "description": "Assertion methods used by Codeception core and Asserts module",
316
- "homepage": "https://codeception.com/",
317
- "keywords": [
318
- "codeception"
319
- ],
320
- "support": {
321
- "issues": "https://github.com/Codeception/lib-asserts/issues",
322
- "source": "https://github.com/Codeception/lib-asserts/tree/1.13.2"
323
- },
324
- "time": "2020-10-21T16:26:20+00:00"
325
- },
326
- {
327
- "name": "codeception/lib-innerbrowser",
328
- "version": "1.5.1",
329
- "source": {
330
- "type": "git",
331
- "url": "https://github.com/Codeception/lib-innerbrowser.git",
332
- "reference": "31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2"
333
- },
334
- "dist": {
335
- "type": "zip",
336
- "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2",
337
- "reference": "31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2",
338
- "shasum": ""
339
- },
340
- "require": {
341
- "codeception/codeception": "4.*@dev",
342
- "ext-dom": "*",
343
- "ext-json": "*",
344
- "ext-mbstring": "*",
345
- "php": ">=5.6.0 <9.0",
346
- "symfony/browser-kit": ">=2.7 <6.0",
347
- "symfony/dom-crawler": ">=2.7 <6.0"
348
- },
349
- "conflict": {
350
- "codeception/codeception": "<4.0"
351
- },
352
- "require-dev": {
353
- "codeception/util-universalframework": "dev-master"
354
- },
355
- "type": "library",
356
- "autoload": {
357
- "classmap": [
358
- "src/"
359
- ]
360
- },
361
- "notification-url": "https://packagist.org/downloads/",
362
- "license": [
363
- "MIT"
364
- ],
365
- "authors": [
366
- {
367
- "name": "Michael Bodnarchuk",
368
- "email": "davert@mail.ua",
369
- "homepage": "http://codegyre.com"
370
- },
371
- {
372
- "name": "Gintautas Miselis"
373
- }
374
- ],
375
- "description": "Parent library for all Codeception framework modules and PhpBrowser",
376
- "homepage": "https://codeception.com/",
377
- "keywords": [
378
- "codeception"
379
- ],
380
- "support": {
381
- "issues": "https://github.com/Codeception/lib-innerbrowser/issues",
382
- "source": "https://github.com/Codeception/lib-innerbrowser/tree/1.5.1"
383
- },
384
- "time": "2021-08-30T15:21:42+00:00"
385
- },
386
- {
387
- "name": "codeception/module-asserts",
388
- "version": "1.3.1",
389
- "source": {
390
- "type": "git",
391
- "url": "https://github.com/Codeception/module-asserts.git",
392
- "reference": "59374f2fef0cabb9e8ddb53277e85cdca74328de"
393
- },
394
- "dist": {
395
- "type": "zip",
396
- "url": "https://api.github.com/repos/Codeception/module-asserts/zipball/59374f2fef0cabb9e8ddb53277e85cdca74328de",
397
- "reference": "59374f2fef0cabb9e8ddb53277e85cdca74328de",
398
- "shasum": ""
399
- },
400
- "require": {
401
- "codeception/codeception": "*@dev",
402
- "codeception/lib-asserts": "^1.13.1",
403
- "php": ">=5.6.0 <9.0"
404
- },
405
- "conflict": {
406
- "codeception/codeception": "<4.0"
407
- },
408
- "type": "library",
409
- "autoload": {
410
- "classmap": [
411
- "src/"
412
- ]
413
- },
414
- "notification-url": "https://packagist.org/downloads/",
415
- "license": [
416
- "MIT"
417
- ],
418
- "authors": [
419
- {
420
- "name": "Michael Bodnarchuk"
421
- },
422
- {
423
- "name": "Gintautas Miselis"
424
- },
425
- {
426
- "name": "Gustavo Nieves",
427
- "homepage": "https://medium.com/@ganieves"
428
- }
429
- ],
430
- "description": "Codeception module containing various assertions",
431
- "homepage": "https://codeception.com/",
432
- "keywords": [
433
- "assertions",
434
- "asserts",
435
- "codeception"
436
- ],
437
- "support": {
438
- "issues": "https://github.com/Codeception/module-asserts/issues",
439
- "source": "https://github.com/Codeception/module-asserts/tree/1.3.1"
440
- },
441
- "time": "2020-10-21T16:48:15+00:00"
442
- },
443
- {
444
- "name": "codeception/module-cli",
445
- "version": "1.1.1",
446
- "source": {
447
- "type": "git",
448
- "url": "https://github.com/Codeception/module-cli.git",
449
- "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f"
450
- },
451
- "dist": {
452
- "type": "zip",
453
- "url": "https://api.github.com/repos/Codeception/module-cli/zipball/1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f",
454
- "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f",
455
- "shasum": ""
456
- },
457
- "require": {
458
- "codeception/codeception": "*@dev",
459
- "php": ">=5.6.0 <9.0"
460
- },
461
- "conflict": {
462
- "codeception/codeception": "<4.0"
463
- },
464
- "type": "library",
465
- "autoload": {
466
- "classmap": [
467
- "src/"
468
- ]
469
- },
470
- "notification-url": "https://packagist.org/downloads/",
471
- "license": [
472
- "MIT"
473
- ],
474
- "authors": [
475
- {
476
- "name": "Michael Bodnarchuk"
477
- }
478
- ],
479
- "description": "Codeception module for testing basic shell commands and shell output",
480
- "homepage": "http://codeception.com/",
481
- "keywords": [
482
- "codeception"
483
- ],
484
- "support": {
485
- "issues": "https://github.com/Codeception/module-cli/issues",
486
- "source": "https://github.com/Codeception/module-cli/tree/1.1.1"
487
- },
488
- "time": "2020-12-26T16:56:19+00:00"
489
- },
490
- {
491
- "name": "codeception/module-db",
492
- "version": "1.1.0",
493
- "source": {
494
- "type": "git",
495
- "url": "https://github.com/Codeception/module-db.git",
496
- "reference": "8c8076cd05d4db95798acd7dba2a56578210982c"
497
- },
498
- "dist": {
499
- "type": "zip",
500
- "url": "https://api.github.com/repos/Codeception/module-db/zipball/8c8076cd05d4db95798acd7dba2a56578210982c",
501
- "reference": "8c8076cd05d4db95798acd7dba2a56578210982c",
502
- "shasum": ""
503
- },
504
- "require": {
505
- "codeception/codeception": "*@dev",
506
- "php": ">=5.6.0 <9.0"
507
- },
508
- "conflict": {
509
- "codeception/codeception": "<4.0"
510
- },
511
- "type": "library",
512
- "autoload": {
513
- "classmap": [
514
- "src/"
515
- ]
516
- },
517
- "notification-url": "https://packagist.org/downloads/",
518
- "license": [
519
- "MIT"
520
- ],
521
- "authors": [
522
- {
523
- "name": "Michael Bodnarchuk"
524
- },
525
- {
526
- "name": "Gintautas Miselis"
527
- }
528
- ],
529
- "description": "DB module for Codeception",
530
- "homepage": "http://codeception.com/",
531
- "keywords": [
532
- "codeception",
533
- "database-testing",
534
- "db-testing"
535
- ],
536
- "support": {
537
- "issues": "https://github.com/Codeception/module-db/issues",
538
- "source": "https://github.com/Codeception/module-db/tree/1.1.0"
539
- },
540
- "time": "2020-12-20T13:37:07+00:00"
541
- },
542
- {
543
- "name": "codeception/module-filesystem",
544
- "version": "1.0.3",
545
- "source": {
546
- "type": "git",
547
- "url": "https://github.com/Codeception/module-filesystem.git",
548
- "reference": "781be167fb1557bfc9b61e0a4eac60a32c534ec1"
549
- },
550
- "dist": {
551
- "type": "zip",
552
- "url": "https://api.github.com/repos/Codeception/module-filesystem/zipball/781be167fb1557bfc9b61e0a4eac60a32c534ec1",
553
- "reference": "781be167fb1557bfc9b61e0a4eac60a32c534ec1",
554
- "shasum": ""
555
- },
556
- "require": {
557
- "codeception/codeception": "^4.0",
558
- "php": ">=5.6.0 <9.0",
559
- "symfony/finder": ">=2.7 <6.0"
560
- },
561
- "conflict": {
562
- "codeception/codeception": "<4.0"
563
- },
564
- "type": "library",
565
- "autoload": {
566
- "classmap": [
567
- "src/"
568
- ]
569
- },
570
- "notification-url": "https://packagist.org/downloads/",
571
- "license": [
572
- "MIT"
573
- ],
574
- "authors": [
575
- {
576
- "name": "Michael Bodnarchuk"
577
- },
578
- {
579
- "name": "Gintautas Miselis"
580
- }
581
- ],
582
- "description": "Codeception module for testing local filesystem",
583
- "homepage": "http://codeception.com/",
584
- "keywords": [
585
- "codeception",
586
- "filesystem"
587
- ],
588
- "support": {
589
- "issues": "https://github.com/Codeception/module-filesystem/issues",
590
- "source": "https://github.com/Codeception/module-filesystem/tree/1.0.3"
591
- },
592
- "time": "2020-10-24T14:46:40+00:00"
593
- },
594
- {
595
- "name": "codeception/module-phpbrowser",
596
- "version": "1.0.2",
597
- "source": {
598
- "type": "git",
599
- "url": "https://github.com/Codeception/module-phpbrowser.git",
600
- "reference": "770a6be4160a5c0c08d100dd51bff35f6056bbf1"
601
- },
602
- "dist": {
603
- "type": "zip",
604
- "url": "https://api.github.com/repos/Codeception/module-phpbrowser/zipball/770a6be4160a5c0c08d100dd51bff35f6056bbf1",
605
- "reference": "770a6be4160a5c0c08d100dd51bff35f6056bbf1",
606
- "shasum": ""
607
- },
608
- "require": {
609
- "codeception/codeception": "^4.0",
610
- "codeception/lib-innerbrowser": "^1.3",
611
- "guzzlehttp/guzzle": "^6.3|^7.0",
612
- "php": ">=5.6.0 <9.0"
613
- },
614
- "conflict": {
615
- "codeception/codeception": "<4.0"
616
- },
617
- "require-dev": {
618
- "codeception/module-rest": "^1.0"
619
- },
620
- "suggest": {
621
- "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests"
622
- },
623
- "type": "library",
624
- "autoload": {
625
- "classmap": [
626
- "src/"
627
- ]
628
- },
629
- "notification-url": "https://packagist.org/downloads/",
630
- "license": [
631
- "MIT"
632
- ],
633
- "authors": [
634
- {
635
- "name": "Michael Bodnarchuk"
636
- },
637
- {
638
- "name": "Gintautas Miselis"
639
- }
640
- ],
641
- "description": "Codeception module for testing web application over HTTP",
642
- "homepage": "http://codeception.com/",
643
- "keywords": [
644
- "codeception",
645
- "functional-testing",
646
- "http"
647
- ],
648
- "support": {
649
- "issues": "https://github.com/Codeception/module-phpbrowser/issues",
650
- "source": "https://github.com/Codeception/module-phpbrowser/tree/1.0.2"
651
- },
652
- "time": "2020-10-24T15:29:28+00:00"
653
- },
654
- {
655
- "name": "codeception/module-rest",
656
- "version": "1.4.2",
657
- "source": {
658
- "type": "git",
659
- "url": "https://github.com/Codeception/module-rest.git",
660
- "reference": "9cd7a87fd9343494e7782f7bdb51687c25046917"
661
- },
662
- "dist": {
663
- "type": "zip",
664
- "url": "https://api.github.com/repos/Codeception/module-rest/zipball/9cd7a87fd9343494e7782f7bdb51687c25046917",
665
- "reference": "9cd7a87fd9343494e7782f7bdb51687c25046917",
666
- "shasum": ""
667
- },
668
- "require": {
669
- "codeception/codeception": "^4.0",
670
- "justinrainbow/json-schema": "~5.2.9",
671
- "php": ">=5.6.6 <9.0",
672
- "softcreatr/jsonpath": "^0.5 || ^0.7"
673
- },
674
- "require-dev": {
675
- "codeception/lib-innerbrowser": "^1.0",
676
- "codeception/util-universalframework": "^1.0"
677
- },
678
- "suggest": {
679
- "aws/aws-sdk-php": "For using AWS Auth"
680
- },
681
- "type": "library",
682
- "autoload": {
683
- "classmap": [
684
- "src/"
685
- ]
686
- },
687
- "notification-url": "https://packagist.org/downloads/",
688
- "license": [
689
- "MIT"
690
- ],
691
- "authors": [
692
- {
693
- "name": "Gintautas Miselis"
694
- }
695
- ],
696
- "description": "REST module for Codeception",
697
- "homepage": "http://codeception.com/",
698
- "keywords": [
699
- "codeception",
700
- "rest"
701
- ],
702
- "support": {
703
- "issues": "https://github.com/Codeception/module-rest/issues",
704
- "source": "https://github.com/Codeception/module-rest/tree/1.4.2"
705
- },
706
- "time": "2021-11-18T18:58:15+00:00"
707
- },
708
- {
709
- "name": "codeception/module-webdriver",
710
- "version": "1.4.0",
711
- "source": {
712
- "type": "git",
713
- "url": "https://github.com/Codeception/module-webdriver.git",
714
- "reference": "baa18b7bf70aa024012f967b5ce5021e1faa9151"
715
- },
716
- "dist": {
717
- "type": "zip",
718
- "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/baa18b7bf70aa024012f967b5ce5021e1faa9151",
719
- "reference": "baa18b7bf70aa024012f967b5ce5021e1faa9151",
720
- "shasum": ""
721
- },
722
- "require": {
723
- "codeception/codeception": "^4.0",
724
- "php": ">=5.6.0 <9.0",
725
- "php-webdriver/webdriver": "^1.8.0"
726
- },
727
- "suggest": {
728
- "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests"
729
- },
730
- "type": "library",
731
- "autoload": {
732
- "classmap": [
733
- "src/"
734
- ]
735
- },
736
- "notification-url": "https://packagist.org/downloads/",
737
- "license": [
738
- "MIT"
739
- ],
740
- "authors": [
741
- {
742
- "name": "Michael Bodnarchuk"
743
- },
744
- {
745
- "name": "Gintautas Miselis"
746
- },
747
- {
748
- "name": "Zaahid Bateson"
749
- }
750
- ],
751
- "description": "WebDriver module for Codeception",
752
- "homepage": "http://codeception.com/",
753
- "keywords": [
754
- "acceptance-testing",
755
- "browser-testing",
756
- "codeception"
757
- ],
758
- "support": {
759
- "issues": "https://github.com/Codeception/module-webdriver/issues",
760
- "source": "https://github.com/Codeception/module-webdriver/tree/1.4.0"
761
- },
762
- "time": "2021-09-02T12:01:02+00:00"
763
- },
764
- {
765
- "name": "codeception/phpunit-wrapper",
766
- "version": "9.0.6",
767
- "source": {
768
- "type": "git",
769
- "url": "https://github.com/Codeception/phpunit-wrapper.git",
770
- "reference": "b0c06abb3181eedca690170f7ed0fd26a70bfacc"
771
- },
772
- "dist": {
773
- "type": "zip",
774
- "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/b0c06abb3181eedca690170f7ed0fd26a70bfacc",
775
- "reference": "b0c06abb3181eedca690170f7ed0fd26a70bfacc",
776
- "shasum": ""
777
- },
778
- "require": {
779
- "php": ">=7.2",
780
- "phpunit/phpunit": "^9.0"
781
- },
782
- "require-dev": {
783
- "codeception/specify": "*",
784
- "consolidation/robo": "^3.0.0-alpha3",
785
- "vlucas/phpdotenv": "^3.0"
786
- },
787
- "type": "library",
788
- "autoload": {
789
- "psr-4": {
790
- "Codeception\\PHPUnit\\": "src/"
791
- }
792
- },
793
- "notification-url": "https://packagist.org/downloads/",
794
- "license": [
795
- "MIT"
796
- ],
797
- "authors": [
798
- {
799
- "name": "Davert",
800
- "email": "davert.php@resend.cc"
801
- },
802
- {
803
- "name": "Naktibalda"
804
- }
805
- ],
806
- "description": "PHPUnit classes used by Codeception",
807
- "support": {
808
- "issues": "https://github.com/Codeception/phpunit-wrapper/issues",
809
- "source": "https://github.com/Codeception/phpunit-wrapper/tree/9.0.6"
810
- },
811
- "time": "2020-12-28T13:59:47+00:00"
812
- },
813
- {
814
- "name": "codeception/stub",
815
- "version": "3.7.0",
816
- "source": {
817
- "type": "git",
818
- "url": "https://github.com/Codeception/Stub.git",
819
- "reference": "468dd5fe659f131fc997f5196aad87512f9b1304"
820
- },
821
- "dist": {
822
- "type": "zip",
823
- "url": "https://api.github.com/repos/Codeception/Stub/zipball/468dd5fe659f131fc997f5196aad87512f9b1304",
824
- "reference": "468dd5fe659f131fc997f5196aad87512f9b1304",
825
- "shasum": ""
826
- },
827
- "require": {
828
- "phpunit/phpunit": "^8.4 | ^9.0"
829
- },
830
- "type": "library",
831
- "autoload": {
832
- "psr-4": {
833
- "Codeception\\": "src/"
834
- }
835
- },
836
- "notification-url": "https://packagist.org/downloads/",
837
- "license": [
838
- "MIT"
839
- ],
840
- "description": "Flexible Stub wrapper for PHPUnit's Mock Builder",
841
- "support": {
842
- "issues": "https://github.com/Codeception/Stub/issues",
843
- "source": "https://github.com/Codeception/Stub/tree/3.7.0"
844
- },
845
- "time": "2020-07-03T15:54:43+00:00"
846
- },
847
- {
848
- "name": "codeception/util-universalframework",
849
- "version": "1.0.0",
850
- "source": {
851
- "type": "git",
852
- "url": "https://github.com/Codeception/util-universalframework.git",
853
- "reference": "cc381f364c6d24f9b9c7b70a4c724949725f491a"
854
- },
855
- "dist": {
856
- "type": "zip",
857
- "url": "https://api.github.com/repos/Codeception/util-universalframework/zipball/cc381f364c6d24f9b9c7b70a4c724949725f491a",
858
- "reference": "cc381f364c6d24f9b9c7b70a4c724949725f491a",
859
- "shasum": ""
860
- },
861
- "type": "library",
862
- "autoload": {
863
- "classmap": [
864
- "src/"
865
- ]
866
- },
867
- "notification-url": "https://packagist.org/downloads/",
868
- "license": [
869
- "MIT"
870
- ],
871
- "authors": [
872
- {
873
- "name": "Gintautas Miselis"
874
- }
875
- ],
876
- "description": "Mock framework module used in internal Codeception tests",
877
- "homepage": "http://codeception.com/",
878
- "support": {
879
- "issues": "https://github.com/Codeception/util-universalframework/issues",
880
- "source": "https://github.com/Codeception/util-universalframework/tree/1.0.0"
881
- },
882
- "time": "2019-09-22T06:06:49+00:00"
883
- },
884
- {
885
- "name": "composer/semver",
886
- "version": "3.2.6",
887
- "source": {
888
- "type": "git",
889
- "url": "https://github.com/composer/semver.git",
890
- "reference": "83e511e247de329283478496f7a1e114c9517506"
891
- },
892
- "dist": {
893
- "type": "zip",
894
- "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506",
895
- "reference": "83e511e247de329283478496f7a1e114c9517506",
896
- "shasum": ""
897
- },
898
- "require": {
899
- "php": "^5.3.2 || ^7.0 || ^8.0"
900
- },
901
- "require-dev": {
902
- "phpstan/phpstan": "^0.12.54",
903
- "symfony/phpunit-bridge": "^4.2 || ^5"
904
- },
905
- "type": "library",
906
- "extra": {
907
- "branch-alias": {
908
- "dev-main": "3.x-dev"
909
- }
910
- },
911
- "autoload": {
912
- "psr-4": {
913
- "Composer\\Semver\\": "src"
914
- }
915
- },
916
- "notification-url": "https://packagist.org/downloads/",
917
- "license": [
918
- "MIT"
919
- ],
920
- "authors": [
921
- {
922
- "name": "Nils Adermann",
923
- "email": "naderman@naderman.de",
924
- "homepage": "http://www.naderman.de"
925
- },
926
- {
927
- "name": "Jordi Boggiano",
928
- "email": "j.boggiano@seld.be",
929
- "homepage": "http://seld.be"
930
- },
931
- {
932
- "name": "Rob Bast",
933
- "email": "rob.bast@gmail.com",
934
- "homepage": "http://robbast.nl"
935
- }
936
- ],
937
- "description": "Semver library that offers utilities, version constraint parsing and validation.",
938
- "keywords": [
939
- "semantic",
940
- "semver",
941
- "validation",
942
- "versioning"
943
- ],
944
- "support": {
945
- "irc": "irc://irc.freenode.org/composer",
946
- "issues": "https://github.com/composer/semver/issues",
947
- "source": "https://github.com/composer/semver/tree/3.2.6"
948
- },
949
- "funding": [
950
- {
951
- "url": "https://packagist.com",
952
- "type": "custom"
953
- },
954
- {
955
- "url": "https://github.com/composer",
956
- "type": "github"
957
- },
958
- {
959
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
960
- "type": "tidelift"
961
- }
962
- ],
963
- "time": "2021-10-25T11:34:17+00:00"
964
- },
965
- {
966
- "name": "composer/xdebug-handler",
967
- "version": "2.0.2",
968
- "source": {
969
- "type": "git",
970
- "url": "https://github.com/composer/xdebug-handler.git",
971
- "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
972
- },
973
- "dist": {
974
- "type": "zip",
975
- "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
976
- "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
977
- "shasum": ""
978
- },
979
- "require": {
980
- "php": "^5.3.2 || ^7.0 || ^8.0",
981
- "psr/log": "^1 || ^2 || ^3"
982
- },
983
- "require-dev": {
984
- "phpstan/phpstan": "^0.12.55",
985
- "symfony/phpunit-bridge": "^4.2 || ^5"
986
- },
987
- "type": "library",
988
- "autoload": {
989
- "psr-4": {
990
- "Composer\\XdebugHandler\\": "src"
991
- }
992
- },
993
- "notification-url": "https://packagist.org/downloads/",
994
- "license": [
995
- "MIT"
996
- ],
997
- "authors": [
998
- {
999
- "name": "John Stevenson",
1000
- "email": "john-stevenson@blueyonder.co.uk"
1001
- }
1002
- ],
1003
- "description": "Restarts a process without Xdebug.",
1004
- "keywords": [
1005
- "Xdebug",
1006
- "performance"
1007
- ],
1008
- "support": {
1009
- "irc": "irc://irc.freenode.org/composer",
1010
- "issues": "https://github.com/composer/xdebug-handler/issues",
1011
- "source": "https://github.com/composer/xdebug-handler/tree/2.0.2"
1012
- },
1013
- "funding": [
1014
- {
1015
- "url": "https://packagist.com",
1016
- "type": "custom"
1017
- },
1018
- {
1019
- "url": "https://github.com/composer",
1020
- "type": "github"
1021
- },
1022
- {
1023
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
1024
- "type": "tidelift"
1025
- }
1026
- ],
1027
- "time": "2021-07-31T17:03:58+00:00"
1028
- },
1029
- {
1030
- "name": "consolidation/annotated-command",
1031
- "version": "4.4.0",
1032
- "source": {
1033
- "type": "git",
1034
- "url": "https://github.com/consolidation/annotated-command.git",
1035
- "reference": "308f6ac178566a1ce9aa90ed908dac90a2c1e707"
1036
- },
1037
- "dist": {
1038
- "type": "zip",
1039
- "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/308f6ac178566a1ce9aa90ed908dac90a2c1e707",
1040
- "reference": "308f6ac178566a1ce9aa90ed908dac90a2c1e707",
1041
- "shasum": ""
1042
- },
1043
- "require": {
1044
- "consolidation/output-formatters": "^4.1.1",
1045
- "php": ">=7.1.3",
1046
- "psr/log": "^1|^2",
1047
- "symfony/console": "^4.4.8|~5.1.0",
1048
- "symfony/event-dispatcher": "^4.4.8|^5",
1049
- "symfony/finder": "^4.4.8|^5"
1050
- },
1051
- "require-dev": {
1052
- "phpunit/phpunit": "^7.5.20 || ^8 || ^9",
1053
- "squizlabs/php_codesniffer": "^3",
1054
- "yoast/phpunit-polyfills": "^0.2.0"
1055
- },
1056
- "type": "library",
1057
- "extra": {
1058
- "branch-alias": {
1059
- "dev-main": "4.x-dev"
1060
- }
1061
- },
1062
- "autoload": {
1063
- "psr-4": {
1064
- "Consolidation\\AnnotatedCommand\\": "src"
1065
- }
1066
- },
1067
- "notification-url": "https://packagist.org/downloads/",
1068
- "license": [
1069
- "MIT"
1070
- ],
1071
- "authors": [
1072
- {
1073
- "name": "Greg Anderson",
1074
- "email": "greg.1.anderson@greenknowe.org"
1075
- }
1076
- ],
1077
- "description": "Initialize Symfony Console commands from annotated command class methods.",
1078
- "support": {
1079
- "issues": "https://github.com/consolidation/annotated-command/issues",
1080
- "source": "https://github.com/consolidation/annotated-command/tree/4.4.0"
1081
- },
1082
- "time": "2021-09-30T01:08:15+00:00"
1083
- },
1084
- {
1085
- "name": "consolidation/config",
1086
- "version": "2.0.1",
1087
- "source": {
1088
- "type": "git",
1089
- "url": "https://github.com/consolidation/config.git",
1090
- "reference": "9a2c2a7b2aea1b3525984a4378743a8b74c14e1c"
1091
- },
1092
- "dist": {
1093
- "type": "zip",
1094
- "url": "https://api.github.com/repos/consolidation/config/zipball/9a2c2a7b2aea1b3525984a4378743a8b74c14e1c",
1095
- "reference": "9a2c2a7b2aea1b3525984a4378743a8b74c14e1c",
1096
- "shasum": ""
1097
- },
1098
- "require": {
1099
- "dflydev/dot-access-data": "^1.1.0",
1100
- "grasmash/expander": "^1",
1101
- "php": ">=7.1.3",
1102
- "psr/log": "^1.1",
1103
- "symfony/event-dispatcher": "^4||^5"
1104
- },
1105
- "require-dev": {
1106
- "phpunit/phpunit": ">=7.5.20",
1107
- "squizlabs/php_codesniffer": "^3",
1108
- "symfony/console": "^4||^5",
1109
- "symfony/yaml": "^4||^5",
1110
- "yoast/phpunit-polyfills": "^0.2.0"
1111
- },
1112
- "suggest": {
1113
- "symfony/event-dispatcher": "Required to inject configuration into Command options",
1114
- "symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader"
1115
- },
1116
- "type": "library",
1117
- "extra": {
1118
- "branch-alias": {
1119
- "dev-main": "2.x-dev"
1120
- }
1121
- },
1122
- "autoload": {
1123
- "psr-4": {
1124
- "Consolidation\\Config\\": "src"
1125
- }
1126
- },
1127
- "notification-url": "https://p