YITH WooCommerce Catalog Mode - Version 1.0.0

Version Description

  • Initial release

=

Download this release

Release Info

Developer yithemes
Plugin Icon 128x128 YITH WooCommerce Catalog Mode
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

Files changed (138) hide show
  1. assets/css/yith-catalog-mode.css +3 -0
  2. class.yith-woocommerce-catalog-mode.php +383 -0
  3. init.php +104 -0
  4. languages/default.po +1031 -0
  5. languages/ywctm.pot +1029 -0
  6. plugin-fw/assets/css/chosen/chosen.css +435 -0
  7. plugin-fw/assets/css/codemirror/codemirror.css +260 -0
  8. plugin-fw/assets/css/metaboxes.css +598 -0
  9. plugin-fw/assets/css/overcast/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  10. plugin-fw/assets/css/overcast/images/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  11. plugin-fw/assets/css/overcast/images/ui-bg_flat_55_c0402a_40x100.png +0 -0
  12. plugin-fw/assets/css/overcast/images/ui-bg_flat_55_eeeeee_40x100.png +0 -0
  13. plugin-fw/assets/css/overcast/images/ui-bg_glass_100_f8f8f8_1x400.png +0 -0
  14. plugin-fw/assets/css/overcast/images/ui-bg_glass_35_dddddd_1x400.png +0 -0
  15. plugin-fw/assets/css/overcast/images/ui-bg_glass_60_eeeeee_1x400.png +0 -0
  16. plugin-fw/assets/css/overcast/images/ui-bg_inset-hard_75_999999_1x100.png +0 -0
  17. plugin-fw/assets/css/overcast/images/ui-bg_inset-soft_50_c9c9c9_1x100.png +0 -0
  18. plugin-fw/assets/css/overcast/images/ui-icons_3383bb_256x240.png +0 -0
  19. plugin-fw/assets/css/overcast/images/ui-icons_454545_256x240.png +0 -0
  20. plugin-fw/assets/css/overcast/images/ui-icons_70b2e1_256x240.png +0 -0
  21. plugin-fw/assets/css/overcast/images/ui-icons_999999_256x240.png +0 -0
  22. plugin-fw/assets/css/overcast/images/ui-icons_fbc856_256x240.png +0 -0
  23. plugin-fw/assets/css/overcast/jquery-ui-1.8.9.custom.css +322 -0
  24. plugin-fw/assets/css/yit-plugin-panel.css +614 -0
  25. plugin-fw/assets/css/yit-upgrader.css +14 -0
  26. plugin-fw/assets/images/chosen/chosen-sprite.png +0 -0
  27. plugin-fw/assets/images/chosen/chosen-sprite@2x.png +0 -0
  28. plugin-fw/assets/images/double-sidebar.png +0 -0
  29. plugin-fw/assets/images/licence-error.png +0 -0
  30. plugin-fw/assets/images/no-sidebar.png +0 -0
  31. plugin-fw/assets/images/off.png +0 -0
  32. plugin-fw/assets/images/on.png +0 -0
  33. plugin-fw/assets/images/select.png +0 -0
  34. plugin-fw/assets/images/sidebar-left.png +0 -0
  35. plugin-fw/assets/images/sidebar-right.png +0 -0
  36. plugin-fw/assets/images/sleep.png +0 -0
  37. plugin-fw/assets/images/slider/grey.gif +0 -0
  38. plugin-fw/assets/images/slider/handle.png +0 -0
  39. plugin-fw/assets/images/slider/orange.gif +0 -0
  40. plugin-fw/assets/images/slider/tooltip.png +0 -0
  41. plugin-fw/assets/images/spinner.png +0 -0
  42. plugin-fw/assets/images/ui-icons_222222_256x240.png +0 -0
  43. plugin-fw/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  44. plugin-fw/assets/images/ui-icons_454545_256x240.png +0 -0
  45. plugin-fw/assets/images/ui-icons_888888_256x240.png +0 -0
  46. plugin-fw/assets/images/x.png +0 -0
  47. plugin-fw/assets/images/yithemes-icon.png +0 -0
  48. plugin-fw/assets/js/chosen/chosen.jquery.js +1211 -0
  49. plugin-fw/assets/js/codemirror/codemirror.js +5799 -0
  50. plugin-fw/assets/js/codemirror/javascript.js +630 -0
  51. plugin-fw/assets/js/metabox.js +350 -0
  52. plugin-fw/assets/js/metabox.min.js +11 -0
  53. plugin-fw/assets/js/multisite-updater.js +216 -0
  54. plugin-fw/assets/js/multisite-updater.min.js +4 -0
  55. plugin-fw/assets/js/panel.spinner.js +139 -0
  56. plugin-fw/assets/js/panel.spinner.min.js +3 -0
  57. plugin-fw/assets/js/yit-cpt-unlimited.js +79 -0
  58. plugin-fw/assets/js/yit-cpt-unlimited.min.js +2 -0
  59. plugin-fw/assets/js/yit-cptu-sortable-posts.js +32 -0
  60. plugin-fw/assets/js/yit-plugin-panel.js +286 -0
  61. plugin-fw/assets/js/yit-plugin-panel.min.js +9 -0
  62. plugin-fw/assets/js/yit-wp-pointer.js +84 -0
  63. plugin-fw/assets/js/yit-wp-pointer.min.js +3 -0
  64. plugin-fw/lib/yit-cpt-unlimited.php +1775 -0
  65. plugin-fw/lib/yit-metabox.php +537 -0
  66. plugin-fw/lib/yit-plugin-common.php +1034 -0
  67. plugin-fw/lib/yit-plugin-gradients.php +536 -0
  68. plugin-fw/lib/yit-plugin-panel-wc.php +341 -0
  69. plugin-fw/lib/yit-plugin-panel.php +710 -0
  70. plugin-fw/lib/yit-plugin-subpanel.php +160 -0
  71. plugin-fw/lib/yit-pointers.php +390 -0
  72. plugin-fw/lib/yit-upgrade.php +538 -0
  73. plugin-fw/lib/yit-video.php +184 -0
  74. plugin-fw/licence/assets/css/yit-licence.css +337 -0
  75. plugin-fw/licence/assets/images/licence-error.png +0 -0
  76. plugin-fw/licence/assets/js/yit-licence.js +139 -0
  77. plugin-fw/licence/assets/js/yit-licence.min.js +4 -0
  78. plugin-fw/licence/lib/yit-licence.php +543 -0
  79. plugin-fw/licence/lib/yit-plugin-licence.php +156 -0
  80. plugin-fw/licence/lib/yit-theme-licence.php +155 -0
  81. plugin-fw/licence/templates/panel/activation/activation-panel.php +153 -0
  82. plugin-fw/templates/metaboxes/tab.php +64 -0
  83. plugin-fw/templates/metaboxes/types/ajax-products.php +64 -0
  84. plugin-fw/templates/metaboxes/types/categories.php +88 -0
  85. plugin-fw/templates/metaboxes/types/checkbox.php +23 -0
  86. plugin-fw/templates/metaboxes/types/chosen.php +32 -0
  87. plugin-fw/templates/metaboxes/types/colorpicker.php +22 -0
  88. plugin-fw/templates/metaboxes/types/contactform.php +553 -0
  89. plugin-fw/templates/metaboxes/types/customtabs.php +152 -0
  90. plugin-fw/templates/metaboxes/types/datepicker.php +21 -0
  91. plugin-fw/templates/metaboxes/types/hidden.php +18 -0
  92. plugin-fw/templates/metaboxes/types/icon-list.php +135 -0
  93. plugin-fw/templates/metaboxes/types/image-gallery.php +43 -0
  94. plugin-fw/templates/metaboxes/types/images.php +85 -0
  95. plugin-fw/templates/metaboxes/types/number.php +37 -0
  96. plugin-fw/templates/metaboxes/types/onoff.php +43 -0
  97. plugin-fw/templates/metaboxes/types/responsivesliders.php +31 -0
  98. plugin-fw/templates/metaboxes/types/select-icon.php +72 -0
  99. plugin-fw/templates/metaboxes/types/select-mailchimp.php +32 -0
  100. plugin-fw/templates/metaboxes/types/select.php +32 -0
  101. plugin-fw/templates/metaboxes/types/sep.php +18 -0
  102. plugin-fw/templates/metaboxes/types/sidebar-layout.php +61 -0
  103. plugin-fw/templates/metaboxes/types/sidebarlist.php +29 -0
  104. plugin-fw/templates/metaboxes/types/sidebars.php +124 -0
  105. plugin-fw/templates/metaboxes/types/simple-text.php +20 -0
  106. plugin-fw/templates/metaboxes/types/slider.php +35 -0
  107. plugin-fw/templates/metaboxes/types/text-array.php +30 -0
  108. plugin-fw/templates/metaboxes/types/text.php +24 -0
  109. plugin-fw/templates/metaboxes/types/textarea-editor.php +42 -0
  110. plugin-fw/templates/metaboxes/types/textarea.php +25 -0
  111. plugin-fw/templates/metaboxes/types/title.php +18 -0
  112. plugin-fw/templates/metaboxes/types/typography.php +255 -0
  113. plugin-fw/templates/metaboxes/types/upload.php +24 -0
  114. plugin-fw/templates/panel/types/chosen.php +36 -0
  115. plugin-fw/templates/panel/types/connected-list.php +27 -0
  116. plugin-fw/templates/panel/types/layout-panel.php +0 -0
  117. plugin-fw/templates/panel/types/on-off.php +34 -0
  118. plugin-fw/templates/panel/types/select-mailchimp.php +36 -0
  119. plugin-fw/templates/panel/types/select.php +41 -0
  120. plugin-fw/templates/panel/types/slider.php +40 -0
  121. plugin-fw/templates/panel/types/text-button.php +36 -0
  122. plugin-fw/templates/panel/types/text.php +35 -0
  123. plugin-fw/templates/panel/types/textarea-codemirror.php +40 -0
  124. plugin-fw/templates/panel/types/textarea.php +35 -0
  125. plugin-fw/templates/panel/types/upload.php +45 -0
  126. plugin-fw/templates/panel/woocommerce/woocommerce-boxinfo.php +36 -0
  127. plugin-fw/templates/panel/woocommerce/woocommerce-form.php +12 -0
  128. plugin-fw/templates/panel/woocommerce/woocommerce-panel.php +12 -0
  129. plugin-fw/templates/panel/woocommerce/woocommerce-upload.php +52 -0
  130. plugin-fw/templates/panel/woocommerce/woocommerce-videobox.php +83 -0
  131. plugin-fw/yit-deactive-plugin.php +35 -0
  132. plugin-fw/yit-functions.php +819 -0
  133. plugin-fw/yit-plugin-registration-hook.php +23 -0
  134. plugin-fw/yit-plugin.php +46 -0
  135. plugin-options/premium-landing-options.php +23 -0
  136. plugin-options/settings-options.php +109 -0
  137. readme.txt +76 -0
  138. screenshot-1.jpg +0 -0
assets/css/yith-catalog-mode.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ .widget.woocommerce.widget_shopping_cart{
2
+ display: none !important;
3
+ }
class.yith-woocommerce-catalog-mode.php ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ /**
8
+ * Implements features of YITH WooCommerce Catalog Mode plugin
9
+ *
10
+ * @class YITH_WC_Catalog_Mode
11
+ * @package Yithemes
12
+ * @since 1.0.0
13
+ * @author Your Inspiration Themes
14
+ */
15
+ class YITH_WC_Catalog_Mode {
16
+
17
+ /**
18
+ * @var $_panel Panel Object
19
+ */
20
+ protected $_panel;
21
+
22
+ /**
23
+ * @var $_premium string Premium tab template file name
24
+ */
25
+ protected $_premium = 'premium.php';
26
+
27
+ /**
28
+ * @var string Premium version landing link
29
+ */
30
+ protected $_premium_landing = 'http://yithemes.com/themes/plugins/yith-woocommerce-catalog-mode/';
31
+
32
+ /**
33
+ * @var string Plugin official documentation
34
+ */
35
+ protected $_official_documentation = 'http://yithemes.com/docs-plugins/yith-woocommerce-catalog-mode/';
36
+
37
+ /**
38
+ * @var string Yith WooCommerce Catalog Mode panel page
39
+ */
40
+ protected $_panel_page = 'yith_wc_catalog_mode_panel';
41
+
42
+ /**
43
+ * Constructor
44
+ *
45
+ * Initialize plugin and registers actions and filters to be used
46
+ *
47
+ * @since 1.0
48
+ * @author Alberto Ruggiero
49
+ */
50
+ public function __construct() {
51
+ if ( ! function_exists( 'WC' ) ) {
52
+ return;
53
+ }
54
+
55
+ // Load Plugin Framework
56
+ add_action( 'after_setup_theme', array( $this, 'plugin_fw_loader' ), 1 );
57
+
58
+ //Add action links
59
+ add_filter( 'plugin_action_links_' . plugin_basename( YWCTM_DIR . '/' . basename( YWCTM_FILE ) ), array(
60
+ $this,
61
+ 'action_links'
62
+ ) );
63
+
64
+ add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 4 );
65
+
66
+ // Add stylesheets and scripts files
67
+ add_action( 'admin_menu', array( $this, 'add_menu_page' ), 5 );
68
+ add_action( 'yith_catalog_mode_premium', array( $this, 'premium_tab' ) );
69
+
70
+ if ( get_option( 'ywctm_enable_plugin' ) == 'yes' ){
71
+
72
+ if ( !( current_user_can( 'administrator' ) && is_user_logged_in() && get_option( 'ywctm_admin_view' ) == 'no' ) ){
73
+
74
+ add_action( 'init', array( $this, 'check_pages_status' ) );
75
+
76
+ if ( ! is_admin() ) {
77
+
78
+ if ( get_option( 'ywctm_hide_add_to_cart_single' ) == 'yes' ) {
79
+ add_action( 'woocommerce_single_product_summary',array( $this, 'hide_add_to_cart_single' ), 10 );
80
+ }
81
+
82
+ if ( get_option( 'ywctm_hide_add_to_cart_loop' ) == 'yes' ) {
83
+ add_action( 'woocommerce_after_shop_loop_item',array( $this, 'hide_add_to_cart_loop' ), 5 );
84
+ }
85
+
86
+ if ( get_option( 'ywctm_hide_cart_header' ) == 'yes' ) {
87
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
88
+ }
89
+ }
90
+
91
+ }
92
+ }
93
+ else {
94
+ self::reactivate_hidden_pages();
95
+ }
96
+
97
+ }
98
+
99
+ /**
100
+ * Hides "Add to cart" button, if not excluded, from single product page
101
+ *
102
+ * @since 1.0
103
+ * @author Alberto Ruggiero
104
+ * @return void
105
+ */
106
+ public function hide_add_to_cart_single(){
107
+ global $post;
108
+
109
+ $exclude_catalog = get_post_meta( $post->ID, '_ywctm_exclude_catalog_mode', true );
110
+ $enable_exclusion = get_option( 'ywctm_exclude_hide_add_to_cart' );
111
+
112
+ if ( $enable_exclusion == '' || $enable_exclusion == 'no' ) {
113
+
114
+ remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
115
+
116
+ } else {
117
+
118
+ if ( $exclude_catalog == '' || $exclude_catalog == 'no' ) {
119
+ remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
120
+ }
121
+
122
+ }
123
+
124
+ }
125
+
126
+ /**
127
+ * Hides "Add to cart" button, if not excluded, from loop page
128
+ *
129
+ * @since 1.0
130
+ * @author Alberto Ruggiero
131
+ * @return void
132
+ */
133
+ public function hide_add_to_cart_loop(){
134
+ global $post;
135
+
136
+ $exclude_catalog = get_post_meta( $post->ID, '_ywctm_exclude_catalog_mode', true );
137
+ $enable_exclusion = get_option( 'ywctm_exclude_hide_add_to_cart' );
138
+
139
+ if ( $enable_exclusion == '' || $enable_exclusion == 'no' ) {
140
+
141
+ remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
142
+
143
+ } else {
144
+
145
+ if ( $exclude_catalog == '' || $exclude_catalog == 'no' ) {
146
+ remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
147
+ }
148
+ else {
149
+ add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
150
+ }
151
+ }
152
+
153
+ }
154
+
155
+ /**
156
+ * Enqueue css file
157
+ *
158
+ * @since 1.0
159
+ * @author Alberto Ruggiero
160
+ * @return void
161
+ */
162
+ public function enqueue_styles() {
163
+ wp_enqueue_style( 'yit-style', YWCTM_ASSETS_URL . '/css/yith-catalog-mode.css' );
164
+ }
165
+
166
+ /**
167
+ * Hides Cart and Checkout pages if option selected, otherwise shows them
168
+ *
169
+ * @since 1.0
170
+ * @author Alberto Ruggiero
171
+ * @return void
172
+ */
173
+ public function check_pages_status(){
174
+
175
+ $pages_to_check = array(
176
+ get_option( 'woocommerce_cart_page_id' ),
177
+ get_option( 'woocommerce_checkout_page_id' )
178
+ );
179
+
180
+ if ( get_option( 'ywctm_hide_cart_header' ) == 'yes' ) {
181
+
182
+ foreach ( $pages_to_check as $page_id ) {
183
+ if ( get_post_status( $page_id ) != 'draft' ) {
184
+ $page = array(
185
+ 'ID' => $page_id,
186
+ 'post_status' => 'draft'
187
+ );
188
+
189
+ wp_update_post( $page );
190
+ }
191
+ }
192
+
193
+ } else {
194
+
195
+ foreach ( $pages_to_check as $page_id ) {
196
+ if ( get_post_status ( $page_id ) != 'publish' ) {
197
+ $page = array(
198
+ 'ID' => $page_id,
199
+ 'post_status' => 'publish'
200
+ );
201
+
202
+ wp_update_post( $page );
203
+ }
204
+ }
205
+
206
+ }
207
+
208
+ }
209
+
210
+ /**
211
+ * Enqueue css file
212
+ *
213
+ * @since 1.0
214
+ * @access public
215
+ * @return void
216
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
217
+ */
218
+ public function plugin_fw_loader() {
219
+ if ( ! defined( 'YIT' ) || ! defined( 'YIT_CORE_PLUGIN' ) ) {
220
+ require_once( 'plugin-fw/yit-plugin.php' );
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Add a panel under YITH Plugins tab
226
+ *
227
+ * @return void
228
+ * @since 1.0
229
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
230
+ * @use /Yit_Plugin_Panel class
231
+ * @see plugin-fw/lib/yit-plugin-panel.php
232
+ */
233
+ public function add_menu_page() {
234
+ if ( ! empty( $this->_panel ) ) {
235
+ return;
236
+ }
237
+
238
+ $admin_tabs = array(
239
+ 'settings' => __( 'Settings', 'ywctm' ),
240
+ );
241
+
242
+ if ( defined( 'YWCTM_PREMIUM' ) ) {
243
+ $admin_tabs['premium'] = __( 'Premium Settings', 'ywctm' );
244
+ $admin_tabs['exclusions'] = __( 'Exclusions List', 'ywctm' );
245
+ } else {
246
+ // $admin_tabs['premium-landing'] = __( 'Premium Version', 'ywctm' );
247
+ }
248
+
249
+ $args = array(
250
+ 'create_menu_page' => true,
251
+ 'parent_slug' => '',
252
+ 'page_title' => __( 'Catalog Mode', 'ywctm' ),
253
+ 'menu_title' => __( 'Catalog Mode', 'ywctm' ),
254
+ 'capability' => 'manage_options',
255
+ 'parent' => '',
256
+ 'parent_page' => 'yit_plugin_panel',
257
+ 'page' => $this->_panel_page,
258
+ 'admin-tabs' => $admin_tabs,
259
+ 'options-path' => YWCTM_DIR . '/plugin-options'
260
+ );
261
+
262
+ $this->_panel = new YIT_Plugin_Panel_WooCommerce( $args );
263
+ }
264
+
265
+ /**
266
+ * Premium Tab Template
267
+ *
268
+ * Load the premium tab template on admin page
269
+ *
270
+ * @since 1.0
271
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
272
+ * @return void
273
+ */
274
+ public function premium_tab() {
275
+ $premium_tab_template = YWCTM_TEMPLATE_PATH . '/admin/' . $this->_premium;
276
+ if ( file_exists( $premium_tab_template ) ) {
277
+ include_once( $premium_tab_template );
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Action Links
283
+ *
284
+ * add the action links to plugin admin page
285
+ *
286
+ * @param $links | links plugin array
287
+ *
288
+ * @return mixed Array
289
+ * @since 1.0
290
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
291
+ * @return mixed
292
+ * @use plugin_action_links_{$plugin_file_name}
293
+ */
294
+ public function action_links( $links ) {
295
+
296
+ $links[] = '<a href="' . admin_url( "admin.php?page={$this->_panel_page}" ) . '">' . __( 'Settings', 'ywctm' ) . '</a>';
297
+
298
+ if ( defined( 'YWCTM_FREE_INIT' ) ) {
299
+ // $links[] = '<a href="' . $this->_premium_landing . '" target="_blank">' . __( 'Premium Version', 'ywctm' ) . '</a>';
300
+ }
301
+
302
+ return $links;
303
+ }
304
+
305
+ /**
306
+ * plugin_row_meta
307
+ *
308
+ * add the action links to plugin admin page
309
+ *
310
+ * @param $plugin_meta
311
+ * @param $plugin_file
312
+ * @param $plugin_data
313
+ * @param $status
314
+ *
315
+ * @return Array
316
+ * @since 1.0
317
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
318
+ * @use plugin_row_meta
319
+ */
320
+ public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $status ) {
321
+ if ( ( defined( 'YWCTM_INIT' ) && ( YWCTM_INIT == $plugin_file ) ) ||
322
+ ( defined( 'YWCTM_FREE_INIT' ) && ( YWCTM_FREE_INIT == $plugin_file ) )
323
+ ) {
324
+
325
+ $plugin_meta[] = '<a href="' . $this->_official_documentation . '" target="_blank">' . __( 'Plugin Documentation', 'ywctm' ) . '</a>';
326
+ }
327
+
328
+ return $plugin_meta;
329
+ }
330
+
331
+ public function register_pointer() {
332
+ if ( ! class_exists( 'YIT_Pointers' ) ) {
333
+
334
+ include_once( 'plugin-fw/lib/yit-pointers.php' );
335
+ }
336
+
337
+ $premium_message = defined( 'YWCTM_PREMIUM' )
338
+ ? ''
339
+ : __( 'YITH WooCommerce Catalog Mode is available in an outstanding PREMIUM version with many new options, discover it now.', 'ywctm' ) .
340
+ ' <a href="' . $this->_premium_landing . '">' . __( 'Premium version', 'ywctm' ) . '</a>';
341
+
342
+ $args[] = array(
343
+ 'screen_id' => 'plugins',
344
+ 'pointer_id' => $this->_panel_page,
345
+ 'target' => '#toplevel_page_yit_plugin_panel',
346
+ 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
347
+ __( 'YITH WooCommerce Catalog Mode', 'ywctm' ),
348
+ __( 'In the YIT Plugins tab you can find the YITH WooCommerce Catalog Mode options. With this menu, you can access to all the settings of our plugins that you have activated.', 'ywctm' ) . '<br>' . $premium_message
349
+ ),
350
+ 'position' => array( 'edge' => 'left', 'align' => 'center' ),
351
+ 'init' => defined( 'YWCTM_PREMIUM' ) ? YWCTM_INIT : YWCTM_FREE_INIT
352
+ );
353
+
354
+ YIT_Pointers()->register( $args );
355
+ }
356
+
357
+ /**
358
+ * On plugin deactivation, publish cart and checkout pages if se to draft
359
+ *
360
+ * @since 1.0.0
361
+ * @author Alberto Ruggiero
362
+ * @return void
363
+ */
364
+ static function reactivate_hidden_pages () {
365
+
366
+ $pages_to_check = array(
367
+ get_option( 'woocommerce_cart_page_id' ),
368
+ get_option( 'woocommerce_checkout_page_id' )
369
+ );
370
+
371
+ foreach ( $pages_to_check as $page_id ) {
372
+ if ( get_post_status ( $page_id ) != 'publish' ) {
373
+ $page = array(
374
+ 'ID' => $page_id,
375
+ 'post_status' => 'publish'
376
+ );
377
+
378
+ wp_update_post( $page );
379
+ }
380
+ }
381
+ }
382
+
383
+ }
init.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: YITH WooCommerce Catalog Mode
4
+ Plugin URI: http://yithemes.com/themes/plugins/yith-woocommerce-catalog-mode/
5
+ Description: YITH Woocommerce Catalog Mode allows you to disable shop functions.
6
+ Author: Yithemes
7
+ Text Domain: ywctm
8
+ Version: 1.0.0
9
+ Author URI: http://yithemes.com/
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ } // Exit if accessed directly
15
+
16
+ if ( ! function_exists( 'is_plugin_active' ) ) {
17
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
18
+ }
19
+
20
+ function ywctm_install_woocommerce_admin_notice() {
21
+ ?>
22
+ <div class="error">
23
+ <p><?php _e( 'YITH WooCommerce Catalog Mode is enabled but not effective. It requires Woocommerce in order to work.', 'ywctm' ); ?></p>
24
+ </div>
25
+ <?php
26
+ }
27
+
28
+ function ywctm_install_free_admin_notice() {
29
+ ?>
30
+ <div class="error">
31
+ <p><?php _e( 'You can\'t activate the free version of YITH WooCommerce Catalog Mode while you are using the premium one.', 'ywctm' ); ?></p>
32
+ </div>
33
+ <?php
34
+ }
35
+
36
+ if ( ! defined( 'YWCTM_VERSION' ) ) {
37
+ define( 'YWCTM_VERSION', '1.0.0' );
38
+ }
39
+
40
+ if ( ! defined( 'YWCTM_FREE_INIT' ) ) {
41
+ define( 'YWCTM_FREE_INIT', plugin_basename( __FILE__ ) );
42
+ }
43
+
44
+ if ( ! defined( 'YWCTM_FILE' ) ) {
45
+ define( 'YWCTM_FILE', __FILE__ );
46
+ }
47
+
48
+ if ( ! defined( 'YWCTM_DIR' ) ) {
49
+ define( 'YWCTM_DIR', plugin_dir_path( __FILE__ ) );
50
+ }
51
+
52
+ if ( ! defined( 'YWCTM_URL' ) ) {
53
+ define( 'YWCTM_URL', plugins_url( '/', __FILE__ ) );
54
+ }
55
+
56
+ if ( ! defined( 'YWCTM_ASSETS_URL' ) ) {
57
+ define( 'YWCTM_ASSETS_URL', YWCTM_URL . 'assets/' );
58
+ }
59
+
60
+ if ( ! defined( 'YWCTM_TEMPLATE_PATH' ) ) {
61
+ define( 'YWCTM_TEMPLATE_PATH', YWCTM_DIR . 'templates/' );
62
+ }
63
+
64
+ function ywctm_init() {
65
+
66
+ /* Load YWCTM text domain */
67
+ load_plugin_textdomain( 'ywctm', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
68
+
69
+ /**
70
+ * Init default plugin settings
71
+ */
72
+ if ( !function_exists( 'yith_plugin_registration_hook' ) ) {
73
+ require_once 'plugin-fw/yit-plugin-registration-hook.php';
74
+ }
75
+
76
+ require_once( YWCTM_DIR . 'class.yith-woocommerce-catalog-mode.php' );
77
+
78
+ register_activation_hook( __FILE__, 'yith_plugin_registration_hook' );
79
+ register_deactivation_hook( __FILE__, array('YITH_WC_Catalog_Mode', 'reactivate_hidden_pages' ) );
80
+
81
+ $YITH_WC_Catalog_Mode = new YITH_WC_Catalog_Mode();
82
+ }
83
+ add_action( 'ywctm_init', 'ywctm_init' );
84
+
85
+ function ywctm_install() {
86
+
87
+ if ( ! function_exists( 'WC' ) ) {
88
+ add_action( 'admin_notices', 'ywctm_install_woocommerce_admin_notice' );
89
+ }
90
+ elseif ( defined( 'YWCTM_PREMIUM' ) ) {
91
+ add_action( 'admin_notices', 'ywctm_install_free_admin_notice' );
92
+ deactivate_plugins( plugin_basename( __FILE__ ) );
93
+ }
94
+ else {
95
+ do_action( 'ywctm_init' );
96
+ }
97
+ }
98
+ add_action( 'plugins_loaded', 'ywctm_install', 11 );
99
+
100
+
101
+
102
+
103
+
104
+
languages/default.po ADDED
@@ -0,0 +1,1031 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: YIT WooCommerce Catalog Mode\n"
4
+ "POT-Creation-Date: 2015-02-10 11:38+0100\n"
5
+ "PO-Revision-Date: 2015-02-10 11:43+0100\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Your Inspiration Themes <plugins@yithemes.com>\n"
8
+ "Language: en\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.7.4\n"
13
+ "X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_e;_n:1,2;__ngettext:1,2;"
14
+ "__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;"
15
+ "_nx_noop:4c,1,2\n"
16
+ "X-Poedit-Basepath: .\n"
17
+ "Plural-Forms: nplurals=2; plural=n!=1;\n"
18
+ "X-Poedit-SourceCharset: UTF-8\n"
19
+ "X-Poedit-SearchPath-0: ..\n"
20
+
21
+ #: ../class.yith-woocommerce-catalog-mode.php:150
22
+ #: ../class.yith-woocommerce-catalog-mode.php:207
23
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1048
24
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1196
25
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1202
26
+ #: ../plugin-fw/lib/yit-plugin-panel.php:62
27
+ #: ../plugin-options/settings-options.php:41
28
+ msgid "Settings"
29
+ msgstr ""
30
+
31
+ #: ../class.yith-woocommerce-catalog-mode.php:154
32
+ msgid "Premium Settings"
33
+ msgstr ""
34
+
35
+ #: ../class.yith-woocommerce-catalog-mode.php:162
36
+ #: ../class.yith-woocommerce-catalog-mode.php:163
37
+ msgid "Catalog Mode"
38
+ msgstr ""
39
+
40
+ #: ../class.yith-woocommerce-catalog-mode.php:210
41
+ msgid "Premium Version"
42
+ msgstr ""
43
+
44
+ #: ../class.yith-woocommerce-catalog-mode.php:236
45
+ msgid "Plugin Documentation"
46
+ msgstr ""
47
+
48
+ #: ../class.yith-woocommerce-catalog-mode.php:250
49
+ msgid ""
50
+ "YITH WooCommerce Catalog Mode is available in an outstanding PREMIUM version "
51
+ "with many new options, discover it now."
52
+ msgstr ""
53
+
54
+ #: ../class.yith-woocommerce-catalog-mode.php:251
55
+ msgid "Premium version"
56
+ msgstr ""
57
+
58
+ #: ../class.yith-woocommerce-catalog-mode.php:258
59
+ #: ../plugin-options/settings-options.php:19
60
+ #: ../plugin-options/settings-options.php:25
61
+ msgid "YITH WooCommerce Catalog Mode"
62
+ msgstr ""
63
+
64
+ #: ../class.yith-woocommerce-catalog-mode.php:259
65
+ msgid ""
66
+ "In the YIT Plugins tab you can find the YITH WooCommerce Catalog Mode "
67
+ "options. With this menu, you can access to all the settings of our plugins "
68
+ "that you have activated."
69
+ msgstr ""
70
+
71
+ #: ../init.php:24
72
+ msgid ""
73
+ "YITH WooCommerce Catalog Mode is enabled but not effective. It requires "
74
+ "Woocommerce in order to work."
75
+ msgstr ""
76
+
77
+ #: ../init.php:36
78
+ msgid ""
79
+ "You can't activate the free version of YITH WooCommerce Catalog Mode while "
80
+ "you are using the premium one."
81
+ msgstr ""
82
+
83
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:460
84
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:574
85
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:719
86
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1632
87
+ #, php-format
88
+ msgid "Add %s"
89
+ msgstr ""
90
+
91
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:461
92
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:575
93
+ #, php-format
94
+ msgid "Add New %s"
95
+ msgstr ""
96
+
97
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:462
98
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:576
99
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1267
100
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1304
101
+ #, php-format
102
+ msgid "Edit %s"
103
+ msgstr ""
104
+
105
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:463
106
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:577
107
+ #, php-format
108
+ msgid "New %s"
109
+ msgstr ""
110
+
111
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:464
112
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:578
113
+ #, php-format
114
+ msgid "All %s"
115
+ msgstr ""
116
+
117
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:465
118
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:579
119
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1251
120
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1305
121
+ #, php-format
122
+ msgid "View %s"
123
+ msgstr ""
124
+
125
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:466
126
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:580
127
+ #, php-format
128
+ msgid "Search %s"
129
+ msgstr ""
130
+
131
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:467
132
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:581
133
+ #, php-format
134
+ msgid "No %s found"
135
+ msgstr ""
136
+
137
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:468
138
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:582
139
+ #, php-format
140
+ msgid "No %s found in Trash"
141
+ msgstr ""
142
+
143
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:625
144
+ #, php-format
145
+ msgctxt "taxonomy general name"
146
+ msgid "%s Categories"
147
+ msgstr ""
148
+
149
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:626
150
+ msgctxt "taxonomy singular name"
151
+ msgid "Category"
152
+ msgstr ""
153
+
154
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:627
155
+ msgid "Search Categories"
156
+ msgstr ""
157
+
158
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:628
159
+ msgid "All Categories"
160
+ msgstr ""
161
+
162
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:629
163
+ msgid "Parent Category"
164
+ msgstr ""
165
+
166
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:630
167
+ msgid "Parent Category:"
168
+ msgstr ""
169
+
170
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:631
171
+ msgid "Edit Category"
172
+ msgstr ""
173
+
174
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:632
175
+ msgid "Update Category"
176
+ msgstr ""
177
+
178
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:633
179
+ msgid "Add New Category"
180
+ msgstr ""
181
+
182
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:634
183
+ msgid "New Category Name"
184
+ msgstr ""
185
+
186
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:635
187
+ msgid "Category"
188
+ msgstr ""
189
+
190
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:724
191
+ msgid "Categories"
192
+ msgstr ""
193
+
194
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1042
195
+ #, php-format
196
+ msgid "%s Settings"
197
+ msgstr ""
198
+
199
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1051
200
+ msgid "Type"
201
+ msgstr ""
202
+
203
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1052
204
+ msgid "The layout for this "
205
+ msgstr ""
206
+
207
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1058
208
+ msgid "Rewrite"
209
+ msgstr ""
210
+
211
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1059
212
+ msgid "The word used for the URL of each project (the slug of post if empty)"
213
+ msgstr ""
214
+
215
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1064
216
+ msgid "Label Singular"
217
+ msgstr ""
218
+
219
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1065
220
+ msgid ""
221
+ "Set the label in singular to use for each label (the title of portfolio if "
222
+ "empty)"
223
+ msgstr ""
224
+
225
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1070
226
+ msgid "Label Plural"
227
+ msgstr ""
228
+
229
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1071
230
+ msgid ""
231
+ "Set the label in plural to use for each label (the title of portfolio if "
232
+ "empty)"
233
+ msgstr ""
234
+
235
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1076
236
+ msgid "Taxonomy"
237
+ msgstr ""
238
+
239
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1077
240
+ msgid ""
241
+ "If you want to use a category section for the portfolio, set the name of "
242
+ "taxonomy. Name should be in slug form (must not contain capital letters or "
243
+ "spaces) and not more than 32 characters long (database structure "
244
+ "restriction)."
245
+ msgstr ""
246
+
247
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1082
248
+ msgid "Taxonomy Rewrite"
249
+ msgstr ""
250
+
251
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1083
252
+ msgid "Set the word to use in the URL for each category page."
253
+ msgstr ""
254
+
255
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1088
256
+ msgid "Single layout"
257
+ msgstr ""
258
+
259
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1089
260
+ msgid "The layout for single page of this portfolio"
261
+ msgstr ""
262
+
263
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1130
264
+ msgid "layout settings"
265
+ msgstr ""
266
+
267
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1222
268
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1235
269
+ msgid "Quick links"
270
+ msgstr ""
271
+
272
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1475
273
+ #, php-format
274
+ msgid "Show the frontend of the %s"
275
+ msgstr ""
276
+
277
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1482
278
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:46
279
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:90
280
+ msgid "Name"
281
+ msgstr ""
282
+
283
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1631
284
+ #, php-format
285
+ msgid "Add %s by images"
286
+ msgstr ""
287
+
288
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1633
289
+ msgid "Add with multiupload"
290
+ msgstr ""
291
+
292
+ #: ../plugin-fw/lib/yit-plugin-panel-wc.php:303
293
+ msgid "The changes you made will be lost if you navigate away from this page."
294
+ msgstr ""
295
+
296
+ #: ../plugin-fw/lib/yit-plugin-panel.php:61
297
+ msgid "Plugin Settings"
298
+ msgstr ""
299
+
300
+ #: ../plugin-fw/lib/yit-plugin-panel.php:92
301
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:101
302
+ msgid "YIT Plugins"
303
+ msgstr ""
304
+
305
+ #: ../plugin-fw/lib/yit-plugin-panel.php:271
306
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:142
307
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:5
308
+ msgid "Save Changes"
309
+ msgstr ""
310
+
311
+ #: ../plugin-fw/lib/yit-plugin-panel.php:274
312
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:145
313
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:8
314
+ msgid ""
315
+ "If you continue with this action, you will reset all options are in this "
316
+ "page."
317
+ msgstr ""
318
+
319
+ #: ../plugin-fw/lib/yit-plugin-panel.php:276
320
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:147
321
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:10
322
+ msgid "Reset Defaults"
323
+ msgstr ""
324
+
325
+ #: ../plugin-fw/lib/yit-plugin-panel.php:276
326
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:147
327
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:10
328
+ msgid "Are you sure of it?"
329
+ msgstr ""
330
+
331
+ #: ../plugin-fw/lib/yit-plugin-panel.php:410
332
+ msgid ""
333
+ "The element you have written is already exists. Please, add another name."
334
+ msgstr ""
335
+
336
+ #: ../plugin-fw/lib/yit-plugin-panel.php:411
337
+ msgid "Settings saved"
338
+ msgstr ""
339
+
340
+ #: ../plugin-fw/lib/yit-plugin-panel.php:412
341
+ msgid "Settings reset"
342
+ msgstr ""
343
+
344
+ #: ../plugin-fw/lib/yit-plugin-panel.php:413
345
+ msgid "Element deleted correctly."
346
+ msgstr ""
347
+
348
+ #: ../plugin-fw/lib/yit-plugin-panel.php:414
349
+ #: ../plugin-fw/lib/yit-plugin-panel.php:415
350
+ msgid "Element updated correctly."
351
+ msgstr ""
352
+
353
+ #: ../plugin-fw/lib/yit-plugin-panel.php:416
354
+ msgid "Database imported correctly."
355
+ msgstr ""
356
+
357
+ #: ../plugin-fw/lib/yit-plugin-panel.php:417
358
+ msgid "An error encoured during during import. Please try again."
359
+ msgstr ""
360
+
361
+ #: ../plugin-fw/lib/yit-plugin-panel.php:418
362
+ msgid "The file you have insert doesn't valid."
363
+ msgstr ""
364
+
365
+ #: ../plugin-fw/lib/yit-plugin-panel.php:419
366
+ msgid "I'm sorry, the import featured is disabled."
367
+ msgstr ""
368
+
369
+ #: ../plugin-fw/lib/yit-plugin-panel.php:420
370
+ msgid "Sorting done correctly."
371
+ msgstr ""
372
+
373
+ #: ../plugin-fw/lib/yit-pointers.php:70
374
+ msgid "Plugins Activated"
375
+ msgstr ""
376
+
377
+ #: ../plugin-fw/lib/yit-pointers.php:71
378
+ msgid ""
379
+ "From now on, you can find all the options of your plugins under the YIT "
380
+ "Plugin menu voice.\n"
381
+ " For every installation of our new "
382
+ "plugins, a new voice will be added to access to the customization settings."
383
+ msgstr ""
384
+
385
+ #: ../plugin-fw/lib/yit-pointers.php:73 ../plugin-fw/lib/yit-pointers.php:89
386
+ msgid "Discover all our plugins available on:"
387
+ msgstr ""
388
+
389
+ #: ../plugin-fw/lib/yit-pointers.php:74 ../plugin-fw/lib/yit-pointers.php:90
390
+ msgid "and"
391
+ msgstr ""
392
+
393
+ #: ../plugin-fw/lib/yit-pointers.php:84
394
+ msgid "Plugins Upgraded"
395
+ msgstr ""
396
+
397
+ #: ../plugin-fw/lib/yit-pointers.php:85
398
+ msgid ""
399
+ "From now on, you can find all the options of your plugins under the YIT "
400
+ "Plugin menu voice.\n"
401
+ " When one of our plugins updates, a new "
402
+ "voice will be added to this menu.\n"
403
+ " For example, after the update, the "
404
+ "options from the plugins (YITH WooCommerce Wishlist, YITH WooCommerce Ajax "
405
+ "Search, etc.)\n"
406
+ " will be removed from the previous "
407
+ "location and moved under the YIT Plugin tab."
408
+ msgstr ""
409
+
410
+ #: ../plugin-fw/lib/yit-upgrade.php:119
411
+ msgid "There is a new version of %plugin_name% available."
412
+ msgstr ""
413
+
414
+ #: ../plugin-fw/lib/yit-upgrade.php:120
415
+ msgid "View version %latest% details."
416
+ msgstr ""
417
+
418
+ #: ../plugin-fw/lib/yit-upgrade.php:121
419
+ msgid "Automatic update is unavailable for this plugin,"
420
+ msgstr ""
421
+
422
+ #: ../plugin-fw/lib/yit-upgrade.php:122
423
+ msgid ""
424
+ "please <a href=\"%activate_link%\"> activate </a> your copy of %plugin_name%."
425
+ msgstr ""
426
+
427
+ #: ../plugin-fw/lib/yit-upgrade.php:123
428
+ msgid "Update now."
429
+ msgstr ""
430
+
431
+ #: ../plugin-fw/lib/yit-upgrade.php:226
432
+ msgid "Yithemes Repository"
433
+ msgstr ""
434
+
435
+ #: ../plugin-fw/lib/yit-upgrade.php:260
436
+ msgid "Invalid URL Provided."
437
+ msgstr ""
438
+
439
+ #: ../plugin-fw/lib/yit-upgrade.php:273
440
+ msgid "Could not create Temporary file."
441
+ msgstr ""
442
+
443
+ #: ../plugin-fw/lib/yit-upgrade.php:414
444
+ #, php-format
445
+ msgid ""
446
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
447
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a>."
448
+ msgstr ""
449
+
450
+ #: ../plugin-fw/lib/yit-upgrade.php:416
451
+ #, php-format
452
+ msgid ""
453
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
454
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a>. <em>You "
455
+ "have to activate the plugin on a single site of the network to benefit from "
456
+ "the automatic updates.</em>"
457
+ msgstr ""
458
+
459
+ #: ../plugin-fw/lib/yit-upgrade.php:418
460
+ #, php-format
461
+ msgid ""
462
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
463
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a>. "
464
+ "<em>Automatic update is unavailable for this plugin, please <a href=\"%5$s\" "
465
+ "title=\"Licence activation\">activate</a> your copy of %6s.</em>"
466
+ msgstr ""
467
+
468
+ #: ../plugin-fw/lib/yit-upgrade.php:420
469
+ #, php-format
470
+ msgid ""
471
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
472
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a> or <a "
473
+ "href=\"%5$s\">update now</a>."
474
+ msgstr ""
475
+
476
+ #: ../plugin-fw/lib/yit-upgrade.php:493
477
+ msgid "You can't update plugins for this site."
478
+ msgstr ""
479
+
480
+ #: ../plugin-fw/lib/yit-upgrade.php:497
481
+ msgid "You do not have sufficient permissions to update plugins for this site."
482
+ msgstr ""
483
+
484
+ #: ../plugin-fw/lib/yit-upgrade.php:504
485
+ msgid "Update Plugin"
486
+ msgstr ""
487
+
488
+ #: ../plugin-fw/licence/lib/yit-licence.php:148
489
+ #, php-format
490
+ msgid "%field% field can not be empty"
491
+ msgstr ""
492
+
493
+ #: ../plugin-fw/licence/lib/yit-licence.php:149
494
+ msgid "%field_1% and %field_2% fields can not be empty"
495
+ msgstr ""
496
+
497
+ #: ../plugin-fw/licence/lib/yit-licence.php:150
498
+ msgid "Unable to contact the remote server, please try again later. Thanks!"
499
+ msgstr ""
500
+
501
+ #: ../plugin-fw/licence/lib/yit-licence.php:529
502
+ msgid "Invalid Request"
503
+ msgstr ""
504
+
505
+ #: ../plugin-fw/licence/lib/yit-licence.php:530
506
+ msgid "Invalid licence key"
507
+ msgstr ""
508
+
509
+ #: ../plugin-fw/licence/lib/yit-licence.php:531
510
+ msgid "Software has been deactive"
511
+ msgstr ""
512
+
513
+ #: ../plugin-fw/licence/lib/yit-licence.php:532
514
+ msgid "Exceeded maximum number of activations"
515
+ msgstr ""
516
+
517
+ #: ../plugin-fw/licence/lib/yit-licence.php:533
518
+ msgid "Invalid instance ID"
519
+ msgstr ""
520
+
521
+ #: ../plugin-fw/licence/lib/yit-licence.php:534
522
+ msgid "Invalid security key"
523
+ msgstr ""
524
+
525
+ #: ../plugin-fw/licence/lib/yit-licence.php:535
526
+ msgid "Licence key has expired"
527
+ msgstr ""
528
+
529
+ #: ../plugin-fw/licence/lib/yit-licence.php:536
530
+ msgid "Licence key has be banned"
531
+ msgstr ""
532
+
533
+ #: ../plugin-fw/licence/lib/yit-plugin-licence.php:63
534
+ #: ../plugin-fw/licence/lib/yit-plugin-licence.php:64
535
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:63
536
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:64
537
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:106
538
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:107
539
+ msgid "Licence Activation"
540
+ msgstr ""
541
+
542
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:114
543
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:115
544
+ #, php-format
545
+ msgid "%s"
546
+ msgstr ""
547
+
548
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:19
549
+ msgid "Yithemes Licence Activation"
550
+ msgstr ""
551
+
552
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:23
553
+ msgid ""
554
+ "Have you updated your licenses? Have you asked for an extension? Update "
555
+ "information concerning your products."
556
+ msgstr ""
557
+
558
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:25
559
+ msgid "Update licence information"
560
+ msgstr ""
561
+
562
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:35
563
+ msgid "To Active"
564
+ msgstr ""
565
+
566
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:54
567
+ msgid "Activate"
568
+ msgstr ""
569
+
570
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:73
571
+ msgid "Activated"
572
+ msgstr ""
573
+
574
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:77
575
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:108
576
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:132
577
+ msgid "Product Name"
578
+ msgstr ""
579
+
580
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:78
581
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:109
582
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:133
583
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:145
584
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:337
585
+ msgid "Email"
586
+ msgstr ""
587
+
588
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:79
589
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:110
590
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:134
591
+ msgid "Licence Key"
592
+ msgstr ""
593
+
594
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:80
595
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:135
596
+ msgid "Expires"
597
+ msgstr ""
598
+
599
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:81
600
+ msgid "Remaining"
601
+ msgstr ""
602
+
603
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:82
604
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:95
605
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:136
606
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:146
607
+ msgid "Renew"
608
+ msgstr ""
609
+
610
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:93
611
+ #, php-format
612
+ msgid "%1s out of %2s"
613
+ msgstr ""
614
+
615
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:104
616
+ msgid "Banned"
617
+ msgstr ""
618
+
619
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:128
620
+ msgid "Expired"
621
+ msgstr ""
622
+
623
+ #: ../plugin-fw/templates/metaboxes/types/ajax-products.php:23
624
+ msgid "Search for a product"
625
+ msgstr ""
626
+
627
+ #: ../plugin-fw/templates/metaboxes/types/categories.php:36
628
+ msgid "No categories."
629
+ msgstr ""
630
+
631
+ #: ../plugin-fw/templates/metaboxes/types/categories.php:42
632
+ msgid "+ Add New Category"
633
+ msgstr ""
634
+
635
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:5
636
+ msgid "Text Input"
637
+ msgstr ""
638
+
639
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:6
640
+ msgid "Checkbox"
641
+ msgstr ""
642
+
643
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:7
644
+ msgid "Select"
645
+ msgstr ""
646
+
647
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:8
648
+ msgid "Textarea"
649
+ msgstr ""
650
+
651
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:9
652
+ msgid "Radio Input"
653
+ msgstr ""
654
+
655
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:10
656
+ msgid "Password Field"
657
+ msgstr ""
658
+
659
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:11
660
+ msgid "File Upload"
661
+ msgstr ""
662
+
663
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:45
664
+ msgid "Theme Icon"
665
+ msgstr ""
666
+
667
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:46
668
+ msgid "Custom Icon"
669
+ msgstr ""
670
+
671
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:47
672
+ #: ../plugin-fw/templates/metaboxes/types/responsivesliders.php:24
673
+ msgid "None"
674
+ msgstr ""
675
+
676
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:57
677
+ msgid "Add field"
678
+ msgstr ""
679
+
680
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:66
681
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:258
682
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:37
683
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:82
684
+ msgid "Remove"
685
+ msgstr ""
686
+
687
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:67
688
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:259
689
+ msgid "Click to toggle"
690
+ msgstr ""
691
+
692
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:74
693
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:266
694
+ msgid "Title Field"
695
+ msgstr ""
696
+
697
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:78
698
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:270
699
+ msgid "Insert the title of field."
700
+ msgstr ""
701
+
702
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:83
703
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:275
704
+ msgid "Data Name"
705
+ msgstr ""
706
+
707
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:87
708
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:279
709
+ msgid ""
710
+ "REQUIRED: The identification name of this field, that you can insert into "
711
+ "body email configuration. <strong>Note:</strong>Use only lowercase "
712
+ "characters and underscores."
713
+ msgstr ""
714
+
715
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:92
716
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:284
717
+ msgid "Type field"
718
+ msgstr ""
719
+
720
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:100
721
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:292
722
+ msgid "Select the type of this field."
723
+ msgstr ""
724
+
725
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:105
726
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:297
727
+ msgid "Checked"
728
+ msgstr ""
729
+
730
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:109
731
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:301
732
+ msgid "Select this if you want this field already checked."
733
+ msgstr ""
734
+
735
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:114
736
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:306
737
+ msgid "Add options "
738
+ msgstr ""
739
+
740
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:115
741
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:307
742
+ msgid "Add option"
743
+ msgstr ""
744
+
745
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:118
746
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:310
747
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:432
748
+ msgid "Selected"
749
+ msgstr ""
750
+
751
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:121
752
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:313
753
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:432
754
+ msgid "Delete option"
755
+ msgstr ""
756
+
757
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:127
758
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:319
759
+ msgid "Message Error"
760
+ msgstr ""
761
+
762
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:131
763
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:323
764
+ msgid "Insert the error message for validation."
765
+ msgstr ""
766
+
767
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:136
768
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:328
769
+ msgid "Required"
770
+ msgstr ""
771
+
772
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:140
773
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:332
774
+ msgid "Select this if it must be required."
775
+ msgstr ""
776
+
777
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:149
778
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:341
779
+ msgid "Select this if it must be a valid email."
780
+ msgstr ""
781
+
782
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:154
783
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:346
784
+ msgid "Reply To"
785
+ msgstr ""
786
+
787
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:158
788
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:350
789
+ msgid "Select this if it's the email where you can reply."
790
+ msgstr ""
791
+
792
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:163
793
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:355
794
+ msgid "Class"
795
+ msgstr ""
796
+
797
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:167
798
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:359
799
+ msgid ""
800
+ "Insert an additional class(es) (separateb by comma) for more personalization."
801
+ msgstr ""
802
+
803
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:172
804
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:364
805
+ msgid "Icon"
806
+ msgstr ""
807
+
808
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:200
809
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:388
810
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:69
811
+ #: ../plugin-fw/templates/metaboxes/types/select-icon.php:33
812
+ #: ../plugin-fw/templates/metaboxes/types/upload.php:21
813
+ #: ../plugin-fw/templates/panel/types/upload.php:31
814
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-upload.php:35
815
+ msgid "Upload"
816
+ msgstr ""
817
+
818
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:206
819
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:394
820
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:75
821
+ #: ../plugin-fw/templates/metaboxes/types/select-icon.php:39
822
+ msgid "Image preview"
823
+ msgstr ""
824
+
825
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:214
826
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:402
827
+ msgid "Insert an icon for more personalization."
828
+ msgstr ""
829
+
830
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:219
831
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:406
832
+ msgid "Width"
833
+ msgstr ""
834
+
835
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:244
836
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:418
837
+ msgid "Choose how much long will be the field."
838
+ msgstr ""
839
+
840
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:28
841
+ msgid "Close all"
842
+ msgstr ""
843
+
844
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:28
845
+ msgid "Expand all"
846
+ msgstr ""
847
+
848
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:52
849
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:95
850
+ msgid "Value"
851
+ msgstr ""
852
+
853
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:53
854
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:96
855
+ msgid "The content of the tab. (HTML is supported)"
856
+ msgstr ""
857
+
858
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:65
859
+ msgid "Add custom product tab"
860
+ msgstr ""
861
+
862
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:107
863
+ msgid "Do you want to remove the custom tab?"
864
+ msgstr ""
865
+
866
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:89
867
+ #, php-format
868
+ msgid "(Default: %s <img src=\"%s\"/>)"
869
+ msgstr ""
870
+
871
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:91
872
+ #, php-format
873
+ msgid "(Default: <i %s></i> )"
874
+ msgstr ""
875
+
876
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:35
877
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
878
+ #: ../plugin-fw/templates/metaboxes/types/images.php:33
879
+ #: ../plugin-fw/templates/metaboxes/types/images.php:59
880
+ msgid "Delete image"
881
+ msgstr ""
882
+
883
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
884
+ msgid "Add Images to Gallery"
885
+ msgstr ""
886
+
887
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
888
+ msgid "Add to gallery"
889
+ msgstr ""
890
+
891
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
892
+ msgid "Add images"
893
+ msgstr ""
894
+
895
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
896
+ msgid "Delete"
897
+ msgstr ""
898
+
899
+ #: ../plugin-fw/templates/metaboxes/types/images.php:37
900
+ msgid "Upload new images"
901
+ msgstr ""
902
+
903
+ #: ../plugin-fw/templates/metaboxes/types/images.php:70
904
+ msgid "Are you sure you want to remove this image?"
905
+ msgstr ""
906
+
907
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:25
908
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:36
909
+ msgid "Left sidebar"
910
+ msgstr ""
911
+
912
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:28
913
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:42
914
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:45
915
+ msgid "No sidebar"
916
+ msgstr ""
917
+
918
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:28
919
+ msgid "No sideabr"
920
+ msgstr ""
921
+
922
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:31
923
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:39
924
+ msgid "Right sidebar"
925
+ msgstr ""
926
+
927
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:34
928
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:53
929
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:64
930
+ msgid "Choose a sidebar"
931
+ msgstr ""
932
+
933
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:51
934
+ msgid "Sidebar Left"
935
+ msgstr ""
936
+
937
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:62
938
+ msgid "Sidebar Right"
939
+ msgstr ""
940
+
941
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:42
942
+ msgid "px"
943
+ msgstr ""
944
+
945
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:43
946
+ msgid "em"
947
+ msgstr ""
948
+
949
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:44
950
+ msgid "pt"
951
+ msgstr ""
952
+
953
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:45
954
+ msgid "rem"
955
+ msgstr ""
956
+
957
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:59
958
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:153
959
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:217
960
+ msgid "Web fonts"
961
+ msgstr ""
962
+
963
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:71
964
+ msgid "Google fonts"
965
+ msgstr ""
966
+
967
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:96
968
+ msgid "Regular"
969
+ msgstr ""
970
+
971
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:97
972
+ msgid "Bold"
973
+ msgstr ""
974
+
975
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:98
976
+ msgid "Extra bold"
977
+ msgstr ""
978
+
979
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:99
980
+ msgid "Italic"
981
+ msgstr ""
982
+
983
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:100
984
+ msgid "Italic bold"
985
+ msgstr ""
986
+
987
+ #: ../plugin-options/settings-options.php:16
988
+ msgid "Upgrade to the PREMIUM VERSION"
989
+ msgstr ""
990
+
991
+ #: ../plugin-options/settings-options.php:20
992
+ msgid "Discover the Advanced Features"
993
+ msgstr ""
994
+
995
+ #: ../plugin-options/settings-options.php:21
996
+ msgid ""
997
+ "Upgrade to the PREMIUM VERSION of YITH WooCommerce Catalog Mode to benefit "
998
+ "from all features!"
999
+ msgstr ""
1000
+
1001
+ #: ../plugin-options/settings-options.php:27
1002
+ msgid "Get Support and Pro Features"
1003
+ msgstr ""
1004
+
1005
+ #: ../plugin-options/settings-options.php:28
1006
+ msgid ""
1007
+ "By purchasing the premium version of the plugin, you will take advantage of "
1008
+ "the advanced features of the product and you will get one year of free "
1009
+ "updates and support through our platform available 24h/24."
1010
+ msgstr ""
1011
+
1012
+ #: ../plugin-options/settings-options.php:47
1013
+ #: ../plugin-options/settings-options.php:55
1014
+ msgid "\"Add to cart\" button visibility"
1015
+ msgstr ""
1016
+
1017
+ #: ../plugin-options/settings-options.php:49
1018
+ msgid "Show in product's details page"
1019
+ msgstr ""
1020
+
1021
+ #: ../plugin-options/settings-options.php:57
1022
+ msgid "Show in other pages"
1023
+ msgstr ""
1024
+
1025
+ #: ../plugin-options/settings-options.php:63
1026
+ msgid "\"Cart\" and \"Checkout\" visibility"
1027
+ msgstr ""
1028
+
1029
+ #: ../plugin-options/settings-options.php:65
1030
+ msgid "Show"
1031
+ msgstr ""
languages/ywctm.pot ADDED
@@ -0,0 +1,1029 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: YIT WooCommerce Catalog Mode\n"
4
+ "POT-Creation-Date: 2015-02-10 11:38+0100\n"
5
+ "PO-Revision-Date: 2015-02-10 11:40+0100\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Your Inspiration Themes <plugins@yithemes.com>\n"
8
+ "Language: en\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.7.4\n"
13
+ "X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_e;_n:1,2;__ngettext:1,2;"
14
+ "__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;"
15
+ "_nx_noop:4c,1,2\n"
16
+ "Plural-Forms: nplurals=2; plural=n!=1;\n"
17
+ "X-Poedit-SourceCharset: UTF-8\n"
18
+
19
+ #: ../class.yith-woocommerce-catalog-mode.php:150
20
+ #: ../class.yith-woocommerce-catalog-mode.php:207
21
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1048
22
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1196
23
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1202
24
+ #: ../plugin-fw/lib/yit-plugin-panel.php:62
25
+ #: ../plugin-options/settings-options.php:41
26
+ msgid "Settings"
27
+ msgstr ""
28
+
29
+ #: ../class.yith-woocommerce-catalog-mode.php:154
30
+ msgid "Premium Settings"
31
+ msgstr ""
32
+
33
+ #: ../class.yith-woocommerce-catalog-mode.php:162
34
+ #: ../class.yith-woocommerce-catalog-mode.php:163
35
+ msgid "Catalog Mode"
36
+ msgstr ""
37
+
38
+ #: ../class.yith-woocommerce-catalog-mode.php:210
39
+ msgid "Premium Version"
40
+ msgstr ""
41
+
42
+ #: ../class.yith-woocommerce-catalog-mode.php:236
43
+ msgid "Plugin Documentation"
44
+ msgstr ""
45
+
46
+ #: ../class.yith-woocommerce-catalog-mode.php:250
47
+ msgid ""
48
+ "YITH WooCommerce Catalog Mode is available in an outstanding PREMIUM version "
49
+ "with many new options, discover it now."
50
+ msgstr ""
51
+
52
+ #: ../class.yith-woocommerce-catalog-mode.php:251
53
+ msgid "Premium version"
54
+ msgstr ""
55
+
56
+ #: ../class.yith-woocommerce-catalog-mode.php:258
57
+ #: ../plugin-options/settings-options.php:19
58
+ #: ../plugin-options/settings-options.php:25
59
+ msgid "YITH WooCommerce Catalog Mode"
60
+ msgstr ""
61
+
62
+ #: ../class.yith-woocommerce-catalog-mode.php:259
63
+ msgid ""
64
+ "In the YIT Plugins tab you can find the YITH WooCommerce Catalog Mode "
65
+ "options. With this menu, you can access to all the settings of our plugins "
66
+ "that you have activated."
67
+ msgstr ""
68
+
69
+ #: ../init.php:24
70
+ msgid ""
71
+ "YITH WooCommerce Catalog Mode is enabled but not effective. It requires "
72
+ "Woocommerce in order to work."
73
+ msgstr ""
74
+
75
+ #: ../init.php:36
76
+ msgid ""
77
+ "You can't activate the free version of YITH WooCommerce Catalog Mode while "
78
+ "you are using the premium one."
79
+ msgstr ""
80
+
81
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:460
82
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:574
83
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:719
84
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1632
85
+ #, php-format
86
+ msgid "Add %s"
87
+ msgstr ""
88
+
89
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:461
90
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:575
91
+ #, php-format
92
+ msgid "Add New %s"
93
+ msgstr ""
94
+
95
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:462
96
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:576
97
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1267
98
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1304
99
+ #, php-format
100
+ msgid "Edit %s"
101
+ msgstr ""
102
+
103
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:463
104
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:577
105
+ #, php-format
106
+ msgid "New %s"
107
+ msgstr ""
108
+
109
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:464
110
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:578
111
+ #, php-format
112
+ msgid "All %s"
113
+ msgstr ""
114
+
115
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:465
116
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:579
117
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1251
118
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1305
119
+ #, php-format
120
+ msgid "View %s"
121
+ msgstr ""
122
+
123
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:466
124
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:580
125
+ #, php-format
126
+ msgid "Search %s"
127
+ msgstr ""
128
+
129
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:467
130
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:581
131
+ #, php-format
132
+ msgid "No %s found"
133
+ msgstr ""
134
+
135
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:468
136
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:582
137
+ #, php-format
138
+ msgid "No %s found in Trash"
139
+ msgstr ""
140
+
141
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:625
142
+ #, php-format
143
+ msgctxt "taxonomy general name"
144
+ msgid "%s Categories"
145
+ msgstr ""
146
+
147
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:626
148
+ msgctxt "taxonomy singular name"
149
+ msgid "Category"
150
+ msgstr ""
151
+
152
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:627
153
+ msgid "Search Categories"
154
+ msgstr ""
155
+
156
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:628
157
+ msgid "All Categories"
158
+ msgstr ""
159
+
160
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:629
161
+ msgid "Parent Category"
162
+ msgstr ""
163
+
164
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:630
165
+ msgid "Parent Category:"
166
+ msgstr ""
167
+
168
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:631
169
+ msgid "Edit Category"
170
+ msgstr ""
171
+
172
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:632
173
+ msgid "Update Category"
174
+ msgstr ""
175
+
176
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:633
177
+ msgid "Add New Category"
178
+ msgstr ""
179
+
180
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:634
181
+ msgid "New Category Name"
182
+ msgstr ""
183
+
184
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:635
185
+ msgid "Category"
186
+ msgstr ""
187
+
188
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:724
189
+ msgid "Categories"
190
+ msgstr ""
191
+
192
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1042
193
+ #, php-format
194
+ msgid "%s Settings"
195
+ msgstr ""
196
+
197
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1051
198
+ msgid "Type"
199
+ msgstr ""
200
+
201
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1052
202
+ msgid "The layout for this "
203
+ msgstr ""
204
+
205
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1058
206
+ msgid "Rewrite"
207
+ msgstr ""
208
+
209
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1059
210
+ msgid "The word used for the URL of each project (the slug of post if empty)"
211
+ msgstr ""
212
+
213
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1064
214
+ msgid "Label Singular"
215
+ msgstr ""
216
+
217
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1065
218
+ msgid ""
219
+ "Set the label in singular to use for each label (the title of portfolio if "
220
+ "empty)"
221
+ msgstr ""
222
+
223
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1070
224
+ msgid "Label Plural"
225
+ msgstr ""
226
+
227
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1071
228
+ msgid ""
229
+ "Set the label in plural to use for each label (the title of portfolio if "
230
+ "empty)"
231
+ msgstr ""
232
+
233
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1076
234
+ msgid "Taxonomy"
235
+ msgstr ""
236
+
237
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1077
238
+ msgid ""
239
+ "If you want to use a category section for the portfolio, set the name of "
240
+ "taxonomy. Name should be in slug form (must not contain capital letters or "
241
+ "spaces) and not more than 32 characters long (database structure "
242
+ "restriction)."
243
+ msgstr ""
244
+
245
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1082
246
+ msgid "Taxonomy Rewrite"
247
+ msgstr ""
248
+
249
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1083
250
+ msgid "Set the word to use in the URL for each category page."
251
+ msgstr ""
252
+
253
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1088
254
+ msgid "Single layout"
255
+ msgstr ""
256
+
257
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1089
258
+ msgid "The layout for single page of this portfolio"
259
+ msgstr ""
260
+
261
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1130
262
+ msgid "layout settings"
263
+ msgstr ""
264
+
265
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1222
266
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1235
267
+ msgid "Quick links"
268
+ msgstr ""
269
+
270
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1475
271
+ #, php-format
272
+ msgid "Show the frontend of the %s"
273
+ msgstr ""
274
+
275
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1482
276
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:46
277
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:90
278
+ msgid "Name"
279
+ msgstr ""
280
+
281
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1631
282
+ #, php-format
283
+ msgid "Add %s by images"
284
+ msgstr ""
285
+
286
+ #: ../plugin-fw/lib/yit-cpt-unlimited.php:1633
287
+ msgid "Add with multiupload"
288
+ msgstr ""
289
+
290
+ #: ../plugin-fw/lib/yit-plugin-panel-wc.php:303
291
+ msgid "The changes you made will be lost if you navigate away from this page."
292
+ msgstr ""
293
+
294
+ #: ../plugin-fw/lib/yit-plugin-panel.php:61
295
+ msgid "Plugin Settings"
296
+ msgstr ""
297
+
298
+ #: ../plugin-fw/lib/yit-plugin-panel.php:92
299
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:101
300
+ msgid "YIT Plugins"
301
+ msgstr ""
302
+
303
+ #: ../plugin-fw/lib/yit-plugin-panel.php:271
304
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:142
305
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:5
306
+ msgid "Save Changes"
307
+ msgstr ""
308
+
309
+ #: ../plugin-fw/lib/yit-plugin-panel.php:274
310
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:145
311
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:8
312
+ msgid ""
313
+ "If you continue with this action, you will reset all options are in this "
314
+ "page."
315
+ msgstr ""
316
+
317
+ #: ../plugin-fw/lib/yit-plugin-panel.php:276
318
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:147
319
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:10
320
+ msgid "Reset Defaults"
321
+ msgstr ""
322
+
323
+ #: ../plugin-fw/lib/yit-plugin-panel.php:276
324
+ #: ../plugin-fw/lib/yit-plugin-subpanel.php:147
325
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-form.php:10
326
+ msgid "Are you sure of it?"
327
+ msgstr ""
328
+
329
+ #: ../plugin-fw/lib/yit-plugin-panel.php:410
330
+ msgid ""
331
+ "The element you have written is already exists. Please, add another name."
332
+ msgstr ""
333
+
334
+ #: ../plugin-fw/lib/yit-plugin-panel.php:411
335
+ msgid "Settings saved"
336
+ msgstr ""
337
+
338
+ #: ../plugin-fw/lib/yit-plugin-panel.php:412
339
+ msgid "Settings reset"
340
+ msgstr ""
341
+
342
+ #: ../plugin-fw/lib/yit-plugin-panel.php:413
343
+ msgid "Element deleted correctly."
344
+ msgstr ""
345
+
346
+ #: ../plugin-fw/lib/yit-plugin-panel.php:414
347
+ #: ../plugin-fw/lib/yit-plugin-panel.php:415
348
+ msgid "Element updated correctly."
349
+ msgstr ""
350
+
351
+ #: ../plugin-fw/lib/yit-plugin-panel.php:416
352
+ msgid "Database imported correctly."
353
+ msgstr ""
354
+
355
+ #: ../plugin-fw/lib/yit-plugin-panel.php:417
356
+ msgid "An error encoured during during import. Please try again."
357
+ msgstr ""
358
+
359
+ #: ../plugin-fw/lib/yit-plugin-panel.php:418
360
+ msgid "The file you have insert doesn't valid."
361
+ msgstr ""
362
+
363
+ #: ../plugin-fw/lib/yit-plugin-panel.php:419
364
+ msgid "I'm sorry, the import featured is disabled."
365
+ msgstr ""
366
+
367
+ #: ../plugin-fw/lib/yit-plugin-panel.php:420
368
+ msgid "Sorting done correctly."
369
+ msgstr ""
370
+
371
+ #: ../plugin-fw/lib/yit-pointers.php:70
372
+ msgid "Plugins Activated"
373
+ msgstr ""
374
+
375
+ #: ../plugin-fw/lib/yit-pointers.php:71
376
+ msgid ""
377
+ "From now on, you can find all the options of your plugins under the YIT "
378
+ "Plugin menu voice.\n"
379
+ " For every installation of our new "
380
+ "plugins, a new voice will be added to access to the customization settings."
381
+ msgstr ""
382
+
383
+ #: ../plugin-fw/lib/yit-pointers.php:73 ../plugin-fw/lib/yit-pointers.php:89
384
+ msgid "Discover all our plugins available on:"
385
+ msgstr ""
386
+
387
+ #: ../plugin-fw/lib/yit-pointers.php:74 ../plugin-fw/lib/yit-pointers.php:90
388
+ msgid "and"
389
+ msgstr ""
390
+
391
+ #: ../plugin-fw/lib/yit-pointers.php:84
392
+ msgid "Plugins Upgraded"
393
+ msgstr ""
394
+
395
+ #: ../plugin-fw/lib/yit-pointers.php:85
396
+ msgid ""
397
+ "From now on, you can find all the options of your plugins under the YIT "
398
+ "Plugin menu voice.\n"
399
+ " When one of our plugins updates, a new "
400
+ "voice will be added to this menu.\n"
401
+ " For example, after the update, the "
402
+ "options from the plugins (YITH WooCommerce Wishlist, YITH WooCommerce Ajax "
403
+ "Search, etc.)\n"
404
+ " will be removed from the previous "
405
+ "location and moved under the YIT Plugin tab."
406
+ msgstr ""
407
+
408
+ #: ../plugin-fw/lib/yit-upgrade.php:119
409
+ msgid "There is a new version of %plugin_name% available."
410
+ msgstr ""
411
+
412
+ #: ../plugin-fw/lib/yit-upgrade.php:120
413
+ msgid "View version %latest% details."
414
+ msgstr ""
415
+
416
+ #: ../plugin-fw/lib/yit-upgrade.php:121
417
+ msgid "Automatic update is unavailable for this plugin,"
418
+ msgstr ""
419
+
420
+ #: ../plugin-fw/lib/yit-upgrade.php:122
421
+ msgid ""
422
+ "please <a href=\"%activate_link%\"> activate </a> your copy of %plugin_name%."
423
+ msgstr ""
424
+
425
+ #: ../plugin-fw/lib/yit-upgrade.php:123
426
+ msgid "Update now."
427
+ msgstr ""
428
+
429
+ #: ../plugin-fw/lib/yit-upgrade.php:226
430
+ msgid "Yithemes Repository"
431
+ msgstr ""
432
+
433
+ #: ../plugin-fw/lib/yit-upgrade.php:260
434
+ msgid "Invalid URL Provided."
435
+ msgstr ""
436
+
437
+ #: ../plugin-fw/lib/yit-upgrade.php:273
438
+ msgid "Could not create Temporary file."
439
+ msgstr ""
440
+
441
+ #: ../plugin-fw/lib/yit-upgrade.php:414
442
+ #, php-format
443
+ msgid ""
444
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
445
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a>."
446
+ msgstr ""
447
+
448
+ #: ../plugin-fw/lib/yit-upgrade.php:416
449
+ #, php-format
450
+ msgid ""
451
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
452
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a>. <em>You "
453
+ "have to activate the plugin on a single site of the network to benefit from "
454
+ "the automatic updates.</em>"
455
+ msgstr ""
456
+
457
+ #: ../plugin-fw/lib/yit-upgrade.php:418
458
+ #, php-format
459
+ msgid ""
460
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
461
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a>. "
462
+ "<em>Automatic update is unavailable for this plugin, please <a href=\"%5$s\" "
463
+ "title=\"Licence activation\">activate</a> your copy of %6s.</em>"
464
+ msgstr ""
465
+
466
+ #: ../plugin-fw/lib/yit-upgrade.php:420
467
+ #, php-format
468
+ msgid ""
469
+ "There is a new version of %1$s available. <a href=\"%2$s\" class=\"thickbox "
470
+ "yit-changelog-button\" title=\"%3$s\">View version %4$s details</a> or <a "
471
+ "href=\"%5$s\">update now</a>."
472
+ msgstr ""
473
+
474
+ #: ../plugin-fw/lib/yit-upgrade.php:493
475
+ msgid "You can't update plugins for this site."
476
+ msgstr ""
477
+
478
+ #: ../plugin-fw/lib/yit-upgrade.php:497
479
+ msgid "You do not have sufficient permissions to update plugins for this site."
480
+ msgstr ""
481
+
482
+ #: ../plugin-fw/lib/yit-upgrade.php:504
483
+ msgid "Update Plugin"
484
+ msgstr ""
485
+
486
+ #: ../plugin-fw/licence/lib/yit-licence.php:148
487
+ #, php-format
488
+ msgid "%field% field can not be empty"
489
+ msgstr ""
490
+
491
+ #: ../plugin-fw/licence/lib/yit-licence.php:149
492
+ msgid "%field_1% and %field_2% fields can not be empty"
493
+ msgstr ""
494
+
495
+ #: ../plugin-fw/licence/lib/yit-licence.php:150
496
+ msgid "Unable to contact the remote server, please try again later. Thanks!"
497
+ msgstr ""
498
+
499
+ #: ../plugin-fw/licence/lib/yit-licence.php:529
500
+ msgid "Invalid Request"
501
+ msgstr ""
502
+
503
+ #: ../plugin-fw/licence/lib/yit-licence.php:530
504
+ msgid "Invalid licence key"
505
+ msgstr ""
506
+
507
+ #: ../plugin-fw/licence/lib/yit-licence.php:531
508
+ msgid "Software has been deactive"
509
+ msgstr ""
510
+
511
+ #: ../plugin-fw/licence/lib/yit-licence.php:532
512
+ msgid "Exceeded maximum number of activations"
513
+ msgstr ""
514
+
515
+ #: ../plugin-fw/licence/lib/yit-licence.php:533
516
+ msgid "Invalid instance ID"
517
+ msgstr ""
518
+
519
+ #: ../plugin-fw/licence/lib/yit-licence.php:534
520
+ msgid "Invalid security key"
521
+ msgstr ""
522
+
523
+ #: ../plugin-fw/licence/lib/yit-licence.php:535
524
+ msgid "Licence key has expired"
525
+ msgstr ""
526
+
527
+ #: ../plugin-fw/licence/lib/yit-licence.php:536
528
+ msgid "Licence key has be banned"
529
+ msgstr ""
530
+
531
+ #: ../plugin-fw/licence/lib/yit-plugin-licence.php:63
532
+ #: ../plugin-fw/licence/lib/yit-plugin-licence.php:64
533
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:63
534
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:64
535
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:106
536
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:107
537
+ msgid "Licence Activation"
538
+ msgstr ""
539
+
540
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:114
541
+ #: ../plugin-fw/licence/lib/yit-theme-licence.php:115
542
+ #, php-format
543
+ msgid "%s"
544
+ msgstr ""
545
+
546
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:19
547
+ msgid "Yithemes Licence Activation"
548
+ msgstr ""
549
+
550
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:23
551
+ msgid ""
552
+ "Have you updated your licenses? Have you asked for an extension? Update "
553
+ "information concerning your products."
554
+ msgstr ""
555
+
556
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:25
557
+ msgid "Update licence information"
558
+ msgstr ""
559
+
560
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:35
561
+ msgid "To Active"
562
+ msgstr ""
563
+
564
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:54
565
+ msgid "Activate"
566
+ msgstr ""
567
+
568
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:73
569
+ msgid "Activated"
570
+ msgstr ""
571
+
572
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:77
573
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:108
574
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:132
575
+ msgid "Product Name"
576
+ msgstr ""
577
+
578
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:78
579
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:109
580
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:133
581
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:145
582
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:337
583
+ msgid "Email"
584
+ msgstr ""
585
+
586
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:79
587
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:110
588
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:134
589
+ msgid "Licence Key"
590
+ msgstr ""
591
+
592
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:80
593
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:135
594
+ msgid "Expires"
595
+ msgstr ""
596
+
597
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:81
598
+ msgid "Remaining"
599
+ msgstr ""
600
+
601
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:82
602
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:95
603
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:136
604
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:146
605
+ msgid "Renew"
606
+ msgstr ""
607
+
608
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:93
609
+ #, php-format
610
+ msgid "%1s out of %2s"
611
+ msgstr ""
612
+
613
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:104
614
+ msgid "Banned"
615
+ msgstr ""
616
+
617
+ #: ../plugin-fw/licence/templates/panel/activation/activation-panel.php:128
618
+ msgid "Expired"
619
+ msgstr ""
620
+
621
+ #: ../plugin-fw/templates/metaboxes/types/ajax-products.php:23
622
+ msgid "Search for a product"
623
+ msgstr ""
624
+
625
+ #: ../plugin-fw/templates/metaboxes/types/categories.php:36
626
+ msgid "No categories."
627
+ msgstr ""
628
+
629
+ #: ../plugin-fw/templates/metaboxes/types/categories.php:42
630
+ msgid "+ Add New Category"
631
+ msgstr ""
632
+
633
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:5
634
+ msgid "Text Input"
635
+ msgstr ""
636
+
637
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:6
638
+ msgid "Checkbox"
639
+ msgstr ""
640
+
641
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:7
642
+ msgid "Select"
643
+ msgstr ""
644
+
645
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:8
646
+ msgid "Textarea"
647
+ msgstr ""
648
+
649
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:9
650
+ msgid "Radio Input"
651
+ msgstr ""
652
+
653
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:10
654
+ msgid "Password Field"
655
+ msgstr ""
656
+
657
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:11
658
+ msgid "File Upload"
659
+ msgstr ""
660
+
661
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:45
662
+ msgid "Theme Icon"
663
+ msgstr ""
664
+
665
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:46
666
+ msgid "Custom Icon"
667
+ msgstr ""
668
+
669
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:47
670
+ #: ../plugin-fw/templates/metaboxes/types/responsivesliders.php:24
671
+ msgid "None"
672
+ msgstr ""
673
+
674
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:57
675
+ msgid "Add field"
676
+ msgstr ""
677
+
678
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:66
679
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:258
680
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:37
681
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:82
682
+ msgid "Remove"
683
+ msgstr ""
684
+
685
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:67
686
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:259
687
+ msgid "Click to toggle"
688
+ msgstr ""
689
+
690
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:74
691
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:266
692
+ msgid "Title Field"
693
+ msgstr ""
694
+
695
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:78
696
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:270
697
+ msgid "Insert the title of field."
698
+ msgstr ""
699
+
700
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:83
701
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:275
702
+ msgid "Data Name"
703
+ msgstr ""
704
+
705
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:87
706
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:279
707
+ msgid ""
708
+ "REQUIRED: The identification name of this field, that you can insert into "
709
+ "body email configuration. <strong>Note:</strong>Use only lowercase "
710
+ "characters and underscores."
711
+ msgstr ""
712
+
713
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:92
714
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:284
715
+ msgid "Type field"
716
+ msgstr ""
717
+
718
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:100
719
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:292
720
+ msgid "Select the type of this field."
721
+ msgstr ""
722
+
723
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:105
724
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:297
725
+ msgid "Checked"
726
+ msgstr ""
727
+
728
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:109
729
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:301
730
+ msgid "Select this if you want this field already checked."
731
+ msgstr ""
732
+
733
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:114
734
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:306
735
+ msgid "Add options "
736
+ msgstr ""
737
+
738
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:115
739
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:307
740
+ msgid "Add option"
741
+ msgstr ""
742
+
743
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:118
744
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:310
745
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:432
746
+ msgid "Selected"
747
+ msgstr ""
748
+
749
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:121
750
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:313
751
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:432
752
+ msgid "Delete option"
753
+ msgstr ""
754
+
755
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:127
756
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:319
757
+ msgid "Message Error"
758
+ msgstr ""
759
+
760
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:131
761
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:323
762
+ msgid "Insert the error message for validation."
763
+ msgstr ""
764
+
765
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:136
766
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:328
767
+ msgid "Required"
768
+ msgstr ""
769
+
770
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:140
771
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:332
772
+ msgid "Select this if it must be required."
773
+ msgstr ""
774
+
775
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:149
776
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:341
777
+ msgid "Select this if it must be a valid email."
778
+ msgstr ""
779
+
780
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:154
781
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:346
782
+ msgid "Reply To"
783
+ msgstr ""
784
+
785
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:158
786
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:350
787
+ msgid "Select this if it's the email where you can reply."
788
+ msgstr ""
789
+
790
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:163
791
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:355
792
+ msgid "Class"
793
+ msgstr ""
794
+
795
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:167
796
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:359
797
+ msgid ""
798
+ "Insert an additional class(es) (separateb by comma) for more personalization."
799
+ msgstr ""
800
+
801
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:172
802
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:364
803
+ msgid "Icon"
804
+ msgstr ""
805
+
806
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:200
807
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:388
808
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:69
809
+ #: ../plugin-fw/templates/metaboxes/types/select-icon.php:33
810
+ #: ../plugin-fw/templates/metaboxes/types/upload.php:21
811
+ #: ../plugin-fw/templates/panel/types/upload.php:31
812
+ #: ../plugin-fw/templates/panel/woocommerce/woocommerce-upload.php:35
813
+ msgid "Upload"
814
+ msgstr ""
815
+
816
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:206
817
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:394
818
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:75
819
+ #: ../plugin-fw/templates/metaboxes/types/select-icon.php:39
820
+ msgid "Image preview"
821
+ msgstr ""
822
+
823
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:214
824
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:402
825
+ msgid "Insert an icon for more personalization."
826
+ msgstr ""
827
+
828
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:219
829
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:406
830
+ msgid "Width"
831
+ msgstr ""
832
+
833
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:244
834
+ #: ../plugin-fw/templates/metaboxes/types/contactform.php:418
835
+ msgid "Choose how much long will be the field."
836
+ msgstr ""
837
+
838
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:28
839
+ msgid "Close all"
840
+ msgstr ""
841
+
842
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:28
843
+ msgid "Expand all"
844
+ msgstr ""
845
+
846
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:52
847
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:95
848
+ msgid "Value"
849
+ msgstr ""
850
+
851
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:53
852
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:96
853
+ msgid "The content of the tab. (HTML is supported)"
854
+ msgstr ""
855
+
856
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:65
857
+ msgid "Add custom product tab"
858
+ msgstr ""
859
+
860
+ #: ../plugin-fw/templates/metaboxes/types/customtabs.php:107
861
+ msgid "Do you want to remove the custom tab?"
862
+ msgstr ""
863
+
864
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:89
865
+ #, php-format
866
+ msgid "(Default: %s <img src=\"%s\"/>)"
867
+ msgstr ""
868
+
869
+ #: ../plugin-fw/templates/metaboxes/types/icon-list.php:91
870
+ #, php-format
871
+ msgid "(Default: <i %s></i> )"
872
+ msgstr ""
873
+
874
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:35
875
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
876
+ #: ../plugin-fw/templates/metaboxes/types/images.php:33
877
+ #: ../plugin-fw/templates/metaboxes/types/images.php:59
878
+ msgid "Delete image"
879
+ msgstr ""
880
+
881
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
882
+ msgid "Add Images to Gallery"
883
+ msgstr ""
884
+
885
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
886
+ msgid "Add to gallery"
887
+ msgstr ""
888
+
889
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
890
+ msgid "Add images"
891
+ msgstr ""
892
+
893
+ #: ../plugin-fw/templates/metaboxes/types/image-gallery.php:40
894
+ msgid "Delete"
895
+ msgstr ""
896
+
897
+ #: ../plugin-fw/templates/metaboxes/types/images.php:37
898
+ msgid "Upload new images"
899
+ msgstr ""
900
+
901
+ #: ../plugin-fw/templates/metaboxes/types/images.php:70
902
+ msgid "Are you sure you want to remove this image?"
903
+ msgstr ""
904
+
905
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:25
906
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:36
907
+ msgid "Left sidebar"
908
+ msgstr ""
909
+
910
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:28
911
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:42
912
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:45
913
+ msgid "No sidebar"
914
+ msgstr ""
915
+
916
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:28
917
+ msgid "No sideabr"
918
+ msgstr ""
919
+
920
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:31
921
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:39
922
+ msgid "Right sidebar"
923
+ msgstr ""
924
+
925
+ #: ../plugin-fw/templates/metaboxes/types/sidebar-layout.php:34
926
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:53
927
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:64
928
+ msgid "Choose a sidebar"
929
+ msgstr ""
930
+
931
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:51
932
+ msgid "Sidebar Left"
933
+ msgstr ""
934
+
935
+ #: ../plugin-fw/templates/metaboxes/types/sidebars.php:62
936
+ msgid "Sidebar Right"
937
+ msgstr ""
938
+
939
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:42
940
+ msgid "px"
941
+ msgstr ""
942
+
943
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:43
944
+ msgid "em"
945
+ msgstr ""
946
+
947
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:44
948
+ msgid "pt"
949
+ msgstr ""
950
+
951
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:45
952
+ msgid "rem"
953
+ msgstr ""
954
+
955
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:59
956
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:153
957
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:217
958
+ msgid "Web fonts"
959
+ msgstr ""
960
+
961
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:71
962
+ msgid "Google fonts"
963
+ msgstr ""
964
+
965
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:96
966
+ msgid "Regular"
967
+ msgstr ""
968
+
969
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:97
970
+ msgid "Bold"
971
+ msgstr ""
972
+
973
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:98
974
+ msgid "Extra bold"
975
+ msgstr ""
976
+
977
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:99
978
+ msgid "Italic"
979
+ msgstr ""
980
+
981
+ #: ../plugin-fw/templates/metaboxes/types/typography.php:100
982
+ msgid "Italic bold"
983
+ msgstr ""
984
+
985
+ #: ../plugin-options/settings-options.php:16
986
+ msgid "Upgrade to the PREMIUM VERSION"
987
+ msgstr ""
988
+
989
+ #: ../plugin-options/settings-options.php:20
990
+ msgid "Discover the Advanced Features"
991
+ msgstr ""
992
+
993
+ #: ../plugin-options/settings-options.php:21
994
+ msgid ""
995
+ "Upgrade to the PREMIUM VERSION of YITH WooCommerce Catalog Mode to benefit "
996
+ "from all features!"
997
+ msgstr ""
998
+
999
+ #: ../plugin-options/settings-options.php:27
1000
+ msgid "Get Support and Pro Features"
1001
+ msgstr ""
1002
+
1003
+ #: ../plugin-options/settings-options.php:28
1004
+ msgid ""
1005
+ "By purchasing the premium version of the plugin, you will take advantage of "
1006
+ "the advanced features of the product and you will get one year of free "
1007
+ "updates and support through our platform available 24h/24."
1008
+ msgstr ""
1009
+
1010
+ #: ../plugin-options/settings-options.php:47
1011
+ #: ../plugin-options/settings-options.php:55
1012
+ msgid "\"Add to cart\" button visibility"
1013
+ msgstr ""
1014
+
1015
+ #: ../plugin-options/settings-options.php:49
1016
+ msgid "Show in product's details page"
1017
+ msgstr ""
1018
+
1019
+ #: ../plugin-options/settings-options.php:57
1020
+ msgid "Show in other pages"
1021
+ msgstr ""
1022
+
1023
+ #: ../plugin-options/settings-options.php:63
1024
+ msgid "\"Cart\" and \"Checkout\" visibility"
1025
+ msgstr ""
1026
+
1027
+ #: ../plugin-options/settings-options.php:65
1028
+ msgid "Show"
1029
+ msgstr ""
plugin-fw/assets/css/chosen/chosen.css ADDED
@@ -0,0 +1,435 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.1.0
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ /* @group Base */
14
+ .chosen-container {
15
+ position: relative;
16
+ display: inline-block;
17
+ vertical-align: middle;
18
+ font-size: 13px;
19
+ zoom: 1;
20
+ *display: inline;
21
+ -webkit-user-select: none;
22
+ -moz-user-select: none;
23
+ user-select: none;
24
+ }
25
+ .chosen-container .chosen-drop {
26
+ position: absolute;
27
+ top: 100%;
28
+ left: -9999px;
29
+ z-index: 1010;
30
+ -webkit-box-sizing: border-box;
31
+ -moz-box-sizing: border-box;
32
+ box-sizing: border-box;
33
+ width: 100%;
34
+ border: 1px solid #aaa;
35
+ border-top: 0;
36
+ background: #fff;
37
+ box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
38
+ }
39
+ .chosen-container.chosen-with-drop .chosen-drop {
40
+ left: 0;
41
+ }
42
+ .chosen-container a {
43
+ cursor: pointer;
44
+ }
45
+
46
+ /* @end */
47
+ /* @group Single Chosen */
48
+ .chosen-container-single .chosen-single {
49
+ position: relative;
50
+ display: block;
51
+ overflow: hidden;
52
+ padding: 0 0 0 8px;
53
+ height: 23px;
54
+ border: 1px solid #aaa;
55
+ border-radius: 5px;
56
+ background-color: #fff;
57
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
58
+ background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
59
+ background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
60
+ background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
61
+ background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
62
+ background-clip: padding-box;
63
+ box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
64
+ color: #444;
65
+ text-decoration: none;
66
+ white-space: nowrap;
67
+ line-height: 24px;
68
+ }
69
+ .chosen-container-single .chosen-default {
70
+ color: #999;
71
+ }
72
+ .chosen-container-single .chosen-single span {
73
+ display: block;
74
+ overflow: hidden;
75
+ margin-right: 26px;
76
+ text-overflow: ellipsis;
77
+ white-space: nowrap;
78
+ }
79
+ .chosen-container-single .chosen-single-with-deselect span {
80
+ margin-right: 38px;
81
+ }
82
+ .chosen-container-single .chosen-single abbr {
83
+ position: absolute;
84
+ top: 6px;
85
+ right: 26px;
86
+ display: block;
87
+ width: 12px;
88
+ height: 12px;
89
+ background: url('../../images/chosen/chosen-sprite.png') -42px 1px no-repeat;
90
+ font-size: 1px;
91
+ }
92
+ .chosen-container-single .chosen-single abbr:hover {
93
+ background-position: -42px -10px;
94
+ }
95
+ .chosen-container-single.chosen-disabled .chosen-single abbr:hover {
96
+ background-position: -42px -10px;
97
+ }
98
+ .chosen-container-single .chosen-single div {
99
+ position: absolute;
100
+ top: 0;
101
+ right: 0;
102
+ display: block;
103
+ width: 18px;
104
+ height: 100%;
105
+ }
106
+ .chosen-container-single .chosen-single div b {
107
+ display: block;
108
+ width: 100%;
109
+ height: 100%;
110
+ background: url('../../images/chosen/chosen-sprite.png') no-repeat 0px 2px;
111
+ }
112
+ .chosen-container-single .chosen-search {
113
+ position: relative;
114
+ z-index: 1010;
115
+ margin: 0;
116
+ padding: 3px 4px;
117
+ white-space: nowrap;
118
+ }
119
+ .chosen-container-single .chosen-search input[type="text"] {
120
+ -webkit-box-sizing: border-box;
121
+ -moz-box-sizing: border-box;
122
+ box-sizing: border-box;
123
+ margin: 1px 0;
124
+ padding: 4px 20px 4px 5px;
125
+ width: 100%;
126
+ height: auto;
127
+ outline: 0;
128
+ border: 1px solid #aaa;
129
+ background: white url('../../images/chosen/chosen-sprite.png') no-repeat 100% -20px;
130
+ background: url('../../images/chosen/chosen-sprite.png') no-repeat 100% -20px;
131
+ font-size: 1em;
132
+ font-family: sans-serif;
133
+ line-height: normal;
134
+ border-radius: 0;
135
+ }
136
+ .chosen-container-single .chosen-drop {
137
+ margin-top: -1px;
138
+ border-radius: 0 0 4px 4px;
139
+ background-clip: padding-box;
140
+ }
141
+ .chosen-container-single.chosen-container-single-nosearch .chosen-search {
142
+ position: absolute;
143
+ left: -9999px;
144
+ }
145
+
146
+ /* @end */
147
+ /* @group Results */
148
+ .chosen-container .chosen-results {
149
+ position: relative;
150
+ overflow-x: hidden;
151
+ overflow-y: auto;
152
+ margin: 0 4px 4px 0;
153
+ padding: 0 0 0 4px;
154
+ max-height: 240px;
155
+ -webkit-overflow-scrolling: touch;
156
+ }
157
+ .chosen-container .chosen-results li {
158
+ display: none;
159
+ margin: 0;
160
+ padding: 5px 6px;
161
+ list-style: none;
162
+ line-height: 15px;
163
+ -webkit-touch-callout: none;
164
+ }
165
+ .chosen-container .chosen-results li.active-result {
166
+ display: list-item;
167
+ cursor: pointer;
168
+ }
169
+ .chosen-container .chosen-results li.disabled-result {
170
+ display: list-item;
171
+ color: #ccc;
172
+ cursor: default;
173
+ }
174
+ .chosen-container .chosen-results li.highlighted {
175
+ background-color: #3875d7;
176
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
177
+ background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
178
+ background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
179
+ background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
180
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
181
+ color: #fff;
182
+ }
183
+ .chosen-container .chosen-results li.no-results {
184
+ display: list-item;
185
+ background: #f4f4f4;
186
+ }
187
+ .chosen-container .chosen-results li.group-result {
188
+ display: list-item;
189
+ font-weight: bold;
190
+ cursor: default;
191
+ }
192
+ .chosen-container .chosen-results li.group-option {
193
+ padding-left: 15px;
194
+ }
195
+ .chosen-container .chosen-results li em {
196
+ font-style: normal;
197
+ text-decoration: underline;
198
+ }
199
+
200
+ /* @end */
201
+ /* @group Multi Chosen */
202
+ .chosen-container-multi .chosen-choices {
203
+ position: relative;
204
+ overflow: hidden;
205
+ -webkit-box-sizing: border-box;
206
+ -moz-box-sizing: border-box;
207
+ box-sizing: border-box;
208
+ margin: 0;
209
+ padding: 0;
210
+ width: 100%;
211
+ height: auto !important;
212
+ height: 1%;
213
+ border: 1px solid #aaa;
214
+ background-color: #fff;
215
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
216
+ background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
217
+ background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
218
+ background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
219
+ background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
220
+ cursor: text;
221
+ }
222
+ .chosen-container-multi .chosen-choices li {
223
+ float: left;
224
+ list-style: none;
225
+ }
226
+ .chosen-container-multi .chosen-choices li.search-field {
227
+ margin: 0;
228
+ padding: 0;
229
+ white-space: nowrap;
230
+ }
231
+ .chosen-container-multi .chosen-choices li.search-field input[type="text"] {
232
+ margin: 1px 0;
233
+ padding: 5px;
234
+ height: 15px;
235
+ outline: 0;
236
+ border: 0 !important;
237
+ background: transparent !important;
238
+ box-shadow: none;
239
+ color: #666;
240
+ font-size: 100%;
241
+ font-family: sans-serif;
242
+ line-height: normal;
243
+ border-radius: 0;
244
+ }
245
+ .chosen-container-multi .chosen-choices li.search-field .default {
246
+ color: #999;
247
+ }
248
+ .chosen-container-multi .chosen-choices li.search-choice {
249
+ position: relative;
250
+ margin: 3px 0 3px 5px;
251
+ padding: 3px 20px 3px 5px;
252
+ border: 1px solid #aaa;
253
+ border-radius: 3px;
254
+ background-color: #e4e4e4;
255
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
256
+ background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
257
+ background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
258
+ background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
259
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
260
+ background-clip: padding-box;
261
+ box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
262
+ color: #333;
263
+ line-height: 13px;
264
+ cursor: default;
265
+ }
266
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
267
+ position: absolute;
268
+ top: 4px;
269
+ right: 3px;
270
+ display: block;
271
+ width: 12px;
272
+ height: 12px;
273
+ background: url('../../images/chosen/chosen-sprite.png') -42px 1px no-repeat;
274
+ font-size: 1px;
275
+ }
276
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
277
+ background-position: -42px -10px;
278
+ }
279
+ .chosen-container-multi .chosen-choices li.search-choice-disabled {
280
+ padding-right: 5px;
281
+ border: 1px solid #ccc;
282
+ background-color: #e4e4e4;
283
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
284
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
285
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
286
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
287
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
288
+ color: #666;
289
+ }
290
+ .chosen-container-multi .chosen-choices li.search-choice-focus {
291
+ background: #d4d4d4;
292
+ }
293
+ .chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
294
+ background-position: -42px -10px;
295
+ }
296
+ .chosen-container-multi .chosen-results {
297
+ margin: 0;
298
+ padding: 0;
299
+ }
300
+ .chosen-container-multi .chosen-drop .result-selected {
301
+ display: list-item;
302
+ color: #ccc;
303
+ cursor: default;
304
+ }
305
+
306
+ /* @end */
307
+ /* @group Active */
308
+ .chosen-container-active .chosen-single {
309
+ border: 1px solid #5897fb;
310
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
311
+ }
312
+ .chosen-container-active.chosen-with-drop .chosen-single {
313
+ border: 1px solid #aaa;
314
+ -moz-border-radius-bottomright: 0;
315
+ border-bottom-right-radius: 0;
316
+ -moz-border-radius-bottomleft: 0;
317
+ border-bottom-left-radius: 0;
318
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
319
+ background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
320
+ background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
321
+ background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
322
+ background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
323
+ box-shadow: 0 1px 0 #fff inset;
324
+ }
325
+ .chosen-container-active.chosen-with-drop .chosen-single div {
326
+ border-left: none;
327
+ background: transparent;
328
+ }
329
+ .chosen-container-active.chosen-with-drop .chosen-single div b {
330
+ background-position: -18px 2px;
331
+ }
332
+ .chosen-container-active .chosen-choices {
333
+ border: 1px solid #5897fb;
334
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
335
+ }
336
+ .chosen-container-active .chosen-choices li.search-field input[type="text"] {
337
+ color: #111 !important;
338
+ }
339
+
340
+ /* @end */
341
+ /* @group Disabled Support */
342
+ .chosen-disabled {
343
+ opacity: 0.5 !important;
344
+ cursor: default;
345
+ }
346
+ .chosen-disabled .chosen-single {
347
+ cursor: default;
348
+ }
349
+ .chosen-disabled .chosen-choices .search-choice .search-choice-close {
350
+ cursor: default;
351
+ }
352
+
353
+ /* @end */
354
+ /* @group Right to Left */
355
+ .chosen-rtl {
356
+ text-align: right;
357
+ }
358
+ .chosen-rtl .chosen-single {
359
+ overflow: visible;
360
+ padding: 0 8px 0 0;
361
+ }
362
+ .chosen-rtl .chosen-single span {
363
+ margin-right: 0;
364
+ margin-left: 26px;
365
+ direction: rtl;
366
+ }
367
+ .chosen-rtl .chosen-single-with-deselect span {
368
+ margin-left: 38px;
369
+ }
370
+ .chosen-rtl .chosen-single div {
371
+ right: auto;
372
+ left: 3px;
373
+ }
374
+ .chosen-rtl .chosen-single abbr {
375
+ right: auto;
376
+ left: 26px;
377
+ }
378
+ .chosen-rtl .chosen-choices li {
379
+ float: right;
380
+ }
381
+ .chosen-rtl .chosen-choices li.search-field input[type="text"] {
382
+ direction: rtl;
383
+ }
384
+ .chosen-rtl .chosen-choices li.search-choice {
385
+ margin: 3px 5px 3px 0;
386
+ padding: 3px 5px 3px 19px;
387
+ }
388
+ .chosen-rtl .chosen-choices li.search-choice .search-choice-close {
389
+ right: auto;
390
+ left: 4px;
391
+ }
392
+ .chosen-rtl.chosen-container-single-nosearch .chosen-search,
393
+ .chosen-rtl .chosen-drop {
394
+ left: 9999px;
395
+ }
396
+ .chosen-rtl.chosen-container-single .chosen-results {
397
+ margin: 0 0 4px 4px;
398
+ padding: 0 4px 0 0;
399
+ }
400
+ .chosen-rtl .chosen-results li.group-option {
401
+ padding-right: 15px;
402
+ padding-left: 0;
403
+ }
404
+ .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
405
+ border-right: none;
406
+ }
407
+ .chosen-rtl .chosen-search input[type="text"] {
408
+ padding: 4px 5px 4px 20px;
409
+ background: white url('../../images/chosen/chosen-sprite.png') no-repeat -30px -20px;
410
+ background: url('../../images/chosen/chosen-sprite.png') no-repeat -30px -20px;
411
+ direction: rtl;
412
+ }
413
+ .chosen-rtl.chosen-container-single .chosen-single div b {
414
+ background-position: 6px 2px;
415
+ }
416
+ .chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
417
+ background-position: -12px 2px;
418
+ }
419
+
420
+ /* @end */
421
+ /* @group Retina compatibility */
422
+ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
423
+ .chosen-rtl .chosen-search input[type="text"],
424
+ .chosen-container-single .chosen-single abbr,
425
+ .chosen-container-single .chosen-single div b,
426
+ .chosen-container-single .chosen-search input[type="text"],
427
+ .chosen-container-multi .chosen-choices .search-choice .search-choice-close,
428
+ .chosen-container .chosen-results-scroll-down span,
429
+ .chosen-container .chosen-results-scroll-up span {
430
+ background-image: url('../../images/chosen/chosen-sprite@2x.png') !important;
431
+ background-size: 52px 37px !important;
432
+ background-repeat: no-repeat !important;
433
+ }
434
+ }
435
+ /* @end */
plugin-fw/assets/css/codemirror/codemirror.css ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* BASICS */
2
+
3
+ .CodeMirror {
4
+ /* Set height, width, borders, and global font properties here */
5
+ font-family: monospace;
6
+ height: 400px;
7
+ clear: both;
8
+ padding: 0;
9
+ }
10
+ .CodeMirror-scroll {
11
+ /* Set scrolling behaviour here */
12
+ overflow: auto;
13
+ }
14
+
15
+ /* PADDING */
16
+
17
+ .CodeMirror-lines {
18
+ padding: 4px 0; /* Vertical padding around content */
19
+ }
20
+ .CodeMirror pre {
21
+ padding: 0 4px; /* Horizontal padding of content */
22
+ }
23
+
24
+ .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
25
+ background-color: white; /* The little square between H and V scrollbars */
26
+ }
27
+
28
+ /* GUTTER */
29
+
30
+ .CodeMirror-gutters {
31
+ border-right: 1px solid #ddd;
32
+ background-color: #f7f7f7;
33
+ white-space: nowrap;
34
+ }
35
+ .CodeMirror-linenumbers {}
36
+ .CodeMirror-linenumber {
37
+ padding: 0 3px 0 5px;
38
+ min-width: 20px;
39
+ text-align: right;
40
+ color: #999;
41
+ }
42
+
43
+ /* CURSOR */
44
+
45
+ .CodeMirror div.CodeMirror-cursor {
46
+ border-left: 1px solid black;
47
+ z-index: 3;
48
+ }
49
+ /* Shown when moving in bi-directional text */
50
+ .CodeMirror div.CodeMirror-secondarycursor {
51
+ border-left: 1px solid silver;
52
+ }
53
+ .CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
54
+ width: auto;
55
+ border: 0;
56
+ background: #7e7;
57
+ z-index: 1;
58
+ }
59
+ /* Can style cursor different in overwrite (non-insert) mode */
60
+ .CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
61
+
62
+ .cm-tab { display: inline-block; }
63
+
64
+ /* DEFAULT THEME */
65
+
66
+ .cm-s-default .cm-keyword {color: #708;}
67
+ .cm-s-default .cm-atom {color: #219;}
68
+ .cm-s-default .cm-number {color: #164;}
69
+ .cm-s-default .cm-def {color: #00f;}
70
+ .cm-s-default .cm-variable {color: black;}
71
+ .cm-s-default .cm-variable-2 {color: #05a;}
72
+ .cm-s-default .cm-variable-3 {color: #085;}
73
+ .cm-s-default .cm-property {color: black;}
74
+ .cm-s-default .cm-operator {color: black;}
75
+ .cm-s-default .cm-comment {color: #a50;}
76
+ .cm-s-default .cm-string {color: #a11;}
77
+ .cm-s-default .cm-string-2 {color: #f50;}
78
+ .cm-s-default .cm-meta {color: #555;}
79
+ .cm-s-default .cm-error {color: #f00;}
80
+ .cm-s-default .cm-qualifier {color: #555;}
81
+ .cm-s-default .cm-builtin {color: #30a;}
82
+ .cm-s-default .cm-bracket {color: #997;}
83
+ .cm-s-default .cm-tag {color: #170;}
84
+ .cm-s-default .cm-attribute {color: #00c;}
85
+ .cm-s-default .cm-header {color: blue;}
86
+ .cm-s-default .cm-quote {color: #090;}
87
+ .cm-s-default .cm-hr {color: #999;}
88
+ .cm-s-default .cm-link {color: #00c;}
89
+
90
+ .cm-negative {color: #d44;}
91
+ .cm-positive {color: #292;}
92
+ .cm-header, .cm-strong {font-weight: bold;}
93
+ .cm-em {font-style: italic;}
94
+ .cm-link {text-decoration: underline;}
95
+
96
+ .cm-invalidchar {color: #f00;}
97
+
98
+ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
99
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
100
+
101
+ /* STOP */
102
+
103
+ /* The rest of this file contains styles related to the mechanics of
104
+ the editor. You probably shouldn't touch them. */
105
+
106
+ .CodeMirror {
107
+ line-height: 1;
108
+ position: relative;
109
+ overflow: hidden;
110
+ background: #fafafa;
111
+ color: black;
112
+ }
113
+
114
+ .CodeMirror-scroll {
115
+ /* 30px is the magic margin used to hide the element's real scrollbars */
116
+ /* See overflow: hidden in .CodeMirror */
117
+ margin-bottom: -30px; margin-right: -30px;
118
+ padding-bottom: 30px; padding-right: 30px;
119
+ height: 100%;
120
+ outline: none; /* Prevent dragging from highlighting the element */
121
+ position: relative;
122
+ }
123
+ .CodeMirror-sizer {
124
+ position: relative;
125
+ }
126
+
127
+ /* The fake, visible scrollbars. Used to force redraw during scrolling
128
+ before actuall scrolling happens, thus preventing shaking and
129
+ flickering artifacts. */
130
+ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
131
+ position: absolute;
132
+ z-index: 6;
133
+ display: none;
134
+ }
135
+ .CodeMirror-vscrollbar {
136
+ right: 0; top: 0;
137
+ overflow-x: hidden;
138
+ overflow-y: scroll;
139
+ }
140
+ .CodeMirror-hscrollbar {
141
+ bottom: 0; left: 0;
142
+ overflow-y: hidden;
143
+ overflow-x: scroll;
144
+ }
145
+ .CodeMirror-scrollbar-filler {
146
+ right: 0; bottom: 0;
147
+ }
148
+ .CodeMirror-gutter-filler {
149
+ left: 0; bottom: 0;
150
+ }
151
+
152
+ .CodeMirror-gutters {
153
+ position: absolute; left: 0; top: 0;
154
+ padding-bottom: 30px;
155
+ z-index: 3;
156
+ }
157
+ .CodeMirror-gutter {
158
+ white-space: normal;
159
+ height: 100%;
160
+ padding-bottom: 30px;
161
+ margin-bottom: -32px;
162
+ display: inline-block;
163
+ /* Hack to make IE7 behave */
164
+ *zoom:1;
165
+ *display:inline;
166
+ }
167
+ .CodeMirror-gutter-elt {
168
+ position: absolute;
169
+ cursor: default;
170
+ z-index: 4;
171
+ }
172
+
173
+ .CodeMirror-lines {
174
+ cursor: text;
175
+ }
176
+ .CodeMirror pre {
177
+ /* Reset some styles that the rest of the page might have set */
178
+ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
179
+ border-width: 0;
180
+ background: transparent;
181
+ font-family: inherit;
182
+ font-size: inherit;
183
+ margin: 0;
184
+ white-space: pre;
185
+ word-wrap: normal;
186
+ line-height: inherit;
187
+ color: inherit;
188
+ z-index: 2;
189
+ position: relative;
190
+ overflow: visible;
191
+ }
192
+ .CodeMirror-wrap pre {
193
+ word-wrap: break-word;
194
+ white-space: pre-wrap;
195
+ word-break: normal;
196
+ }
197
+ .CodeMirror-code pre {
198
+ border-right: 30px solid transparent;
199
+ width: -webkit-fit-content;
200
+ width: -moz-fit-content;
201
+ width: fit-content;
202
+ }
203
+ .CodeMirror-wrap .CodeMirror-code pre {
204
+ border-right: none;
205
+ width: auto;
206
+ }
207
+ .CodeMirror-linebackground {
208
+ position: absolute;
209
+ left: 0; right: 0; top: 0; bottom: 0;
210
+ z-index: 0;
211
+ }
212
+
213
+ .CodeMirror-linewidget {
214
+ position: relative;
215
+ z-index: 2;
216
+ overflow: auto;
217
+ }
218
+
219
+ .CodeMirror-widget {
220
+ }
221
+
222
+ .CodeMirror-wrap .CodeMirror-scroll {
223
+ overflow-x: hidden;
224
+ }
225
+
226
+ .CodeMirror-measure {
227
+ position: absolute;
228
+ width: 100%; height: 0px;
229
+ overflow: hidden;
230
+ visibility: hidden;
231
+ }
232
+ .CodeMirror-measure pre { position: static; }
233
+
234
+ .CodeMirror div.CodeMirror-cursor {
235
+ position: absolute;
236
+ visibility: hidden;
237
+ border-right: none;
238
+ width: 0;
239
+ }
240
+ .CodeMirror-focused div.CodeMirror-cursor {
241
+ visibility: visible;
242
+ }
243
+
244
+ .CodeMirror-selected { background: #d9d9d9; }
245
+ .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
246
+
247
+ .cm-searching {
248
+ background: #ffa;
249
+ background: rgba(255, 255, 0, .4);
250
+ }
251
+
252
+ /* IE7 hack to prevent it from returning funny offsetTops on the spans */
253
+ .CodeMirror span { *vertical-align: text-bottom; }
254
+
255
+ @media print {
256
+ /* Hide the cursor when printing */
257
+ .CodeMirror div.CodeMirror-cursor {
258
+ visibility: hidden;
259
+ }
260
+ }
plugin-fw/assets/css/metaboxes.css ADDED
@@ -0,0 +1,598 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* self-clear floats */
2
+ .clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden; overflow:hidden; }
3
+ /* ie.css */
4
+ * html .clearfix { /* IE6 */
5
+ height:1%;
6
+ }
7
+ *:first-child+html .clearfix { /* IE7 */
8
+ min-height:1%;
9
+ }
10
+
11
+ .clearboth { clear: both }
12
+
13
+ /* === TAB STYLE */
14
+ .metaboxes-tab { margin:-6px -12px -8px; }
15
+ .metaboxes-tab div.tabs-panel { height:auto; overflow:visible; margin-top:0px; padding:0 10px; background:none; border:0; border-top:1px solid #D4D4D4; }
16
+ .metaboxes-tab ul.metaboxes-tabs { background:#F5F5F5; margin:0; padding:10px 0 0 5px; }
17
+ .metaboxes-tab ul.metaboxes-tabs li { padding:8px 15px; border:1px solid #D4D4D4; float:left; background:#EDEDED; border-bottom-color:#EDEDED; margin:0 0 -1px 5px; box-shadow:1px 1px 1px 0 #FFFFFF inset; }
18
+ .metaboxes-tab ul.metaboxes-tabs li a { color:#555; text-decoration:none; }
19
+ .metaboxes-tab ul.metaboxes-tabs li.tabs { background:#F6F6F6; border-bottom:1px solid #F6F6F6; }
20
+ .metaboxes-tab p.field-row { margin:20px 0; }
21
+ .metaboxes-tab div.sep { height:1px; background:#DFDFDF; clear:both; margin-left:-10px; margin-right:-10px; }
22
+ .metaboxes-tab label { font-weight:bold; width:160px; float:left; line-height:23px; margin-left:-184px; }
23
+ .metaboxes-tab label small { font-weight:normal; line-height:15px; font-style:italic; color:#999; display:block; }
24
+ .metaboxes-tab input[type="text"], .metaboxes-tab select, .metaboxes-tab textarea { width:30%; }
25
+ .metaboxes-tab input[type="checkbox"] { vertical-align: middle }
26
+ .metaboxes-tab select {padding:0;}
27
+ .metaboxes-tab input.button-secondary, .metaboxes-tab input.checkbox { width:auto; }
28
+ .metaboxes-tab .description { color:#AFAFAF; font-size:90%; font-style:italic; line-height:23px; padding-left:5px; }
29
+ .metaboxes-tab p.field-row.textarea .description { vertical-align:top; }
30
+ .metaboxes-tab p.field-row.checkbox {background:none;}
31
+
32
+ .metaboxes-tab .the-metabox { margin:20px 0; margin-left:184px;}
33
+ .metaboxes-tab .the-metabox.no-label { margin:20px 0; margin-left:0;}
34
+ .metaboxes-tab hr { height: 0px; border-top: 1px solid #dadada; width: auto; margin-left: -10px; margin-right: -10px; }
35
+ .metaboxes-tab .the-metabox p { margin:0;}
36
+ .metaboxes-tab .the-metabox:last-child { border-bottom: 0px; }
37
+ .metaboxes-tab .the-metabox.checkbox { background:none; }
38
+ .metaboxes-tab .the-metabox.slider .ui-slider { margin-right:15px; }
39
+
40
+ .metaboxes-tab span.desc { font-size: 11px; color: #AFAFAF; }
41
+ .metaboxes-tab span.desc.inline { display: inline-block; vertical-align: top; line-height: 23px; }
42
+ .metaboxes-tab .onoff span.desc, .metaboxes-tab .onoff label { padding:6px 0; }
43
+ .metaboxes-tab .select span.desc, .metaboxes-tab .select label { padding:2px 0; }
44
+ .metaboxes-tab .slider span.desc, .metaboxes-tab .slider label { padding:15px 0; }
45
+ .metaboxes-tab .slider span.desc { display:block; padding:20px 0; }
46
+
47
+ .metaboxes-tab ul.metaboxes-tabs li {
48
+ -webkit-border-top-left-radius: 3px;
49
+ -webkit-border-top-right-radius: 3px;
50
+ -moz-border-radius-topleft: 3px;
51
+ -moz-border-radius-topright: 3px;
52
+ border-top-left-radius: 3px;
53
+ border-top-right-radius: 3px;
54
+ }
55
+
56
+ /* image gallery */
57
+ .metaboxes-tab .image-gallery ul li{
58
+ display: inline-block;
59
+ width: 80px;
60
+ margin-left: 10px;
61
+ position: relative;
62
+ }
63
+ .metaboxes-tab .image-gallery ul li img{
64
+ width: 80px;
65
+ border: 1px solid #ccc;
66
+ }
67
+ .metaboxes-tab .image-gallery ul li ul{
68
+ position: absolute;
69
+ top: -6px;
70
+ right: -1px;
71
+ width: 20px;
72
+ height: 20px;
73
+ }
74
+ .metaboxes-tab .image-gallery ul a.delete{
75
+ background: url(../images/x.png) no-repeat;
76
+ width: 20px;
77
+ height: 20px;
78
+ display: block;
79
+ text-indent: -99999px;
80
+ }
81
+ /* sidebar layout */
82
+ .yit-sidebar-layout input[type="radio"] {
83
+ display: none;
84
+ width: 0px;
85
+ }
86
+ .yit-sidebar-layout input[type="radio"]:first-child {
87
+ margin-right: -2px;
88
+ }
89
+
90
+ .yit-sidebar-layout input[type="radio"] + img {
91
+ border: 2px solid #fff;
92
+ padding: 1px;
93
+ }
94
+
95
+ .yit-sidebar-layout input[type="radio"] + img:hover {
96
+ cursor: pointer;
97
+ }
98
+
99
+ .yit-sidebar-layout input[checked] + img {
100
+ border: 2px solid #f2ad35;
101
+ padding: 1px;
102
+ }
103
+
104
+ .yit-sidebar-layout select {
105
+ vertical-align: 12px;
106
+ width: inherit !important;
107
+ }
108
+
109
+ /* wp editor */
110
+ .the-metabox.textarea-editor .mceIframeContainer {
111
+ background:#fff;
112
+ }
113
+ .the-metabox.textarea-editor label {
114
+ margin-top:24px;
115
+ }
116
+
117
+ /* categories */
118
+ .categories-panel { width:30%; float:left; margin-right:4px; }
119
+ .categories-panel .box { height:200px; border:1px solid #DFDFDF; background:#fff; padding:6px 10px; overflow: auto; }
120
+ .categories-panel ul { list-style:none; margin:0; }
121
+ .categories-panel ul li { line-height: 19px; margin: 0; padding: 0; word-wrap: break-word; }
122
+ .categories-panel ul li label { font-weight:normal !important; margin-left:0 !important; }
123
+ .categories-panel input.newcategory { width:100%; margin-bottom:3px; }
124
+
125
+ /* contact form */
126
+ .contactform_item {
127
+ border-style: solid;
128
+ border-width: 1px;
129
+ line-height: 1;
130
+ margin-bottom: 20px;
131
+ padding: 0;
132
+ background-color: #F5F5F5;
133
+ background-image: -moz-linear-gradient(center top , #F9F9F9, #F5F5F5);
134
+ border-color: #DFDFDF;
135
+ border-radius: 3px 3px 3px 3px;
136
+ box-shadow: 0 1px 0 #FFFFFF inset;
137
+ min-width: 255px;
138
+ position: relative;
139
+ }
140
+ .contactform_item .handlediv { position:relative; top: -4px; }
141
+ .contactform_item h3 { min-height: 21px }
142
+ .contactform_item .inside { padding: 10px !important; }
143
+ .contactform_item .deps { display: none; }
144
+ .contactform_item .addoptions p.option { margin: 5px 0 5px 200px }
145
+ .contactform_item .addoptions p label { width: 80px !important; }
146
+ .contactform_item .add-field-option { margin-bottom: 10px !important; }
147
+ .remove_item { float: right; }
148
+ .metabox-sortable-placeholder { border: 1px dotted #dedede; margin: 10px 0 }
149
+
150
+ /* features tab */
151
+ .featurestab_item{
152
+ border-style: solid;
153
+ border-width: 1px;
154
+ line-height: 1;
155
+ margin-bottom: 20px;
156
+ padding: 0;
157
+ background-color: #F5F5F5;
158
+ background-image: -moz-linear-gradient(center top , #F9F9F9, #F5F5F5);
159
+ border-color: #DFDFDF;
160
+ border-radius: 3px 3px 3px 3px;
161
+ box-shadow: 0 1px 0 #FFFFFF inset;
162
+ min-width: 255px;
163
+ position: relative;
164
+ }
165
+ .featurestab_item .handlediv { position:relative; top: -4px; }
166
+ .featurestab_item h3 { min-height: 21px }
167
+ .featurestab_item .inside { padding: 10px !important; }
168
+ .featurestab_item .deps { display: none; }
169
+ .featurestab_item .addoptions p.option { margin: 5px 0 5px 200px }
170
+ .featurestab_item .addoptions p label { width: 80px !important; }
171
+ .featurestab_item .add-field-option { margin-bottom: 10px !important; }
172
+
173
+ /* slider */
174
+ .the-metabox.slider { padding-top:20px; }
175
+
176
+ /* on off */
177
+ .the-metabox .rm_onoff span.onoff { float:left; margin-right:5px; margin-left:-4px; /* image fix */ }
178
+
179
+ /* select */
180
+ .the-metabox .select_wrapper { width:341px; background-color:#fff; }
181
+ .the-metabox .select_wrapper select { width:100%; }
182
+ .the-metabox .icon_type{ width:30%; float: left; margin-right: 40px }
183
+ .the-metabox .icon_type select, .the-metabox div.option .select_wrapper select{ width: 100% }
184
+
185
+ #post-type-settings .category-list label { width: 187px; }
186
+ .remove_cat { float: right; text-align:center; display: block; width: 20px; height: 20px; border-radius: 20px; font-weight: bold; font-size: 10px; background: #efefef; text-decoration: none; }
187
+
188
+ .the-metabox .select_wrapper {
189
+ background: url("../images/select.png") no-repeat scroll right center #FAFAFA;
190
+ border-color: #CCCCCC #EEEEEE #EEEEEE #CCCCCC;
191
+ border-radius: 4px 4px 4px 4px;
192
+ border-style: solid;
193
+ border-width: 1px;
194
+ color: #555555;
195
+ display: block;
196
+ float: left;
197
+ font-family: sans-serif;
198
+ font-size: 12px;
199
+ min-height: 26px;
200
+ margin-bottom: 9px !important;
201
+ margin-left: 0;
202
+ margin-right: 5px;
203
+ margin-top: 0;
204
+ width: 400px;
205
+ position: relative;
206
+ }
207
+
208
+ /*chosen*/
209
+
210
+ .chosen .select_wrapper {
211
+ background: none;
212
+ border: none;
213
+ }
214
+ .chosen .select_wrapper .chosen-container{
215
+ width: 338px!important;
216
+ }
217
+ .chosen .select_wrapper .chosen-container .search-field input{
218
+ height: 27px!important;
219
+ color: #333;
220
+ }
221
+ .chosen .select_wrapper .chosen-container .chosen-choices{
222
+ border: 1px solid #ddd;
223
+ box-shadow: none;
224
+ }
225
+ .chosen .select_wrapper .chosen-container .chosen-choices li.search-choice{
226
+ height: 15px!important;
227
+ min-width: 105px;
228
+ }
229
+ .chosen .select_wrapper .chosen-container .chosen-choices li.search-choice span{
230
+ line-height: 15px;
231
+ height: 15px;
232
+ padding-top: 2px;
233
+ }
234
+ .chosen .select_wrapper .chosen-container .chosen-choices li.search-choice a.search-choice-close{
235
+ top: 5px;
236
+ }
237
+ .chosen .select_wrapper .chosen-container .chosen-drop .chosen-search input{
238
+ width: 100%!important;
239
+ }
240
+
241
+ /* typography */
242
+ .the-metabox.typography .select_wrapper.font-family { width:200px; }
243
+ .the-metabox.typography .spinner_container { float:left; margin-right:10px; }
244
+ .the-metabox.typography .spinner_container input.number {
245
+ width:50px !important;
246
+ -webkit-border-top-right-radius: 0px;
247
+ -webkit-border-bottom-right-radius: 0px;
248
+ -moz-border-radius-topright: 0px;
249
+ -moz-border-radius-bottomright: 0px;
250
+ border-top-right-radius: 0px;
251
+ border-bottom-right-radius: 0px;
252
+ }
253
+
254
+ /* number */
255
+ .the-metabox.number input.number { width:50px !important; }
256
+ /* number */
257
+ .rm_number .number {
258
+ width: 70px;
259
+ text-align: right;
260
+ -webkit-border-top-right-radius: 0px;
261
+ -webkit-border-bottom-right-radius: 0px;
262
+ -moz-border-radius-topright: 0px;
263
+ -moz-border-radius-bottomright: 0px;
264
+ border-top-right-radius: 0px;
265
+ border-bottom-right-radius: 0px;
266
+ }
267
+
268
+ .spinner-wrapper { position: relative; height: 23px; overflow: hidden; }
269
+ .spinner-wrapper input.number { float: left; }
270
+ .spinner-wrapper .spinner-button { cursor:pointer; float: left; position: absolute; left: 69px; width: 15px; height: 12px; border: 1px solid #DFDFDF; background: #fff; margin: 0; padding: 0; line-height: 9999px; overflow: hidden; background: url('../images/spinner.png') no-repeat center -11px }
271
+ .spinner-wrapper .spinner-button.button-plus { top: 0; -webkit-border-top-right-radius: 3px !important; -moz-border-radius-topright: 3px !important; border-top-right-radius: 3px !important; }
272
+ .spinner-wrapper .spinner-button.button-minus { bottom: 0; background-position: center -30px; -webkit-border-bottom-right-radius: 3px !important; -moz-border-radius-bottomright: 3px !important; border-bottom-right-radius: 3px !important; }
273
+
274
+
275
+ .spinner-wrapper .spinner-button.button-plus:active { background-position: center 0px; }
276
+ .spinner-wrapper .spinner-button.button-minus:active { background-position: center -20px; }
277
+
278
+
279
+ .rm_typography .spinner_container { float: left; margin-right: 10px; }
280
+ .rm_typography .spinner-wrapper { height: 28px; }
281
+ .rm_typography .spinner-wrapper input.number { height: 28px; }
282
+ .rm_typography .spinner-wrapper .spinner-button.button-plus { height: 15px; background-position: center -10px; }
283
+ .rm_typography .spinner-wrapper .spinner-button.button-minus { height: 14px; }
284
+
285
+ .the-metabox .spinner-wrapper .spinner-button { left: 49px; }
286
+ .the-metabox.typography .spinner-wrapper .spinner-button { left: 35px; }
287
+
288
+ /* colorpicker */
289
+ .the-metabox.colorpicker { display:block; width: auto; height: auto; overflow: visible; background-image: none; position: static; font-family: inherit;}
290
+ .the-metabox.colorpicker input { background-color: transparent; border: 1px solid #DFDFDF; position: static; font-size: inherit; font-family: inherit; color: inherit; text-align: center; margin: 0 5px 0px; padding: 0; outline: none; width: auto; }
291
+
292
+ /* images */
293
+ .the-metabox.images, .the-metabox.images label { margin-left:0; display:block; }
294
+ .the-metabox.images .slides-wrapper { clear:both; }
295
+ .the-metabox.images .slides-wrapper li { position:relative; }
296
+ .the-metabox.images a.delete { display:block; margin-left:4px; text-decoration:none; font-weight:bold; color:red; position:absolute; top:0; right:0; width:10px; height:18px; z-index:10; cursor:pointer !important; }
297
+
298
+ /* wp editor */
299
+ .wp_themeSkin iframe { background: #fff !important; }
300
+
301
+ /* custom tabs */
302
+ .customtab_item {
303
+ border-style: solid;
304
+ border-width: 1px;
305
+ line-height: 1;
306
+ margin-bottom: 20px;
307
+ padding: 0;
308
+ background-color: #F5F5F5;
309
+ background-image: -moz-linear-gradient(center top , #F9F9F9, #F5F5F5);
310
+ border-color: #DFDFDF;
311
+ border-radius: 3px 3px 3px 3px;
312
+ box-shadow: 0 1px 0 #FFFFFF inset;
313
+ min-width: 255px;
314
+ position: relative;
315
+ }
316
+ .customtab_item .handlediv { position:relative; top: -4px; }
317
+ .customtab_item h3 { min-height: 21px }
318
+ .customtab_item .inside { padding: 10px !important; }
319
+ .customtab_item .deps { display: none; }
320
+ .customtab_item .addoptions p.option { margin: 5px 0 5px 200px }
321
+ .customtab_item .addoptions p label { width: 80px !important; }
322
+ .customtab_item .add-field-option { margin-bottom: 10px !important; }
323
+ .customtab_item .remove_item { float: right; }
324
+ .metabox-sortable-placeholder { border: 1px dotted #dedede; margin: 10px 0 }
325
+
326
+ .the-metabox.customtabs {
327
+ margin-left: 0;
328
+ }
329
+
330
+ #customtab_item_sample {
331
+ display: none;
332
+ }
333
+
334
+ .the-metabox.customtabs .field-row {
335
+ margin-bottom: 10px;
336
+ }
337
+
338
+ #yit_custom_tabs label {
339
+ font-weight: normal;
340
+ width: auto;
341
+ float: none;
342
+ line-height: auto;
343
+ margin-left: 0;
344
+ }
345
+
346
+
347
+ .wp-admin p label input[type=radio]{
348
+ width: 16px;
349
+ margin-right: 10px;
350
+ margin-top: 3px;
351
+ }
352
+ .wp-admin .form-field._preset_onsale_icon_field label input[type=radio]{
353
+ margin-top: 0;
354
+ }
355
+
356
+ .the-metabox .spinner {
357
+ margin-top: 5px;
358
+ float: none;
359
+ }
360
+
361
+ /* slider */
362
+ /*numbers*/
363
+ .ui-slider .maxCaption, .ui-slider .minCaption {
364
+ margin-bottom: 5px;
365
+ }
366
+ .ui-slider .feedback {
367
+ background: url(../images/slider/tooltip.png) no-repeat center top;
368
+ position: absolute;
369
+ top: -25px;
370
+ width: 35px;
371
+ height: 43px;
372
+ text-align: center;
373
+ width: 100%;
374
+ display: block;
375
+ }
376
+ .ui-slider .feedback strong {
377
+ display: inline-block;
378
+ padding-top: 4px;
379
+ top: -30px;
380
+ }
381
+ /*handle*/
382
+ .ui-slider-horizontal .ui-slider-handle{
383
+ background: transparent url(../images/slider/handle.png) no-repeat left top !important;
384
+ border: 0px !important;
385
+ top: -.35em !important;
386
+ width: 18px !important;
387
+ height: 19px !important;
388
+ }
389
+
390
+ /*bg on the left:grey*/
391
+ .ui-slider.ui-widget-content {
392
+ background: url(../images/slider/grey.gif) repeat-x left center !important;
393
+ border-color: #c1c1c0 !important;
394
+ height: 10px !important;
395
+ }
396
+
397
+ .iris-slider-offset.ui-slider.ui-widget-content {
398
+ background: transparent!important;
399
+ height: auto!important;
400
+ }
401
+
402
+ /*bg on the right:orange*/
403
+ .ui-slider.ui-widget-content .ui-widget-header {
404
+ background: url(../images/slider/orange.gif) repeat-x left center !important;
405
+ left: 2px !important;
406
+ -webkit-border-radius: 15px;
407
+ -moz-border-radius: 15px;
408
+ -khtml-border-radius: 15px;
409
+ border-radius: 15px;
410
+ }
411
+
412
+
413
+ /*sidebars*/
414
+
415
+ #choose-sidebars.choose{
416
+ margin-left: 0px;
417
+ }
418
+
419
+
420
+ #_active_page_options-container label, #_active_page_options-container p{
421
+ display: inline-block;
422
+ margin: 0px;
423
+ }
424
+ #_active_page_options-container label{
425
+ margin-right: 10px;
426
+ margin-top: 3px;
427
+ }
428
+ #_active_page_options-container {
429
+ float: right;
430
+ margin-right: 20px;
431
+ margin-top: 5px;
432
+ }
433
+
434
+ /* sortable table posts */
435
+
436
+ #the-list.ui-sortable tr:hover {
437
+ cursor: move;
438
+ }
439
+
440
+
441
+ /*datepicker*/
442
+ /*! jQuery UI - v1.11.2 - 2015-01-21
443
+ * http://jqueryui.com
444
+ * Includes: core.css, datepicker.css, theme.css
445
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=0px&bgColorHeader=%23dddddd&bgTextureHeader=flat&bgImgOpacityHeader=60&borderColorHeader=%23aaaaaa&fcHeader=%23222222&iconColorHeader=%23222222&bgColorContent=%23ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=%23aaaaaa&fcContent=%23222222&iconColorContent=%23222222&bgColorDefault=%23e9e9e9&bgTextureDefault=flat&bgImgOpacityDefault=75&borderColorDefault=%23d3d3d3&fcDefault=%23555555&iconColorDefault=%23888888&bgColorHover=%23dadada&bgTextureHover=flat&bgImgOpacityHover=75&borderColorHover=%23999999&fcHover=%23212121&iconColorHover=%23454545&bgColorActive=%23ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=%23aaaaaa&fcActive=%23212121&iconColorActive=%23454545&bgColorHighlight=%23fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=%2389b17e&fcHighlight=%23363636&iconColorHighlight=%232e83ff&bgColorError=%23fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=%23cd0a0a&fcError=%23cd0a0a&iconColorError=%23cd0a0a&bgColorOverlay=%23aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=%23aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
446
+ * Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
447
+
448
+ /* Layout helpers
449
+ ----------------------------------*/
450
+ .ui-helper-hidden {
451
+ display: none;
452
+ }
453
+ .ui-helper-hidden-accessible {
454
+ border: 0;
455
+ clip: rect(0 0 0 0);
456
+ height: 1px;
457
+ margin: -1px;
458
+ overflow: hidden;
459
+ padding: 0;
460
+ position: absolute;
461
+ width: 1px;
462
+ }
463
+ .ui-helper-reset {
464
+ margin: 0;
465
+ padding: 0;
466
+ border: 0;
467
+ outline: 0;
468
+ line-height: 1.3;
469
+ text-decoration: none;
470
+ font-size: 100%;
471
+ list-style: none;
472
+ }
473
+ .ui-helper-clearfix:before,
474
+ .ui-helper-clearfix:after {
475
+ content: "";
476
+ display: table;
477
+ border-collapse: collapse;
478
+ }
479
+ .ui-helper-clearfix:after {
480
+ clear: both;
481
+ }
482
+ .ui-helper-clearfix {
483
+ min-height: 0; /* support: IE7 */
484
+ }
485
+ .ui-helper-zfix {
486
+ width: 100%;
487
+ height: 100%;
488
+ top: 0;
489
+ left: 0;
490
+ position: absolute;
491
+ opacity: 0;
492
+ filter:Alpha(Opacity=0); /* support: IE8 */
493
+ }
494
+
495
+ .ui-front {
496
+ z-index: 100;
497
+ }
498
+
499
+
500
+ /* Interaction Cues
501
+ ----------------------------------*/
502
+ .ui-state-disabled {
503
+ cursor: default !important;
504
+ }
505
+
506
+
507
+ /* Icons
508
+ ----------------------------------*/
509
+
510
+ /* states and images */
511
+ .ui-icon {
512
+ display: block;
513
+ text-indent: -99999px;
514
+ overflow: hidden;
515
+ background-repeat: no-repeat;
516
+ }
517
+
518
+
519
+ /* DATE PICKER
520
+ ----------------------------------*/
521
+
522
+ .ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}
523
+ .ui-datepicker{width:17em;padding:.2em .2em 0;display:none;z-index:100!important;}
524
+ .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}
525
+ .ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}
526
+ .ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}
527
+ .ui-datepicker .ui-datepicker-prev{left:2px}
528
+ .ui-datepicker .ui-datepicker-next{right:2px}
529
+ .ui-datepicker .ui-datepicker-prev-hover{left:1px}
530
+ .ui-datepicker .ui-datepicker-next-hover{right:1px}
531
+ .ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}
532
+ .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}
533
+ .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}
534
+ .ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}
535
+ .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}
536
+ .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}
537
+ .ui-datepicker td{border:0;padding:1px}
538
+ .ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}
539
+ .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}
540
+ .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}
541
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}
542
+ .ui-datepicker.ui-datepicker-multi{width:auto}
543
+ .ui-datepicker-multi .ui-datepicker-group{float:left}
544
+ .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}
545
+ .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}
546
+ .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}
547
+ .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}
548
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}
549
+ .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}
550
+ .ui-datepicker-row-break{clear:both;width:100%;font-size:0}
551
+ .ui-datepicker-rtl{direction:rtl}
552
+ .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}
553
+ .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}
554
+ .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}
555
+ .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}
556
+ .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}
557
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}
558
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}
559
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}
560
+ .ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}
561
+ .ui-widget .ui-widget{font-size:1em}
562
+ .ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}
563
+ .ui-widget-content{border:1px solid #aaa;background:#fff 50% 50% repeat-x;color:#222}
564
+ .ui-widget-content a{color:#222}
565
+ .ui-widget-header{border:1px solid #aaa;background:#ddd 50% 50% repeat-x;color:#222;font-weight:700}
566
+ .ui-widget-header a{color:#222}
567
+ .ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:0 solid #d3d3d3;background:#e9e9e9 50% 50% repeat-x;font-weight:400;color:#555}
568
+ .ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}
569
+ .ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:0 solid #999;background:#dadada 50% 50% repeat-x;font-weight:400;color:#212121}
570
+ .ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}
571
+ .ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:0 solid #aaa;background:#fff 50% 50% repeat-x;font-weight:400;color:#212121}
572
+ .ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}
573
+ .ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:0 solid #89b17e;background:#fbf9ee 50% 50% repeat-x;color:#363636}
574
+ .ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}
575
+ .ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:0 solid #cd0a0a;background:#fef1ec 50% 50% repeat-x;color:#cd0a0a}
576
+ .ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}
577
+ .ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}
578
+ .ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:700}
579
+ .ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}
580
+ .ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}
581
+ .ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}
582
+ .ui-icon{width:16px;height:16px}
583
+ .ui-icon,.ui-widget-content .ui-icon{background-image:url(../images/ui-icons_222222_256x240.png)}
584
+ .ui-widget-header .ui-icon{background-image:url(../images/ui-icons_222222_256x240.png)}
585
+ .ui-state-default .ui-icon{background-image:url(../images/ui-icons_888888_256x240.png)}
586
+ .ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(../images/ui-icons_454545_256x240.png)}
587
+ .ui-state-active .ui-icon{background-image:url(../images/ui-icons_454545_256x240.png)}
588
+ .ui-state-highlight .ui-icon{background-image:url(../images/ui-icons_2e83ff_256x240.png)}
589
+ .ui-icon-circle-triangle-e{background-position:-48px -192px}
590
+ .ui-icon-circle-triangle-s{background-position:-64px -192px}
591
+ .ui-icon-circle-triangle-w{background-position:-80px -192px}
592
+ .ui-icon-circle-triangle-n{background-position:-96px -192px}
593
+ .ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:0}
594
+ .ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:0}
595
+ .ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:0}
596
+ .ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:0}
597
+ .ui-widget-overlay{background:#aaa 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}
598
+ .ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
plugin-fw/assets/css/overcast/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_flat_0_eeeeee_40x100.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_flat_55_c0402a_40x100.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_flat_55_eeeeee_40x100.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_glass_100_f8f8f8_1x400.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_glass_35_dddddd_1x400.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_glass_60_eeeeee_1x400.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_inset-hard_75_999999_1x100.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-bg_inset-soft_50_c9c9c9_1x100.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-icons_3383bb_256x240.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-icons_454545_256x240.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-icons_70b2e1_256x240.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-icons_999999_256x240.png ADDED
Binary file
plugin-fw/assets/css/overcast/images/ui-icons_fbc856_256x240.png ADDED
Binary file
plugin-fw/assets/css/overcast/jquery-ui-1.8.9.custom.css ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery UI CSS Framework 1.8.8
3
+ *
4
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI/Theming/API
9
+ */
10
+
11
+ /* Layout helpers
12
+ ----------------------------------*/
13
+ .ui-helper-hidden { display: none; }
14
+ .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
15
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
16
+ .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
17
+ .ui-helper-clearfix { display: inline-block; }
18
+ /* required comment for clearfix to work in Opera \*/
19
+ * html .ui-helper-clearfix { height:1%; }
20
+ .ui-helper-clearfix { display:block; }
21
+ /* end clearfix */
22
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
23
+
24
+
25
+ /* Interaction Cues
26
+ ----------------------------------*/
27
+ .ui-state-disabled { cursor: default !important; }
28
+
29
+
30
+ /* Icons
31
+ ----------------------------------*/
32
+
33
+ /* states and images */
34
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
35
+
36
+
37
+ /* Misc visuals
38
+ ----------------------------------*/
39
+
40
+ /* Overlays */
41
+ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
42
+
43
+
44
+ /*
45
+ * jQuery UI CSS Framework 1.8.8
46
+ *
47
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
48
+ * Dual licensed under the MIT or GPL Version 2 licenses.
49
+ * http://jquery.org/license
50
+ *
51
+ * http://docs.jquery.com/UI/Theming/API
52
+ *
53
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Helvetica,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=dddddd&bgTextureHeader=02_glass.png&bgImgOpacityHeader=35&borderColorHeader=bbbbbb&fcHeader=444444&iconColorHeader=999999&bgColorContent=c9c9c9&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=50&borderColorContent=aaaaaa&fcContent=333333&iconColorContent=999999&bgColorDefault=eeeeee&bgTextureDefault=02_glass.png&bgImgOpacityDefault=60&borderColorDefault=cccccc&fcDefault=3383bb&iconColorDefault=70b2e1&bgColorHover=f8f8f8&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=bbbbbb&fcHover=599fcf&iconColorHover=3383bb&bgColorActive=999999&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=75&borderColorActive=999999&fcActive=ffffff&iconColorActive=454545&bgColorHighlight=eeeeee&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=ffffff&fcHighlight=444444&iconColorHighlight=3383bb&bgColorError=c0402a&bgTextureError=01_flat.png&bgImgOpacityError=55&borderColorError=c0402a&fcError=ffffff&iconColorError=fbc856&bgColorOverlay=eeeeee&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=80&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=60&thicknessShadow=4px&offsetTopShadow=-4px&offsetLeftShadow=-4px&cornerRadiusShadow=0pxdow=0px
54
+ */
55
+
56
+
57
+ /* Component containers
58
+ ----------------------------------*/
59
+ .ui-widget { font-family: Trebuchet MS, Helvetica, Arial, sans-serif; font-size: 1.1em; }
60
+ .ui-widget .ui-widget { font-size: 1em; }
61
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Helvetica, Arial, sans-serif; font-size: 1em; }
62
+ .ui-widget-content { border: 1px solid #aaaaaa; background: #f1f1f1; color: #333333; }
63
+ .ui-widget-content a { color: #333333; }
64
+ .ui-widget-header { border: 1px solid #bbbbbb; background: #ccc; color: #444444; font-weight: bold; }
65
+ .ui-widget-header a { color: #444444; }
66
+
67
+ /* Interaction states
68
+ ----------------------------------*/
69
+ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #eeeeee url(images/ui-bg_glass_60_eeeeee_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #3383bb; }
70
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #3383bb; text-decoration: none; }
71
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #bbbbbb; background: #f8f8f8 url(images/ui-bg_glass_100_f8f8f8_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #599fcf; }
72
+ .ui-state-hover a, .ui-state-hover a:hover { color: #599fcf; text-decoration: none; }
73
+ .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #999999; background: #999999 url(images/ui-bg_inset-hard_75_999999_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; }
74
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
75
+ .ui-widget :active { outline: none; }
76
+
77
+ /* Interaction Cues
78
+ ----------------------------------*/
79
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #ffffff; background: #eeeeee url(images/ui-bg_flat_55_eeeeee_40x100.png) 50% 50% repeat-x; color: #444444; }
80
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #444444; }
81
+ .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #c0402a; background: #c0402a url(images/ui-bg_flat_55_c0402a_40x100.png) 50% 50% repeat-x; color: #ffffff; }
82
+ .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
83
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
84
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
85
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
86
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
87
+ .ui-sortable-placeholder { border: 1px dotted black; visibility: visible !important; }
88
+ .ui-sortable-placeholder * { visibility: hidden; }
89
+
90
+ /* Icons
91
+ ----------------------------------*/
92
+
93
+ /* states and images */
94
+ /*.ui-widget-content .ui-icon {background-image: url(images/ui-icons_999999_256x240.png); }
95
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_999999_256x240.png); } */
96
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_70b2e1_256x240.png); }
97
+ /*.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_3383bb_256x240.png); }
98
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
99
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_3383bb_256x240.png); }
100
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_fbc856_256x240.png); } */
101
+
102
+ /* positioning */
103
+ /*.ui-icon-carat-1-n { background-position: 0 0; }
104
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
105
+ .ui-icon-carat-1-e { background-position: -32px 0; }
106
+ .ui-icon-carat-1-se { background-position: -48px 0; }
107
+ .ui-icon-carat-1-s { background-position: -64px 0; }
108
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
109
+ .ui-icon-carat-1-w { background-position: -96px 0; }
110
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
111
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
112
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
113
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
114
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
115
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
116
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
117
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
118
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
119
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
120
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
121
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
122
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
123
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
124
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
125
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
126
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
127
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
128
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
129
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
130
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
131
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
132
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
133
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
134
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
135
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
136
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
137
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
138
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
139
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
140
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
141
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
142
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
143
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
144
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
145
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
146
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
147
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
148
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
149
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
150
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
151
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
152
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
153
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
154
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
155
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
156
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
157
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
158
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
159
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
160
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
161
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
162
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
163
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
164
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
165
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
166
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
167
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
168
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
169
+ .ui-icon-extlink { background-position: -32px -80px; }
170
+ .ui-icon-newwin { background-position: -48px -80px; }
171
+ .ui-icon-refresh { background-position: -64px -80px; }
172
+ .ui-icon-shuffle { background-position: -80px -80px; }
173
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
174
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
175
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
176
+ .ui-icon-folder-open { background-position: -16px -96px; }
177
+ .ui-icon-document { background-position: -32px -96px; }
178
+ .ui-icon-document-b { background-position: -48px -96px; }
179
+ .ui-icon-note { background-position: -64px -96px; }
180
+ .ui-icon-mail-closed { background-position: -80px -96px; }
181
+ .ui-icon-mail-open { background-position: -96px -96px; }
182
+ .ui-icon-suitcase { background-position: -112px -96px; }
183
+ .ui-icon-comment { background-position: -128px -96px; }
184
+ .ui-icon-person { background-position: -144px -96px; }
185
+ .ui-icon-print { background-position: -160px -96px; }
186
+ .ui-icon-trash { background-position: -176px -96px; }
187
+ .ui-icon-locked { background-position: -192px -96px; }
188
+ .ui-icon-unlocked { background-position: -208px -96px; }
189
+ .ui-icon-bookmark { background-position: -224px -96px; }
190
+ .ui-icon-tag { background-position: -240px -96px; }
191
+ .ui-icon-home { background-position: 0 -112px; }
192
+ .ui-icon-flag { background-position: -16px -112px; }
193
+ .ui-icon-calendar { background-position: -32px -112px; }
194
+ .ui-icon-cart { background-position: -48px -112px; }
195
+ .ui-icon-pencil { background-position: -64px -112px; }
196
+ .ui-icon-clock { background-position: -80px -112px; }
197
+ .ui-icon-disk { background-position: -96px -112px; }
198
+ .ui-icon-calculator { background-position: -112px -112px; }
199
+ .ui-icon-zoomin { background-position: -128px -112px; }
200
+ .ui-icon-zoomout { background-position: -144px -112px; }
201
+ .ui-icon-search { background-position: -160px -112px; }
202
+ .ui-icon-wrench { background-position: -176px -112px; }
203
+ .ui-icon-gear { background-position: -192px -112px; }
204
+ .ui-icon-heart { background-position: -208px -112px; }
205
+ .ui-icon-star { background-position: -224px -112px; }
206
+ .ui-icon-link { background-position: -240px -112px; }
207
+ .ui-icon-cancel { background-position: 0 -128px; } */
208
+ .ui-icon-plus { background-position: -16px -128px; }
209
+ .ui-icon-minus { background-position: -48px -128px; }
210
+ .ui-icon-minusthick { background-position: -64px -128px; }
211
+ /*.ui-icon-plusthick { background-position: -32px -128px; }
212
+ .ui-icon-close { background-position: -80px -128px; }
213
+ .ui-icon-closethick { background-position: -96px -128px; }
214
+ .ui-icon-key { background-position: -112px -128px; }
215
+ .ui-icon-lightbulb { background-position: -128px -128px; }
216
+ .ui-icon-scissors { background-position: -144px -128px; }
217
+ .ui-icon-clipboard { background-position: -160px -128px; }
218
+ .ui-icon-copy { background-position: -176px -128px; }
219
+ .ui-icon-contact { background-position: -192px -128px; }
220
+ .ui-icon-image { background-position: -208px -128px; }
221
+ .ui-icon-video { background-position: -224px -128px; }
222
+ .ui-icon-script { background-position: -240px -128px; }
223
+ .ui-icon-alert { background-position: 0 -144px; }
224
+ .ui-icon-info { background-position: -16px -144px; }
225
+ .ui-icon-notice { background-position: -32px -144px; }
226
+ .ui-icon-help { background-position: -48px -144px; }
227
+ .ui-icon-check { background-position: -64px -144px; }
228
+ .ui-icon-bullet { background-position: -80px -144px; }
229
+ .ui-icon-radio-off { background-position: -96px -144px; }
230
+ .ui-icon-radio-on { background-position: -112px -144px; }
231
+ .ui-icon-pin-w { background-position: -128px -144px; }
232
+ .ui-icon-pin-s { background-position: -144px -144px; }
233
+ .ui-icon-play { background-position: 0 -160px; }
234
+ .ui-icon-pause { background-position: -16px -160px; }
235
+ .ui-icon-seek-next { background-position: -32px -160px; }
236
+ .ui-icon-seek-prev { background-position: -48px -160px; }
237
+ .ui-icon-seek-end { background-position: -64px -160px; }
238
+ .ui-icon-seek-start { background-position: -80px -160px; } */
239
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
240
+ /*.ui-icon-seek-first { background-position: -80px -160px; }
241
+ .ui-icon-stop { background-position: -96px -160px; }
242
+ .ui-icon-eject { background-position: -112px -160px; }
243
+ .ui-icon-volume-off { background-position: -128px -160px; }
244
+ .ui-icon-volume-on { background-position: -144px -160px; }
245
+ .ui-icon-power { background-position: 0 -176px; }
246
+ .ui-icon-signal-diag { background-position: -16px -176px; }
247
+ .ui-icon-signal { background-position: -32px -176px; }
248
+ .ui-icon-battery-0 { background-position: -48px -176px; }
249
+ .ui-icon-battery-1 { background-position: -64px -176px; }
250
+ .ui-icon-battery-2 { background-position: -80px -176px; }
251
+ .ui-icon-battery-3 { background-position: -96px -176px; }
252
+ .ui-icon-circle-plus { background-position: 0 -192px; }
253
+ .ui-icon-circle-minus { background-position: -16px -192px; }
254
+ .ui-icon-circle-close { background-position: -32px -192px; }
255
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
256
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
257
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
258
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
259
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
260
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
261
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
262
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
263
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
264
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
265
+ .ui-icon-circle-check { background-position: -208px -192px; }
266
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
267
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
268
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
269
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
270
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
271
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
272
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
273
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
274
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
275
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
276
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
277
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; } */
278
+
279
+
280
+ /* Misc visuals
281
+ ----------------------------------*/
282
+
283
+ /* Corner radius */
284
+ .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; }
285
+ .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
286
+ .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
287
+ .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
288
+ .ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
289
+ .ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
290
+ .ui-corner-right { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
291
+ .ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
292
+ .ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; }
293
+
294
+ /* Overlays */
295
+ .ui-widget-overlay { background: #eeeeee url(images/ui-bg_flat_0_eeeeee_40x100.png) 50% 50% repeat-x; opacity: .80;filter:Alpha(Opacity=80); }
296
+ .ui-widget-shadow { margin: -4px 0 0 -4px; padding: 4px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .60;filter:Alpha(Opacity=60); -moz-border-radius: 0pxdow=0px; -webkit-border-radius: 0pxdow=0px; border-radius: 0pxdow=0px; }/*
297
+ * jQuery UI Slider 1.8.8
298
+ *
299
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
300
+ * Dual licensed under the MIT or GPL Version 2 licenses.
301
+ * http://jquery.org/license
302
+ *
303
+ * http://docs.jquery.com/UI/Slider#theming
304
+ */
305
+ .ui-slider { position: relative; text-align: left; width:340px; float:left }
306
+ .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
307
+ .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
308
+ .ui-slider .minCaption { float: left }
309
+ .ui-slider .maxCaption { float: right }
310
+ .ui-slider .feedback { text-align:center; width:100%; display:block }
311
+
312
+ .ui-slider-horizontal { height: .8em; }
313
+ .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
314
+ .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
315
+ .ui-slider-horizontal .ui-slider-range-min { left: 0; }
316
+ .ui-slider-horizontal .ui-slider-range-max { right: 0; }
317
+
318
+ .ui-slider-vertical { width: .8em; height: 100px; }
319
+ .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
320
+ .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
321
+ .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
322
+ .ui-slider-vertical .ui-slider-range-max { top: 0; }
plugin-fw/assets/css/yit-plugin-panel.css ADDED
@@ -0,0 +1,614 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * This file belongs to the YIT Plugin Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+
10
+ /* onoff */
11
+ .rm_onoff input {
12
+ display: none;
13
+ }
14
+
15
+ .rm_onoff input + span {
16
+ cursor: pointer;
17
+ text-indent: -9999px;
18
+ display: block;
19
+ width: 85px;
20
+ height: 37px;
21
+ background: transparent url(../images/off.png);
22
+ }
23
+
24
+ .rm_onoff input:checked + span {
25
+ background: transparent url(../images/on.png);
26
+ }
27
+
28
+ .rm_onoff input.onoffchecked + span {
29
+ background: transparent url(../images/on.png);
30
+ }
31
+
32
+ /* slider */
33
+ /*numbers*/
34
+ .ui-slider .maxCaption, .ui-slider .minCaption {
35
+ margin-bottom: 5px;
36
+ }
37
+ .ui-slider .feedback {
38
+ background: url(../images/slider/tooltip.png) no-repeat center top;
39
+ position: absolute;
40
+ top: -25px;
41
+ width: 35px;
42
+ height: 43px;
43
+ text-align: center;
44
+ width: 100%;
45
+ display: block;
46
+ }
47
+ .ui-slider .feedback strong {
48
+ display: inline-block;
49
+ padding-top: 4px;
50
+ top: -30px;
51
+ }
52
+ /*handle*/
53
+ .yit-options .ui-slider-horizontal .ui-slider-handle {
54
+ background: transparent url(../images/slider/handle.png) no-repeat left top !important;
55
+ border: 0px !important;
56
+ top: -.35em !important;
57
+ width: 18px !important;
58
+ height: 19px !important;
59
+ }
60
+
61
+ /*bg on the left:grey*/
62
+ .yit-options .ui-slider.ui-widget-content {
63
+ background: url(../images/slider/grey.gif) repeat-x left center !important;
64
+ border-color: #c1c1c0 !important;
65
+ height: 10px !important;
66
+ }
67
+
68
+ .iris-slider-offset.ui-slider.ui-widget-content {
69
+ background: transparent!important;
70
+ height: auto!important;
71
+ }
72
+
73
+ /*bg on the right:orange*/
74
+ .ui-slider.ui-widget-content .ui-widget-header {
75
+ background: url(../images/slider/orange.gif) repeat-x left center !important;
76
+ left: 2px !important;
77
+ -webkit-border-radius: 15px;
78
+ -moz-border-radius: 15px;
79
+ -khtml-border-radius: 15px;
80
+ border-radius: 15px;
81
+ }
82
+
83
+ .plugin-option tr{
84
+ border-bottom: 1px solid #ccc;
85
+ }
86
+ .plugin-option .yit_options{
87
+ border-bottom: 0px;
88
+ }
89
+ .plugin-option .yit_options .option {
90
+ width: 600px;
91
+ float: left;
92
+ }
93
+
94
+ .plugin-option .form-table td{
95
+ padding: 25px 10px;
96
+ }
97
+
98
+ .yit-options .select_wrapper {
99
+ background: url("../images/select.png") no-repeat scroll right center #FAFAFA;
100
+ border-color: #CCCCCC #EEEEEE #EEEEEE #CCCCCC;
101
+ border-radius: 4px 4px 4px 4px;
102
+ border-style: solid;
103
+ border-width: 1px;
104
+ color: #555555;
105
+ display: block;
106
+ float: left;
107
+ font-family: sans-serif;
108
+ font-size: 12px;
109
+ height: 26px;
110
+ margin-bottom: 9px !important;
111
+ margin-left: 0;
112
+ margin-right: 5px;
113
+ margin-top: 0;
114
+ width: 400px;
115
+ }
116
+ .chosen .select_wrapper {
117
+ background: none;
118
+ border: none;
119
+ }
120
+ .chosen .select_wrapper .chosen-container{
121
+ width: 338px!important;
122
+ }
123
+ .chosen .select_wrapper .chosen-container .search-field input{
124
+ height: 27px!important;
125
+ color: #333;
126
+ }
127
+ .chosen .select_wrapper .chosen-container .chosen-choices{
128
+ border: 1px solid #ddd;
129
+ box-shadow: none;
130
+ }
131
+ .chosen .select_wrapper .chosen-container .chosen-choices li.search-choice{
132
+ height: 15px!important;
133
+ min-width: 105px;
134
+ }
135
+ .chosen .select_wrapper .chosen-container .chosen-choices li.search-choice span{
136
+ line-height: 15px;
137
+ height: 15px;
138
+ padding-top: 2px;
139
+ }
140
+ .chosen .select_wrapper .chosen-container .chosen-choices li.search-choice a.search-choice-close{
141
+ top: 5px;
142
+ }
143
+ .chosen .select_wrapper .chosen-container .chosen-drop .chosen-search input{
144
+ width: 100%!important;
145
+ }
146
+
147
+ /* === Chosen Customizzation === */
148
+
149
+ .yith-choosen .chosen-choices {
150
+ line-height: 27px;
151
+ min-height: 27px;
152
+ border: 1px solid #ddd;
153
+ }
154
+
155
+ .yith-choosen .chosen-container-active .chosen-choices{
156
+ border: 1px solid #5b9dd9;
157
+ -webkit-box-shadow: 0 0 2px rgba(30,140,190,.8);
158
+ box-shadow: 0 0 2px rgba(30,140,190,.8);
159
+ }
160
+
161
+ .select_wrapper span {
162
+ height: 26px;
163
+ line-height: 26px;
164
+ padding-left: 6px;
165
+ position: absolute;
166
+ z-index: 2;
167
+ }
168
+ .ie8 .yit_options select {
169
+ height: 26px;
170
+ }
171
+ .yit_options select, .the-metabox .select_wrapper select {
172
+ cursor: pointer;
173
+ height: 28px;
174
+ margin: 0;
175
+ opacity: 0;
176
+ padding: 0;
177
+ position: relative;
178
+ width: inherit;
179
+ z-index: 4;
180
+ background-color: #FAFAFA;
181
+ }
182
+
183
+
184
+ /* Style to woocommerce panel*/
185
+ #plugin-fw-wc{
186
+ padding-top: 20px;
187
+ }
188
+ #plugin-fw-wc table.form-table{
189
+ background-color: #fff;
190
+ margin-bottom: 20px;
191
+ }
192
+ #plugin-fw-wc table.form-table th {
193
+ padding: 20px;
194
+ }
195
+ #plugin-fw-wc h3{
196
+ padding:0px 10px 10px ;
197
+ border-bottom: 1px solid #eee;
198
+ }
199
+ #plugin-fw-wc .yith_videobox .column{
200
+ width: 45%;
201
+ float: left;
202
+ padding-right: 2.5%;
203
+ border-right: 1px solid #ebebeb;
204
+ padding-bottom: 2em;
205
+ }
206
+ #plugin-fw-wc .yith_videobox .column.two{
207
+ margin-right: 0;
208
+ padding-right: 0;
209
+ padding-left: 2.5%;
210
+ border: 0;
211
+ max-width: 49%;
212
+ }
213
+ #plugin-fw-wc .yith_videobox h2{
214
+ font-size: 16px;
215
+ margin-bottom: 20px;
216
+ }
217
+ #plugin-fw-wc .postbox .inside{
218
+ display: inline-block;
219
+ }
220
+ #plugin-fw-wc .yith-video-link {
221
+ width: 100%;
222
+ max-width: 200px;
223
+ float: left;
224
+ margin: 0 1.5em 1.5em 0;
225
+ }
226
+ #plugin-fw-wc .yith-video-link {
227
+ width: 100%;
228
+ max-width: 200px;
229
+ float: left;
230
+ margin: 0 1.5em 1.5em 0;
231
+ }
232
+ #plugin-fw-wc .yith-image-frame img {
233
+ max-width: 100%;
234
+ height: auto;
235
+ }
236
+
237
+ #plugin-fw-wc .yith-video-link img {
238
+ max-width: 100%;
239
+ height: auto;
240
+ }
241
+ #plugin-fw-wc .yith-video-iframe {
242
+ display: none;
243
+
244
+ }
245
+
246
+ /* === Plugins Upgrader === */
247
+
248
+ .yit-plugin-changelog-wrapper {
249
+ display: none;
250
+ }
251
+
252
+ .yit-plugin-changelog-title {
253
+ text-transform: uppercase;
254
+ }
255
+
256
+ .yit-plugin-changelog {
257
+ background: #fcfcfc;
258
+ height: 97%;
259
+ z-index: 999;
260
+ overflow: auto;
261
+ }
262
+
263
+ /* === Plugins Licence Activation === */
264
+
265
+ .yit-container.plugin-licence-activation {
266
+ font-family: 'Raleway', sans-serif;
267
+ }
268
+
269
+ .yit-container.plugin-licence-activation .to-active-wrapper {
270
+ margin-bottom: 60px;
271
+ }
272
+
273
+ .yit-container.plugin-licence-activation .to-active-wrapper form.to-active-form {
274
+ position: relative;
275
+ border-color: #e1e1e1;
276
+ border-style: solid;
277
+ border-width: 0;
278
+ }
279
+
280
+ .yit-container.plugin-licence-activation .to-active-wrapper form.to-active-form:first-child {
281
+ border-top-width: 1px;
282
+ }
283
+
284
+ .yit-container.plugin-licence-activation .to-active-wrapper form.to-active-form:last-child {
285
+ border-bottom-width: 1px;
286
+ }
287
+
288
+ .yit-container.plugin-licence-activation .to-active-wrapper table.to-active-table {
289
+ border-width: 0;
290
+ border-spacing: 0;
291
+ width: 100%;
292
+ }
293
+
294
+ .yit-container.plugin-licence-activation .message {
295
+ display: none;
296
+ line-height: normal;
297
+ background: #ffffff url(../images/licence-error.png) 15px center no-repeat;
298
+ padding-left: 65px;
299
+ padding-right: 15px;
300
+ width: 150px;
301
+ }
302
+
303
+ .yit-container.plugin-licence-activation .message-wrapper {
304
+ height: 75px;
305
+ display: none;
306
+ position: absolute;
307
+ top: 0;
308
+ right: -250px;
309
+ border: 1px solid #ff3838;
310
+ }
311
+
312
+ .yit-container.plugin-licence-activation .message-wrapper.visible {
313
+ display: table;
314
+ }
315
+
316
+ .yit-container.plugin-licence-activation .message {
317
+ display: table-cell;
318
+ vertical-align: middle;
319
+ }
320
+
321
+ .yit-container.plugin-licence-activation .arrow-left:after,
322
+ .yit-container.plugin-licence-activation .arrow-left:before {
323
+ content: "";
324
+ display: block;
325
+ width: 0;
326
+ height: 0;
327
+ position: absolute;
328
+ }
329
+
330
+ .yit-container.plugin-licence-activation .arrow-left:before {
331
+ border-top: 9px solid transparent;
332
+ border-bottom: 9px solid transparent;
333
+ border-right: 9px solid #ff3838;
334
+ top: 26px;
335
+ left: -9px;
336
+ }
337
+
338
+ .yit-container.plugin-licence-activation .arrow-left:after {
339
+ border-top: 8px solid transparent;
340
+ border-bottom: 8px solid transparent;
341
+ border-right: 8px solid #fff;
342
+ left: -8px;
343
+ top: 27px;
344
+ }
345
+
346
+ .yit-container.plugin-licence-activation h2,
347
+ .yit-container.plugin-licence-activation h3 {
348
+ text-transform: uppercase;
349
+ font-weight: 800;
350
+ margin-bottom: 30px;
351
+ }
352
+
353
+ .yit-container.plugin-licence-activation h2 {
354
+ color: #808a97;
355
+ font-size: 25px;
356
+ }
357
+ .yit-container.plugin-licence-activation h3 {
358
+ color: #313131;
359
+ font-size: 15px;
360
+ height: 20px;
361
+ }
362
+
363
+ .yit-container.plugin-licence-activation h3.to-active {
364
+ height: 20px;
365
+ position: relative;
366
+ vertical-align: top;
367
+ }
368
+
369
+ .yit-container.plugin-licence-activation .spinner.show{
370
+ display: inline-block;
371
+ vertical-align: middle;
372
+ float: none;
373
+ }
374
+
375
+ .yit-container.plugin-licence-activation h3.to-active > .spinner.show {
376
+ display: inline-block;
377
+ float: none;
378
+ top: -3px;
379
+ position: relative;
380
+ }
381
+
382
+ .yit-container.plugin-licence-activation .licence-check-section{
383
+ margin-bottom: 60px;
384
+ }
385
+
386
+ .yit-container.plugin-licence-activation span.licence-label {
387
+ font-weight: 500;
388
+ color: #606060;
389
+ margin-bottom: 30px;
390
+ }
391
+
392
+ .yit-container.plugin-licence-activation .button-licence {
393
+ border: 0;
394
+ font-size: 13px;
395
+ text-transform: uppercase;
396
+ background-color: #808a97;
397
+ color: #fff;
398
+ font-weight: 700;
399
+ border-radius: 3px;
400
+ cursor: pointer;
401
+ text-decoration: none;
402
+ padding: 5px 7px;
403
+ -webkit-transition: background-color 0.3s ease;
404
+ -moz-transition: background-color 0.3s ease;
405
+ -ms-transition: background-color 0.3s ease;
406
+ -o-transition: background-color 0.3s ease;
407
+ transition: background-color 0.3s ease;
408
+ }
409
+
410
+ .yit-container.plugin-licence-activation .button-licence:hover {
411
+ background-color: #4d5c6f;
412
+ }
413
+
414
+ .yit-container.plugin-licence-activation .button-licence.clicked {
415
+ cursor: not-allowed;
416
+ background-color: #e2e2e2 !important;
417
+ }
418
+
419
+ .yit-container.plugin-licence-activation .button-licence.licence-check {
420
+ font-weight: 400;
421
+ padding: 12px 19px;
422
+ }
423
+
424
+ .yit-container.plugin-licence-activation .button-licence.licence-renew {
425
+ text-decoration: none;
426
+ padding: 7px 12px;
427
+ font-size: 9px;
428
+ }
429
+
430
+ .yit-container.plugin-licence-activation .button-licence.licence-renew:focus {
431
+ box-shadow: none;
432
+ }
433
+
434
+ .yit-container.plugin-licence-activation table:not(.to-active-table) {
435
+ width: 100%;
436
+ border: 1px solid #dcdcdc;
437
+ border-spacing: 0;
438
+ border-radius: 5px;
439
+ border-collapse: separate;
440
+ overflow: hidden;
441
+ }
442
+
443
+ .yit-container.plugin-licence-activation table:not(.to-active-table) th {
444
+ border-bottom: 1px solid #dcdcdc;
445
+ }
446
+
447
+ .yit-container.plugin-licence-activation table:not(.to-active-table) td,
448
+ .yit-container.plugin-licence-activation table:not(.to-active-table) th {
449
+ border-right: 1px solid #dcdcdc;
450
+ }
451
+ .yit-container.plugin-licence-activation table td:last-child,
452
+ .yit-container.plugin-licence-activation table th:last-child {
453
+ border-right: 0;
454
+ }
455
+
456
+ .yit-container.plugin-licence-activation table thead tr {
457
+ background-color: #f6f4f4;
458
+ }
459
+
460
+ .yit-container.plugin-licence-activation table tbody tr {
461
+ background-color: #ffffff;
462
+ }
463
+
464
+ .yit-container.plugin-licence-activation table thead tr th {
465
+ font-size: 13px;
466
+ color: #313131;
467
+ text-transform: uppercase;
468
+ font-weight: bold;
469
+ }
470
+
471
+ .yit-container.plugin-licence-activation table thead tr,
472
+ .yit-container.plugin-licence-activation table tbody tr {
473
+ line-height: 60px;
474
+ }
475
+
476
+ .yit-container.plugin-licence-activation table tbody tr td{
477
+ text-align: center;
478
+ line-height: 20px;
479
+ padding: 10px 5px;
480
+ }
481
+
482
+ .yit-container.plugin-licence-activation .button-licence.licence-activation {
483
+ padding: 12px 18px;
484
+ }
485
+
486
+ .yit-container.plugin-licence-activation .to-active-table tr {
487
+ line-height: 75px;
488
+ }
489
+
490
+ .yit-container.plugin-licence-activation .to-active-table tr.plugin-row {
491
+ background-color: transparent;
492
+ -webkit-transition: all 0.3s ease;
493
+ -moz-transition: all 0.3s ease;
494
+ -ms-transition: all 0.3s ease;
495
+ -o-transition: all 0.3s ease;
496
+ transition: all 0.3s ease;
497
+ }
498
+
499
+ .yit-container.plugin-licence-activation .to-active-table tr.plugin-row.error {
500
+ background-color: #ffdcdc;
501
+ }
502
+
503
+ .yit-container.plugin-licence-activation .to-active-table td {
504
+ padding-right: 12px;
505
+ width: 33%;
506
+ }
507
+
508
+
509
+ .yit-container.plugin-licence-activation .to-active-table td.plugin-name {
510
+ color: #808a97;
511
+ font-size: 12px;
512
+ text-transform: uppercase;
513
+ font-weight: bold;
514
+ line-height: 20px;
515
+ width: 20%;
516
+ padding-left: 20px;
517
+ }
518
+
519
+ .yit-container.plugin-licence-activation .to-active-table td.activate-button {
520
+ width: 15%;
521
+ position: relative;
522
+ }
523
+
524
+ .yit-container.plugin-licence-activation input[type=text],
525
+ .yit-container.plugin-licence-activation input[type=email]{
526
+ -webkit-transition: all 0.3s ease;
527
+ -moz-transition: all 0.3s ease;
528
+ -ms-transition: all 0.3s ease;
529
+ -o-transition: all 0.3s ease;
530
+ transition: all 0.3s ease;
531
+
532
+ border: 1px solid #dcdcdc;
533
+ padding: 0 15px;
534
+ border-radius: 3px;
535
+ height: 41px;
536
+ width: 100%;
537
+ }
538
+
539
+ .yit-container.plugin-licence-activation input[type=text].require,
540
+ .yit-container.plugin-licence-activation input[type=email].require {
541
+ border: 1px solid #ff3838;
542
+ }
543
+
544
+ .yit-container.plugin-licence-activation input[type=text]:focus,
545
+ .yit-container.plugin-licence-activation input[type=email]:focus{
546
+ webkit-box-shadow: 0 0 1px rgba(30,140,190,.8);
547
+ box-shadow: 0 0 1px rgba(30,140,190,.8);
548
+ }
549
+
550
+ .yit-container.plugin-licence-activation input[type=text]{
551
+ text-transform: uppercase;
552
+ text-align: center;
553
+ }
554
+
555
+ .yit-container.plugin-licence-activation input[type=email] {
556
+ text-align: left;
557
+ }
558
+
559
+ .yit-container.plugin-licence-activation input[type=submit]:focus{
560
+ outline: 0;
561
+ }
562
+
563
+ /* === Woocommerce panel === */
564
+ #plugin-fw-wc .yit_options{
565
+ padding: 0;
566
+ border: 0;
567
+ }
568
+ #plugin-fw-wc .yit_options input.upload_button, .yit_options input.button{
569
+ background: none;
570
+ border: 1px solid #ccc;
571
+ }
572
+
573
+ /* === WP Pointers === */
574
+
575
+ #adminmenu li.menu-top.yit-pointer-selected-row,
576
+ #adminmenu li.menu-top.yit-pointer-selected-row:hover,
577
+ #adminmenu li.yit-pointer-selected-row a.menu-top {
578
+ background-color: #acc327;
579
+ color: #000;
580
+ }
581
+
582
+ #adminmenu a.menu-top.toplevel_page_yit_plugin_panel.yit-pointer{
583
+ color: #000;
584
+ }
585
+
586
+ #adminmenu a.menu-top.toplevel_page_yit_plugin_panel.yit-pointer:hover,
587
+ #adminmenu .wp-submenu a.yit-pointer-selected-row {
588
+ color: #fff;
589
+ }
590
+
591
+ #adminmenu .wp-submenu a.yit-pointer-selected-row:hover {
592
+ color: #45bbe6;
593
+ }
594
+
595
+ /* === Responsive === */
596
+
597
+ @media (max-width: 767px) {}
598
+
599
+ @media (max-width: 480px) {}
600
+
601
+ @media (min-width: 768px) and (max-width: 992px) {}
602
+
603
+ @media (min-width: 980px) and (max-width: 1199px) {}
604
+
605
+ @media (min-width: 1200px) {
606
+ .yit-container.plugin-licence-activation{
607
+ width: 900px;
608
+ }
609
+ }
610
+
611
+ @media only screen and (-webkit-min-device-pixel-ratio: 1.5),
612
+ only screen and (-o-min-device-pixel-ratio: 3/2),
613
+ only screen and (min--moz-device-pixel-ratio: 1.5),
614
+ only screen and (min-device-pixel-ratio: 1.5) {}
plugin-fw/assets/css/yit-upgrader.css ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* === Plugins Upgrader === */
2
+
3
+ .yit-plugin-changelog-wrapper {
4
+ display: none;
5
+ }
6
+
7
+ .yit-plugin-changelog-title {
8
+ text-transform: uppercase;
9
+ }
10
+
11
+ .yit-plugin-changelog {
12
+ background: #fcfcfc;
13
+ height: 97%;
14
+ }
plugin-fw/assets/images/chosen/chosen-sprite.png ADDED
Binary file
plugin-fw/assets/images/chosen/chosen-sprite@2x.png ADDED
Binary file
plugin-fw/assets/images/double-sidebar.png ADDED
Binary file
plugin-fw/assets/images/licence-error.png ADDED
Binary file
plugin-fw/assets/images/no-sidebar.png ADDED
Binary file
plugin-fw/assets/images/off.png ADDED
Binary file
plugin-fw/assets/images/on.png ADDED
Binary file
plugin-fw/assets/images/select.png ADDED
Binary file
plugin-fw/assets/images/sidebar-left.png ADDED
Binary file
plugin-fw/assets/images/sidebar-right.png ADDED
Binary file
plugin-fw/assets/images/sleep.png ADDED
Binary file
plugin-fw/assets/images/slider/grey.gif ADDED
Binary file
plugin-fw/assets/images/slider/handle.png ADDED
Binary file
plugin-fw/assets/images/slider/orange.gif ADDED
Binary file
plugin-fw/assets/images/slider/tooltip.png ADDED
Binary file
plugin-fw/assets/images/spinner.png ADDED
Binary file
plugin-fw/assets/images/ui-icons_222222_256x240.png ADDED
Binary file
plugin-fw/assets/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
plugin-fw/assets/images/ui-icons_454545_256x240.png ADDED
Binary file
plugin-fw/assets/images/ui-icons_888888_256x240.png ADDED
Binary file
plugin-fw/assets/images/x.png ADDED
Binary file
plugin-fw/assets/images/yithemes-icon.png ADDED
Binary file
plugin-fw/assets/js/chosen/chosen.jquery.js ADDED
@@ -0,0 +1,1211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.1.0
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ (function() {
14
+ var $, AbstractChosen, Chosen, SelectParser, _ref,
15
+ __hasProp = {}.hasOwnProperty,
16
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
17
+
18
+ SelectParser = (function() {
19
+ function SelectParser() {
20
+ this.options_index = 0;
21
+ this.parsed = [];
22
+ }
23
+
24
+ SelectParser.prototype.add_node = function(child) {
25
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
26
+ return this.add_group(child);
27
+ } else {
28
+ return this.add_option(child);
29
+ }
30
+ };
31
+
32
+ SelectParser.prototype.add_group = function(group) {
33
+ var group_position, option, _i, _len, _ref, _results;
34
+ group_position = this.parsed.length;
35
+ this.parsed.push({
36
+ array_index: group_position,
37
+ group: true,
38
+ label: this.escapeExpression(group.label),
39
+ children: 0,
40
+ disabled: group.disabled
41
+ });
42
+ _ref = group.childNodes;
43
+ _results = [];
44
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
45
+ option = _ref[_i];
46
+ _results.push(this.add_option(option, group_position, group.disabled));
47
+ }
48
+ return _results;
49
+ };
50
+
51
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
52
+ if (option.nodeName.toUpperCase() === "OPTION") {
53
+ if (option.text !== "") {
54
+ if (group_position != null) {
55
+ this.parsed[group_position].children += 1;
56
+ }
57
+ this.parsed.push({
58
+ array_index: this.parsed.length,
59
+ options_index: this.options_index,
60
+ value: option.value,
61
+ text: option.text,
62
+ html: option.innerHTML,
63
+ selected: option.selected,
64
+ disabled: group_disabled === true ? group_disabled : option.disabled,
65
+ group_array_index: group_position,
66
+ classes: option.className,
67
+ style: option.style.cssText
68
+ });
69
+ } else {
70
+ this.parsed.push({
71
+ array_index: this.parsed.length,
72
+ options_index: this.options_index,
73
+ empty: true
74
+ });
75
+ }
76
+ return this.options_index += 1;
77
+ }
78
+ };
79
+
80
+ SelectParser.prototype.escapeExpression = function(text) {
81
+ var map, unsafe_chars;
82
+ if ((text == null) || text === false) {
83
+ return "";
84
+ }
85
+ if (!/[\&\<\>\"\'\`]/.test(text)) {
86
+ return text;
87
+ }
88
+ map = {
89
+ "<": "&lt;",
90
+ ">": "&gt;",
91
+ '"': "&quot;",
92
+ "'": "&#x27;",
93
+ "`": "&#x60;"
94
+ };
95
+ unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
96
+ return text.replace(unsafe_chars, function(chr) {
97
+ return map[chr] || "&amp;";
98
+ });
99
+ };
100
+
101
+ return SelectParser;
102
+
103
+ })();
104
+
105
+ SelectParser.select_to_array = function(select) {
106
+ var child, parser, _i, _len, _ref;
107
+ parser = new SelectParser();
108
+ _ref = select.childNodes;
109
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
110
+ child = _ref[_i];
111
+ parser.add_node(child);
112
+ }
113
+ return parser.parsed;
114
+ };
115
+
116
+ AbstractChosen = (function() {
117
+ function AbstractChosen(form_field, options) {
118
+ this.form_field = form_field;
119
+ this.options = options != null ? options : {};
120
+ if (!AbstractChosen.browser_is_supported()) {
121
+ return;
122
+ }
123
+ this.is_multiple = this.form_field.multiple;
124
+ this.set_default_text();
125
+ this.set_default_values();
126
+ this.setup();
127
+ this.set_up_html();
128
+ this.register_observers();
129
+ }
130
+
131
+ AbstractChosen.prototype.set_default_values = function() {
132
+ var _this = this;
133
+ this.click_test_action = function(evt) {
134
+ return _this.test_active_click(evt);
135
+ };
136
+ this.activate_action = function(evt) {
137
+ return _this.activate_field(evt);
138
+ };
139
+ this.active_field = false;
140
+ this.mouse_on_container = false;
141
+ this.results_showing = false;
142
+ this.result_highlighted = null;
143
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
144
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
145
+ this.disable_search = this.options.disable_search || false;
146
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
147
+ this.group_search = this.options.group_search != null ? this.options.group_search : true;
148
+ this.search_contains = this.options.search_contains || false;
149
+ this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
150
+ this.max_selected_options = this.options.max_selected_options || Infinity;
151
+ this.inherit_select_classes = this.options.inherit_select_classes || false;
152
+ this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
153
+ return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
154
+ };
155
+
156
+ AbstractChosen.prototype.set_default_text = function() {
157
+ if (this.form_field.getAttribute("data-placeholder")) {
158
+ this.default_text = this.form_field.getAttribute("data-placeholder");
159
+ } else if (this.is_multiple) {
160
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
161
+ } else {
162
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
163
+ }
164
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
165
+ };
166
+
167
+ AbstractChosen.prototype.mouse_enter = function() {
168
+ return this.mouse_on_container = true;
169
+ };
170
+
171
+ AbstractChosen.prototype.mouse_leave = function() {
172
+ return this.mouse_on_container = false;
173
+ };
174
+
175
+ AbstractChosen.prototype.input_focus = function(evt) {
176
+ var _this = this;
177
+ if (this.is_multiple) {
178
+ if (!this.active_field) {
179
+ return setTimeout((function() {
180
+ return _this.container_mousedown();
181
+ }), 50);
182
+ }
183
+ } else {
184
+ if (!this.active_field) {
185
+ return this.activate_field();
186
+ }
187
+ }
188
+ };
189
+
190
+ AbstractChosen.prototype.input_blur = function(evt) {
191
+ var _this = this;
192
+ if (!this.mouse_on_container) {
193
+ this.active_field = false;
194
+ return setTimeout((function() {
195
+ return _this.blur_test();
196
+ }), 100);
197
+ }
198
+ };
199
+
200
+ AbstractChosen.prototype.results_option_build = function(options) {
201
+ var content, data, _i, _len, _ref;
202
+ content = '';
203
+ _ref = this.results_data;
204
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
205
+ data = _ref[_i];
206
+ if (data.group) {
207
+ content += this.result_add_group(data);
208
+ } else {
209
+ content += this.result_add_option(data);
210
+ }
211
+ if (options != null ? options.first : void 0) {
212
+ if (data.selected && this.is_multiple) {
213
+ this.choice_build(data);
214
+ } else if (data.selected && !this.is_multiple) {
215
+ this.single_set_selected_text(data.text);
216
+ }
217
+ }
218
+ }
219
+ return content;
220
+ };
221
+
222
+ AbstractChosen.prototype.result_add_option = function(option) {
223
+ var classes, option_el;
224
+ if (!option.search_match) {
225
+ return '';
226
+ }
227
+ if (!this.include_option_in_results(option)) {
228
+ return '';
229
+ }
230
+ classes = [];
231
+ if (!option.disabled && !(option.selected && this.is_multiple)) {
232
+ classes.push("active-result");
233
+ }
234
+ if (option.disabled && !(option.selected && this.is_multiple)) {
235
+ classes.push("disabled-result");
236
+ }
237
+ if (option.selected) {
238
+ classes.push("result-selected");
239
+ }
240
+ if (option.group_array_index != null) {
241
+ classes.push("group-option");
242
+ }
243
+ if (option.classes !== "") {
244
+ classes.push(option.classes);
245
+ }
246
+ option_el = document.createElement("li");
247
+ option_el.className = classes.join(" ");
248
+ option_el.style.cssText = option.style;
249
+ option_el.setAttribute("data-option-array-index", option.array_index);
250
+ option_el.innerHTML = option.search_text;
251
+ return this.outerHTML(option_el);
252
+ };
253
+
254
+ AbstractChosen.prototype.result_add_group = function(group) {
255
+ var group_el;
256
+ if (!(group.search_match || group.group_match)) {
257
+ return '';
258
+ }
259
+ if (!(group.active_options > 0)) {
260
+ return '';
261
+ }
262
+ group_el = document.createElement("li");
263
+ group_el.className = "group-result";
264
+ group_el.innerHTML = group.search_text;
265
+ return this.outerHTML(group_el);
266
+ };
267
+
268
+ AbstractChosen.prototype.results_update_field = function() {
269
+ this.set_default_text();
270
+ if (!this.is_multiple) {
271
+ this.results_reset_cleanup();
272
+ }
273
+ this.result_clear_highlight();
274
+ this.results_build();
275
+ if (this.results_showing) {
276
+ return this.winnow_results();
277
+ }
278
+ };
279
+
280
+ AbstractChosen.prototype.reset_single_select_options = function() {
281
+ var result, _i, _len, _ref, _results;
282
+ _ref = this.results_data;
283
+ _results = [];
284
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
285
+ result = _ref[_i];
286
+ if (result.selected) {
287
+ _results.push(result.selected = false);
288
+ } else {
289
+ _results.push(void 0);
290
+ }
291
+ }
292
+ return _results;
293
+ };
294
+
295
+ AbstractChosen.prototype.results_toggle = function() {
296
+ if (this.results_showing) {
297
+ return this.results_hide();
298
+ } else {
299
+ return this.results_show();
300
+ }
301
+ };
302
+
303
+ AbstractChosen.prototype.results_search = function(evt) {
304
+ if (this.results_showing) {
305
+ return this.winnow_results();
306
+ } else {
307
+ return this.results_show();
308
+ }
309
+ };
310
+
311
+ AbstractChosen.prototype.winnow_results = function() {
312
+ var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
313
+ this.no_results_clear();
314
+ results = 0;
315
+ searchText = this.get_search_text();
316
+ escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
317
+ regexAnchor = this.search_contains ? "" : "^";
318
+ regex = new RegExp(regexAnchor + escapedSearchText, 'i');
319
+ zregex = new RegExp(escapedSearchText, 'i');
320
+ _ref = this.results_data;
321
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
322
+ option = _ref[_i];
323
+ option.search_match = false;
324
+ results_group = null;
325
+ if (this.include_option_in_results(option)) {
326
+ if (option.group) {
327
+ option.group_match = false;
328
+ option.active_options = 0;
329
+ }
330
+ if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
331
+ results_group = this.results_data[option.group_array_index];
332
+ if (results_group.active_options === 0 && results_group.search_match) {
333
+ results += 1;
334
+ }
335
+ results_group.active_options += 1;
336
+ }
337
+ if (!(option.group && !this.group_search)) {
338
+ option.search_text = option.group ? option.label : option.html;
339
+ option.search_match = this.search_string_match(option.search_text, regex);
340
+ if (option.search_match && !option.group) {
341
+ results += 1;
342
+ }
343
+ if (option.search_match) {
344
+ if (searchText.length) {
345
+ startpos = option.search_text.search(zregex);
346
+ text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
347
+ option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
348
+ }
349
+ if (results_group != null) {
350
+ results_group.group_match = true;
351
+ }
352
+ } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
353
+ option.search_match = true;
354
+ }
355
+ }
356
+ }
357
+ }
358
+ this.result_clear_highlight();
359
+ if (results < 1 && searchText.length) {
360
+ this.update_results_content("");
361
+ return this.no_results(searchText);
362
+ } else {
363
+ this.update_results_content(this.results_option_build());
364
+ return this.winnow_results_set_highlight();
365
+ }
366
+ };
367
+
368
+ AbstractChosen.prototype.search_string_match = function(search_string, regex) {
369
+ var part, parts, _i, _len;
370
+ if (regex.test(search_string)) {
371
+ return true;
372
+ } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
373
+ parts = search_string.replace(/\[|\]/g, "").split(" ");
374
+ if (parts.length) {
375
+ for (_i = 0, _len = parts.length; _i < _len; _i++) {
376
+ part = parts[_i];
377
+ if (regex.test(part)) {
378
+ return true;
379
+ }
380
+ }
381
+ }
382
+ }
383
+ };
384
+
385
+ AbstractChosen.prototype.choices_count = function() {
386
+ var option, _i, _len, _ref;
387
+ if (this.selected_option_count != null) {
388
+ return this.selected_option_count;
389
+ }
390
+ this.selected_option_count = 0;
391
+ _ref = this.form_field.options;
392
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
393
+ option = _ref[_i];
394
+ if (option.selected) {
395
+ this.selected_option_count += 1;
396
+ }
397
+ }
398
+ return this.selected_option_count;
399
+ };
400
+
401
+ AbstractChosen.prototype.choices_click = function(evt) {
402
+ evt.preventDefault();
403
+ if (!(this.results_showing || this.is_disabled)) {
404
+ return this.results_show();
405
+ }
406
+ };
407
+
408
+ AbstractChosen.prototype.keyup_checker = function(evt) {
409
+ var stroke, _ref;
410
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
411
+ this.search_field_scale();
412
+ switch (stroke) {
413
+ case 8:
414
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
415
+ return this.keydown_backstroke();
416
+ } else if (!this.pending_backstroke) {
417
+ this.result_clear_highlight();
418
+ return this.results_search();
419
+ }
420
+ break;
421
+ case 13:
422
+ evt.preventDefault();
423
+ if (this.results_showing) {
424
+ return this.result_select(evt);
425
+ }
426
+ break;
427
+ case 27:
428
+ if (this.results_showing) {
429
+ this.results_hide();
430
+ }
431
+ return true;
432
+ case 9:
433
+ case 38:
434
+ case 40:
435
+ case 16:
436
+ case 91:
437
+ case 17:
438
+ break;
439
+ default:
440
+ return this.results_search();
441
+ }
442
+ };
443
+
444
+ AbstractChosen.prototype.clipboard_event_checker = function(evt) {
445
+ var _this = this;
446
+ return setTimeout((function() {
447
+ return _this.results_search();
448
+ }), 50);
449
+ };
450
+
451
+ AbstractChosen.prototype.container_width = function() {
452
+ if (this.options.width != null) {
453
+ return this.options.width;
454
+ } else {
455
+ return "" + this.form_field.offsetWidth + "px";
456
+ }
457
+ };
458
+
459
+ AbstractChosen.prototype.include_option_in_results = function(option) {
460
+ if (this.is_multiple && (!this.display_selected_options && option.selected)) {
461
+ return false;
462
+ }
463
+ if (!this.display_disabled_options && option.disabled) {
464
+ return false;
465
+ }
466
+ if (option.empty) {
467
+ return false;
468
+ }
469
+ return true;
470
+ };
471
+
472
+ AbstractChosen.prototype.search_results_touchstart = function(evt) {
473
+ this.touch_started = true;
474
+ return this.search_results_mouseover(evt);
475
+ };
476
+
477
+ AbstractChosen.prototype.search_results_touchmove = function(evt) {
478
+ this.touch_started = false;
479
+ return this.search_results_mouseout(evt);
480
+ };
481
+
482
+ AbstractChosen.prototype.search_results_touchend = function(evt) {
483
+ if (this.touch_started) {
484
+ return this.search_results_mouseup(evt);
485
+ }
486
+ };
487
+
488
+ AbstractChosen.prototype.outerHTML = function(element) {
489
+ var tmp;
490
+ if (element.outerHTML) {
491
+ return element.outerHTML;
492
+ }
493
+ tmp = document.createElement("div");
494
+ tmp.appendChild(element);
495
+ return tmp.innerHTML;
496
+ };
497
+
498
+ AbstractChosen.browser_is_supported = function() {
499
+ if (window.navigator.appName === "Microsoft Internet Explorer") {
500
+ return document.documentMode >= 8;
501
+ }
502
+ if (/iP(od|hone)/i.test(window.navigator.userAgent)) {
503
+ return false;
504
+ }
505
+ if (/Android/i.test(window.navigator.userAgent)) {
506
+ if (/Mobile/i.test(window.navigator.userAgent)) {
507
+ return false;
508
+ }
509
+ }
510
+ return true;
511
+ };
512
+
513
+ AbstractChosen.default_multiple_text = "Select Some Options";
514
+
515
+ AbstractChosen.default_single_text = "Select an Option";
516
+
517
+ AbstractChosen.default_no_result_text = "No results match";
518
+
519
+ return AbstractChosen;
520
+
521
+ })();
522
+
523
+ $ = jQuery;
524
+
525
+ $.fn.extend({
526
+ chosen: function(options) {
527
+ if (!AbstractChosen.browser_is_supported()) {
528
+ return this;
529
+ }
530
+ return this.each(function(input_field) {
531
+ var $this, chosen;
532
+ $this = $(this);
533
+ chosen = $this.data('chosen');
534
+ if (options === 'destroy' && chosen) {
535
+ chosen.destroy();
536
+ } else if (!chosen) {
537
+ $this.data('chosen', new Chosen(this, options));
538
+ }
539
+ });
540
+ }
541
+ });
542
+
543
+ Chosen = (function(_super) {
544
+ __extends(Chosen, _super);
545
+
546
+ function Chosen() {
547
+ _ref = Chosen.__super__.constructor.apply(this, arguments);
548
+ return _ref;
549
+ }
550
+
551
+ Chosen.prototype.setup = function() {
552
+ this.form_field_jq = $(this.form_field);
553
+ this.current_selectedIndex = this.form_field.selectedIndex;
554
+ return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
555
+ };
556
+
557
+ Chosen.prototype.set_up_html = function() {
558
+ var container_classes, container_props;
559
+ container_classes = ["chosen-container"];
560
+ container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
561
+ if (this.inherit_select_classes && this.form_field.className) {
562
+ container_classes.push(this.form_field.className);
563
+ }
564
+ if (this.is_rtl) {
565
+ container_classes.push("chosen-rtl");
566
+ }
567
+ container_props = {
568
+ 'class': container_classes.join(' '),
569
+ 'style': "width: " + (this.container_width()) + ";",
570
+ 'title': this.form_field.title
571
+ };
572
+ if (this.form_field.id.length) {
573
+ container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
574
+ }
575
+ this.container = $("<div />", container_props);
576
+ if (this.is_multiple) {
577
+ this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
578
+ } else {
579
+ this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
580
+ }
581
+ this.form_field_jq.hide().after(this.container);
582
+ this.dropdown = this.container.find('div.chosen-drop').first();
583
+ this.search_field = this.container.find('input').first();
584
+ this.search_results = this.container.find('ul.chosen-results').first();
585
+ this.search_field_scale();
586
+ this.search_no_results = this.container.find('li.no-results').first();
587
+ if (this.is_multiple) {
588
+ this.search_choices = this.container.find('ul.chosen-choices').first();
589
+ this.search_container = this.container.find('li.search-field').first();
590
+ } else {
591
+ this.search_container = this.container.find('div.chosen-search').first();
592
+ this.selected_item = this.container.find('.chosen-single').first();
593
+ }
594
+ this.results_build();
595
+ this.set_tab_index();
596
+ this.set_label_behavior();
597
+ return this.form_field_jq.trigger("chosen:ready", {
598
+ chosen: this
599
+ });
600
+ };
601
+
602
+ Chosen.prototype.register_observers = function() {
603
+ var _this = this;
604
+ this.container.bind('mousedown.chosen', function(evt) {
605
+ _this.container_mousedown(evt);
606
+ });
607
+ this.container.bind('mouseup.chosen', function(evt) {
608
+ _this.container_mouseup(evt);
609
+ });
610
+ this.container.bind('mouseenter.chosen', function(evt) {
611
+ _this.mouse_enter(evt);
612
+ });
613
+ this.container.bind('mouseleave.chosen', function(evt) {
614
+ _this.mouse_leave(evt);
615
+ });
616
+ this.search_results.bind('mouseup.chosen', function(evt) {
617
+ _this.search_results_mouseup(evt);
618
+ });
619
+ this.search_results.bind('mouseover.chosen', function(evt) {
620
+ _this.search_results_mouseover(evt);
621
+ });
622
+ this.search_results.bind('mouseout.chosen', function(evt) {
623
+ _this.search_results_mouseout(evt);
624
+ });
625
+ this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
626
+ _this.search_results_mousewheel(evt);
627
+ });
628
+ this.search_results.bind('touchstart.chosen', function(evt) {
629
+ _this.search_results_touchstart(evt);
630
+ });
631
+ this.search_results.bind('touchmove.chosen', function(evt) {
632
+ _this.search_results_touchmove(evt);
633
+ });
634
+ this.search_results.bind('touchend.chosen', function(evt) {
635
+ _this.search_results_touchend(evt);
636
+ });
637
+ this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
638
+ _this.results_update_field(evt);
639
+ });
640
+ this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
641
+ _this.activate_field(evt);
642
+ });
643
+ this.form_field_jq.bind("chosen:open.chosen", function(evt) {
644
+ _this.container_mousedown(evt);
645
+ });
646
+ this.form_field_jq.bind("chosen:close.chosen", function(evt) {
647
+ _this.input_blur(evt);
648
+ });
649
+ this.search_field.bind('blur.chosen', function(evt) {
650
+ _this.input_blur(evt);
651
+ });
652
+ this.search_field.bind('keyup.chosen', function(evt) {
653
+ _this.keyup_checker(evt);
654
+ });
655
+ this.search_field.bind('keydown.chosen', function(evt) {
656
+ _this.keydown_checker(evt);
657
+ });
658
+ this.search_field.bind('focus.chosen', function(evt) {
659
+ _this.input_focus(evt);
660
+ });
661
+ this.search_field.bind('cut.chosen', function(evt) {
662
+ _this.clipboard_event_checker(evt);
663
+ });
664
+ this.search_field.bind('paste.chosen', function(evt) {
665
+ _this.clipboard_event_checker(evt);
666
+ });
667
+ if (this.is_multiple) {
668
+ return this.search_choices.bind('click.chosen', function(evt) {
669
+ _this.choices_click(evt);
670
+ });
671
+ } else {
672
+ return this.container.bind('click.chosen', function(evt) {
673
+ evt.preventDefault();
674
+ });
675
+ }
676
+ };
677
+
678
+ Chosen.prototype.destroy = function() {
679
+ $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
680
+ if (this.search_field[0].tabIndex) {
681
+ this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
682
+ }
683
+ this.container.remove();
684
+ this.form_field_jq.removeData('chosen');
685
+ return this.form_field_jq.show();
686
+ };
687
+
688
+ Chosen.prototype.search_field_disabled = function() {
689
+ this.is_disabled = this.form_field_jq[0].disabled;
690
+ if (this.is_disabled) {
691
+ this.container.addClass('chosen-disabled');
692
+ this.search_field[0].disabled = true;
693
+ if (!this.is_multiple) {
694
+ this.selected_item.unbind("focus.chosen", this.activate_action);
695
+ }
696
+ return this.close_field();
697
+ } else {
698
+ this.container.removeClass('chosen-disabled');
699
+ this.search_field[0].disabled = false;
700
+ if (!this.is_multiple) {
701
+ return this.selected_item.bind("focus.chosen", this.activate_action);
702
+ }
703
+ }
704
+ };
705
+
706
+ Chosen.prototype.container_mousedown = function(evt) {
707
+ if (!this.is_disabled) {
708
+ if (evt && evt.type === "mousedown" && !this.results_showing) {
709
+ evt.preventDefault();
710
+ }
711
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
712
+ if (!this.active_field) {
713
+ if (this.is_multiple) {
714
+ this.search_field.val("");
715
+ }
716
+ $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);
717
+ this.results_show();
718
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
719
+ evt.preventDefault();
720
+ this.results_toggle();
721
+ }
722
+ return this.activate_field();
723
+ }
724
+ }
725
+ };
726
+
727
+ Chosen.prototype.container_mouseup = function(evt) {
728
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
729
+ return this.results_reset(evt);
730
+ }
731
+ };
732
+
733
+ Chosen.prototype.search_results_mousewheel = function(evt) {
734
+ var delta;
735
+ if (evt.originalEvent) {
736
+ delta = -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
737
+ }
738
+ if (delta != null) {
739
+ evt.preventDefault();
740
+ if (evt.type === 'DOMMouseScroll') {
741
+ delta = delta * 40;
742
+ }
743
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
744
+ }
745
+ };
746
+
747
+ Chosen.prototype.blur_test = function(evt) {
748
+ if (!this.active_field && this.container.hasClass("chosen-container-active")) {
749
+ return this.close_field();
750
+ }
751
+ };
752
+
753
+ Chosen.prototype.close_field = function() {
754
+ $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
755
+ this.active_field = false;
756
+ this.results_hide();
757
+ this.container.removeClass("chosen-container-active");
758
+ this.clear_backstroke();
759
+ this.show_search_field_default();
760
+ return this.search_field_scale();
761
+ };
762
+
763
+ Chosen.prototype.activate_field = function() {
764
+ this.container.addClass("chosen-container-active");
765
+ this.active_field = true;
766
+ this.search_field.val(this.search_field.val());
767
+ return this.search_field.focus();
768
+ };
769
+
770
+ Chosen.prototype.test_active_click = function(evt) {
771
+ var active_container;
772
+ active_container = $(evt.target).closest('.chosen-container');
773
+ if (active_container.length && this.container[0] === active_container[0]) {
774
+ return this.active_field = true;
775
+ } else {
776
+ return this.close_field();
777
+ }
778
+ };
779
+
780
+ Chosen.prototype.results_build = function() {
781
+ this.parsing = true;
782
+ this.selected_option_count = null;
783
+ this.results_data = SelectParser.select_to_array(this.form_field);
784
+ if (this.is_multiple) {
785
+ this.search_choices.find("li.search-choice").remove();
786
+ } else if (!this.is_multiple) {
787
+ this.single_set_selected_text();
788
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
789
+ this.search_field[0].readOnly = true;
790
+ this.container.addClass("chosen-container-single-nosearch");
791
+ } else {
792
+ this.search_field[0].readOnly = false;
793
+ this.container.removeClass("chosen-container-single-nosearch");
794
+ }
795
+ }
796
+ this.update_results_content(this.results_option_build({
797
+ first: true
798
+ }));
799
+ this.search_field_disabled();
800
+ this.show_search_field_default();
801
+ this.search_field_scale();
802
+ return this.parsing = false;
803
+ };
804
+
805
+ Chosen.prototype.result_do_highlight = function(el) {
806
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
807
+ if (el.length) {
808
+ this.result_clear_highlight();
809
+ this.result_highlight = el;
810
+ this.result_highlight.addClass("highlighted");
811
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
812
+ visible_top = this.search_results.scrollTop();
813
+ visible_bottom = maxHeight + visible_top;
814
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
815
+ high_bottom = high_top + this.result_highlight.outerHeight();
816
+ if (high_bottom >= visible_bottom) {
817
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
818
+ } else if (high_top < visible_top) {
819
+ return this.search_results.scrollTop(high_top);
820
+ }
821
+ }
822
+ };
823
+
824
+ Chosen.prototype.result_clear_highlight = function() {
825
+ if (this.result_highlight) {
826
+ this.result_highlight.removeClass("highlighted");
827
+ }
828
+ return this.result_highlight = null;
829
+ };
830
+
831
+ Chosen.prototype.results_show = function() {
832
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
833
+ this.form_field_jq.trigger("chosen:maxselected", {
834
+ chosen: this
835
+ });
836
+ return false;
837
+ }
838
+ this.container.addClass("chosen-with-drop");
839
+ this.results_showing = true;
840
+ this.search_field.focus();
841
+ this.search_field.val(this.search_field.val());
842
+ this.winnow_results();
843
+ return this.form_field_jq.trigger("chosen:showing_dropdown", {
844
+ chosen: this
845
+ });
846
+ };
847
+
848
+ Chosen.prototype.update_results_content = function(content) {
849
+ return this.search_results.html(content);
850
+ };
851
+
852
+ Chosen.prototype.results_hide = function() {
853
+ if (this.results_showing) {
854
+ this.result_clear_highlight();
855
+ this.container.removeClass("chosen-with-drop");
856
+ this.form_field_jq.trigger("chosen:hiding_dropdown", {
857
+ chosen: this
858
+ });
859
+ }
860
+ return this.results_showing = false;
861
+ };
862
+
863
+ Chosen.prototype.set_tab_index = function(el) {
864
+ var ti;
865
+ if (this.form_field.tabIndex) {
866
+ ti = this.form_field.tabIndex;
867
+ this.form_field.tabIndex = -1;
868
+ return this.search_field[0].tabIndex = ti;
869
+ }
870
+ };
871
+
872
+ Chosen.prototype.set_label_behavior = function() {
873
+ var _this = this;
874
+ this.form_field_label = this.form_field_jq.parents("label");
875
+ if (!this.form_field_label.length && this.form_field.id.length) {
876
+ this.form_field_label = $("label[for='" + this.form_field.id + "']");
877
+ }
878
+ if (this.form_field_label.length > 0) {
879
+ return this.form_field_label.bind('click.chosen', function(evt) {
880
+ if (_this.is_multiple) {
881
+ return _this.container_mousedown(evt);
882
+ } else {
883
+ return _this.activate_field();
884
+ }
885
+ });
886
+ }
887
+ };
888
+
889
+ Chosen.prototype.show_search_field_default = function() {
890
+ if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
891
+ this.search_field.val(this.default_text);
892
+ return this.search_field.addClass("default");
893
+ } else {
894
+ this.search_field.val("");
895
+ return this.search_field.removeClass("default");
896
+ }
897
+ };
898
+
899
+ Chosen.prototype.search_results_mouseup = function(evt) {
900
+ var target;
901
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
902
+ if (target.length) {
903
+ this.result_highlight = target;
904
+ this.result_select(evt);
905
+ return this.search_field.focus();
906
+ }
907
+ };
908
+
909
+ Chosen.prototype.search_results_mouseover = function(evt) {
910
+ var target;
911
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
912
+ if (target) {
913
+ return this.result_do_highlight(target);
914
+ }
915
+ };
916
+
917
+ Chosen.prototype.search_results_mouseout = function(evt) {
918
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
919
+ return this.result_clear_highlight();
920
+ }
921
+ };
922
+
923
+ Chosen.prototype.choice_build = function(item) {
924
+ var choice, close_link,
925
+ _this = this;
926
+ choice = $('<li />', {
927
+ "class": "search-choice"
928
+ }).html("<span>" + item.html + "</span>");
929
+ if (item.disabled) {
930
+ choice.addClass('search-choice-disabled');
931
+ } else {
932
+ close_link = $('<a />', {
933
+ "class": 'search-choice-close',
934
+ 'data-option-array-index': item.array_index
935
+ });
936
+ close_link.bind('click.chosen', function(evt) {
937
+ return _this.choice_destroy_link_click(evt);
938
+ });
939
+ choice.append(close_link);
940
+ }
941
+ return this.search_container.before(choice);
942
+ };
943
+
944
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
945
+ evt.preventDefault();
946
+ evt.stopPropagation();
947
+ if (!this.is_disabled) {
948
+ return this.choice_destroy($(evt.target));
949
+ }
950
+ };
951
+
952
+ Chosen.prototype.choice_destroy = function(link) {
953
+ if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
954
+ this.show_search_field_default();
955
+ if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
956
+ this.results_hide();
957
+ }
958
+ link.parents('li').first().remove();
959
+ return this.search_field_scale();
960
+ }
961
+ };
962
+
963
+ Chosen.prototype.results_reset = function() {
964
+ this.reset_single_select_options();
965
+ this.form_field.options[0].selected = true;
966
+ this.single_set_selected_text();
967
+ this.show_search_field_default();
968
+ this.results_reset_cleanup();
969
+ this.form_field_jq.trigger("change");
970
+ if (this.active_field) {
971
+ return this.results_hide();
972
+ }
973
+ };
974
+
975
+ Chosen.prototype.results_reset_cleanup = function() {
976
+ this.current_selectedIndex = this.form_field.selectedIndex;
977
+ return this.selected_item.find("abbr").remove();
978
+ };
979
+
980
+ Chosen.prototype.result_select = function(evt) {
981
+ var high, item;
982
+ if (this.result_highlight) {
983
+ high = this.result_highlight;
984
+ this.result_clear_highlight();
985
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
986
+ this.form_field_jq.trigger("chosen:maxselected", {
987
+ chosen: this
988
+ });
989
+ return false;
990
+ }
991
+ if (this.is_multiple) {
992
+ high.removeClass("active-result");
993
+ } else {
994
+ this.reset_single_select_options();
995
+ }
996
+ item = this.results_data[high[0].getAttribute("data-option-array-index")];
997
+ item.selected = true;
998
+ this.form_field.options[item.options_index].selected = true;
999
+ this.selected_option_count = null;
1000
+ if (this.is_multiple) {
1001
+ this.choice_build(item);
1002
+ } else {
1003
+ this.single_set_selected_text(item.text);
1004
+ }
1005
+ if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
1006
+ this.results_hide();
1007
+ }
1008
+ this.search_field.val("");
1009
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
1010
+ this.form_field_jq.trigger("change", {
1011
+ 'selected': this.form_field.options[item.options_index].value
1012
+ });
1013
+ }
1014
+ this.current_selectedIndex = this.form_field.selectedIndex;
1015
+ return this.search_field_scale();
1016
+ }
1017
+ };
1018
+
1019
+ Chosen.prototype.single_set_selected_text = function(text) {
1020
+ if (text == null) {
1021
+ text = this.default_text;
1022
+ }
1023
+ if (text === this.default_text) {
1024
+ this.selected_item.addClass("chosen-default");
1025
+ } else {
1026
+ this.single_deselect_control_build();
1027
+ this.selected_item.removeClass("chosen-default");
1028
+ }
1029
+ return this.selected_item.find("span").text(text);
1030
+ };
1031
+
1032
+ Chosen.prototype.result_deselect = function(pos) {
1033
+ var result_data;
1034
+ result_data = this.results_data[pos];
1035
+ if (!this.form_field.options[result_data.options_index].disabled) {
1036
+ result_data.selected = false;
1037
+ this.form_field.options[result_data.options_index].selected = false;
1038
+ this.selected_option_count = null;
1039
+ this.result_clear_highlight();
1040
+ if (this.results_showing) {
1041
+ this.winnow_results();
1042
+ }
1043
+ this.form_field_jq.trigger("change", {
1044
+ deselected: this.form_field.options[result_data.options_index].value
1045
+ });
1046
+ this.search_field_scale();
1047
+ return true;
1048
+ } else {
1049
+ return false;
1050
+ }
1051
+ };
1052
+
1053
+ Chosen.prototype.single_deselect_control_build = function() {
1054
+ if (!this.allow_single_deselect) {
1055
+ return;
1056
+ }
1057
+ if (!this.selected_item.find("abbr").length) {
1058
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
1059
+ }
1060
+ return this.selected_item.addClass("chosen-single-with-deselect");
1061
+ };
1062
+
1063
+ Chosen.prototype.get_search_text = function() {
1064
+ if (this.search_field.val() === this.default_text) {
1065
+ return "";
1066
+ } else {
1067
+ return $('<div/>').text($.trim(this.search_field.val())).html();
1068
+ }
1069
+ };
1070
+
1071
+ Chosen.prototype.winnow_results_set_highlight = function() {
1072
+ var do_high, selected_results;
1073
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
1074
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
1075
+ if (do_high != null) {
1076
+ return this.result_do_highlight(do_high);
1077
+ }
1078
+ };
1079
+
1080
+ Chosen.prototype.no_results = function(terms) {
1081
+ var no_results_html;
1082
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
1083
+ no_results_html.find("span").first().html(terms);
1084
+ this.search_results.append(no_results_html);
1085
+ return this.form_field_jq.trigger("chosen:no_results", {
1086
+ chosen: this
1087
+ });
1088
+ };
1089
+
1090
+ Chosen.prototype.no_results_clear = function() {
1091
+ return this.search_results.find(".no-results").remove();
1092
+ };
1093
+
1094
+ Chosen.prototype.keydown_arrow = function() {
1095
+ var next_sib;
1096
+ if (this.results_showing && this.result_highlight) {
1097
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
1098
+ if (next_sib) {
1099
+ return this.result_do_highlight(next_sib);
1100
+ }
1101
+ } else {
1102
+ return this.results_show();
1103
+ }
1104
+ };
1105
+
1106
+ Chosen.prototype.keyup_arrow = function() {
1107
+ var prev_sibs;
1108
+ if (!this.results_showing && !this.is_multiple) {
1109
+ return this.results_show();
1110
+ } else if (this.result_highlight) {
1111
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
1112
+ if (prev_sibs.length) {
1113
+ return this.result_do_highlight(prev_sibs.first());
1114
+ } else {
1115
+ if (this.choices_count() > 0) {
1116
+ this.results_hide();
1117
+ }
1118
+ return this.result_clear_highlight();
1119
+ }
1120
+ }
1121
+ };
1122
+
1123
+ Chosen.prototype.keydown_backstroke = function() {
1124
+ var next_available_destroy;
1125
+ if (this.pending_backstroke) {
1126
+ this.choice_destroy(this.pending_backstroke.find("a").first());
1127
+ return this.clear_backstroke();
1128
+ } else {
1129
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
1130
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
1131
+ this.pending_backstroke = next_available_destroy;
1132
+ if (this.single_backstroke_delete) {
1133
+ return this.keydown_backstroke();
1134
+ } else {
1135
+ return this.pending_backstroke.addClass("search-choice-focus");
1136
+ }
1137
+ }
1138
+ }
1139
+ };
1140
+
1141
+ Chosen.prototype.clear_backstroke = function() {
1142
+ if (this.pending_backstroke) {
1143
+ this.pending_backstroke.removeClass("search-choice-focus");
1144
+ }
1145
+ return this.pending_backstroke = null;
1146
+ };
1147
+
1148
+ Chosen.prototype.keydown_checker = function(evt) {
1149
+ var stroke, _ref1;
1150
+ stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
1151
+ this.search_field_scale();
1152
+ if (stroke !== 8 && this.pending_backstroke) {
1153
+ this.clear_backstroke();
1154
+ }
1155
+ switch (stroke) {
1156
+ case 8:
1157
+ this.backstroke_length = this.search_field.val().length;
1158
+ break;
1159
+ case 9:
1160
+ if (this.results_showing && !this.is_multiple) {
1161
+ this.result_select(evt);
1162
+ }
1163
+ this.mouse_on_container = false;
1164
+ break;
1165
+ case 13:
1166
+ evt.preventDefault();
1167
+ break;
1168
+ case 38:
1169
+ evt.preventDefault();
1170
+ this.keyup_arrow();
1171
+ break;
1172
+ case 40:
1173
+ evt.preventDefault();
1174
+ this.keydown_arrow();
1175
+ break;
1176
+ }
1177
+ };
1178
+
1179
+ Chosen.prototype.search_field_scale = function() {
1180
+ var div, f_width, h, style, style_block, styles, w, _i, _len;
1181
+ if (this.is_multiple) {
1182
+ h = 0;
1183
+ w = 0;
1184
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
1185
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
1186
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
1187
+ style = styles[_i];
1188
+ style_block += style + ":" + this.search_field.css(style) + ";";
1189
+ }
1190
+ div = $('<div />', {
1191
+ 'style': style_block
1192
+ });
1193
+ div.text(this.search_field.val());
1194
+ $('body').append(div);
1195
+ w = div.width() + 25;
1196
+ div.remove();
1197
+ f_width = this.container.outerWidth();
1198
+ if (w > f_width - 10) {
1199
+ w = f_width - 10;
1200
+ }
1201
+ return this.search_field.css({
1202
+ 'width': w + 'px'
1203
+ });
1204
+ }
1205
+ };
1206
+
1207
+ return Chosen;
1208
+
1209
+ })(AbstractChosen);
1210
+
1211
+ }).call(this);
plugin-fw/assets/js/codemirror/codemirror.js ADDED
@@ -0,0 +1,5799 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror version 3.15
2
+ //
3
+ // CodeMirror is the only global var we claim
4
+ window.CodeMirror = (function() {
5
+ "use strict";
6
+
7
+ // BROWSER SNIFFING
8
+
9
+ // Crude, but necessary to handle a number of hard-to-feature-detect
10
+ // bugs and behavior differences.
11
+ var gecko = /gecko\/\d/i.test(navigator.userAgent);
12
+ var ie = /MSIE \d/.test(navigator.userAgent);
13
+ var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
14
+ var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
15
+ var webkit = /WebKit\//.test(navigator.userAgent);
16
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
17
+ var chrome = /Chrome\//.test(navigator.userAgent);
18
+ var opera = /Opera\//.test(navigator.userAgent);
19
+ var safari = /Apple Computer/.test(navigator.vendor);
20
+ var khtml = /KHTML\//.test(navigator.userAgent);
21
+ var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
22
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
23
+ var phantom = /PhantomJS/.test(navigator.userAgent);
24
+
25
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
26
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
27
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
28
+ var mac = ios || /Mac/.test(navigator.platform);
29
+ var windows = /windows/i.test(navigator.platform);
30
+
31
+ var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
32
+ if (opera_version) opera_version = Number(opera_version[1]);
33
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
34
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
35
+ var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
36
+ var captureMiddleClick = gecko || (ie && !ie_lt9);
37
+
38
+ // Optimize some code when these features are not used
39
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
40
+
41
+ // CONSTRUCTOR
42
+
43
+ function CodeMirror(place, options) {
44
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
45
+
46
+ this.options = options = options || {};
47
+ // Determine effective options based on given values and defaults.
48
+ for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
49
+ options[opt] = defaults[opt];
50
+ setGuttersForLineNumbers(options);
51
+
52
+ var docStart = typeof options.value == "string" ? 0 : options.value.first;
53
+ var display = this.display = makeDisplay(place, docStart);
54
+ display.wrapper.CodeMirror = this;
55
+ updateGutters(this);
56
+ if (options.autofocus && !mobile) focusInput(this);
57
+
58
+ this.state = {keyMaps: [],
59
+ overlays: [],
60
+ modeGen: 0,
61
+ overwrite: false, focused: false,
62
+ suppressEdits: false, pasteIncoming: false,
63
+ draggingText: false,
64
+ highlight: new Delayed()};
65
+
66
+ themeChanged(this);
67
+ if (options.lineWrapping)
68
+ this.display.wrapper.className += " CodeMirror-wrap";
69
+
70
+ var doc = options.value;
71
+ if (typeof doc == "string") doc = new Doc(options.value, options.mode);
72
+ operation(this, attachDoc)(this, doc);
73
+
74
+ // Override magic textarea content restore that IE sometimes does
75
+ // on our hidden textarea on reload
76
+ if (ie) setTimeout(bind(resetInput, this, true), 20);
77
+
78
+ registerEventHandlers(this);
79
+ // IE throws unspecified error in certain cases, when
80
+ // trying to access activeElement before onload
81
+ var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
82
+ if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
83
+ else onBlur(this);
84
+
85
+ operation(this, function() {
86
+ for (var opt in optionHandlers)
87
+ if (optionHandlers.propertyIsEnumerable(opt))
88
+ optionHandlers[opt](this, options[opt], Init);
89
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
90
+ })();
91
+ }
92
+
93
+ // DISPLAY CONSTRUCTOR
94
+
95
+ function makeDisplay(place, docStart) {
96
+ var d = {};
97
+
98
+ var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
99
+ if (webkit) input.style.width = "1000px";
100
+ else input.setAttribute("wrap", "off");
101
+ // if border: 0; -- iOS fails to open keyboard (issue #1287)
102
+ if (ios) input.style.border = "1px solid black";
103
+ input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
104
+
105
+ // Wraps and hides input textarea
106
+ d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
107
+ // The actual fake scrollbars.
108
+ d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
109
+ d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
110
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
111
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
112
+ // DIVs containing the selection and the actual code
113
+ d.lineDiv = elt("div", null, "CodeMirror-code");
114
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
115
+ // Blinky cursor, and element used to ensure cursor fits at the end of a line
116
+ d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
117
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
118
+ d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
119
+ // Used to measure text size
120
+ d.measure = elt("div", null, "CodeMirror-measure");
121
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
122
+ d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
123
+ null, "position: relative; outline: none");
124
+ // Moved around its parent to cover visible view
125
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
126
+ // Set to the height of the text, causes scrolling
127
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
128
+ // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
129
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
130
+ // Will contain the gutters, if any
131
+ d.gutters = elt("div", null, "CodeMirror-gutters");
132
+ d.lineGutter = null;
133
+ // Provides scrolling
134
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
135
+ d.scroller.setAttribute("tabIndex", "-1");
136
+ // The element in which the editor lives.
137
+ d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
138
+ d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
139
+ // Work around IE7 z-index bug
140
+ if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
141
+ if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
142
+
143
+ // Needed to hide big blue blinking cursor on Mobile Safari
144
+ if (ios) input.style.width = "0px";
145
+ if (!webkit) d.scroller.draggable = true;
146
+ // Needed to handle Tab key in KHTML
147
+ if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
148
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
149
+ else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
150
+
151
+ // Current visible range (may be bigger than the view window).
152
+ d.viewOffset = d.lastSizeC = 0;
153
+ d.showingFrom = d.showingTo = docStart;
154
+
155
+ // Used to only resize the line number gutter when necessary (when
156
+ // the amount of lines crosses a boundary that makes its width change)
157
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
158
+ // See readInput and resetInput
159
+ d.prevInput = "";
160
+ // Set to true when a non-horizontal-scrolling widget is added. As
161
+ // an optimization, widget aligning is skipped when d is false.
162
+ d.alignWidgets = false;
163
+ // Flag that indicates whether we currently expect input to appear
164
+ // (after some event like 'keypress' or 'input') and are polling
165
+ // intensively.
166
+ d.pollingFast = false;
167
+ // Self-resetting timeout for the poller
168
+ d.poll = new Delayed();
169
+
170
+ d.cachedCharWidth = d.cachedTextHeight = null;
171
+ d.measureLineCache = [];
172
+ d.measureLineCachePos = 0;
173
+
174
+ // Tracks when resetInput has punted to just putting a short
175
+ // string instead of the (large) selection.
176
+ d.inaccurateSelection = false;
177
+
178
+ // Tracks the maximum line length so that the horizontal scrollbar
179
+ // can be kept static when scrolling.
180
+ d.maxLine = null;
181
+ d.maxLineLength = 0;
182
+ d.maxLineChanged = false;
183
+
184
+ // Used for measuring wheel scrolling granularity
185
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
186
+
187
+ return d;
188
+ }
189
+
190
+ // STATE UPDATES
191
+
192
+ // Used to get the editor into a consistent state again when options change.
193
+
194
+ function loadMode(cm) {
195
+ cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
196
+ cm.doc.iter(function(line) {
197
+ if (line.stateAfter) line.stateAfter = null;
198
+ if (line.styles) line.styles = null;
199
+ });
200
+ cm.doc.frontier = cm.doc.first;
201
+ startWorker(cm, 100);
202
+ cm.state.modeGen++;
203
+ if (cm.curOp) regChange(cm);
204
+ }
205
+
206
+ function wrappingChanged(cm) {
207
+ if (cm.options.lineWrapping) {
208
+ cm.display.wrapper.className += " CodeMirror-wrap";
209
+ cm.display.sizer.style.minWidth = "";
210
+ } else {
211
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
212
+ computeMaxLength(cm);
213
+ }
214
+ estimateLineHeights(cm);
215
+ regChange(cm);
216
+ clearCaches(cm);
217
+ setTimeout(function(){updateScrollbars(cm);}, 100);
218
+ }
219
+
220
+ function estimateHeight(cm) {
221
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
222
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
223
+ return function(line) {
224
+ if (lineIsHidden(cm.doc, line))
225
+ return 0;
226
+ else if (wrapping)
227
+ return (Math.ceil(line.text.length / perLine) || 1) * th;
228
+ else
229
+ return th;
230
+ };
231
+ }
232
+
233
+ function estimateLineHeights(cm) {
234
+ var doc = cm.doc, est = estimateHeight(cm);
235
+ doc.iter(function(line) {
236
+ var estHeight = est(line);
237
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
238
+ });
239
+ }
240
+
241
+ function keyMapChanged(cm) {
242
+ var map = keyMap[cm.options.keyMap], style = map.style;
243
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
244
+ (style ? " cm-keymap-" + style : "");
245
+ cm.state.disableInput = map.disableInput;
246
+ }
247
+
248
+ function themeChanged(cm) {
249
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
250
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
251
+ clearCaches(cm);
252
+ }
253
+
254
+ function guttersChanged(cm) {
255
+ updateGutters(cm);
256
+ regChange(cm);
257
+ setTimeout(function(){alignHorizontally(cm);}, 20);
258
+ }
259
+
260
+ function updateGutters(cm) {
261
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
262
+ removeChildren(gutters);
263
+ for (var i = 0; i < specs.length; ++i) {
264
+ var gutterClass = specs[i];
265
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
266
+ if (gutterClass == "CodeMirror-linenumbers") {
267
+ cm.display.lineGutter = gElt;
268
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
269
+ }
270
+ }
271
+ gutters.style.display = i ? "" : "none";
272
+ }
273
+
274
+ function lineLength(doc, line) {
275
+ if (line.height == 0) return 0;
276
+ var len = line.text.length, merged, cur = line;
277
+ while (merged = collapsedSpanAtStart(cur)) {
278
+ var found = merged.find();
279
+ cur = getLine(doc, found.from.line);
280
+ len += found.from.ch - found.to.ch;
281
+ }
282
+ cur = line;
283
+ while (merged = collapsedSpanAtEnd(cur)) {
284
+ var found = merged.find();
285
+ len -= cur.text.length - found.from.ch;
286
+ cur = getLine(doc, found.to.line);
287
+ len += cur.text.length - found.to.ch;
288
+ }
289
+ return len;
290
+ }
291
+
292
+ function computeMaxLength(cm) {
293
+ var d = cm.display, doc = cm.doc;
294
+ d.maxLine = getLine(doc, doc.first);
295
+ d.maxLineLength = lineLength(doc, d.maxLine);
296
+ d.maxLineChanged = true;
297
+ doc.iter(function(line) {
298
+ var len = lineLength(doc, line);
299
+ if (len > d.maxLineLength) {
300
+ d.maxLineLength = len;
301
+ d.maxLine = line;
302
+ }
303
+ });
304
+ }
305
+
306
+ // Make sure the gutters options contains the element
307
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
308
+ function setGuttersForLineNumbers(options) {
309
+ var found = false;
310
+ for (var i = 0; i < options.gutters.length; ++i) {
311
+ if (options.gutters[i] == "CodeMirror-linenumbers") {
312
+ if (options.lineNumbers) found = true;
313
+ else options.gutters.splice(i--, 1);
314
+ }
315
+ }
316
+ if (!found && options.lineNumbers)
317
+ options.gutters.push("CodeMirror-linenumbers");
318
+ }
319
+
320
+ // SCROLLBARS
321
+
322
+ // Re-synchronize the fake scrollbars with the actual size of the
323
+ // content. Optionally force a scrollTop.
324
+ function updateScrollbars(cm) {
325
+ var d = cm.display, docHeight = cm.doc.height;
326
+ var totalHeight = docHeight + paddingVert(d);
327
+ d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
328
+ d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
329
+ var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
330
+ var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
331
+ var needsV = scrollHeight > (d.scroller.clientHeight + 1);
332
+ if (needsV) {
333
+ d.scrollbarV.style.display = "block";
334
+ d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
335
+ d.scrollbarV.firstChild.style.height =
336
+ (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
337
+ } else d.scrollbarV.style.display = "";
338
+ if (needsH) {
339
+ d.scrollbarH.style.display = "block";
340
+ d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
341
+ d.scrollbarH.firstChild.style.width =
342
+ (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
343
+ } else d.scrollbarH.style.display = "";
344
+ if (needsH && needsV) {
345
+ d.scrollbarFiller.style.display = "block";
346
+ d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
347
+ } else d.scrollbarFiller.style.display = "";
348
+ if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
349
+ d.gutterFiller.style.display = "block";
350
+ d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
351
+ d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
352
+ } else d.gutterFiller.style.display = "";
353
+
354
+ if (mac_geLion && scrollbarWidth(d.measure) === 0)
355
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
356
+ }
357
+
358
+ function visibleLines(display, doc, viewPort) {
359
+ var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
360
+ if (typeof viewPort == "number") top = viewPort;
361
+ else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
362
+ top = Math.floor(top - paddingTop(display));
363
+ var bottom = Math.ceil(top + height);
364
+ return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
365
+ }
366
+
367
+ // LINE NUMBERS
368
+
369
+ function alignHorizontally(cm) {
370
+ var display = cm.display;
371
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
372
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
373
+ var gutterW = display.gutters.offsetWidth, l = comp + "px";
374
+ for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
375
+ for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
376
+ }
377
+ if (cm.options.fixedGutter)
378
+ display.gutters.style.left = (comp + gutterW) + "px";
379
+ }
380
+
381
+ function maybeUpdateLineNumberWidth(cm) {
382
+ if (!cm.options.lineNumbers) return false;
383
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
384
+ if (last.length != display.lineNumChars) {
385
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
386
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
387
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
388
+ display.lineGutter.style.width = "";
389
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
390
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
391
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
392
+ display.lineGutter.style.width = display.lineNumWidth + "px";
393
+ return true;
394
+ }
395
+ return false;
396
+ }
397
+
398
+ function lineNumberFor(options, i) {
399
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
400
+ }
401
+ function compensateForHScroll(display) {
402
+ return getRect(display.scroller).left - getRect(display.sizer).left;
403
+ }
404
+
405
+ // DISPLAY DRAWING
406
+
407
+ function updateDisplay(cm, changes, viewPort, forced) {
408
+ var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
409
+ var visible = visibleLines(cm.display, cm.doc, viewPort);
410
+ for (;;) {
411
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
412
+ forced = false;
413
+ updated = true;
414
+ updateSelection(cm);
415
+ updateScrollbars(cm);
416
+
417
+ // Clip forced viewport to actual scrollable area
418
+ if (viewPort)
419
+ viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
420
+ typeof viewPort == "number" ? viewPort : viewPort.top);
421
+ visible = visibleLines(cm.display, cm.doc, viewPort);
422
+ if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
423
+ break;
424
+ changes = [];
425
+ }
426
+
427
+ if (updated) {
428
+ signalLater(cm, "update", cm);
429
+ if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
430
+ signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
431
+ }
432
+ return updated;
433
+ }
434
+
435
+ // Uses a set of changes plus the current scroll position to
436
+ // determine which DOM updates have to be made, and makes the
437
+ // updates.
438
+ function updateDisplayInner(cm, changes, visible, forced) {
439
+ var display = cm.display, doc = cm.doc;
440
+ if (!display.wrapper.clientWidth) {
441
+ display.showingFrom = display.showingTo = doc.first;
442
+ display.viewOffset = 0;
443
+ return;
444
+ }
445
+
446
+ // Bail out if the visible area is already rendered and nothing changed.
447
+ if (!forced && changes.length == 0 &&
448
+ visible.from > display.showingFrom && visible.to < display.showingTo)
449
+ return;
450
+
451
+ if (maybeUpdateLineNumberWidth(cm))
452
+ changes = [{from: doc.first, to: doc.first + doc.size}];
453
+ var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
454
+ display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
455
+
456
+ // Used to determine which lines need their line numbers updated
457
+ var positionsChangedFrom = Infinity;
458
+ if (cm.options.lineNumbers)
459
+ for (var i = 0; i < changes.length; ++i)
460
+ if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
461
+
462
+ var end = doc.first + doc.size;
463
+ var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
464
+ var to = Math.min(end, visible.to + cm.options.viewportMargin);
465
+ if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
466
+ if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
467
+ if (sawCollapsedSpans) {
468
+ from = lineNo(visualLine(doc, getLine(doc, from)));
469
+ while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
470
+ }
471
+
472
+ // Create a range of theoretically intact lines, and punch holes
473
+ // in that using the change info.
474
+ var intact = [{from: Math.max(display.showingFrom, doc.first),
475
+ to: Math.min(display.showingTo, end)}];
476
+ if (intact[0].from >= intact[0].to) intact = [];
477
+ else intact = computeIntact(intact, changes);
478
+ // When merged lines are present, we might have to reduce the
479
+ // intact ranges because changes in continued fragments of the
480
+ // intact lines do require the lines to be redrawn.
481
+ if (sawCollapsedSpans)
482
+ for (var i = 0; i < intact.length; ++i) {
483
+ var range = intact[i], merged;
484
+ while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
485
+ var newTo = merged.find().from.line;
486
+ if (newTo > range.from) range.to = newTo;
487
+ else { intact.splice(i--, 1); break; }
488
+ }
489
+ }
490
+
491
+ // Clip off the parts that won't be visible
492
+ var intactLines = 0;
493
+ for (var i = 0; i < intact.length; ++i) {
494
+ var range = intact[i];
495
+ if (range.from < from) range.from = from;
496
+ if (range.to > to) range.to = to;
497
+ if (range.from >= range.to) intact.splice(i--, 1);
498
+ else intactLines += range.to - range.from;
499
+ }
500
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
501
+ updateViewOffset(cm);
502
+ return;
503
+ }
504
+ intact.sort(function(a, b) {return a.from - b.from;});
505
+
506
+ // Avoid crashing on IE's "unspecified error" when in iframes
507
+ try {
508
+ var focused = document.activeElement;
509
+ } catch(e) {}
510
+ if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
511
+ patchDisplay(cm, from, to, intact, positionsChangedFrom);
512
+ display.lineDiv.style.display = "";
513
+ if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
514
+
515
+ var different = from != display.showingFrom || to != display.showingTo ||
516
+ display.lastSizeC != display.wrapper.clientHeight;
517
+ // This is just a bogus formula that detects when the editor is
518
+ // resized or the font size changes.
519
+ if (different) {
520
+ display.lastSizeC = display.wrapper.clientHeight;
521
+ startWorker(cm, 400);
522
+ }
523
+ display.showingFrom = from; display.showingTo = to;
524
+
525
+ updateHeightsInViewport(cm);
526
+ updateViewOffset(cm);
527
+
528
+ return true;
529
+ }
530
+
531
+ function updateHeightsInViewport(cm) {
532
+ var display = cm.display;
533
+ var prevBottom = display.lineDiv.offsetTop;
534
+ for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
535
+ if (ie_lt8) {
536
+ var bot = node.offsetTop + node.offsetHeight;
537
+ height = bot - prevBottom;
538
+ prevBottom = bot;
539
+ } else {
540
+ var box = getRect(node);
541
+ height = box.bottom - box.top;
542
+ }
543
+ var diff = node.lineObj.height - height;
544
+ if (height < 2) height = textHeight(display);
545
+ if (diff > .001 || diff < -.001) {
546
+ updateLineHeight(node.lineObj, height);
547
+ var widgets = node.lineObj.widgets;
548
+ if (widgets) for (var i = 0; i < widgets.length; ++i)
549
+ widgets[i].height = widgets[i].node.offsetHeight;
550
+ }
551
+ }
552
+ }
553
+
554
+ function updateViewOffset(cm) {
555
+ var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
556
+ // Position the mover div to align with the current virtual scroll position
557
+ cm.display.mover.style.top = off + "px";
558
+ }
559
+
560
+ function computeIntact(intact, changes) {
561
+ for (var i = 0, l = changes.length || 0; i < l; ++i) {
562
+ var change = changes[i], intact2 = [], diff = change.diff || 0;
563
+ for (var j = 0, l2 = intact.length; j < l2; ++j) {
564
+ var range = intact[j];
565
+ if (change.to <= range.from && change.diff) {
566
+ intact2.push({from: range.from + diff, to: range.to + diff});
567
+ } else if (change.to <= range.from || change.from >= range.to) {
568
+ intact2.push(range);
569
+ } else {
570
+ if (change.from > range.from)
571
+ intact2.push({from: range.from, to: change.from});
572
+ if (change.to < range.to)
573
+ intact2.push({from: change.to + diff, to: range.to + diff});
574
+ }
575
+ }
576
+ intact = intact2;
577
+ }
578
+ return intact;
579
+ }
580
+
581
+ function getDimensions(cm) {
582
+ var d = cm.display, left = {}, width = {};
583
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
584
+ left[cm.options.gutters[i]] = n.offsetLeft;
585
+ width[cm.options.gutters[i]] = n.offsetWidth;
586
+ }
587
+ return {fixedPos: compensateForHScroll(d),
588
+ gutterTotalWidth: d.gutters.offsetWidth,
589
+ gutterLeft: left,
590
+ gutterWidth: width,
591
+ wrapperWidth: d.wrapper.clientWidth};
592
+ }
593
+
594
+ function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
595
+ var dims = getDimensions(cm);
596
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
597
+ if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
598
+ removeChildren(display.lineDiv);
599
+ var container = display.lineDiv, cur = container.firstChild;
600
+
601
+ function rm(node) {
602
+ var next = node.nextSibling;
603
+ if (webkit && mac && cm.display.currentWheelTarget == node) {
604
+ node.style.display = "none";
605
+ node.lineObj = null;
606
+ } else {
607
+ node.parentNode.removeChild(node);
608
+ }
609
+ return next;
610
+ }
611
+
612
+ var nextIntact = intact.shift(), lineN = from;
613
+ cm.doc.iter(from, to, function(line) {
614
+ if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
615
+ if (lineIsHidden(cm.doc, line)) {
616
+ if (line.height != 0) updateLineHeight(line, 0);
617
+ if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
618
+ var w = line.widgets[i];
619
+ if (w.showIfHidden) {
620
+ var prev = cur.previousSibling;
621
+ if (/pre/i.test(prev.nodeName)) {
622
+ var wrap = elt("div", null, null, "position: relative");
623
+ prev.parentNode.replaceChild(wrap, prev);
624
+ wrap.appendChild(prev);
625
+ prev = wrap;
626
+ }
627
+ var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
628
+ if (!w.handleMouseEvents) wnode.ignoreEvents = true;
629
+ positionLineWidget(w, wnode, prev, dims);
630
+ }
631
+ }
632
+ } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
633
+ // This line is intact. Skip to the actual node. Update its
634
+ // line number if needed.
635
+ while (cur.lineObj != line) cur = rm(cur);
636
+ if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
637
+ setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
638
+ cur = cur.nextSibling;
639
+ } else {
640
+ // For lines with widgets, make an attempt to find and reuse
641
+ // the existing element, so that widgets aren't needlessly
642
+ // removed and re-inserted into the dom
643
+ if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
644
+ if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
645
+ // This line needs to be generated.
646
+ var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
647
+ if (lineNode != reuse) {
648
+ container.insertBefore(lineNode, cur);
649
+ } else {
650
+ while (cur != reuse) cur = rm(cur);
651
+ cur = cur.nextSibling;
652
+ }
653
+
654
+ lineNode.lineObj = line;
655
+ }
656
+ ++lineN;
657
+ });
658
+ while (cur) cur = rm(cur);
659
+ }
660
+
661
+ function buildLineElement(cm, line, lineNo, dims, reuse) {
662
+ var lineElement = lineContent(cm, line);
663
+ var markers = line.gutterMarkers, display = cm.display, wrap;
664
+
665
+ if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
666
+ return lineElement;
667
+
668
+ // Lines with gutter elements, widgets or a background class need
669
+ // to be wrapped again, and have the extra elements added to the
670
+ // wrapper div
671
+
672
+ if (reuse) {
673
+ reuse.alignable = null;
674
+ var isOk = true, widgetsSeen = 0, insertBefore = null;
675
+ for (var n = reuse.firstChild, next; n; n = next) {
676
+ next = n.nextSibling;
677
+ if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
678
+ reuse.removeChild(n);
679
+ } else {
680
+ for (var i = 0; i < line.widgets.length; ++i) {
681
+ var widget = line.widgets[i];
682
+ if (widget.node == n.firstChild) {
683
+ if (!widget.above && !insertBefore) insertBefore = n;
684
+ positionLineWidget(widget, n, reuse, dims);
685
+ ++widgetsSeen;
686
+ break;
687
+ }
688
+ }
689
+ if (i == line.widgets.length) { isOk = false; break; }
690
+ }
691
+ }
692
+ reuse.insertBefore(lineElement, insertBefore);
693
+ if (isOk && widgetsSeen == line.widgets.length) {
694
+ wrap = reuse;
695
+ reuse.className = line.wrapClass || "";
696
+ }
697
+ }
698
+ if (!wrap) {
699
+ wrap = elt("div", null, line.wrapClass, "position: relative");
700
+ wrap.appendChild(lineElement);
701
+ }
702
+ // Kludge to make sure the styled element lies behind the selection (by z-index)
703
+ if (line.bgClass)
704
+ wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
705
+ if (cm.options.lineNumbers || markers) {
706
+ var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
707
+ (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
708
+ wrap.firstChild);
709
+ if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
710
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
711
+ wrap.lineNumber = gutterWrap.appendChild(
712
+ elt("div", lineNumberFor(cm.options, lineNo),
713
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
714
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
715
+ + display.lineNumInnerWidth + "px"));
716
+ if (markers)
717
+ for (var k = 0; k < cm.options.gutters.length; ++k) {
718
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
719
+ if (found)
720
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
721
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
722
+ }
723
+ }
724
+ if (ie_lt8) wrap.style.zIndex = 2;
725
+ if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
726
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
727
+ if (!widget.handleMouseEvents) node.ignoreEvents = true;
728
+ positionLineWidget(widget, node, wrap, dims);
729
+ if (widget.above)
730
+ wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
731
+ else
732
+ wrap.appendChild(node);
733
+ signalLater(widget, "redraw");
734
+ }
735
+ return wrap;
736
+ }
737
+
738
+ function positionLineWidget(widget, node, wrap, dims) {
739
+ if (widget.noHScroll) {
740
+ (wrap.alignable || (wrap.alignable = [])).push(node);
741
+ var width = dims.wrapperWidth;
742
+ node.style.left = dims.fixedPos + "px";
743
+ if (!widget.coverGutter) {
744
+ width -= dims.gutterTotalWidth;
745
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
746
+ }
747
+ node.style.width = width + "px";
748
+ }
749
+ if (widget.coverGutter) {
750
+ node.style.zIndex = 5;
751
+ node.style.position = "relative";
752
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
753
+ }
754
+ }
755
+
756
+ // SELECTION / CURSOR
757
+
758
+ function updateSelection(cm) {
759
+ var display = cm.display;
760
+ var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
761
+ if (collapsed || cm.options.showCursorWhenSelecting)
762
+ updateSelectionCursor(cm);
763
+ else
764
+ display.cursor.style.display = display.otherCursor.style.display = "none";
765
+ if (!collapsed)
766
+ updateSelectionRange(cm);
767
+ else
768
+ display.selectionDiv.style.display = "none";
769
+
770
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
771
+ if (cm.options.moveInputWithCursor) {
772
+ var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
773
+ var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
774
+ display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
775
+ headPos.top + lineOff.top - wrapOff.top)) + "px";
776
+ display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
777
+ headPos.left + lineOff.left - wrapOff.left)) + "px";
778
+ }
779
+ }
780
+
781
+ // No selection, plain cursor
782
+ function updateSelectionCursor(cm) {
783
+ var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
784
+ display.cursor.style.left = pos.left + "px";
785
+ display.cursor.style.top = pos.top + "px";
786
+ display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
787
+ display.cursor.style.display = "";
788
+
789
+ if (pos.other) {
790
+ display.otherCursor.style.display = "";
791
+ display.otherCursor.style.left = pos.other.left + "px";
792
+ display.otherCursor.style.top = pos.other.top + "px";
793
+ display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
794
+ } else { display.otherCursor.style.display = "none"; }
795
+ }
796
+
797
+ // Highlight selection
798
+ function updateSelectionRange(cm) {
799
+ var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
800
+ var fragment = document.createDocumentFragment();
801
+ var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
802
+
803
+ function add(left, top, width, bottom) {
804
+ if (top < 0) top = 0;
805
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
806
+ "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
807
+ "px; height: " + (bottom - top) + "px"));
808
+ }
809
+
810
+ function drawForLine(line, fromArg, toArg) {
811
+ var lineObj = getLine(doc, line);
812
+ var lineLen = lineObj.text.length;
813
+ var start, end;
814
+ function coords(ch, bias) {
815
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
816
+ }
817
+
818
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
819
+ var leftPos = coords(from, "left"), rightPos, left, right;
820
+ if (from == to) {
821
+ rightPos = leftPos;
822
+ left = right = leftPos.left;
823
+ } else {
824
+ rightPos = coords(to - 1, "right");
825
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
826
+ left = leftPos.left;
827
+ right = rightPos.right;
828
+ }
829
+ if (fromArg == null && from == 0) left = pl;
830
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
831
+ add(left, leftPos.top, null, leftPos.bottom);
832
+ left = pl;
833
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
834
+ }
835
+ if (toArg == null && to == lineLen) right = clientWidth;
836
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
837
+ start = leftPos;
838
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
839
+ end = rightPos;
840
+ if (left < pl + 1) left = pl;
841
+ add(left, rightPos.top, right - left, rightPos.bottom);
842
+ });
843
+ return {start: start, end: end};
844
+ }
845
+
846
+ if (sel.from.line == sel.to.line) {
847
+ drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
848
+ } else {
849
+ var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
850
+ var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
851
+ var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
852
+ var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
853
+ if (singleVLine) {
854
+ if (leftEnd.top < rightStart.top - 2) {
855
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
856
+ add(pl, rightStart.top, rightStart.left, rightStart.bottom);
857
+ } else {
858
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
859
+ }
860
+ }
861
+ if (leftEnd.bottom < rightStart.top)
862
+ add(pl, leftEnd.bottom, null, rightStart.top);
863
+ }
864
+
865
+ removeChildrenAndAdd(display.selectionDiv, fragment);
866
+ display.selectionDiv.style.display = "";
867
+ }
868
+
869
+ // Cursor-blinking
870
+ function restartBlink(cm) {
871
+ if (!cm.state.focused) return;
872
+ var display = cm.display;
873
+ clearInterval(display.blinker);
874
+ var on = true;
875
+ display.cursor.style.visibility = display.otherCursor.style.visibility = "";
876
+ display.blinker = setInterval(function() {
877
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
878
+ }, cm.options.cursorBlinkRate);
879
+ }
880
+
881
+ // HIGHLIGHT WORKER
882
+
883
+ function startWorker(cm, time) {
884
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
885
+ cm.state.highlight.set(time, bind(highlightWorker, cm));
886
+ }
887
+
888
+ function highlightWorker(cm) {
889
+ var doc = cm.doc;
890
+ if (doc.frontier < doc.first) doc.frontier = doc.first;
891
+ if (doc.frontier >= cm.display.showingTo) return;
892
+ var end = +new Date + cm.options.workTime;
893
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
894
+ var changed = [], prevChange;
895
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
896
+ if (doc.frontier >= cm.display.showingFrom) { // Visible
897
+ var oldStyles = line.styles;
898
+ line.styles = highlightLine(cm, line, state);
899
+ var ischange = !oldStyles || oldStyles.length != line.styles.length;
900
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
901
+ if (ischange) {
902
+ if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
903
+ else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
904
+ }
905
+ line.stateAfter = copyState(doc.mode, state);
906
+ } else {
907
+ processLine(cm, line, state);
908
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
909
+ }
910
+ ++doc.frontier;
911
+ if (+new Date > end) {
912
+ startWorker(cm, cm.options.workDelay);
913
+ return true;
914
+ }
915
+ });
916
+ if (changed.length)
917
+ operation(cm, function() {
918
+ for (var i = 0; i < changed.length; ++i)
919
+ regChange(this, changed[i].start, changed[i].end);
920
+ })();
921
+ }
922
+
923
+ // Finds the line to start with when starting a parse. Tries to
924
+ // find a line with a stateAfter, so that it can start with a
925
+ // valid state. If that fails, it returns the line with the
926
+ // smallest indentation, which tends to need the least context to
927
+ // parse correctly.
928
+ function findStartLine(cm, n, precise) {
929
+ var minindent, minline, doc = cm.doc;
930
+ for (var search = n, lim = n - 100; search > lim; --search) {
931
+ if (search <= doc.first) return doc.first;
932
+ var line = getLine(doc, search - 1);
933
+ if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
934
+ var indented = countColumn(line.text, null, cm.options.tabSize);
935
+ if (minline == null || minindent > indented) {
936
+ minline = search - 1;
937
+ minindent = indented;
938
+ }
939
+ }
940
+ return minline;
941
+ }
942
+
943
+ function getStateBefore(cm, n, precise) {
944
+ var doc = cm.doc, display = cm.display;
945
+ if (!doc.mode.startState) return true;
946
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
947
+ if (!state) state = startState(doc.mode);
948
+ else state = copyState(doc.mode, state);
949
+ doc.iter(pos, n, function(line) {
950
+ processLine(cm, line, state);
951
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
952
+ line.stateAfter = save ? copyState(doc.mode, state) : null;
953
+ ++pos;
954
+ });
955
+ return state;
956
+ }
957
+
958
+ // POSITION MEASUREMENT
959
+
960
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
961
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
962
+ function paddingLeft(display) {
963
+ var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
964
+ return e.offsetLeft;
965
+ }
966
+
967
+ function measureChar(cm, line, ch, data, bias) {
968
+ var dir = -1;
969
+ data = data || measureLine(cm, line);
970
+
971
+ for (var pos = ch;; pos += dir) {
972
+ var r = data[pos];
973
+ if (r) break;
974
+ if (dir < 0 && pos == 0) dir = 1;
975
+ }
976
+ bias = pos > ch ? "left" : pos < ch ? "right" : bias;
977
+ if (bias == "left" && r.leftSide) r = r.leftSide;
978
+ else if (bias == "right" && r.rightSide) r = r.rightSide;
979
+ return {left: pos < ch ? r.right : r.left,
980
+ right: pos > ch ? r.left : r.right,
981
+ top: r.top,
982
+ bottom: r.bottom};
983
+ }
984
+
985
+ function findCachedMeasurement(cm, line) {
986
+ var cache = cm.display.measureLineCache;
987
+ for (var i = 0; i < cache.length; ++i) {
988
+ var memo = cache[i];
989
+ if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
990
+ cm.display.scroller.clientWidth == memo.width &&
991
+ memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
992
+ return memo;
993
+ }
994
+ }
995
+
996
+ function clearCachedMeasurement(cm, line) {
997
+ var exists = findCachedMeasurement(cm, line);
998
+ if (exists) exists.text = exists.measure = exists.markedSpans = null;
999
+ }
1000
+
1001
+ function measureLine(cm, line) {
1002
+ // First look in the cache
1003
+ var cached = findCachedMeasurement(cm, line);
1004
+ if (cached) return cached.measure;
1005
+
1006
+ // Failing that, recompute and store result in cache
1007
+ var measure = measureLineInner(cm, line);
1008
+ var cache = cm.display.measureLineCache;
1009
+ var memo = {text: line.text, width: cm.display.scroller.clientWidth,
1010
+ markedSpans: line.markedSpans, measure: measure,
1011
+ classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
1012
+ if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1013
+ else cache.push(memo);
1014
+ return measure;
1015
+ }
1016
+
1017
+ function measureLineInner(cm, line) {
1018
+ var display = cm.display, measure = emptyArray(line.text.length);
1019
+ var pre = lineContent(cm, line, measure, true);
1020
+
1021
+ // IE does not cache element positions of inline elements between
1022
+ // calls to getBoundingClientRect. This makes the loop below,
1023
+ // which gathers the positions of all the characters on the line,
1024
+ // do an amount of layout work quadratic to the number of
1025
+ // characters. When line wrapping is off, we try to improve things
1026
+ // by first subdividing the line into a bunch of inline blocks, so
1027
+ // that IE can reuse most of the layout information from caches
1028
+ // for those blocks. This does interfere with line wrapping, so it
1029
+ // doesn't work when wrapping is on, but in that case the
1030
+ // situation is slightly better, since IE does cache line-wrapping
1031
+ // information and only recomputes per-line.
1032
+ if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1033
+ var fragment = document.createDocumentFragment();
1034
+ var chunk = 10, n = pre.childNodes.length;
1035
+ for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
1036
+ var wrap = elt("div", null, null, "display: inline-block");
1037
+ for (var j = 0; j < chunk && n; ++j) {
1038
+ wrap.appendChild(pre.firstChild);
1039
+ --n;
1040
+ }
1041
+ fragment.appendChild(wrap);
1042
+ }
1043
+ pre.appendChild(fragment);
1044
+ }
1045
+
1046
+ removeChildrenAndAdd(display.measure, pre);
1047
+
1048
+ var outer = getRect(display.lineDiv);
1049
+ var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
1050
+ // Work around an IE7/8 bug where it will sometimes have randomly
1051
+ // replaced our pre with a clone at this point.
1052
+ if (ie_lt9 && display.measure.first != pre)
1053
+ removeChildrenAndAdd(display.measure, pre);
1054
+
1055
+ function measureRect(rect) {
1056
+ var top = rect.top - outer.top, bot = rect.bottom - outer.top;
1057
+ if (bot > maxBot) bot = maxBot;
1058
+ if (top < 0) top = 0;
1059
+ for (var i = vranges.length - 2; i >= 0; i -= 2) {
1060
+ var rtop = vranges[i], rbot = vranges[i+1];
1061
+ if (rtop > bot || rbot < top) continue;
1062
+ if (rtop <= top && rbot >= bot ||
1063
+ top <= rtop && bot >= rbot ||
1064
+ Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1065
+ vranges[i] = Math.min(top, rtop);
1066
+ vranges[i+1] = Math.max(bot, rbot);
1067
+ break;
1068
+ }
1069
+ }
1070
+ if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1071
+ return {left: rect.left - outer.left,
1072
+ right: rect.right - outer.left,
1073
+ top: i, bottom: null};
1074
+ }
1075
+ function finishRect(rect) {
1076
+ rect.bottom = vranges[rect.top+1];
1077
+ rect.top = vranges[rect.top];
1078
+ }
1079
+
1080
+ for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1081
+ var node = cur, rect = null;
1082
+ // A widget might wrap, needs special care
1083
+ if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1084
+ if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1085
+ var rects = node.getClientRects();
1086
+ if (rects.length > 1) {
1087
+ rect = data[i] = measureRect(rects[0]);
1088
+ rect.rightSide = measureRect(rects[rects.length - 1]);
1089
+ }
1090
+ }
1091
+ if (!rect) rect = data[i] = measureRect(getRect(node));
1092
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1093
+ if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1094
+ }
1095
+ for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1096
+ finishRect(cur);
1097
+ if (cur.leftSide) finishRect(cur.leftSide);
1098
+ if (cur.rightSide) finishRect(cur.rightSide);
1099
+ }
1100
+ return data;
1101
+ }
1102
+
1103
+ function measureLineWidth(cm, line) {
1104
+ var hasBadSpan = false;
1105
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
1106
+ var sp = line.markedSpans[i];
1107
+ if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1108
+ }
1109
+ var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1110
+ if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1111
+
1112
+ var pre = lineContent(cm, line, null, true);
1113
+ var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1114
+ removeChildrenAndAdd(cm.display.measure, pre);
1115
+ return getRect(end).right - getRect(cm.display.lineDiv).left;
1116
+ }
1117
+
1118
+ function clearCaches(cm) {
1119
+ cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
1120
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
1121
+ if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
1122
+ cm.display.lineNumChars = null;
1123
+ }
1124
+
1125
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
1126
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
1127
+
1128
+ // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1129
+ function intoCoordSystem(cm, lineObj, rect, context) {
1130
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1131
+ var size = widgetHeight(lineObj.widgets[i]);
1132
+ rect.top += size; rect.bottom += size;
1133
+ }
1134
+ if (context == "line") return rect;
1135
+ if (!context) context = "local";
1136
+ var yOff = heightAtLine(cm, lineObj);
1137
+ if (context == "local") yOff += paddingTop(cm.display);
1138
+ else yOff -= cm.display.viewOffset;
1139
+ if (context == "page" || context == "window") {
1140
+ var lOff = getRect(cm.display.lineSpace);
1141
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1142
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1143
+ rect.left += xOff; rect.right += xOff;
1144
+ }
1145
+ rect.top += yOff; rect.bottom += yOff;
1146
+ return rect;
1147
+ }
1148
+
1149
+ // Context may be "window", "page", "div", or "local"/null
1150
+ // Result is in "div" coords
1151
+ function fromCoordSystem(cm, coords, context) {
1152
+ if (context == "div") return coords;
1153
+ var left = coords.left, top = coords.top;
1154
+ // First move into "page" coordinate system
1155
+ if (context == "page") {
1156
+ left -= pageScrollX();
1157
+ top -= pageScrollY();
1158
+ } else if (context == "local" || !context) {
1159
+ var localBox = getRect(cm.display.sizer);
1160
+ left += localBox.left;
1161
+ top += localBox.top;
1162
+ }
1163
+
1164
+ var lineSpaceBox = getRect(cm.display.lineSpace);
1165
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1166
+ }
1167
+
1168
+ function charCoords(cm, pos, context, lineObj, bias) {
1169
+ if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1170
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
1171
+ }
1172
+
1173
+ function cursorCoords(cm, pos, context, lineObj, measurement) {
1174
+ lineObj = lineObj || getLine(cm.doc, pos.line);
1175
+ if (!measurement) measurement = measureLine(cm, lineObj);
1176
+ function get(ch, right) {
1177
+ var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
1178
+ if (right) m.left = m.right; else m.right = m.left;
1179
+ return intoCoordSystem(cm, lineObj, m, context);
1180
+ }
1181
+ function getBidi(ch, partPos) {
1182
+ var part = order[partPos], right = part.level % 2;
1183
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
1184
+ part = order[--partPos];
1185
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
1186
+ right = true;
1187
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
1188
+ part = order[++partPos];
1189
+ ch = bidiLeft(part) - part.level % 2;
1190
+ right = false;
1191
+ }
1192
+ if (right && ch == part.to && ch > part.from) return get(ch - 1);
1193
+ return get(ch, right);
1194
+ }
1195
+ var order = getOrder(lineObj), ch = pos.ch;
1196
+ if (!order) return get(ch);
1197
+ var partPos = getBidiPartAt(order, ch);
1198
+ var val = getBidi(ch, partPos);
1199
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1200
+ return val;
1201
+ }
1202
+
1203
+ function PosWithInfo(line, ch, outside, xRel) {
1204
+ var pos = new Pos(line, ch);
1205
+ pos.xRel = xRel;
1206
+ if (outside) pos.outside = true;
1207
+ return pos;
1208
+ }
1209
+
1210
+ // Coords must be lineSpace-local
1211
+ function coordsChar(cm, x, y) {
1212
+ var doc = cm.doc;
1213
+ y += cm.display.viewOffset;
1214
+ if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1215
+ var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1216
+ if (lineNo > last)
1217
+ return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
1218
+ if (x < 0) x = 0;
1219
+
1220
+ for (;;) {
1221
+ var lineObj = getLine(doc, lineNo);
1222
+ var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1223
+ var merged = collapsedSpanAtEnd(lineObj);
1224
+ var mergedPos = merged && merged.find();
1225
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1226
+ lineNo = mergedPos.to.line;
1227
+ else
1228
+ return found;
1229
+ }
1230
+ }
1231
+
1232
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
1233
+ var innerOff = y - heightAtLine(cm, lineObj);
1234
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
1235
+ var measurement = measureLine(cm, lineObj);
1236
+
1237
+ function getX(ch) {
1238
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
1239
+ lineObj, measurement);
1240
+ wrongLine = true;
1241
+ if (innerOff > sp.bottom) return sp.left - adjust;
1242
+ else if (innerOff < sp.top) return sp.left + adjust;
1243
+ else wrongLine = false;
1244
+ return sp.left;
1245
+ }
1246
+
1247
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
1248
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
1249
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1250
+
1251
+ if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
1252
+ // Do a binary search between these bounds.
1253
+ for (;;) {
1254
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1255
+ var ch = x < fromX || x - fromX <= toX - x ? from : to;
1256
+ var xDiff = x - (ch == from ? fromX : toX);
1257
+ while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1258
+ var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1259
+ xDiff < 0 ? -1 : xDiff ? 1 : 0);
1260
+ return pos;
1261
+ }
1262
+ var step = Math.ceil(dist / 2), middle = from + step;
1263
+ if (bidi) {
1264
+ middle = from;
1265
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
1266
+ }
1267
+ var middleX = getX(middle);
1268
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
1269
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
1270
+ }
1271
+ }
1272
+
1273
+ var measureText;
1274
+ function textHeight(display) {
1275
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
1276
+ if (measureText == null) {
1277
+ measureText = elt("pre");
1278
+ // Measure a bunch of lines, for browsers that compute
1279
+ // fractional heights.
1280
+ for (var i = 0; i < 49; ++i) {
1281
+ measureText.appendChild(document.createTextNode("x"));
1282
+ measureText.appendChild(elt("br"));
1283
+ }
1284
+ measureText.appendChild(document.createTextNode("x"));
1285
+ }
1286
+ removeChildrenAndAdd(display.measure, measureText);
1287
+ var height = measureText.offsetHeight / 50;
1288
+ if (height > 3) display.cachedTextHeight = height;
1289
+ removeChildren(display.measure);
1290
+ return height || 1;
1291
+ }
1292
+
1293
+ function charWidth(display) {
1294
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
1295
+ var anchor = elt("span", "x");
1296
+ var pre = elt("pre", [anchor]);
1297
+ removeChildrenAndAdd(display.measure, pre);
1298
+ var width = anchor.offsetWidth;
1299
+ if (width > 2) display.cachedCharWidth = width;
1300
+ return width || 10;
1301
+ }
1302
+
1303
+ // OPERATIONS
1304
+
1305
+ // Operations are used to wrap changes in such a way that each
1306
+ // change won't have to update the cursor and display (which would
1307
+ // be awkward, slow, and error-prone), but instead updates are
1308
+ // batched and then all combined and executed at once.
1309
+
1310
+ var nextOpId = 0;
1311
+ function startOperation(cm) {
1312
+ cm.curOp = {
1313
+ // An array of ranges of lines that have to be updated. See
1314
+ // updateDisplay.
1315
+ changes: [],
1316
+ forceUpdate: false,
1317
+ updateInput: null,
1318
+ userSelChange: null,
1319
+ textChanged: null,
1320
+ selectionChanged: false,
1321
+ cursorActivity: false,
1322
+ updateMaxLine: false,
1323
+ updateScrollPos: false,
1324
+ id: ++nextOpId
1325
+ };
1326
+ if (!delayedCallbackDepth++) delayedCallbacks = [];
1327
+ }
1328
+
1329
+ function endOperation(cm) {
1330
+ var op = cm.curOp, doc = cm.doc, display = cm.display;
1331
+ cm.curOp = null;
1332
+
1333
+ if (op.updateMaxLine) computeMaxLength(cm);
1334
+ if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
1335
+ var width = measureLineWidth(cm, display.maxLine);
1336
+ display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
1337
+ display.maxLineChanged = false;
1338
+ var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
1339
+ if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
1340
+ setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
1341
+ }
1342
+ var newScrollPos, updated;
1343
+ if (op.updateScrollPos) {
1344
+ newScrollPos = op.updateScrollPos;
1345
+ } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
1346
+ var coords = cursorCoords(cm, doc.sel.head);
1347
+ newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
1348
+ }
1349
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1350
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1351
+ if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1352
+ }
1353
+ if (!updated && op.selectionChanged) updateSelection(cm);
1354
+ if (op.updateScrollPos) {
1355
+ display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
1356
+ display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
1357
+ alignHorizontally(cm);
1358
+ if (op.scrollToPos)
1359
+ scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
1360
+ } else if (newScrollPos) {
1361
+ scrollCursorIntoView(cm);
1362
+ }
1363
+ if (op.selectionChanged) restartBlink(cm);
1364
+
1365
+ if (cm.state.focused && op.updateInput)
1366
+ resetInput(cm, op.userSelChange);
1367
+
1368
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
1369
+ if (hidden) for (var i = 0; i < hidden.length; ++i)
1370
+ if (!hidden[i].lines.length) signal(hidden[i], "hide");
1371
+ if (unhidden) for (var i = 0; i < unhidden.length; ++i)
1372
+ if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
1373
+
1374
+ var delayed;
1375
+ if (!--delayedCallbackDepth) {
1376
+ delayed = delayedCallbacks;
1377
+ delayedCallbacks = null;
1378
+ }
1379
+ if (op.textChanged)
1380
+ signal(cm, "change", cm, op.textChanged);
1381
+ if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1382
+ if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
1383
+ }
1384
+
1385
+ // Wraps a function in an operation. Returns the wrapped function.
1386
+ function operation(cm1, f) {
1387
+ return function() {
1388
+ var cm = cm1 || this, withOp = !cm.curOp;
1389
+ if (withOp) startOperation(cm);
1390
+ try { var result = f.apply(cm, arguments); }
1391
+ finally { if (withOp) endOperation(cm); }
1392
+ return result;
1393
+ };
1394
+ }
1395
+ function docOperation(f) {
1396
+ return function() {
1397
+ var withOp = this.cm && !this.cm.curOp, result;
1398
+ if (withOp) startOperation(this.cm);
1399
+ try { result = f.apply(this, arguments); }
1400
+ finally { if (withOp) endOperation(this.cm); }
1401
+ return result;
1402
+ };
1403
+ }
1404
+ function runInOp(cm, f) {
1405
+ var withOp = !cm.curOp, result;
1406
+ if (withOp) startOperation(cm);
1407
+ try { result = f(); }
1408
+ finally { if (withOp) endOperation(cm); }
1409
+ return result;
1410
+ }
1411
+
1412
+ function regChange(cm, from, to, lendiff) {
1413
+ if (from == null) from = cm.doc.first;
1414
+ if (to == null) to = cm.doc.first + cm.doc.size;
1415
+ cm.curOp.changes.push({from: from, to: to, diff: lendiff});
1416
+ }
1417
+
1418
+ // INPUT HANDLING
1419
+
1420
+ function slowPoll(cm) {
1421
+ if (cm.display.pollingFast) return;
1422
+ cm.display.poll.set(cm.options.pollInterval, function() {
1423
+ readInput(cm);
1424
+ if (cm.state.focused) slowPoll(cm);
1425
+ });
1426
+ }
1427
+
1428
+ function fastPoll(cm) {
1429
+ var missed = false;
1430
+ cm.display.pollingFast = true;
1431
+ function p() {
1432
+ var changed = readInput(cm);
1433
+ if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
1434
+ else {cm.display.pollingFast = false; slowPoll(cm);}
1435
+ }
1436
+ cm.display.poll.set(20, p);
1437
+ }
1438
+
1439
+ // prevInput is a hack to work with IME. If we reset the textarea
1440
+ // on every change, that breaks IME. So we look for changes
1441
+ // compared to the previous content instead. (Modern browsers have
1442
+ // events that indicate IME taking place, but these are not widely
1443
+ // supported or compatible enough yet to rely on.)
1444
+ function readInput(cm) {
1445
+ var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1446
+ if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1447
+ var text = input.value;
1448
+ if (text == prevInput && posEq(sel.from, sel.to)) return false;
1449
+ if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1450
+ resetInput(cm, true);
1451
+ return false;
1452
+ }
1453
+
1454
+ var withOp = !cm.curOp;
1455
+ if (withOp) startOperation(cm);
1456
+ sel.shift = false;
1457
+ var same = 0, l = Math.min(prevInput.length, text.length);
1458
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1459
+ var from = sel.from, to = sel.to;
1460
+ if (same < prevInput.length)
1461
+ from = Pos(from.line, from.ch - (prevInput.length - same));
1462
+ else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1463
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1464
+
1465
+ var updateInput = cm.curOp.updateInput;
1466
+ var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1467
+ origin: cm.state.pasteIncoming ? "paste" : "+input"};
1468
+ makeChange(cm.doc, changeEvent, "end");
1469
+ cm.curOp.updateInput = updateInput;
1470
+ signalLater(cm, "inputRead", cm, changeEvent);
1471
+
1472
+ if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1473
+ else cm.display.prevInput = text;
1474
+ if (withOp) endOperation(cm);
1475
+ cm.state.pasteIncoming = false;
1476
+ return true;
1477
+ }
1478
+
1479
+ function resetInput(cm, user) {
1480
+ var minimal, selected, doc = cm.doc;
1481
+ if (!posEq(doc.sel.from, doc.sel.to)) {
1482
+ cm.display.prevInput = "";
1483
+ minimal = hasCopyEvent &&
1484
+ (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
1485
+ var content = minimal ? "-" : selected || cm.getSelection();
1486
+ cm.display.input.value = content;
1487
+ if (cm.state.focused) selectInput(cm.display.input);
1488
+ if (ie && !ie_lt9) cm.display.inputHasSelection = content;
1489
+ } else if (user) {
1490
+ cm.display.prevInput = cm.display.input.value = "";
1491
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
1492
+ }
1493
+ cm.display.inaccurateSelection = minimal;
1494
+ }
1495
+
1496
+ function focusInput(cm) {
1497
+ if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
1498
+ cm.display.input.focus();
1499
+ }
1500
+
1501
+ function isReadOnly(cm) {
1502
+ return cm.options.readOnly || cm.doc.cantEdit;
1503
+ }
1504
+
1505
+ // EVENT HANDLERS
1506
+
1507
+ function registerEventHandlers(cm) {
1508
+ var d = cm.display;
1509
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
1510
+ if (ie)
1511
+ on(d.scroller, "dblclick", operation(cm, function(e) {
1512
+ if (signalDOMEvent(cm, e)) return;
1513
+ var pos = posFromMouse(cm, e);
1514
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1515
+ e_preventDefault(e);
1516
+ var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
1517
+ extendSelection(cm.doc, word.from, word.to);
1518
+ }));
1519
+ else
1520
+ on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1521
+ on(d.lineSpace, "selectstart", function(e) {
1522
+ if (!eventInWidget(d, e)) e_preventDefault(e);
1523
+ });
1524
+ // Gecko browsers fire contextmenu *after* opening the menu, at
1525
+ // which point we can't mess with it anymore. Context menu is
1526
+ // handled in onMouseDown for Gecko.
1527
+ if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
1528
+
1529
+ on(d.scroller, "scroll", function() {
1530
+ if (d.scroller.clientHeight) {
1531
+ setScrollTop(cm, d.scroller.scrollTop);
1532
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
1533
+ signal(cm, "scroll", cm);
1534
+ }
1535
+ });
1536
+ on(d.scrollbarV, "scroll", function() {
1537
+ if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
1538
+ });
1539
+ on(d.scrollbarH, "scroll", function() {
1540
+ if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
1541
+ });
1542
+
1543
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
1544
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
1545
+
1546
+ function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
1547
+ on(d.scrollbarH, "mousedown", reFocus);
1548
+ on(d.scrollbarV, "mousedown", reFocus);
1549
+ // Prevent wrapper from ever scrolling
1550
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1551
+
1552
+ var resizeTimer;
1553
+ function onResize() {
1554
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
1555
+ resizeTimer = null;
1556
+ // Might be a text scaling operation, clear size caches.
1557
+ d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1558
+ clearCaches(cm);
1559
+ runInOp(cm, bind(regChange, cm));
1560
+ }, 100);
1561
+ }
1562
+ on(window, "resize", onResize);
1563
+ // Above handler holds on to the editor and its data structures.
1564
+ // Here we poll to unregister it when the editor is no longer in
1565
+ // the document, so that it can be garbage-collected.
1566
+ function unregister() {
1567
+ for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
1568
+ if (p) setTimeout(unregister, 5000);
1569
+ else off(window, "resize", onResize);
1570
+ }
1571
+ setTimeout(unregister, 5000);
1572
+
1573
+ on(d.input, "keyup", operation(cm, function(e) {
1574
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1575
+ if (e.keyCode == 16) cm.doc.sel.shift = false;
1576
+ }));
1577
+ on(d.input, "input", bind(fastPoll, cm));
1578
+ on(d.input, "keydown", operation(cm, onKeyDown));
1579
+ on(d.input, "keypress", operation(cm, onKeyPress));
1580
+ on(d.input, "focus", bind(onFocus, cm));
1581
+ on(d.input, "blur", bind(onBlur, cm));
1582
+
1583
+ function drag_(e) {
1584
+ if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1585
+ e_stop(e);
1586
+ }
1587
+ if (cm.options.dragDrop) {
1588
+ on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
1589
+ on(d.scroller, "dragenter", drag_);
1590
+ on(d.scroller, "dragover", drag_);
1591
+ on(d.scroller, "drop", operation(cm, onDrop));
1592
+ }
1593
+ on(d.scroller, "paste", function(e){
1594
+ if (eventInWidget(d, e)) return;
1595
+ focusInput(cm);
1596
+ fastPoll(cm);
1597
+ });
1598
+ on(d.input, "paste", function() {
1599
+ cm.state.pasteIncoming = true;
1600
+ fastPoll(cm);
1601
+ });
1602
+
1603
+ function prepareCopy() {
1604
+ if (d.inaccurateSelection) {
1605
+ d.prevInput = "";
1606
+ d.inaccurateSelection = false;
1607
+ d.input.value = cm.getSelection();
1608
+ selectInput(d.input);
1609
+ }
1610
+ }
1611
+ on(d.input, "cut", prepareCopy);
1612
+ on(d.input, "copy", prepareCopy);
1613
+
1614
+ // Needed to handle Tab key in KHTML
1615
+ if (khtml) on(d.sizer, "mouseup", function() {
1616
+ if (document.activeElement == d.input) d.input.blur();
1617
+ focusInput(cm);
1618
+ });
1619
+ }
1620
+
1621
+ function eventInWidget(display, e) {
1622
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1623
+ if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1624
+ }
1625
+ }
1626
+
1627
+ function posFromMouse(cm, e, liberal) {
1628
+ var display = cm.display;
1629
+ if (!liberal) {
1630
+ var target = e_target(e);
1631
+ if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1632
+ target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1633
+ target == display.scrollbarFiller || target == display.gutterFiller) return null;
1634
+ }
1635
+ var x, y, space = getRect(display.lineSpace);
1636
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1637
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1638
+ return coordsChar(cm, x - space.left, y - space.top);
1639
+ }
1640
+
1641
+ var lastClick, lastDoubleClick;
1642
+ function onMouseDown(e) {
1643
+ if (signalDOMEvent(this, e)) return;
1644
+ var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1645
+ sel.shift = e.shiftKey;
1646
+
1647
+ if (eventInWidget(display, e)) {
1648
+ if (!webkit) {
1649
+ display.scroller.draggable = false;
1650
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
1651
+ }
1652
+ return;
1653
+ }
1654
+ if (clickInGutter(cm, e)) return;
1655
+ var start = posFromMouse(cm, e);
1656
+
1657
+ switch (e_button(e)) {
1658
+ case 3:
1659
+ if (captureMiddleClick) onContextMenu.call(cm, cm, e);
1660
+ return;
1661
+ case 2:
1662
+ if (start) extendSelection(cm.doc, start);
1663
+ setTimeout(bind(focusInput, cm), 20);
1664
+ e_preventDefault(e);
1665
+ return;
1666
+ }
1667
+ // For button 1, if it was clicked inside the editor
1668
+ // (posFromMouse returning non-null), we have to adjust the
1669
+ // selection.
1670
+ if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
1671
+
1672
+ if (!cm.state.focused) onFocus(cm);
1673
+
1674
+ var now = +new Date, type = "single";
1675
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
1676
+ type = "triple";
1677
+ e_preventDefault(e);
1678
+ setTimeout(bind(focusInput, cm), 20);
1679
+ selectLine(cm, start.line);
1680
+ } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
1681
+ type = "double";
1682
+ lastDoubleClick = {time: now, pos: start};
1683
+ e_preventDefault(e);
1684
+ var word = findWordAt(getLine(doc, start.line).text, start);
1685
+ extendSelection(cm.doc, word.from, word.to);
1686
+ } else { lastClick = {time: now, pos: start}; }
1687
+
1688
+ var last = start;
1689
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
1690
+ !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
1691
+ var dragEnd = operation(cm, function(e2) {
1692
+ if (webkit) display.scroller.draggable = false;
1693
+ cm.state.draggingText = false;
1694
+ off(document, "mouseup", dragEnd);
1695
+ off(display.scroller, "drop", dragEnd);
1696
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
1697
+ e_preventDefault(e2);
1698
+ extendSelection(cm.doc, start);
1699
+ focusInput(cm);
1700
+ }
1701
+ });
1702
+ // Let the drag handler handle this.
1703
+ if (webkit) display.scroller.draggable = true;
1704
+ cm.state.draggingText = dragEnd;
1705
+ // IE's approach to draggable
1706
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
1707
+ on(document, "mouseup", dragEnd);
1708
+ on(display.scroller, "drop", dragEnd);
1709
+ return;
1710
+ }
1711
+ e_preventDefault(e);
1712
+ if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
1713
+
1714
+ var startstart = sel.from, startend = sel.to, lastPos = start;
1715
+
1716
+ function doSelect(cur) {
1717
+ if (posEq(lastPos, cur)) return;
1718
+ lastPos = cur;
1719
+
1720
+ if (type == "single") {
1721
+ extendSelection(cm.doc, clipPos(doc, start), cur);
1722
+ return;
1723
+ }
1724
+
1725
+ startstart = clipPos(doc, startstart);
1726
+ startend = clipPos(doc, startend);
1727
+ if (type == "double") {
1728
+ var word = findWordAt(getLine(doc, cur.line).text, cur);
1729
+ if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
1730
+ else extendSelection(cm.doc, startstart, word.to);
1731
+ } else if (type == "triple") {
1732
+ if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
1733
+ else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
1734
+ }
1735
+ }
1736
+
1737
+ var editorSize = getRect(display.wrapper);
1738
+ // Used to ensure timeout re-tries don't fire when another extend
1739
+ // happened in the meantime (clearTimeout isn't reliable -- at
1740
+ // least on Chrome, the timeouts still happen even when cleared,
1741
+ // if the clear happens after their scheduled firing time).
1742
+ var counter = 0;
1743
+
1744
+ function extend(e) {
1745
+ var curCount = ++counter;
1746
+ var cur = posFromMouse(cm, e, true);
1747
+ if (!cur) return;
1748
+ if (!posEq(cur, last)) {
1749
+ if (!cm.state.focused) onFocus(cm);
1750
+ last = cur;
1751
+ doSelect(cur);
1752
+ var visible = visibleLines(display, doc);
1753
+ if (cur.line >= visible.to || cur.line < visible.from)
1754
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
1755
+ } else {
1756
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
1757
+ if (outside) setTimeout(operation(cm, function() {
1758
+ if (counter != curCount) return;
1759
+ display.scroller.scrollTop += outside;
1760
+ extend(e);
1761
+ }), 50);
1762
+ }
1763
+ }
1764
+
1765
+ function done(e) {
1766
+ counter = Infinity;
1767
+ e_preventDefault(e);
1768
+ focusInput(cm);
1769
+ off(document, "mousemove", move);
1770
+ off(document, "mouseup", up);
1771
+ }
1772
+
1773
+ var move = operation(cm, function(e) {
1774
+ if (!ie && !e_button(e)) done(e);
1775
+ else extend(e);
1776
+ });
1777
+ var up = operation(cm, done);
1778
+ on(document, "mousemove", move);
1779
+ on(document, "mouseup", up);
1780
+ }
1781
+
1782
+ function clickInGutter(cm, e) {
1783
+ var display = cm.display;
1784
+ try { var mX = e.clientX, mY = e.clientY; }
1785
+ catch(e) { return false; }
1786
+
1787
+ if (mX >= Math.floor(getRect(display.gutters).right)) return false;
1788
+ e_preventDefault(e);
1789
+ if (!hasHandler(cm, "gutterClick")) return true;
1790
+
1791
+ var lineBox = getRect(display.lineDiv);
1792
+ if (mY > lineBox.bottom) return true;
1793
+ mY -= lineBox.top - display.viewOffset;
1794
+
1795
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
1796
+ var g = display.gutters.childNodes[i];
1797
+ if (g && getRect(g).right >= mX) {
1798
+ var line = lineAtHeight(cm.doc, mY);
1799
+ var gutter = cm.options.gutters[i];
1800
+ signalLater(cm, "gutterClick", cm, line, gutter, e);
1801
+ break;
1802
+ }
1803
+ }
1804
+ return true;
1805
+ }
1806
+
1807
+ // Kludge to work around strange IE behavior where it'll sometimes
1808
+ // re-fire a series of drag-related events right after the drop (#1551)
1809
+ var lastDrop = 0;
1810
+
1811
+ function onDrop(e) {
1812
+ var cm = this;
1813
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1814
+ return;
1815
+ e_preventDefault(e);
1816
+ if (ie) lastDrop = +new Date;
1817
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1818
+ if (!pos || isReadOnly(cm)) return;
1819
+ if (files && files.length && window.FileReader && window.File) {
1820
+ var n = files.length, text = Array(n), read = 0;
1821
+ var loadFile = function(file, i) {
1822
+ var reader = new FileReader;
1823
+ reader.onload = function() {
1824
+ text[i] = reader.result;
1825
+ if (++read == n) {
1826
+ pos = clipPos(cm.doc, pos);
1827
+ makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
1828
+ }
1829
+ };
1830
+ reader.readAsText(file);
1831
+ };
1832
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
1833
+ } else {
1834
+ // Don't do a replace if the drop happened inside of the selected text.
1835
+ if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
1836
+ cm.state.draggingText(e);
1837
+ // Ensure the editor is re-focused
1838
+ setTimeout(bind(focusInput, cm), 20);
1839
+ return;
1840
+ }
1841
+ try {
1842
+ var text = e.dataTransfer.getData("Text");
1843
+ if (text) {
1844
+ var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
1845
+ setSelection(cm.doc, pos, pos);
1846
+ if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
1847
+ cm.replaceSelection(text, null, "paste");
1848
+ focusInput(cm);
1849
+ onFocus(cm);
1850
+ }
1851
+ }
1852
+ catch(e){}
1853
+ }
1854
+ }
1855
+
1856
+ function onDragStart(cm, e) {
1857
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1858
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1859
+
1860
+ var txt = cm.getSelection();
1861
+ e.dataTransfer.setData("Text", txt);
1862
+
1863
+ // Use dummy image instead of default browsers image.
1864
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1865
+ if (e.dataTransfer.setDragImage && !safari) {
1866
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1867
+ if (opera) {
1868
+ img.width = img.height = 1;
1869
+ cm.display.wrapper.appendChild(img);
1870
+ // Force a relayout, or Opera won't use our image for some obscure reason
1871
+ img._top = img.offsetTop;
1872
+ }
1873
+ e.dataTransfer.setDragImage(img, 0, 0);
1874
+ if (opera) img.parentNode.removeChild(img);
1875
+ }
1876
+ }
1877
+
1878
+ function setScrollTop(cm, val) {
1879
+ if (Math.abs(cm.doc.scrollTop - val) < 2) return;
1880
+ cm.doc.scrollTop = val;
1881
+ if (!gecko) updateDisplay(cm, [], val);
1882
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1883
+ if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1884
+ if (gecko) updateDisplay(cm, []);
1885
+ startWorker(cm, 100);
1886
+ }
1887
+ function setScrollLeft(cm, val, isScroller) {
1888
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1889
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
1890
+ cm.doc.scrollLeft = val;
1891
+ alignHorizontally(cm);
1892
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
1893
+ if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
1894
+ }
1895
+
1896
+ // Since the delta values reported on mouse wheel events are
1897
+ // unstandardized between browsers and even browser versions, and
1898
+ // generally horribly unpredictable, this code starts by measuring
1899
+ // the scroll effect that the first few mouse wheel events have,
1900
+ // and, from that, detects the way it can convert deltas to pixel
1901
+ // offsets afterwards.
1902
+ //
1903
+ // The reason we want to know the amount a wheel event will scroll
1904
+ // is that it gives us a chance to update the display before the
1905
+ // actual scrolling happens, reducing flickering.
1906
+
1907
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
1908
+ // Fill in a browser-detected starting value on browsers where we
1909
+ // know one. These don't have to be accurate -- the result of them
1910
+ // being wrong would just be a slight flicker on the first wheel
1911
+ // scroll (if it is large enough).
1912
+ if (ie) wheelPixelsPerUnit = -.53;
1913
+ else if (gecko) wheelPixelsPerUnit = 15;
1914
+ else if (chrome) wheelPixelsPerUnit = -.7;
1915
+ else if (safari) wheelPixelsPerUnit = -1/3;
1916
+
1917
+ function onScrollWheel(cm, e) {
1918
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
1919
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
1920
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
1921
+ else if (dy == null) dy = e.wheelDelta;
1922
+
1923
+ var display = cm.display, scroll = display.scroller;
1924
+ // Quit if there's nothing to scroll here
1925
+ if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
1926
+ dy && scroll.scrollHeight > scroll.clientHeight)) return;
1927
+
1928
+ // Webkit browsers on OS X abort momentum scrolls when the target
1929
+ // of the scroll event is removed from the scrollable element.
1930
+ // This hack (see related code in patchDisplay) makes sure the
1931
+ // element is kept around.
1932
+ if (dy && mac && webkit) {
1933
+ for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
1934
+ if (cur.lineObj) {
1935
+ cm.display.currentWheelTarget = cur;
1936
+ break;
1937
+ }
1938
+ }
1939
+ }
1940
+
1941
+ // On some browsers, horizontal scrolling will cause redraws to
1942
+ // happen before the gutter has been realigned, causing it to
1943
+ // wriggle around in a most unseemly way. When we have an
1944
+ // estimated pixels/delta value, we just handle horizontal
1945
+ // scrolling entirely here. It'll be slightly off from native, but
1946
+ // better than glitching out.
1947
+ if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
1948
+ if (dy)
1949
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
1950
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
1951
+ e_preventDefault(e);
1952
+ display.wheelStartX = null; // Abort measurement, if in progress
1953
+ return;
1954
+ }
1955
+
1956
+ if (dy && wheelPixelsPerUnit != null) {
1957
+ var pixels = dy * wheelPixelsPerUnit;
1958
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
1959
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
1960
+ else bot = Math.min(cm.doc.height, bot + pixels + 50);
1961
+ updateDisplay(cm, [], {top: top, bottom: bot});
1962
+ }
1963
+
1964
+ if (wheelSamples < 20) {
1965
+ if (display.wheelStartX == null) {
1966
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
1967
+ display.wheelDX = dx; display.wheelDY = dy;
1968
+ setTimeout(function() {
1969
+ if (display.wheelStartX == null) return;
1970
+ var movedX = scroll.scrollLeft - display.wheelStartX;
1971
+ var movedY = scroll.scrollTop - display.wheelStartY;
1972
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
1973
+ (movedX && display.wheelDX && movedX / display.wheelDX);
1974
+ display.wheelStartX = display.wheelStartY = null;
1975
+ if (!sample) return;
1976
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
1977
+ ++wheelSamples;
1978
+ }, 200);
1979
+ } else {
1980
+ display.wheelDX += dx; display.wheelDY += dy;
1981
+ }
1982
+ }
1983
+ }
1984
+
1985
+ function doHandleBinding(cm, bound, dropShift) {
1986
+ if (typeof bound == "string") {
1987
+ bound = commands[bound];
1988
+ if (!bound) return false;
1989
+ }
1990
+ // Ensure previous input has been read, so that the handler sees a
1991
+ // consistent view of the document
1992
+ if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
1993
+ var doc = cm.doc, prevShift = doc.sel.shift, done = false;
1994
+ try {
1995
+ if (isReadOnly(cm)) cm.state.suppressEdits = true;
1996
+ if (dropShift) doc.sel.shift = false;
1997
+ done = bound(cm) != Pass;
1998
+ } finally {
1999
+ doc.sel.shift = prevShift;
2000
+ cm.state.suppressEdits = false;
2001
+ }
2002
+ return done;
2003
+ }
2004
+
2005
+ function allKeyMaps(cm) {
2006
+ var maps = cm.state.keyMaps.slice(0);
2007
+ if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
2008
+ maps.push(cm.options.keyMap);
2009
+ return maps;
2010
+ }
2011
+
2012
+ var maybeTransition;
2013
+ function handleKeyBinding(cm, e) {
2014
+ // Handle auto keymap transitions
2015
+ var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
2016
+ clearTimeout(maybeTransition);
2017
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
2018
+ if (getKeyMap(cm.options.keyMap) == startMap) {
2019
+ cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2020
+ keyMapChanged(cm);
2021
+ }
2022
+ }, 50);
2023
+
2024
+ var name = keyName(e, true), handled = false;
2025
+ if (!name) return false;
2026
+ var keymaps = allKeyMaps(cm);
2027
+
2028
+ if (e.shiftKey) {
2029
+ // First try to resolve full name (including 'Shift-'). Failing
2030
+ // that, see if there is a cursor-motion command (starting with
2031
+ // 'go') bound to the keyname without 'Shift-'.
2032
+ handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2033
+ || lookupKey(name, keymaps, function(b) {
2034
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
2035
+ return doHandleBinding(cm, b);
2036
+ });
2037
+ } else {
2038
+ handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
2039
+ }
2040
+
2041
+ if (handled) {
2042
+ e_preventDefault(e);
2043
+ restartBlink(cm);
2044
+ if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2045
+ signalLater(cm, "keyHandled", cm, name, e);
2046
+ }
2047
+ return handled;
2048
+ }
2049
+
2050
+ function handleCharBinding(cm, e, ch) {
2051
+ var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
2052
+ function(b) { return doHandleBinding(cm, b, true); });
2053
+ if (handled) {
2054
+ e_preventDefault(e);
2055
+ restartBlink(cm);
2056
+ signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2057
+ }
2058
+ return handled;
2059
+ }
2060
+
2061
+ var lastStoppedKey = null;
2062
+ function onKeyDown(e) {
2063
+ var cm = this;
2064
+ if (!cm.state.focused) onFocus(cm);
2065
+ if (ie && e.keyCode == 27) { e.returnValue = false; }
2066
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2067
+ var code = e.keyCode;
2068
+ // IE does strange things with escape.
2069
+ cm.doc.sel.shift = code == 16 || e.shiftKey;
2070
+ // First give onKeyEvent option a chance to handle this.
2071
+ var handled = handleKeyBinding(cm, e);
2072
+ if (opera) {
2073
+ lastStoppedKey = handled ? code : null;
2074
+ // Opera has no cut event... we try to at least catch the key combo
2075
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
2076
+ cm.replaceSelection("");
2077
+ }
2078
+ }
2079
+
2080
+ function onKeyPress(e) {
2081
+ var cm = this;
2082
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2083
+ var keyCode = e.keyCode, charCode = e.charCode;
2084
+ if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2085
+ if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2086
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2087
+ if (this.options.electricChars && this.doc.mode.electricChars &&
2088
+ this.options.smartIndent && !isReadOnly(this) &&
2089
+ this.doc.mode.electricChars.indexOf(ch) > -1)
2090
+ setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
2091
+ if (handleCharBinding(cm, e, ch)) return;
2092
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
2093
+ fastPoll(cm);
2094
+ }
2095
+
2096
+ function onFocus(cm) {
2097
+ if (cm.options.readOnly == "nocursor") return;
2098
+ if (!cm.state.focused) {
2099
+ signal(cm, "focus", cm);
2100
+ cm.state.focused = true;
2101
+ if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
2102
+ cm.display.wrapper.className += " CodeMirror-focused";
2103
+ resetInput(cm, true);
2104
+ }
2105
+ slowPoll(cm);
2106
+ restartBlink(cm);
2107
+ }
2108
+ function onBlur(cm) {
2109
+ if (cm.state.focused) {
2110
+ signal(cm, "blur", cm);
2111
+ cm.state.focused = false;
2112
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
2113
+ }
2114
+ clearInterval(cm.display.blinker);
2115
+ setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
2116
+ }
2117
+
2118
+ var detectingSelectAll;
2119
+ function onContextMenu(cm, e) {
2120
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
2121
+ var display = cm.display, sel = cm.doc.sel;
2122
+ if (eventInWidget(display, e)) return;
2123
+
2124
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
2125
+ if (!pos || opera) return; // Opera is difficult.
2126
+ if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
2127
+ operation(cm, setSelection)(cm.doc, pos, pos);
2128
+
2129
+ var oldCSS = display.input.style.cssText;
2130
+ display.inputDiv.style.position = "absolute";
2131
+ display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
2132
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2133
+ "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
2134
+ focusInput(cm);
2135
+ resetInput(cm, true);
2136
+ // Adds "Select all" to context menu in FF
2137
+ if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2138
+
2139
+ function prepareSelectAllHack() {
2140
+ if (display.input.selectionStart != null) {
2141
+ var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
2142
+ display.prevInput = " ";
2143
+ display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2144
+ }
2145
+ }
2146
+ function rehide() {
2147
+ display.inputDiv.style.position = "relative";
2148
+ display.input.style.cssText = oldCSS;
2149
+ if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
2150
+ slowPoll(cm);
2151
+
2152
+ // Try to detect the user choosing select-all
2153
+ if (display.input.selectionStart != null) {
2154
+ if (!ie || ie_lt9) prepareSelectAllHack();
2155
+ clearTimeout(detectingSelectAll);
2156
+ var i = 0, poll = function(){
2157
+ if (display.prevInput == " " && display.input.selectionStart == 0)
2158
+ operation(cm, commands.selectAll)(cm);
2159
+ else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2160
+ else resetInput(cm);
2161
+ };
2162
+ detectingSelectAll = setTimeout(poll, 200);
2163
+ }
2164
+ }
2165
+
2166
+ if (ie && !ie_lt9) prepareSelectAllHack();
2167
+ if (captureMiddleClick) {
2168
+ e_stop(e);
2169
+ var mouseup = function() {
2170
+ off(window, "mouseup", mouseup);
2171
+ setTimeout(rehide, 20);
2172
+ };
2173
+ on(window, "mouseup", mouseup);
2174
+ } else {
2175
+ setTimeout(rehide, 50);
2176
+ }
2177
+ }
2178
+
2179
+ // UPDATING
2180
+
2181
+ var changeEnd = CodeMirror.changeEnd = function(change) {
2182
+ if (!change.text) return change.to;
2183
+ return Pos(change.from.line + change.text.length - 1,
2184
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2185
+ };
2186
+
2187
+ // Make sure a position will be valid after the given change.
2188
+ function clipPostChange(doc, change, pos) {
2189
+ if (!posLess(change.from, pos)) return clipPos(doc, pos);
2190
+ var diff = (change.text.length - 1) - (change.to.line - change.from.line);
2191
+ if (pos.line > change.to.line + diff) {
2192
+ var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
2193
+ if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
2194
+ return clipToLen(pos, getLine(doc, preLine).text.length);
2195
+ }
2196
+ if (pos.line == change.to.line + diff)
2197
+ return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
2198
+ getLine(doc, change.to.line).text.length - change.to.ch);
2199
+ var inside = pos.line - change.from.line;
2200
+ return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
2201
+ }
2202
+
2203
+ // Hint can be null|"end"|"start"|"around"|{anchor,head}
2204
+ function computeSelAfterChange(doc, change, hint) {
2205
+ if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
2206
+ return {anchor: clipPostChange(doc, change, hint.anchor),
2207
+ head: clipPostChange(doc, change, hint.head)};
2208
+
2209
+ if (hint == "start") return {anchor: change.from, head: change.from};
2210
+
2211
+ var end = changeEnd(change);
2212
+ if (hint == "around") return {anchor: change.from, head: end};
2213
+ if (hint == "end") return {anchor: end, head: end};
2214
+
2215
+ // hint is null, leave the selection alone as much as possible
2216
+ var adjustPos = function(pos) {
2217
+ if (posLess(pos, change.from)) return pos;
2218
+ if (!posLess(change.to, pos)) return end;
2219
+
2220
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
2221
+ if (pos.line == change.to.line) ch += end.ch - change.to.ch;
2222
+ return Pos(line, ch);
2223
+ };
2224
+ return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2225
+ }
2226
+
2227
+ function filterChange(doc, change, update) {
2228
+ var obj = {
2229
+ canceled: false,
2230
+ from: change.from,
2231
+ to: change.to,
2232
+ text: change.text,
2233
+ origin: change.origin,
2234
+ cancel: function() { this.canceled = true; }
2235
+ };
2236
+ if (update) obj.update = function(from, to, text, origin) {
2237
+ if (from) this.from = clipPos(doc, from);
2238
+ if (to) this.to = clipPos(doc, to);
2239
+ if (text) this.text = text;
2240
+ if (origin !== undefined) this.origin = origin;
2241
+ };
2242
+ signal(doc, "beforeChange", doc, obj);
2243
+ if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2244
+
2245
+ if (obj.canceled) return null;
2246
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
2247
+ }
2248
+
2249
+ // Replace the range from from to to by the strings in replacement.
2250
+ // change is a {from, to, text [, origin]} object
2251
+ function makeChange(doc, change, selUpdate, ignoreReadOnly) {
2252
+ if (doc.cm) {
2253
+ if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
2254
+ if (doc.cm.state.suppressEdits) return;
2255
+ }
2256
+
2257
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2258
+ change = filterChange(doc, change, true);
2259
+ if (!change) return;
2260
+ }
2261
+
2262
+ // Possibly split or suppress the update based on the presence
2263
+ // of read-only spans in its range.
2264
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
2265
+ if (split) {
2266
+ for (var i = split.length - 1; i >= 1; --i)
2267
+ makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
2268
+ if (split.length)
2269
+ makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
2270
+ } else {
2271
+ makeChangeNoReadonly(doc, change, selUpdate);
2272
+ }
2273
+ }
2274
+
2275
+ function makeChangeNoReadonly(doc, change, selUpdate) {
2276
+ var selAfter = computeSelAfterChange(doc, change, selUpdate);
2277
+ addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
2278
+
2279
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
2280
+ var rebased = [];
2281
+
2282
+ linkedDocs(doc, function(doc, sharedHist) {
2283
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2284
+ rebaseHist(doc.history, change);
2285
+ rebased.push(doc.history);
2286
+ }
2287
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
2288
+ });
2289
+ }
2290
+
2291
+ function makeChangeFromHistory(doc, type) {
2292
+ if (doc.cm && doc.cm.state.suppressEdits) return;
2293
+
2294
+ var hist = doc.history;
2295
+ var event = (type == "undo" ? hist.done : hist.undone).pop();
2296
+ if (!event) return;
2297
+
2298
+ var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2299
+ anchorAfter: event.anchorBefore, headAfter: event.headBefore,
2300
+ generation: hist.generation};
2301
+ (type == "undo" ? hist.undone : hist.done).push(anti);
2302
+ hist.generation = event.generation || ++hist.maxGeneration;
2303
+
2304
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
2305
+
2306
+ for (var i = event.changes.length - 1; i >= 0; --i) {
2307
+ var change = event.changes[i];
2308
+ change.origin = type;
2309
+ if (filter && !filterChange(doc, change, false)) {
2310
+ (type == "undo" ? hist.done : hist.undone).length = 0;
2311
+ return;
2312
+ }
2313
+
2314
+ anti.changes.push(historyChangeFromChange(doc, change));
2315
+
2316
+ var after = i ? computeSelAfterChange(doc, change, null)
2317
+ : {anchor: event.anchorBefore, head: event.headBefore};
2318
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
2319
+ var rebased = [];
2320
+
2321
+ linkedDocs(doc, function(doc, sharedHist) {
2322
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2323
+ rebaseHist(doc.history, change);
2324
+ rebased.push(doc.history);
2325
+ }
2326
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
2327
+ });
2328
+ }
2329
+ }
2330
+
2331
+ function shiftDoc(doc, distance) {
2332
+ function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
2333
+ doc.first += distance;
2334
+ if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
2335
+ doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
2336
+ doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
2337
+ }
2338
+
2339
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
2340
+ if (doc.cm && !doc.cm.curOp)
2341
+ return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
2342
+
2343
+ if (change.to.line < doc.first) {
2344
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
2345
+ return;
2346
+ }
2347
+ if (change.from.line > doc.lastLine()) return;
2348
+
2349
+ // Clip the change to the size of this doc
2350
+ if (change.from.line < doc.first) {
2351
+ var shift = change.text.length - 1 - (doc.first - change.from.line);
2352
+ shiftDoc(doc, shift);
2353
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
2354
+ text: [lst(change.text)], origin: change.origin};
2355
+ }
2356
+ var last = doc.lastLine();
2357
+ if (change.to.line > last) {
2358
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
2359
+ text: [change.text[0]], origin: change.origin};
2360
+ }
2361
+
2362
+ change.removed = getBetween(doc, change.from, change.to);
2363
+
2364
+ if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
2365
+ if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
2366
+ else updateDoc(doc, change, spans, selAfter);
2367
+ }
2368
+
2369
+ function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
2370
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
2371
+
2372
+ var recomputeMaxLength = false, checkWidthStart = from.line;
2373
+ if (!cm.options.lineWrapping) {
2374
+ checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
2375
+ doc.iter(checkWidthStart, to.line + 1, function(line) {
2376
+ if (line == display.maxLine) {
2377
+ recomputeMaxLength = true;
2378
+ return true;
2379
+ }
2380
+ });
2381
+ }
2382
+
2383
+ if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
2384
+ cm.curOp.cursorActivity = true;
2385
+
2386
+ updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
2387
+
2388
+ if (!cm.options.lineWrapping) {
2389
+ doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
2390
+ var len = lineLength(doc, line);
2391
+ if (len > display.maxLineLength) {
2392
+ display.maxLine = line;
2393
+ display.maxLineLength = len;
2394
+ display.maxLineChanged = true;
2395
+ recomputeMaxLength = false;
2396
+ }
2397
+ });
2398
+ if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
2399
+ }
2400
+
2401
+ // Adjust frontier, schedule worker
2402
+ doc.frontier = Math.min(doc.frontier, from.line);
2403
+ startWorker(cm, 400);
2404
+
2405
+ var lendiff = change.text.length - (to.line - from.line) - 1;
2406
+ // Remember that these lines changed, for updating the display
2407
+ regChange(cm, from.line, to.line + 1, lendiff);
2408
+
2409
+ if (hasHandler(cm, "change")) {
2410
+ var changeObj = {from: from, to: to,
2411
+ text: change.text,
2412
+ removed: change.removed,
2413
+ origin: change.origin};
2414
+ if (cm.curOp.textChanged) {
2415
+ for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
2416
+ cur.next = changeObj;
2417
+ } else cm.curOp.textChanged = changeObj;
2418
+ }
2419
+ }
2420
+
2421
+ function replaceRange(doc, code, from, to, origin) {
2422
+ if (!to) to = from;
2423
+ if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
2424
+ if (typeof code == "string") code = splitLines(code);
2425
+ makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
2426
+ }
2427
+
2428
+ // POSITION OBJECT
2429
+
2430
+ function Pos(line, ch) {
2431
+ if (!(this instanceof Pos)) return new Pos(line, ch);
2432
+ this.line = line; this.ch = ch;
2433
+ }
2434
+ CodeMirror.Pos = Pos;
2435
+
2436
+ function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2437
+ function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2438
+ function copyPos(x) {return Pos(x.line, x.ch);}
2439
+
2440
+ // SELECTION
2441
+
2442
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2443
+ function clipPos(doc, pos) {
2444
+ if (pos.line < doc.first) return Pos(doc.first, 0);
2445
+ var last = doc.first + doc.size - 1;
2446
+ if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2447
+ return clipToLen(pos, getLine(doc, pos.line).text.length);
2448
+ }
2449
+ function clipToLen(pos, linelen) {
2450
+ var ch = pos.ch;
2451
+ if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2452
+ else if (ch < 0) return Pos(pos.line, 0);
2453
+ else return pos;
2454
+ }
2455
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2456
+
2457
+ // If shift is held, this will move the selection anchor. Otherwise,
2458
+ // it'll set the whole selection.
2459
+ function extendSelection(doc, pos, other, bias) {
2460
+ if (doc.sel.shift || doc.sel.extend) {
2461
+ var anchor = doc.sel.anchor;
2462
+ if (other) {
2463
+ var posBefore = posLess(pos, anchor);
2464
+ if (posBefore != posLess(other, anchor)) {
2465
+ anchor = pos;
2466
+ pos = other;
2467
+ } else if (posBefore != posLess(pos, other)) {
2468
+ pos = other;
2469
+ }
2470
+ }
2471
+ setSelection(doc, anchor, pos, bias);
2472
+ } else {
2473
+ setSelection(doc, pos, other || pos, bias);
2474
+ }
2475
+ if (doc.cm) doc.cm.curOp.userSelChange = true;
2476
+ }
2477
+
2478
+ function filterSelectionChange(doc, anchor, head) {
2479
+ var obj = {anchor: anchor, head: head};
2480
+ signal(doc, "beforeSelectionChange", doc, obj);
2481
+ if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2482
+ obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
2483
+ return obj;
2484
+ }
2485
+
2486
+ // Update the selection. Last two args are only used by
2487
+ // updateDoc, since they have to be expressed in the line
2488
+ // numbers before the update.
2489
+ function setSelection(doc, anchor, head, bias, checkAtomic) {
2490
+ if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
2491
+ var filtered = filterSelectionChange(doc, anchor, head);
2492
+ head = filtered.head;
2493
+ anchor = filtered.anchor;
2494
+ }
2495
+
2496
+ var sel = doc.sel;
2497
+ sel.goalColumn = null;
2498
+ // Skip over atomic spans.
2499
+ if (checkAtomic || !posEq(anchor, sel.anchor))
2500
+ anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
2501
+ if (checkAtomic || !posEq(head, sel.head))
2502
+ head = skipAtomic(doc, head, bias, checkAtomic != "push");
2503
+
2504
+ if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
2505
+
2506
+ sel.anchor = anchor; sel.head = head;
2507
+ var inv = posLess(head, anchor);
2508
+ sel.from = inv ? head : anchor;
2509
+ sel.to = inv ? anchor : head;
2510
+
2511
+ if (doc.cm)
2512
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
2513
+ doc.cm.curOp.cursorActivity = true;
2514
+
2515
+ signalLater(doc, "cursorActivity", doc);
2516
+ }
2517
+
2518
+ function reCheckSelection(cm) {
2519
+ setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
2520
+ }
2521
+
2522
+ function skipAtomic(doc, pos, bias, mayClear) {
2523
+ var flipped = false, curPos = pos;
2524
+ var dir = bias || 1;
2525
+ doc.cantEdit = false;
2526
+ search: for (;;) {
2527
+ var line = getLine(doc, curPos.line);
2528
+ if (line.markedSpans) {
2529
+ for (var i = 0; i < line.markedSpans.length; ++i) {
2530
+ var sp = line.markedSpans[i], m = sp.marker;
2531
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2532
+ (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2533
+ if (mayClear) {
2534
+ signal(m, "beforeCursorEnter");
2535
+ if (m.explicitlyCleared) {
2536
+ if (!line.markedSpans) break;
2537
+ else {--i; continue;}
2538
+ }
2539
+ }
2540
+ if (!m.atomic) continue;
2541
+ var newPos = m.find()[dir < 0 ? "from" : "to"];
2542
+ if (posEq(newPos, curPos)) {
2543
+ newPos.ch += dir;
2544
+ if (newPos.ch < 0) {
2545
+ if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2546
+ else newPos = null;
2547
+ } else if (newPos.ch > line.text.length) {
2548
+ if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2549
+ else newPos = null;
2550
+ }
2551
+ if (!newPos) {
2552
+ if (flipped) {
2553
+ // Driven in a corner -- no valid cursor position found at all
2554
+ // -- try again *with* clearing, if we didn't already
2555
+ if (!mayClear) return skipAtomic(doc, pos, bias, true);
2556
+ // Otherwise, turn off editing until further notice, and return the start of the doc
2557
+ doc.cantEdit = true;
2558
+ return Pos(doc.first, 0);
2559
+ }
2560
+ flipped = true; newPos = pos; dir = -dir;
2561
+ }
2562
+ }
2563
+ curPos = newPos;
2564
+ continue search;
2565
+ }
2566
+ }
2567
+ }
2568
+ return curPos;
2569
+ }
2570
+ }
2571
+
2572
+ // SCROLLING
2573
+
2574
+ function scrollCursorIntoView(cm) {
2575
+ var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
2576
+ if (!cm.state.focused) return;
2577
+ var display = cm.display, box = getRect(display.sizer), doScroll = null;
2578
+ if (coords.top + box.top < 0) doScroll = true;
2579
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2580
+ if (doScroll != null && !phantom) {
2581
+ var hidden = display.cursor.style.display == "none";
2582
+ if (hidden) {
2583
+ display.cursor.style.display = "";
2584
+ display.cursor.style.left = coords.left + "px";
2585
+ display.cursor.style.top = (coords.top - display.viewOffset) + "px";
2586
+ }
2587
+ display.cursor.scrollIntoView(doScroll);
2588
+ if (hidden) display.cursor.style.display = "none";
2589
+ }
2590
+ }
2591
+
2592
+ function scrollPosIntoView(cm, pos, margin) {
2593
+ if (margin == null) margin = 0;
2594
+ for (;;) {
2595
+ var changed = false, coords = cursorCoords(cm, pos);
2596
+ var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
2597
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
2598
+ if (scrollPos.scrollTop != null) {
2599
+ setScrollTop(cm, scrollPos.scrollTop);
2600
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
2601
+ }
2602
+ if (scrollPos.scrollLeft != null) {
2603
+ setScrollLeft(cm, scrollPos.scrollLeft);
2604
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
2605
+ }
2606
+ if (!changed) return coords;
2607
+ }
2608
+ }
2609
+
2610
+ function scrollIntoView(cm, x1, y1, x2, y2) {
2611
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
2612
+ if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
2613
+ if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
2614
+ }
2615
+
2616
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
2617
+ var display = cm.display, snapMargin = textHeight(cm.display);
2618
+ if (y1 < 0) y1 = 0;
2619
+ var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2620
+ var docBottom = cm.doc.height + paddingVert(display);
2621
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
2622
+ if (y1 < screentop) {
2623
+ result.scrollTop = atTop ? 0 : y1;
2624
+ } else if (y2 > screentop + screen) {
2625
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
2626
+ if (newTop != screentop) result.scrollTop = newTop;
2627
+ }
2628
+
2629
+ var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
2630
+ x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
2631
+ var gutterw = display.gutters.offsetWidth;
2632
+ var atLeft = x1 < gutterw + 10;
2633
+ if (x1 < screenleft + gutterw || atLeft) {
2634
+ if (atLeft) x1 = 0;
2635
+ result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
2636
+ } else if (x2 > screenw + screenleft - 3) {
2637
+ result.scrollLeft = x2 + 10 - screenw;
2638
+ }
2639
+ return result;
2640
+ }
2641
+
2642
+ function updateScrollPos(cm, left, top) {
2643
+ cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
2644
+ scrollTop: top == null ? cm.doc.scrollTop : top};
2645
+ }
2646
+
2647
+ function addToScrollPos(cm, left, top) {
2648
+ var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
2649
+ var scroll = cm.display.scroller;
2650
+ pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
2651
+ pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
2652
+ }
2653
+
2654
+ // API UTILITIES
2655
+
2656
+ function indentLine(cm, n, how, aggressive) {
2657
+ var doc = cm.doc;
2658
+ if (how == null) how = "add";
2659
+ if (how == "smart") {
2660
+ if (!cm.doc.mode.indent) how = "prev";
2661
+ else var state = getStateBefore(cm, n);
2662
+ }
2663
+
2664
+ var tabSize = cm.options.tabSize;
2665
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
2666
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
2667
+ if (how == "smart") {
2668
+ indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2669
+ if (indentation == Pass) {
2670
+ if (!aggressive) return;
2671
+ how = "prev";
2672
+ }
2673
+ }
2674
+ if (how == "prev") {
2675
+ if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
2676
+ else indentation = 0;
2677
+ } else if (how == "add") {
2678
+ indentation = curSpace + cm.options.indentUnit;
2679
+ } else if (how == "subtract") {
2680
+ indentation = curSpace - cm.options.indentUnit;
2681
+ } else if (typeof how == "number") {
2682
+ indentation = curSpace + how;
2683
+ }
2684
+ indentation = Math.max(0, indentation);
2685
+
2686
+ var indentString = "", pos = 0;
2687
+ if (cm.options.indentWithTabs)
2688
+ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
2689
+ if (pos < indentation) indentString += spaceStr(indentation - pos);
2690
+
2691
+ if (indentString != curSpaceString)
2692
+ replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
2693
+ line.stateAfter = null;
2694
+ }
2695
+
2696
+ function changeLine(cm, handle, op) {
2697
+ var no = handle, line = handle, doc = cm.doc;
2698
+ if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
2699
+ else no = lineNo(handle);
2700
+ if (no == null) return null;
2701
+ if (op(line, no)) regChange(cm, no, no + 1);
2702
+ else return null;
2703
+ return line;
2704
+ }
2705
+
2706
+ function findPosH(doc, pos, dir, unit, visually) {
2707
+ var line = pos.line, ch = pos.ch, origDir = dir;
2708
+ var lineObj = getLine(doc, line);
2709
+ var possible = true;
2710
+ function findNextLine() {
2711
+ var l = line + dir;
2712
+ if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
2713
+ line = l;
2714
+ return lineObj = getLine(doc, l);
2715
+ }
2716
+ function moveOnce(boundToLine) {
2717
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
2718
+ if (next == null) {
2719
+ if (!boundToLine && findNextLine()) {
2720
+ if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
2721
+ else ch = dir < 0 ? lineObj.text.length : 0;
2722
+ } else return (possible = false);
2723
+ } else ch = next;
2724
+ return true;
2725
+ }
2726
+
2727
+ if (unit == "char") moveOnce();
2728
+ else if (unit == "column") moveOnce(true);
2729
+ else if (unit == "word" || unit == "group") {
2730
+ var sawType = null, group = unit == "group";
2731
+ for (var first = true;; first = false) {
2732
+ if (dir < 0 && !moveOnce(!first)) break;
2733
+ var cur = lineObj.text.charAt(ch) || "\n";
2734
+ var type = isWordChar(cur) ? "w"
2735
+ : !group ? null
2736
+ : /\s/.test(cur) ? null
2737
+ : "p";
2738
+ if (sawType && sawType != type) {
2739
+ if (dir < 0) {dir = 1; moveOnce();}
2740
+ break;
2741
+ }
2742
+ if (type) sawType = type;
2743
+ if (dir > 0 && !moveOnce(!first)) break;
2744
+ }
2745
+ }
2746
+ var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2747
+ if (!possible) result.hitSide = true;
2748
+ return result;
2749
+ }
2750
+
2751
+ function findPosV(cm, pos, dir, unit) {
2752
+ var doc = cm.doc, x = pos.left, y;
2753
+ if (unit == "page") {
2754
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
2755
+ y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
2756
+ } else if (unit == "line") {
2757
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
2758
+ }
2759
+ for (;;) {
2760
+ var target = coordsChar(cm, x, y);
2761
+ if (!target.outside) break;
2762
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
2763
+ y += dir * 5;
2764
+ }
2765
+ return target;
2766
+ }
2767
+
2768
+ function findWordAt(line, pos) {
2769
+ var start = pos.ch, end = pos.ch;
2770
+ if (line) {
2771
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
2772
+ var startChar = line.charAt(start);
2773
+ var check = isWordChar(startChar) ? isWordChar
2774
+ : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2775
+ : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
2776
+ while (start > 0 && check(line.charAt(start - 1))) --start;
2777
+ while (end < line.length && check(line.charAt(end))) ++end;
2778
+ }
2779
+ return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
2780
+ }
2781
+
2782
+ function selectLine(cm, line) {
2783
+ extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
2784
+ }
2785
+
2786
+ // PROTOTYPE
2787
+
2788
+ // The publicly visible API. Note that operation(null, f) means
2789
+ // 'wrap f in an operation, performed on its `this` parameter'
2790
+
2791
+ CodeMirror.prototype = {
2792
+ constructor: CodeMirror,
2793
+ focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2794
+
2795
+ setOption: function(option, value) {
2796
+ var options = this.options, old = options[option];
2797
+ if (options[option] == value && option != "mode") return;
2798
+ options[option] = value;
2799
+ if (optionHandlers.hasOwnProperty(option))
2800
+ operation(this, optionHandlers[option])(this, value, old);
2801
+ },
2802
+
2803
+ getOption: function(option) {return this.options[option];},
2804
+ getDoc: function() {return this.doc;},
2805
+
2806
+ addKeyMap: function(map, bottom) {
2807
+ this.state.keyMaps[bottom ? "push" : "unshift"](map);
2808
+ },
2809
+ removeKeyMap: function(map) {
2810
+ var maps = this.state.keyMaps;
2811
+ for (var i = 0; i < maps.length; ++i)
2812
+ if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2813
+ maps.splice(i, 1);
2814
+ return true;
2815
+ }
2816
+ },
2817
+
2818
+ addOverlay: operation(null, function(spec, options) {
2819
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
2820
+ if (mode.startState) throw new Error("Overlays may not be stateful.");
2821
+ this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
2822
+ this.state.modeGen++;
2823
+ regChange(this);
2824
+ }),
2825
+ removeOverlay: operation(null, function(spec) {
2826
+ var overlays = this.state.overlays;
2827
+ for (var i = 0; i < overlays.length; ++i) {
2828
+ var cur = overlays[i].modeSpec;
2829
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
2830
+ overlays.splice(i, 1);
2831
+ this.state.modeGen++;
2832
+ regChange(this);
2833
+ return;
2834
+ }
2835
+ }
2836
+ }),
2837
+
2838
+ indentLine: operation(null, function(n, dir, aggressive) {
2839
+ if (typeof dir != "string" && typeof dir != "number") {
2840
+ if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2841
+ else dir = dir ? "add" : "subtract";
2842
+ }
2843
+ if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
2844
+ }),
2845
+ indentSelection: operation(null, function(how) {
2846
+ var sel = this.doc.sel;
2847
+ if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
2848
+ var e = sel.to.line - (sel.to.ch ? 0 : 1);
2849
+ for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
2850
+ }),
2851
+
2852
+ // Fetch the parser token for a given character. Useful for hacks
2853
+ // that want to inspect the mode state (say, for completion).
2854
+ getTokenAt: function(pos, precise) {
2855
+ var doc = this.doc;
2856
+ pos = clipPos(doc, pos);
2857
+ var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2858
+ var line = getLine(doc, pos.line);
2859
+ var stream = new StringStream(line.text, this.options.tabSize);
2860
+ while (stream.pos < pos.ch && !stream.eol()) {
2861
+ stream.start = stream.pos;
2862
+ var style = mode.token(stream, state);
2863
+ }
2864
+ return {start: stream.start,
2865
+ end: stream.pos,
2866
+ string: stream.current(),
2867
+ className: style || null, // Deprecated, use 'type' instead
2868
+ type: style || null,
2869
+ state: state};
2870
+ },
2871
+
2872
+ getTokenTypeAt: function(pos) {
2873
+ pos = clipPos(this.doc, pos);
2874
+ var styles = getLineStyles(this, getLine(this.doc, pos.line));
2875
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2876
+ if (ch == 0) return styles[2];
2877
+ for (;;) {
2878
+ var mid = (before + after) >> 1;
2879
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2880
+ else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2881
+ else return styles[mid * 2 + 2];
2882
+ }
2883
+ },
2884
+
2885
+ getModeAt: function(pos) {
2886
+ var mode = this.doc.mode;
2887
+ if (!mode.innerMode) return mode;
2888
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2889
+ },
2890
+
2891
+ getHelper: function(pos, type) {
2892
+ if (!helpers.hasOwnProperty(type)) return;
2893
+ var help = helpers[type], mode = this.getModeAt(pos);
2894
+ return mode[type] && help[mode[type]] ||
2895
+ mode.helperType && help[mode.helperType] ||
2896
+ help[mode.name];
2897
+ },
2898
+
2899
+ getStateAfter: function(line, precise) {
2900
+ var doc = this.doc;
2901
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2902
+ return getStateBefore(this, line + 1, precise);
2903
+ },
2904
+
2905
+ cursorCoords: function(start, mode) {
2906
+ var pos, sel = this.doc.sel;
2907
+ if (start == null) pos = sel.head;
2908
+ else if (typeof start == "object") pos = clipPos(this.doc, start);
2909
+ else pos = start ? sel.from : sel.to;
2910
+ return cursorCoords(this, pos, mode || "page");
2911
+ },
2912
+
2913
+ charCoords: function(pos, mode) {
2914
+ return charCoords(this, clipPos(this.doc, pos), mode || "page");
2915
+ },
2916
+
2917
+ coordsChar: function(coords, mode) {
2918
+ coords = fromCoordSystem(this, coords, mode || "page");
2919
+ return coordsChar(this, coords.left, coords.top);
2920
+ },
2921
+
2922
+ lineAtHeight: function(height, mode) {
2923
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
2924
+ return lineAtHeight(this.doc, height + this.display.viewOffset);
2925
+ },
2926
+ heightAtLine: function(line, mode) {
2927
+ var end = false, last = this.doc.first + this.doc.size - 1;
2928
+ if (line < this.doc.first) line = this.doc.first;
2929
+ else if (line > last) { line = last; end = true; }
2930
+ var lineObj = getLine(this.doc, line);
2931
+ return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
2932
+ (end ? lineObj.height : 0);
2933
+ },
2934
+
2935
+ defaultTextHeight: function() { return textHeight(this.display); },
2936
+ defaultCharWidth: function() { return charWidth(this.display); },
2937
+
2938
+ setGutterMarker: operation(null, function(line, gutterID, value) {
2939
+ return changeLine(this, line, function(line) {
2940
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
2941
+ markers[gutterID] = value;
2942
+ if (!value && isEmpty(markers)) line.gutterMarkers = null;
2943
+ return true;
2944
+ });
2945
+ }),
2946
+
2947
+ clearGutter: operation(null, function(gutterID) {
2948
+ var cm = this, doc = cm.doc, i = doc.first;
2949
+ doc.iter(function(line) {
2950
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
2951
+ line.gutterMarkers[gutterID] = null;
2952
+ regChange(cm, i, i + 1);
2953
+ if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
2954
+ }
2955
+ ++i;
2956
+ });
2957
+ }),
2958
+
2959
+ addLineClass: operation(null, function(handle, where, cls) {
2960
+ return changeLine(this, handle, function(line) {
2961
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2962
+ if (!line[prop]) line[prop] = cls;
2963
+ else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
2964
+ else line[prop] += " " + cls;
2965
+ return true;
2966
+ });
2967
+ }),
2968
+
2969
+ removeLineClass: operation(null, function(handle, where, cls) {
2970
+ return changeLine(this, handle, function(line) {
2971
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2972
+ var cur = line[prop];
2973
+ if (!cur) return false;
2974
+ else if (cls == null) line[prop] = null;
2975
+ else {
2976
+ var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2977
+ if (!found) return false;
2978
+ var end = found.index + found[0].length;
2979
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
2980
+ }
2981
+ return true;
2982
+ });
2983
+ }),
2984
+
2985
+ addLineWidget: operation(null, function(handle, node, options) {
2986
+ return addLineWidget(this, handle, node, options);
2987
+ }),
2988
+
2989
+ removeLineWidget: function(widget) { widget.clear(); },
2990
+
2991
+ lineInfo: function(line) {
2992
+ if (typeof line == "number") {
2993
+ if (!isLine(this.doc, line)) return null;
2994
+ var n = line;
2995
+ line = getLine(this.doc, line);
2996
+ if (!line) return null;
2997
+ } else {
2998
+ var n = lineNo(line);
2999
+ if (n == null) return null;
3000
+ }
3001
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
3002
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
3003
+ widgets: line.widgets};
3004
+ },
3005
+
3006
+ getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
3007
+
3008
+ addWidget: function(pos, node, scroll, vert, horiz) {
3009
+ var display = this.display;
3010
+ pos = cursorCoords(this, clipPos(this.doc, pos));
3011
+ var top = pos.bottom, left = pos.left;
3012
+ node.style.position = "absolute";
3013
+ display.sizer.appendChild(node);
3014
+ if (vert == "over") {
3015
+ top = pos.top;
3016
+ } else if (vert == "above" || vert == "near") {
3017
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
3018
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
3019
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
3020
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
3021
+ top = pos.top - node.offsetHeight;
3022
+ else if (pos.bottom + node.offsetHeight <= vspace)
3023
+ top = pos.bottom;
3024
+ if (left + node.offsetWidth > hspace)
3025
+ left = hspace - node.offsetWidth;
3026
+ }
3027
+ node.style.top = top + "px";
3028
+ node.style.left = node.style.right = "";
3029
+ if (horiz == "right") {
3030
+ left = display.sizer.clientWidth - node.offsetWidth;
3031
+ node.style.right = "0px";
3032
+ } else {
3033
+ if (horiz == "left") left = 0;
3034
+ else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
3035
+ node.style.left = left + "px";
3036
+ }
3037
+ if (scroll)
3038
+ scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
3039
+ },
3040
+
3041
+ triggerOnKeyDown: operation(null, onKeyDown),
3042
+
3043
+ execCommand: function(cmd) {return commands[cmd](this);},
3044
+
3045
+ findPosH: function(from, amount, unit, visually) {
3046
+ var dir = 1;
3047
+ if (amount < 0) { dir = -1; amount = -amount; }
3048
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3049
+ cur = findPosH(this.doc, cur, dir, unit, visually);
3050
+ if (cur.hitSide) break;
3051
+ }
3052
+ return cur;
3053
+ },
3054
+
3055
+ moveH: operation(null, function(dir, unit) {
3056
+ var sel = this.doc.sel, pos;
3057
+ if (sel.shift || sel.extend || posEq(sel.from, sel.to))
3058
+ pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
3059
+ else
3060
+ pos = dir < 0 ? sel.from : sel.to;
3061
+ extendSelection(this.doc, pos, pos, dir);
3062
+ }),
3063
+
3064
+ deleteH: operation(null, function(dir, unit) {
3065
+ var sel = this.doc.sel;
3066
+ if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
3067
+ else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
3068
+ this.curOp.userSelChange = true;
3069
+ }),
3070
+
3071
+ findPosV: function(from, amount, unit, goalColumn) {
3072
+ var dir = 1, x = goalColumn;
3073
+ if (amount < 0) { dir = -1; amount = -amount; }
3074
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3075
+ var coords = cursorCoords(this, cur, "div");
3076
+ if (x == null) x = coords.left;
3077
+ else coords.left = x;
3078
+ cur = findPosV(this, coords, dir, unit);
3079
+ if (cur.hitSide) break;
3080
+ }
3081
+ return cur;
3082
+ },
3083
+
3084
+ moveV: operation(null, function(dir, unit) {
3085
+ var sel = this.doc.sel;
3086
+ var pos = cursorCoords(this, sel.head, "div");
3087
+ if (sel.goalColumn != null) pos.left = sel.goalColumn;
3088
+ var target = findPosV(this, pos, dir, unit);
3089
+
3090
+ if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3091
+ extendSelection(this.doc, target, target, dir);
3092
+ sel.goalColumn = pos.left;
3093
+ }),
3094
+
3095
+ toggleOverwrite: function(value) {
3096
+ if (value != null && value == this.state.overwrite) return;
3097
+ if (this.state.overwrite = !this.state.overwrite)
3098
+ this.display.cursor.className += " CodeMirror-overwrite";
3099
+ else
3100
+ this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
3101
+ },
3102
+ hasFocus: function() { return this.state.focused; },
3103
+
3104
+ scrollTo: operation(null, function(x, y) {
3105
+ updateScrollPos(this, x, y);
3106
+ }),
3107
+ getScrollInfo: function() {
3108
+ var scroller = this.display.scroller, co = scrollerCutOff;
3109
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
3110
+ height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
3111
+ clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
3112
+ },
3113
+
3114
+ scrollIntoView: operation(null, function(pos, margin) {
3115
+ if (typeof pos == "number") pos = Pos(pos, 0);
3116
+ if (!margin) margin = 0;
3117
+ var coords = pos;
3118
+
3119
+ if (!pos || pos.line != null) {
3120
+ this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
3121
+ this.curOp.scrollToPosMargin = margin;
3122
+ coords = cursorCoords(this, this.curOp.scrollToPos);
3123
+ }
3124
+ var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
3125
+ updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
3126
+ }),
3127
+
3128
+ setSize: operation(null, function(width, height) {
3129
+ function interpret(val) {
3130
+ return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
3131
+ }
3132
+ if (width != null) this.display.wrapper.style.width = interpret(width);
3133
+ if (height != null) this.display.wrapper.style.height = interpret(height);
3134
+ if (this.options.lineWrapping)
3135
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3136
+ this.curOp.forceUpdate = true;
3137
+ }),
3138
+
3139
+ operation: function(f){return runInOp(this, f);},
3140
+
3141
+ refresh: operation(null, function() {
3142
+ clearCaches(this);
3143
+ updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
3144
+ regChange(this);
3145
+ }),
3146
+
3147
+ swapDoc: operation(null, function(doc) {
3148
+ var old = this.doc;
3149
+ old.cm = null;
3150
+ attachDoc(this, doc);
3151
+ clearCaches(this);
3152
+ resetInput(this, true);
3153
+ updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
3154
+ return old;
3155
+ }),
3156
+
3157
+ getInputField: function(){return this.display.input;},
3158
+ getWrapperElement: function(){return this.display.wrapper;},
3159
+ getScrollerElement: function(){return this.display.scroller;},
3160
+ getGutterElement: function(){return this.display.gutters;}
3161
+ };
3162
+ eventMixin(CodeMirror);
3163
+
3164
+ // OPTION DEFAULTS
3165
+
3166
+ var optionHandlers = CodeMirror.optionHandlers = {};
3167
+
3168
+ // The default configuration options.
3169
+ var defaults = CodeMirror.defaults = {};
3170
+
3171
+ function option(name, deflt, handle, notOnInit) {
3172
+ CodeMirror.defaults[name] = deflt;
3173
+ if (handle) optionHandlers[name] =
3174
+ notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
3175
+ }
3176
+
3177
+ var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
3178
+
3179
+ // These two are, on init, called from the constructor because they
3180
+ // have to be initialized before the editor can start at all.
3181
+ option("value", "", function(cm, val) {
3182
+ cm.setValue(val);
3183
+ }, true);
3184
+ option("mode", null, function(cm, val) {
3185
+ cm.doc.modeOption = val;
3186
+ loadMode(cm);
3187
+ }, true);
3188
+
3189
+ option("indentUnit", 2, loadMode, true);
3190
+ option("indentWithTabs", false);
3191
+ option("smartIndent", true);
3192
+ option("tabSize", 4, function(cm) {
3193
+ loadMode(cm);
3194
+ clearCaches(cm);
3195
+ regChange(cm);
3196
+ }, true);
3197
+ option("electricChars", true);
3198
+ option("rtlMoveVisually", !windows);
3199
+
3200
+ option("theme", "default", function(cm) {
3201
+ themeChanged(cm);
3202
+ guttersChanged(cm);
3203
+ }, true);
3204
+ option("keyMap", "default", keyMapChanged);
3205
+ option("extraKeys", null);
3206
+
3207
+ option("onKeyEvent", null);
3208
+ option("onDragEvent", null);
3209
+
3210
+ option("lineWrapping", false, wrappingChanged, true);
3211
+ option("gutters", [], function(cm) {
3212
+ setGuttersForLineNumbers(cm.options);
3213
+ guttersChanged(cm);
3214
+ }, true);
3215
+ option("fixedGutter", true, function(cm, val) {
3216
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3217
+ cm.refresh();
3218
+ }, true);
3219
+ option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3220
+ option("lineNumbers", false, function(cm) {
3221
+ setGuttersForLineNumbers(cm.options);
3222
+ guttersChanged(cm);
3223
+ }, true);
3224
+ option("firstLineNumber", 1, guttersChanged, true);
3225
+ option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
3226
+ option("showCursorWhenSelecting", false, updateSelection, true);
3227
+
3228
+ option("readOnly", false, function(cm, val) {
3229
+ if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
3230
+ else if (!val) resetInput(cm, true);
3231
+ });
3232
+ option("dragDrop", true);
3233
+
3234
+ option("cursorBlinkRate", 530);
3235
+ option("cursorScrollMargin", 0);
3236
+ option("cursorHeight", 1);
3237
+ option("workTime", 100);
3238
+ option("workDelay", 100);
3239
+ option("flattenSpans", true);
3240
+ option("pollInterval", 100);
3241
+ option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
3242
+ option("historyEventDelay", 500);
3243
+ option("viewportMargin", 10, function(cm){cm.refresh();}, true);
3244
+ option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
3245
+ option("moveInputWithCursor", true, function(cm, val) {
3246
+ if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
3247
+ });
3248
+
3249
+ option("tabindex", null, function(cm, val) {
3250
+ cm.display.input.tabIndex = val || "";
3251
+ });
3252
+ option("autofocus", null);
3253
+
3254
+ // MODE DEFINITION AND QUERYING
3255
+
3256
+ // Known modes, by name and by MIME
3257
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
3258
+
3259
+ CodeMirror.defineMode = function(name, mode) {
3260
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
3261
+ if (arguments.length > 2) {
3262
+ mode.dependencies = [];
3263
+ for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
3264
+ }
3265
+ modes[name] = mode;
3266
+ };
3267
+
3268
+ CodeMirror.defineMIME = function(mime, spec) {
3269
+ mimeModes[mime] = spec;
3270
+ };
3271
+
3272
+ CodeMirror.resolveMode = function(spec) {
3273
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3274
+ spec = mimeModes[spec];
3275
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
3276
+ var found = mimeModes[spec.name];
3277
+ spec = createObj(found, spec);
3278
+ spec.name = found.name;
3279
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
3280
+ return CodeMirror.resolveMode("application/xml");
3281
+ }
3282
+ if (typeof spec == "string") return {name: spec};
3283
+ else return spec || {name: "null"};
3284
+ };
3285
+
3286
+ CodeMirror.getMode = function(options, spec) {
3287
+ var spec = CodeMirror.resolveMode(spec);
3288
+ var mfactory = modes[spec.name];
3289
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
3290
+ var modeObj = mfactory(options, spec);
3291
+ if (modeExtensions.hasOwnProperty(spec.name)) {
3292
+ var exts = modeExtensions[spec.name];
3293
+ for (var prop in exts) {
3294
+ if (!exts.hasOwnProperty(prop)) continue;
3295
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
3296
+ modeObj[prop] = exts[prop];
3297
+ }
3298
+ }
3299
+ modeObj.name = spec.name;
3300
+
3301
+ return modeObj;
3302
+ };
3303
+
3304
+ CodeMirror.defineMode("null", function() {
3305
+ return {token: function(stream) {stream.skipToEnd();}};
3306
+ });
3307
+ CodeMirror.defineMIME("text/plain", "null");
3308
+
3309
+ var modeExtensions = CodeMirror.modeExtensions = {};
3310
+ CodeMirror.extendMode = function(mode, properties) {
3311
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
3312
+ copyObj(properties, exts);
3313
+ };
3314
+
3315
+ // EXTENSIONS
3316
+
3317
+ CodeMirror.defineExtension = function(name, func) {
3318
+ CodeMirror.prototype[name] = func;
3319
+ };
3320
+ CodeMirror.defineDocExtension = function(name, func) {
3321
+ Doc.prototype[name] = func;
3322
+ };
3323
+ CodeMirror.defineOption = option;
3324
+
3325
+ var initHooks = [];
3326
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
3327
+
3328
+ var helpers = CodeMirror.helpers = {};
3329
+ CodeMirror.registerHelper = function(type, name, value) {
3330
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3331
+ helpers[type][name] = value;
3332
+ };
3333
+
3334
+ // UTILITIES
3335
+
3336
+ CodeMirror.isWordChar = isWordChar;
3337
+
3338
+ // MODE STATE HANDLING
3339
+
3340
+ // Utility functions for working with state. Exported because modes
3341
+ // sometimes need to do this.
3342
+ function copyState(mode, state) {
3343
+ if (state === true) return state;
3344
+ if (mode.copyState) return mode.copyState(state);
3345
+ var nstate = {};
3346
+ for (var n in state) {
3347
+ var val = state[n];
3348
+ if (val instanceof Array) val = val.concat([]);
3349
+ nstate[n] = val;
3350
+ }
3351
+ return nstate;
3352
+ }
3353
+ CodeMirror.copyState = copyState;
3354
+
3355
+ function startState(mode, a1, a2) {
3356
+ return mode.startState ? mode.startState(a1, a2) : true;
3357
+ }
3358
+ CodeMirror.startState = startState;
3359
+
3360
+ CodeMirror.innerMode = function(mode, state) {
3361
+ while (mode.innerMode) {
3362
+ var info = mode.innerMode(state);
3363
+ if (!info || info.mode == mode) break;
3364
+ state = info.state;
3365
+ mode = info.mode;
3366
+ }
3367
+ return info || {mode: mode, state: state};
3368
+ };
3369
+
3370
+ // STANDARD COMMANDS
3371
+
3372
+ var commands = CodeMirror.commands = {
3373
+ selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
3374
+ killLine: function(cm) {
3375
+ var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
3376
+ if (!sel && cm.getLine(from.line).length == from.ch)
3377
+ cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
3378
+ else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
3379
+ },
3380
+ deleteLine: function(cm) {
3381
+ var l = cm.getCursor().line;
3382
+ cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3383
+ },
3384
+ delLineLeft: function(cm) {
3385
+ var cur = cm.getCursor();
3386
+ cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3387
+ },
3388
+ undo: function(cm) {cm.undo();},
3389
+ redo: function(cm) {cm.redo();},
3390
+ goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3391
+ goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
3392
+ goLineStart: function(cm) {
3393
+ cm.extendSelection(lineStart(cm, cm.getCursor().line));
3394
+ },
3395
+ goLineStartSmart: function(cm) {
3396
+ var cur = cm.getCursor(), start = lineStart(cm, cur.line);
3397
+ var line = cm.getLineHandle(start.line);
3398
+ var order = getOrder(line);
3399
+ if (!order || order[0].level == 0) {
3400
+ var firstNonWS = Math.max(0, line.text.search(/\S/));
3401
+ var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
3402
+ cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
3403
+ } else cm.extendSelection(start);
3404
+ },
3405
+ goLineEnd: function(cm) {
3406
+ cm.extendSelection(lineEnd(cm, cm.getCursor().line));
3407
+ },
3408
+ goLineRight: function(cm) {
3409
+ var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3410
+ cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
3411
+ },
3412
+ goLineLeft: function(cm) {
3413
+ var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3414
+ cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
3415
+ },
3416
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
3417
+ goLineDown: function(cm) {cm.moveV(1, "line");},
3418
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
3419
+ goPageDown: function(cm) {cm.moveV(1, "page");},
3420
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
3421
+ goCharRight: function(cm) {cm.moveH(1, "char");},
3422
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
3423
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
3424
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
3425
+ goGroupRight: function(cm) {cm.moveH(1, "group");},
3426
+ goGroupLeft: function(cm) {cm.moveH(-1, "group");},
3427
+ goWordRight: function(cm) {cm.moveH(1, "word");},
3428
+ delCharBefore: function(cm) {cm.deleteH(-1, "char");},
3429
+ delCharAfter: function(cm) {cm.deleteH(1, "char");},
3430
+ delWordBefore: function(cm) {cm.deleteH(-1, "word");},
3431
+ delWordAfter: function(cm) {cm.deleteH(1, "word");},
3432
+ delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
3433
+ delGroupAfter: function(cm) {cm.deleteH(1, "group");},
3434
+ indentAuto: function(cm) {cm.indentSelection("smart");},
3435
+ indentMore: function(cm) {cm.indentSelection("add");},
3436
+ indentLess: function(cm) {cm.indentSelection("subtract");},
3437
+ insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
3438
+ defaultTab: function(cm) {
3439
+ if (cm.somethingSelected()) cm.indentSelection("add");
3440
+ else cm.replaceSelection("\t", "end", "+input");
3441
+ },
3442
+ transposeChars: function(cm) {
3443
+ var cur = cm.getCursor(), line = cm.getLine(cur.line);
3444
+ if (cur.ch > 0 && cur.ch < line.length - 1)
3445
+ cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
3446
+ Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
3447
+ },
3448
+ newlineAndIndent: function(cm) {
3449
+ operation(cm, function() {
3450
+ cm.replaceSelection("\n", "end", "+input");
3451
+ cm.indentLine(cm.getCursor().line, null, true);
3452
+ })();
3453
+ },
3454
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
3455
+ };
3456
+
3457
+ // STANDARD KEYMAPS
3458
+
3459
+ var keyMap = CodeMirror.keyMap = {};
3460
+ keyMap.basic = {
3461
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
3462
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
3463
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
3464
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
3465
+ };
3466
+ // Note that the save and find-related commands aren't defined by
3467
+ // default. Unknown commands are simply ignored.
3468
+ keyMap.pcDefault = {
3469
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
3470
+ "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
3471
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
3472
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
3473
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
3474
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
3475
+ fallthrough: "basic"
3476
+ };
3477
+ keyMap.macDefault = {
3478
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
3479
+ "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
3480
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3481
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3482
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3483
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
3484
+ fallthrough: ["basic", "emacsy"]
3485
+ };
3486
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
3487
+ keyMap.emacsy = {
3488
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
3489
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
3490
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
3491
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
3492
+ };
3493
+
3494
+ // KEYMAP DISPATCH
3495
+
3496
+ function getKeyMap(val) {
3497
+ if (typeof val == "string") return keyMap[val];
3498
+ else return val;
3499
+ }
3500
+
3501
+ function lookupKey(name, maps, handle) {
3502
+ function lookup(map) {
3503
+ map = getKeyMap(map);
3504
+ var found = map[name];
3505
+ if (found === false) return "stop";
3506
+ if (found != null && handle(found)) return true;
3507
+ if (map.nofallthrough) return "stop";
3508
+
3509
+ var fallthrough = map.fallthrough;
3510
+ if (fallthrough == null) return false;
3511
+ if (Object.prototype.toString.call(fallthrough) != "[object Array]")
3512
+ return lookup(fallthrough);
3513
+ for (var i = 0, e = fallthrough.length; i < e; ++i) {
3514
+ var done = lookup(fallthrough[i]);
3515
+ if (done) return done;
3516
+ }
3517
+ return false;
3518
+ }
3519
+
3520
+ for (var i = 0; i < maps.length; ++i) {
3521
+ var done = lookup(maps[i]);
3522
+ if (done) return done != "stop";
3523
+ }
3524
+ }
3525
+ function isModifierKey(event) {
3526
+ var name = keyNames[event.keyCode];
3527
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
3528
+ }
3529
+ function keyName(event, noShift) {
3530
+ if (opera && event.keyCode == 34 && event["char"]) return false;
3531
+ var name = keyNames[event.keyCode];
3532
+ if (name == null || event.altGraphKey) return false;
3533
+ if (event.altKey) name = "Alt-" + name;
3534
+ if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
3535
+ if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
3536
+ if (!noShift && event.shiftKey) name = "Shift-" + name;
3537
+ return name;
3538
+ }
3539
+ CodeMirror.lookupKey = lookupKey;
3540
+ CodeMirror.isModifierKey = isModifierKey;
3541
+ CodeMirror.keyName = keyName;
3542
+
3543
+ // FROMTEXTAREA
3544
+
3545
+ CodeMirror.fromTextArea = function(textarea, options) {
3546
+ if (!options) options = {};
3547
+ options.value = textarea.value;
3548
+ if (!options.tabindex && textarea.tabindex)
3549
+ options.tabindex = textarea.tabindex;
3550
+ if (!options.placeholder && textarea.placeholder)
3551
+ options.placeholder = textarea.placeholder;
3552
+ // Set autofocus to true if this textarea is focused, or if it has
3553
+ // autofocus and no other element is focused.
3554
+ if (options.autofocus == null) {
3555
+ var hasFocus = document.body;
3556
+ // doc.activeElement occasionally throws on IE
3557
+ try { hasFocus = document.activeElement; } catch(e) {}
3558
+ options.autofocus = hasFocus == textarea ||
3559
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
3560
+ }
3561
+
3562
+ function save() {textarea.value = cm.getValue();}
3563
+ if (textarea.form) {
3564
+ on(textarea.form, "submit", save);
3565
+ // Deplorable hack to make the submit method do the right thing.
3566
+ if (!options.leaveSubmitMethodAlone) {
3567
+ var form = textarea.form, realSubmit = form.submit;
3568
+ try {
3569
+ var wrappedSubmit = form.submit = function() {
3570
+ save();
3571
+ form.submit = realSubmit;
3572
+ form.submit();
3573
+ form.submit = wrappedSubmit;
3574
+ };
3575
+ } catch(e) {}
3576
+ }
3577
+ }
3578
+
3579
+ textarea.style.display = "none";
3580
+ var cm = CodeMirror(function(node) {
3581
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
3582
+ }, options);
3583
+ cm.save = save;
3584
+ cm.getTextArea = function() { return textarea; };
3585
+ cm.toTextArea = function() {
3586
+ save();
3587
+ textarea.parentNode.removeChild(cm.getWrapperElement());
3588
+ textarea.style.display = "";
3589
+ if (textarea.form) {
3590
+ off(textarea.form, "submit", save);
3591
+ if (typeof textarea.form.submit == "function")
3592
+ textarea.form.submit = realSubmit;
3593
+ }
3594
+ };
3595
+ return cm;
3596
+ };
3597
+
3598
+ // STRING STREAM
3599
+
3600
+ // Fed to the mode parsers, provides helper functions to make
3601
+ // parsers more succinct.
3602
+
3603
+ // The character stream used by a mode's parser.
3604
+ function StringStream(string, tabSize) {
3605
+ this.pos = this.start = 0;
3606
+ this.string = string;
3607
+ this.tabSize = tabSize || 8;
3608
+ this.lastColumnPos = this.lastColumnValue = 0;
3609
+ }
3610
+
3611
+ StringStream.prototype = {
3612
+ eol: function() {return this.pos >= this.string.length;},
3613
+ sol: function() {return this.pos == 0;},
3614
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
3615
+ next: function() {
3616
+ if (this.pos < this.string.length)
3617
+ return this.string.charAt(this.pos++);
3618
+ },
3619
+ eat: function(match) {
3620
+ var ch = this.string.charAt(this.pos);
3621
+ if (typeof match == "string") var ok = ch == match;
3622
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
3623
+ if (ok) {++this.pos; return ch;}
3624
+ },
3625
+ eatWhile: function(match) {
3626
+ var start = this.pos;
3627
+ while (this.eat(match)){}
3628
+ return this.pos > start;
3629
+ },
3630
+ eatSpace: function() {
3631
+ var start = this.pos;
3632
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
3633
+ return this.pos > start;
3634
+ },
3635
+ skipToEnd: function() {this.pos = this.string.length;},
3636
+ skipTo: function(ch) {
3637
+ var found = this.string.indexOf(ch, this.pos);
3638
+ if (found > -1) {this.pos = found; return true;}
3639
+ },
3640
+ backUp: function(n) {this.pos -= n;},
3641
+ column: function() {
3642
+ if (this.lastColumnPos < this.start) {
3643
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3644
+ this.lastColumnPos = this.start;
3645
+ }
3646
+ return this.lastColumnValue;
3647
+ },
3648
+ indentation: function() {return countColumn(this.string, null, this.tabSize);},
3649
+ match: function(pattern, consume, caseInsensitive) {
3650
+ if (typeof pattern == "string") {
3651
+ var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
3652
+ var substr = this.string.substr(this.pos, pattern.length);
3653
+ if (cased(substr) == cased(pattern)) {
3654
+ if (consume !== false) this.pos += pattern.length;
3655
+ return true;
3656
+ }
3657
+ } else {
3658
+ var match = this.string.slice(this.pos).match(pattern);
3659
+ if (match && match.index > 0) return null;
3660
+ if (match && consume !== false) this.pos += match[0].length;
3661
+ return match;
3662
+ }
3663
+ },
3664
+ current: function(){return this.string.slice(this.start, this.pos);}
3665
+ };
3666
+ CodeMirror.StringStream = StringStream;
3667
+
3668
+ // TEXTMARKERS
3669
+
3670
+ function TextMarker(doc, type) {
3671
+ this.lines = [];
3672
+ this.type = type;
3673
+ this.doc = doc;
3674
+ }
3675
+ CodeMirror.TextMarker = TextMarker;
3676
+ eventMixin(TextMarker);
3677
+
3678
+ TextMarker.prototype.clear = function() {
3679
+ if (this.explicitlyCleared) return;
3680
+ var cm = this.doc.cm, withOp = cm && !cm.curOp;
3681
+ if (withOp) startOperation(cm);
3682
+ if (hasHandler(this, "clear")) {
3683
+ var found = this.find();
3684
+ if (found) signalLater(this, "clear", found.from, found.to);
3685
+ }
3686
+ var min = null, max = null;
3687
+ for (var i = 0; i < this.lines.length; ++i) {
3688
+ var line = this.lines[i];
3689
+ var span = getMarkedSpanFor(line.markedSpans, this);
3690
+ if (span.to != null) max = lineNo(line);
3691
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
3692
+ if (span.from != null)
3693
+ min = lineNo(line);
3694
+ else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
3695
+ updateLineHeight(line, textHeight(cm.display));
3696
+ }
3697
+ if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
3698
+ var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
3699
+ if (len > cm.display.maxLineLength) {
3700
+ cm.display.maxLine = visual;
3701
+ cm.display.maxLineLength = len;
3702
+ cm.display.maxLineChanged = true;
3703
+ }
3704
+ }
3705
+
3706
+ if (min != null && cm) regChange(cm, min, max + 1);
3707
+ this.lines.length = 0;
3708
+ this.explicitlyCleared = true;
3709
+ if (this.atomic && this.doc.cantEdit) {
3710
+ this.doc.cantEdit = false;
3711
+ if (cm) reCheckSelection(cm);
3712
+ }
3713
+ if (withOp) endOperation(cm);
3714
+ };
3715
+
3716
+ TextMarker.prototype.find = function() {
3717
+ var from, to;
3718
+ for (var i = 0; i < this.lines.length; ++i) {
3719
+ var line = this.lines[i];
3720
+ var span = getMarkedSpanFor(line.markedSpans, this);
3721
+ if (span.from != null || span.to != null) {
3722
+ var found = lineNo(line);
3723
+ if (span.from != null) from = Pos(found, span.from);
3724
+ if (span.to != null) to = Pos(found, span.to);
3725
+ }
3726
+ }
3727
+ if (this.type == "bookmark") return from;
3728
+ return from && {from: from, to: to};
3729
+ };
3730
+
3731
+ TextMarker.prototype.changed = function() {
3732
+ var pos = this.find(), cm = this.doc.cm;
3733
+ if (!pos || !cm) return;
3734
+ var line = getLine(this.doc, pos.from.line);
3735
+ clearCachedMeasurement(cm, line);
3736
+ if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
3737
+ for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3738
+ if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3739
+ break;
3740
+ }
3741
+ runInOp(cm, function() {
3742
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3743
+ });
3744
+ }
3745
+ };
3746
+
3747
+ TextMarker.prototype.attachLine = function(line) {
3748
+ if (!this.lines.length && this.doc.cm) {
3749
+ var op = this.doc.cm.curOp;
3750
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
3751
+ (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
3752
+ }
3753
+ this.lines.push(line);
3754
+ };
3755
+ TextMarker.prototype.detachLine = function(line) {
3756
+ this.lines.splice(indexOf(this.lines, line), 1);
3757
+ if (!this.lines.length && this.doc.cm) {
3758
+ var op = this.doc.cm.curOp;
3759
+ (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
3760
+ }
3761
+ };
3762
+
3763
+ function markText(doc, from, to, options, type) {
3764
+ if (options && options.shared) return markTextShared(doc, from, to, options, type);
3765
+ if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3766
+
3767
+ var marker = new TextMarker(doc, type);
3768
+ if (type == "range" && !posLess(from, to)) return marker;
3769
+ if (options) copyObj(options, marker);
3770
+ if (marker.replacedWith) {
3771
+ marker.collapsed = true;
3772
+ marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3773
+ if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3774
+ }
3775
+ if (marker.collapsed) sawCollapsedSpans = true;
3776
+
3777
+ if (marker.addToHistory)
3778
+ addToHistory(doc, {from: from, to: to, origin: "markText"},
3779
+ {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
3780
+
3781
+ var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
3782
+ doc.iter(curLine, to.line + 1, function(line) {
3783
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3784
+ updateMaxLine = true;
3785
+ var span = {from: null, to: null, marker: marker};
3786
+ size += line.text.length;
3787
+ if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
3788
+ if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
3789
+ if (marker.collapsed) {
3790
+ if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
3791
+ if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
3792
+ else updateLineHeight(line, 0);
3793
+ }
3794
+ addMarkedSpan(line, span);
3795
+ ++curLine;
3796
+ });
3797
+ if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
3798
+ if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
3799
+ });
3800
+
3801
+ if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
3802
+
3803
+ if (marker.readOnly) {
3804
+ sawReadOnlySpans = true;
3805
+ if (doc.history.done.length || doc.history.undone.length)
3806
+ doc.clearHistory();
3807
+ }
3808
+ if (marker.collapsed) {
3809
+ if (collapsedAtStart != collapsedAtEnd)
3810
+ throw new Error("Inserting collapsed marker overlapping an existing one");
3811
+ marker.size = size;
3812
+ marker.atomic = true;
3813
+ }
3814
+ if (cm) {
3815
+ if (updateMaxLine) cm.curOp.updateMaxLine = true;
3816
+ if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3817
+ regChange(cm, from.line, to.line + 1);
3818
+ if (marker.atomic) reCheckSelection(cm);
3819
+ }
3820
+ return marker;
3821
+ }
3822
+
3823
+ // SHARED TEXTMARKERS
3824
+
3825
+ function SharedTextMarker(markers, primary) {
3826
+ this.markers = markers;
3827
+ this.primary = primary;
3828
+ for (var i = 0, me = this; i < markers.length; ++i) {
3829
+ markers[i].parent = this;
3830
+ on(markers[i], "clear", function(){me.clear();});
3831
+ }
3832
+ }
3833
+ CodeMirror.SharedTextMarker = SharedTextMarker;
3834
+ eventMixin(SharedTextMarker);
3835
+
3836
+ SharedTextMarker.prototype.clear = function() {
3837
+ if (this.explicitlyCleared) return;
3838
+ this.explicitlyCleared = true;
3839
+ for (var i = 0; i < this.markers.length; ++i)
3840
+ this.markers[i].clear();
3841
+ signalLater(this, "clear");
3842
+ };
3843
+ SharedTextMarker.prototype.find = function() {
3844
+ return this.primary.find();
3845
+ };
3846
+
3847
+ function markTextShared(doc, from, to, options, type) {
3848
+ options = copyObj(options);
3849
+ options.shared = false;
3850
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0];
3851
+ var widget = options.replacedWith;
3852
+ linkedDocs(doc, function(doc) {
3853
+ if (widget) options.replacedWith = widget.cloneNode(true);
3854
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
3855
+ for (var i = 0; i < doc.linked.length; ++i)
3856
+ if (doc.linked[i].isParent) return;
3857
+ primary = lst(markers);
3858
+ });
3859
+ return new SharedTextMarker(markers, primary);
3860
+ }
3861
+
3862
+ // TEXTMARKER SPANS
3863
+
3864
+ function getMarkedSpanFor(spans, marker) {
3865
+ if (spans) for (var i = 0; i < spans.length; ++i) {
3866
+ var span = spans[i];
3867
+ if (span.marker == marker) return span;
3868
+ }
3869
+ }
3870
+ function removeMarkedSpan(spans, span) {
3871
+ for (var r, i = 0; i < spans.length; ++i)
3872
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
3873
+ return r;
3874
+ }
3875
+ function addMarkedSpan(line, span) {
3876
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
3877
+ span.marker.attachLine(line);
3878
+ }
3879
+
3880
+ function markedSpansBefore(old, startCh, isInsert) {
3881
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
3882
+ var span = old[i], marker = span.marker;
3883
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3884
+ if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
3885
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
3886
+ (nw || (nw = [])).push({from: span.from,
3887
+ to: endsAfter ? null : span.to,
3888
+ marker: marker});
3889
+ }
3890
+ }
3891
+ return nw;
3892
+ }
3893
+
3894
+ function markedSpansAfter(old, endCh, isInsert) {
3895
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
3896
+ var span = old[i], marker = span.marker;
3897
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3898
+ if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
3899
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
3900
+ (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
3901
+ to: span.to == null ? null : span.to - endCh,
3902
+ marker: marker});
3903
+ }
3904
+ }
3905
+ return nw;
3906
+ }
3907
+
3908
+ function stretchSpansOverChange(doc, change) {
3909
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
3910
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
3911
+ if (!oldFirst && !oldLast) return null;
3912
+
3913
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
3914
+ // Get the spans that 'stick out' on both sides
3915
+ var first = markedSpansBefore(oldFirst, startCh, isInsert);
3916
+ var last = markedSpansAfter(oldLast, endCh, isInsert);
3917
+
3918
+ // Next, merge those two ends
3919
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
3920
+ if (first) {
3921
+ // Fix up .to properties of first
3922
+ for (var i = 0; i < first.length; ++i) {
3923
+ var span = first[i];
3924
+ if (span.to == null) {
3925
+ var found = getMarkedSpanFor(last, span.marker);
3926
+ if (!found) span.to = startCh;
3927
+ else if (sameLine) span.to = found.to == null ? null : found.to + offset;
3928
+ }
3929
+ }
3930
+ }
3931
+ if (last) {
3932
+ // Fix up .from in last (or move them into first in case of sameLine)
3933
+ for (var i = 0; i < last.length; ++i) {
3934
+ var span = last[i];
3935
+ if (span.to != null) span.to += offset;
3936
+ if (span.from == null) {
3937
+ var found = getMarkedSpanFor(first, span.marker);
3938
+ if (!found) {
3939
+ span.from = offset;
3940
+ if (sameLine) (first || (first = [])).push(span);
3941
+ }
3942
+ } else {
3943
+ span.from += offset;
3944
+ if (sameLine) (first || (first = [])).push(span);
3945
+ }
3946
+ }
3947
+ }
3948
+ if (sameLine && first) {
3949
+ // Make sure we didn't create any zero-length spans
3950
+ for (var i = 0; i < first.length; ++i)
3951
+ if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
3952
+ first.splice(i--, 1);
3953
+ if (!first.length) first = null;
3954
+ }
3955
+
3956
+ var newMarkers = [first];
3957
+ if (!sameLine) {
3958
+ // Fill gap with whole-line-spans
3959
+ var gap = change.text.length - 2, gapMarkers;
3960
+ if (gap > 0 && first)
3961
+ for (var i = 0; i < first.length; ++i)
3962
+ if (first[i].to == null)
3963
+ (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
3964
+ for (var i = 0; i < gap; ++i)
3965
+ newMarkers.push(gapMarkers);
3966
+ newMarkers.push(last);
3967
+ }
3968
+ return newMarkers;
3969
+ }
3970
+
3971
+ function mergeOldSpans(doc, change) {
3972
+ var old = getOldSpans(doc, change);
3973
+ var stretched = stretchSpansOverChange(doc, change);
3974
+ if (!old) return stretched;
3975
+ if (!stretched) return old;
3976
+
3977
+ for (var i = 0; i < old.length; ++i) {
3978
+ var oldCur = old[i], stretchCur = stretched[i];
3979
+ if (oldCur && stretchCur) {
3980
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
3981
+ var span = stretchCur[j];
3982
+ for (var k = 0; k < oldCur.length; ++k)
3983
+ if (oldCur[k].marker == span.marker) continue spans;
3984
+ oldCur.push(span);
3985
+ }
3986
+ } else if (stretchCur) {
3987
+ old[i] = stretchCur;
3988
+ }
3989
+ }
3990
+ return old;
3991
+ }
3992
+
3993
+ function removeReadOnlyRanges(doc, from, to) {
3994
+ var markers = null;
3995
+ doc.iter(from.line, to.line + 1, function(line) {
3996
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
3997
+ var mark = line.markedSpans[i].marker;
3998
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
3999
+ (markers || (markers = [])).push(mark);
4000
+ }
4001
+ });
4002
+ if (!markers) return null;
4003
+ var parts = [{from: from, to: to}];
4004
+ for (var i = 0; i < markers.length; ++i) {
4005
+ var mk = markers[i], m = mk.find();
4006
+ for (var j = 0; j < parts.length; ++j) {
4007
+ var p = parts[j];
4008
+ if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
4009
+ var newParts = [j, 1];
4010
+ if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
4011
+ newParts.push({from: p.from, to: m.from});
4012
+ if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
4013
+ newParts.push({from: m.to, to: p.to});
4014
+ parts.splice.apply(parts, newParts);
4015
+ j += newParts.length - 1;
4016
+ }
4017
+ }
4018
+ return parts;
4019
+ }
4020
+
4021
+ function collapsedSpanAt(line, ch) {
4022
+ var sps = sawCollapsedSpans && line.markedSpans, found;
4023
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4024
+ sp = sps[i];
4025
+ if (!sp.marker.collapsed) continue;
4026
+ if ((sp.from == null || sp.from < ch) &&
4027
+ (sp.to == null || sp.to > ch) &&
4028
+ (!found || found.width < sp.marker.width))
4029
+ found = sp.marker;
4030
+ }
4031
+ return found;
4032
+ }
4033
+ function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
4034
+ function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
4035
+
4036
+ function visualLine(doc, line) {
4037
+ var merged;
4038
+ while (merged = collapsedSpanAtStart(line))
4039
+ line = getLine(doc, merged.find().from.line);
4040
+ return line;
4041
+ }
4042
+
4043
+ function lineIsHidden(doc, line) {
4044
+ var sps = sawCollapsedSpans && line.markedSpans;
4045
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4046
+ sp = sps[i];
4047
+ if (!sp.marker.collapsed) continue;
4048
+ if (sp.from == null) return true;
4049
+ if (sp.marker.replacedWith) continue;
4050
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
4051
+ return true;
4052
+ }
4053
+ }
4054
+ function lineIsHiddenInner(doc, line, span) {
4055
+ if (span.to == null) {
4056
+ var end = span.marker.find().to, endLine = getLine(doc, end.line);
4057
+ return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
4058
+ }
4059
+ if (span.marker.inclusiveRight && span.to == line.text.length)
4060
+ return true;
4061
+ for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4062
+ sp = line.markedSpans[i];
4063
+ if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
4064
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4065
+ lineIsHiddenInner(doc, line, sp)) return true;
4066
+ }
4067
+ }
4068
+
4069
+ function detachMarkedSpans(line) {
4070
+ var spans = line.markedSpans;
4071
+ if (!spans) return;
4072
+ for (var i = 0; i < spans.length; ++i)
4073
+ spans[i].marker.detachLine(line);
4074
+ line.markedSpans = null;
4075
+ }
4076
+
4077
+ function attachMarkedSpans(line, spans) {
4078
+ if (!spans) return;
4079
+ for (var i = 0; i < spans.length; ++i)
4080
+ spans[i].marker.attachLine(line);
4081
+ line.markedSpans = spans;
4082
+ }
4083
+
4084
+ // LINE WIDGETS
4085
+
4086
+ var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4087
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4088
+ this[opt] = options[opt];
4089
+ this.cm = cm;
4090
+ this.node = node;
4091
+ };
4092
+ eventMixin(LineWidget);
4093
+ function widgetOperation(f) {
4094
+ return function() {
4095
+ var withOp = !this.cm.curOp;
4096
+ if (withOp) startOperation(this.cm);
4097
+ try {var result = f.apply(this, arguments);}
4098
+ finally {if (withOp) endOperation(this.cm);}
4099
+ return result;
4100
+ };
4101
+ }
4102
+ LineWidget.prototype.clear = widgetOperation(function() {
4103
+ var ws = this.line.widgets, no = lineNo(this.line);
4104
+ if (no == null || !ws) return;
4105
+ for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4106
+ if (!ws.length) this.line.widgets = null;
4107
+ var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4108
+ updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4109
+ if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4110
+ regChange(this.cm, no, no + 1);
4111
+ });
4112
+ LineWidget.prototype.changed = widgetOperation(function() {
4113
+ var oldH = this.height;
4114
+ this.height = null;
4115
+ var diff = widgetHeight(this) - oldH;
4116
+ if (!diff) return;
4117
+ updateLineHeight(this.line, this.line.height + diff);
4118
+ var no = lineNo(this.line);
4119
+ regChange(this.cm, no, no + 1);
4120
+ });
4121
+
4122
+ function widgetHeight(widget) {
4123
+ if (widget.height != null) return widget.height;
4124
+ if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
4125
+ removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
4126
+ return widget.height = widget.node.offsetHeight;
4127
+ }
4128
+
4129
+ function addLineWidget(cm, handle, node, options) {
4130
+ var widget = new LineWidget(cm, node, options);
4131
+ if (widget.noHScroll) cm.display.alignWidgets = true;
4132
+ changeLine(cm, handle, function(line) {
4133
+ var widgets = line.widgets || (line.widgets = []);
4134
+ if (widget.insertAt == null) widgets.push(widget);
4135
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4136
+ widget.line = line;
4137
+ if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4138
+ var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4139
+ updateLineHeight(line, line.height + widgetHeight(widget));
4140
+ if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4141
+ }
4142
+ return true;
4143
+ });
4144
+ return widget;
4145
+ }
4146
+
4147
+ // LINE DATA STRUCTURE
4148
+
4149
+ // Line objects. These hold state related to a line, including
4150
+ // highlighting info (the styles array).
4151
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4152
+ this.text = text;
4153
+ attachMarkedSpans(this, markedSpans);
4154
+ this.height = estimateHeight ? estimateHeight(this) : 1;
4155
+ };
4156
+ eventMixin(Line);
4157
+
4158
+ function updateLine(line, text, markedSpans, estimateHeight) {
4159
+ line.text = text;
4160
+ if (line.stateAfter) line.stateAfter = null;
4161
+ if (line.styles) line.styles = null;
4162
+ if (line.order != null) line.order = null;
4163
+ detachMarkedSpans(line);
4164
+ attachMarkedSpans(line, markedSpans);
4165
+ var estHeight = estimateHeight ? estimateHeight(line) : 1;
4166
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
4167
+ }
4168
+
4169
+ function cleanUpLine(line) {
4170
+ line.parent = null;
4171
+ detachMarkedSpans(line);
4172
+ }
4173
+
4174
+ // Run the given mode's parser over a line, update the styles
4175
+ // array, which contains alternating fragments of text and CSS
4176
+ // classes.
4177
+ function runMode(cm, text, mode, state, f) {
4178
+ var flattenSpans = mode.flattenSpans;
4179
+ if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4180
+ var curStart = 0, curStyle = null;
4181
+ var stream = new StringStream(text, cm.options.tabSize), style;
4182
+ if (text == "" && mode.blankLine) mode.blankLine(state);
4183
+ while (!stream.eol()) {
4184
+ if (stream.pos > cm.options.maxHighlightLength) {
4185
+ flattenSpans = false;
4186
+ // Webkit seems to refuse to render text nodes longer than 57444 characters
4187
+ stream.pos = Math.min(text.length, stream.start + 50000);
4188
+ style = null;
4189
+ } else {
4190
+ style = mode.token(stream, state);
4191
+ }
4192
+ if (!flattenSpans || curStyle != style) {
4193
+ if (curStart < stream.start) f(stream.start, curStyle);
4194
+ curStart = stream.start; curStyle = style;
4195
+ }
4196
+ stream.start = stream.pos;
4197
+ }
4198
+ if (curStart < stream.pos) f(stream.pos, curStyle);
4199
+ }
4200
+
4201
+ function highlightLine(cm, line, state) {
4202
+ // A styles array always starts with a number identifying the
4203
+ // mode/overlays that it is based on (for easy invalidation).
4204
+ var st = [cm.state.modeGen];
4205
+ // Compute the base array of styles
4206
+ runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4207
+
4208
+ // Run overlays, adjust style array.
4209
+ for (var o = 0; o < cm.state.overlays.length; ++o) {
4210
+ var overlay = cm.state.overlays[o], i = 1, at = 0;
4211
+ runMode(cm, line.text, overlay.mode, true, function(end, style) {
4212
+ var start = i;
4213
+ // Ensure there's a token end at the current position, and that i points at it
4214
+ while (at < end) {
4215
+ var i_end = st[i];
4216
+ if (i_end > end)
4217
+ st.splice(i, 1, end, st[i+1], i_end);
4218
+ i += 2;
4219
+ at = Math.min(end, i_end);
4220
+ }
4221
+ if (!style) return;
4222
+ if (overlay.opaque) {
4223
+ st.splice(start, i - start, end, style);
4224
+ i = start + 2;
4225
+ } else {
4226
+ for (; start < i; start += 2) {
4227
+ var cur = st[start+1];
4228
+ st[start+1] = cur ? cur + " " + style : style;
4229
+ }
4230
+ }
4231
+ });
4232
+ }
4233
+
4234
+ return st;
4235
+ }
4236
+
4237
+ function getLineStyles(cm, line) {
4238
+ if (!line.styles || line.styles[0] != cm.state.modeGen)
4239
+ line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
4240
+ return line.styles;
4241
+ }
4242
+
4243
+ // Lightweight form of highlight -- proceed over this line and
4244
+ // update state, but don't save a style array.
4245
+ function processLine(cm, line, state) {
4246
+ var mode = cm.doc.mode;
4247
+ var stream = new StringStream(line.text, cm.options.tabSize);
4248
+ if (line.text == "" && mode.blankLine) mode.blankLine(state);
4249
+ while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
4250
+ mode.token(stream, state);
4251
+ stream.start = stream.pos;
4252
+ }
4253
+ }
4254
+
4255
+ var styleToClassCache = {};
4256
+ function styleToClass(style) {
4257
+ if (!style) return null;
4258
+ return styleToClassCache[style] ||
4259
+ (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4260
+ }
4261
+
4262
+ function lineContent(cm, realLine, measure, copyWidgets) {
4263
+ var merged, line = realLine, empty = true;
4264
+ while (merged = collapsedSpanAtStart(line))
4265
+ line = getLine(cm.doc, merged.find().from.line);
4266
+
4267
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
4268
+ measure: null, measuredSomething: false, cm: cm,
4269
+ copyWidgets: copyWidgets};
4270
+ if (line.textClass) builder.pre.className = line.textClass;
4271
+
4272
+ do {
4273
+ if (line.text) empty = false;
4274
+ builder.measure = line == realLine && measure;
4275
+ builder.pos = 0;
4276
+ builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4277
+ if ((ie || webkit) && cm.getOption("lineWrapping"))
4278
+ builder.addToken = buildTokenSplitSpaces(builder.addToken);
4279
+ var next = insertLineContent(line, builder, getLineStyles(cm, line));
4280
+ if (measure && line == realLine && !builder.measuredSomething) {
4281
+ measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4282
+ builder.measuredSomething = true;
4283
+ }
4284
+ if (next) line = getLine(cm.doc, next.to.line);
4285
+ } while (next);
4286
+
4287
+ if (measure && !builder.measuredSomething && !measure[0])
4288
+ measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4289
+ if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4290
+ builder.pre.appendChild(document.createTextNode("\u00a0"));
4291
+
4292
+ var order;
4293
+ // Work around problem with the reported dimensions of single-char
4294
+ // direction spans on IE (issue #1129). See also the comment in
4295
+ // cursorCoords.
4296
+ if (measure && ie && (order = getOrder(line))) {
4297
+ var l = order.length - 1;
4298
+ if (order[l].from == order[l].to) --l;
4299
+ var last = order[l], prev = order[l - 1];
4300
+ if (last.from + 1 == last.to && prev && last.level < prev.level) {
4301
+ var span = measure[builder.pos - 1];
4302
+ if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
4303
+ span.nextSibling);
4304
+ }
4305
+ }
4306
+
4307
+ signal(cm, "renderLine", cm, realLine, builder.pre);
4308
+ return builder.pre;
4309
+ }
4310
+
4311
+ var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4312
+ function buildToken(builder, text, style, startStyle, endStyle, title) {
4313
+ if (!text) return;
4314
+ if (!tokenSpecialChars.test(text)) {
4315
+ builder.col += text.length;
4316
+ var content = document.createTextNode(text);
4317
+ } else {
4318
+ var content = document.createDocumentFragment(), pos = 0;
4319
+ while (true) {
4320
+ tokenSpecialChars.lastIndex = pos;
4321
+ var m = tokenSpecialChars.exec(text);
4322
+ var skipped = m ? m.index - pos : text.length - pos;
4323
+ if (skipped) {
4324
+ content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
4325
+ builder.col += skipped;
4326
+ }
4327
+ if (!m) break;
4328
+ pos += skipped + 1;
4329
+ if (m[0] == "\t") {
4330
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
4331
+ content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
4332
+ builder.col += tabWidth;
4333
+ } else {
4334
+ var token = elt("span", "\u2022", "cm-invalidchar");
4335
+ token.title = "\\u" + m[0].charCodeAt(0).toString(16);
4336
+ content.appendChild(token);
4337
+ builder.col += 1;
4338
+ }
4339
+ }
4340
+ }
4341
+ if (style || startStyle || endStyle || builder.measure) {
4342
+ var fullStyle = style || "";
4343
+ if (startStyle) fullStyle += startStyle;
4344
+ if (endStyle) fullStyle += endStyle;
4345
+ var token = elt("span", [content], fullStyle);
4346
+ if (title) token.title = title;
4347
+ return builder.pre.appendChild(token);
4348
+ }
4349
+ builder.pre.appendChild(content);
4350
+ }
4351
+
4352
+ function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4353
+ var wrapping = builder.cm.options.lineWrapping;
4354
+ for (var i = 0; i < text.length; ++i) {
4355
+ var ch = text.charAt(i), start = i == 0;
4356
+ if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4357
+ ch = text.slice(i, i + 2);
4358
+ ++i;
4359
+ } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4360
+ builder.pre.appendChild(elt("wbr"));
4361
+ }
4362
+ var old = builder.measure[builder.pos];
4363
+ var span = builder.measure[builder.pos] =
4364
+ buildToken(builder, ch, style,
4365
+ start && startStyle, i == text.length - 1 && endStyle);
4366
+ if (old) span.leftSide = old.leftSide || old;
4367
+ // In IE single-space nodes wrap differently than spaces
4368
+ // embedded in larger text nodes, except when set to
4369
+ // white-space: normal (issue #1268).
4370
+ if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4371
+ i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4372
+ span.style.whiteSpace = "normal";
4373
+ builder.pos += ch.length;
4374
+ }
4375
+ if (text.length) builder.measuredSomething = true;
4376
+ }
4377
+
4378
+ function buildTokenSplitSpaces(inner) {
4379
+ function split(old) {
4380
+ var out = " ";
4381
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
4382
+ out += " ";
4383
+ return out;
4384
+ }
4385
+ return function(builder, text, style, startStyle, endStyle, title) {
4386
+ return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
4387
+ };
4388
+ }
4389
+
4390
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4391
+ var widget = !ignoreWidget && marker.replacedWith;
4392
+ if (widget) {
4393
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
4394
+ builder.pre.appendChild(widget);
4395
+ if (builder.measure) {
4396
+ if (size) {
4397
+ builder.measure[builder.pos] = widget;
4398
+ } else {
4399
+ var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
4400
+ if (marker.type != "bookmark" || marker.insertLeft)
4401
+ builder.pre.insertBefore(elt, widget);
4402
+ else
4403
+ builder.pre.appendChild(elt);
4404
+ }
4405
+ builder.measuredSomething = true;
4406
+ }
4407
+ }
4408
+ builder.pos += size;
4409
+ }
4410
+
4411
+ // Outputs a number of spans to make up a line, taking highlighting
4412
+ // and marked text into account.
4413
+ function insertLineContent(line, builder, styles) {
4414
+ var spans = line.markedSpans, allText = line.text, at = 0;
4415
+ if (!spans) {
4416
+ for (var i = 1; i < styles.length; i+=2)
4417
+ builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
4418
+ return;
4419
+ }
4420
+
4421
+ var len = allText.length, pos = 0, i = 1, text = "", style;
4422
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
4423
+ for (;;) {
4424
+ if (nextChange == pos) { // Update current marker set
4425
+ spanStyle = spanEndStyle = spanStartStyle = title = "";
4426
+ collapsed = null; nextChange = Infinity;
4427
+ var foundBookmark = null;
4428
+ for (var j = 0; j < spans.length; ++j) {
4429
+ var sp = spans[j], m = sp.marker;
4430
+ if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
4431
+ if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
4432
+ if (m.className) spanStyle += " " + m.className;
4433
+ if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4434
+ if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4435
+ if (m.title && !title) title = m.title;
4436
+ if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4437
+ collapsed = sp;
4438
+ } else if (sp.from > pos && nextChange > sp.from) {
4439
+ nextChange = sp.from;
4440
+ }
4441
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
4442
+ }
4443
+ if (collapsed && (collapsed.from || 0) == pos) {
4444
+ buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4445
+ collapsed.marker, collapsed.from == null);
4446
+ if (collapsed.to == null) return collapsed.marker.find();
4447
+ }
4448
+ if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
4449
+ }
4450
+ if (pos >= len) break;
4451
+
4452
+ var upto = Math.min(len, nextChange);
4453
+ while (true) {
4454
+ if (text) {
4455
+ var end = pos + text.length;
4456
+ if (!collapsed) {
4457
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4458
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4459
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4460
+ }
4461
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
4462
+ pos = end;
4463
+ spanStartStyle = "";
4464
+ }
4465
+ text = allText.slice(at, at = styles[i++]);
4466
+ style = styleToClass(styles[i++]);
4467
+ }
4468
+ }
4469
+ }
4470
+
4471
+ // DOCUMENT DATA STRUCTURE
4472
+
4473
+ function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
4474
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
4475
+ function update(line, text, spans) {
4476
+ updateLine(line, text, spans, estimateHeight);
4477
+ signalLater(line, "change", line, change);
4478
+ }
4479
+
4480
+ var from = change.from, to = change.to, text = change.text;
4481
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4482
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4483
+
4484
+ // First adjust the line structure
4485
+ if (from.ch == 0 && to.ch == 0 && lastText == "") {
4486
+ // This is a whole-line replace. Treated specially to make
4487
+ // sure line objects move the way they are supposed to.
4488
+ for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4489
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4490
+ update(lastLine, lastLine.text, lastSpans);
4491
+ if (nlines) doc.remove(from.line, nlines);
4492
+ if (added.length) doc.insert(from.line, added);
4493
+ } else if (firstLine == lastLine) {
4494
+ if (text.length == 1) {
4495
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4496
+ } else {
4497
+ for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4498
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4499
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4500
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4501
+ doc.insert(from.line + 1, added);
4502
+ }
4503
+ } else if (text.length == 1) {
4504
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4505
+ doc.remove(from.line + 1, nlines);
4506
+ } else {
4507
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4508
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4509
+ for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4510
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4511
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4512
+ doc.insert(from.line + 1, added);
4513
+ }
4514
+
4515
+ signalLater(doc, "change", doc, change);
4516
+ setSelection(doc, selAfter.anchor, selAfter.head, null, true);
4517
+ }
4518
+
4519
+ function LeafChunk(lines) {
4520
+ this.lines = lines;
4521
+ this.parent = null;
4522
+ for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
4523
+ lines[i].parent = this;
4524
+ height += lines[i].height;
4525
+ }
4526
+ this.height = height;
4527
+ }
4528
+
4529
+ LeafChunk.prototype = {
4530
+ chunkSize: function() { return this.lines.length; },
4531
+ removeInner: function(at, n) {
4532
+ for (var i = at, e = at + n; i < e; ++i) {
4533
+ var line = this.lines[i];
4534
+ this.height -= line.height;
4535
+ cleanUpLine(line);
4536
+ signalLater(line, "delete");
4537
+ }
4538
+ this.lines.splice(at, n);
4539
+ },
4540
+ collapse: function(lines) {
4541
+ lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
4542
+ },
4543
+ insertInner: function(at, lines, height) {
4544
+ this.height += height;
4545
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
4546
+ for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
4547
+ },
4548
+ iterN: function(at, n, op) {
4549
+ for (var e = at + n; at < e; ++at)
4550
+ if (op(this.lines[at])) return true;
4551
+ }
4552
+ };
4553
+
4554
+ function BranchChunk(children) {
4555
+ this.children = children;
4556
+ var size = 0, height = 0;
4557
+ for (var i = 0, e = children.length; i < e; ++i) {
4558
+ var ch = children[i];
4559
+ size += ch.chunkSize(); height += ch.height;
4560
+ ch.parent = this;
4561
+ }
4562
+ this.size = size;
4563
+ this.height = height;
4564
+ this.parent = null;
4565
+ }
4566
+
4567
+ BranchChunk.prototype = {
4568
+ chunkSize: function() { return this.size; },
4569
+ removeInner: function(at, n) {
4570
+ this.size -= n;
4571
+ for (var i = 0; i < this.children.length; ++i) {
4572
+ var child = this.children[i], sz = child.chunkSize();
4573
+ if (at < sz) {
4574
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
4575
+ child.removeInner(at, rm);
4576
+ this.height -= oldHeight - child.height;
4577
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
4578
+ if ((n -= rm) == 0) break;
4579
+ at = 0;
4580
+ } else at -= sz;
4581
+ }
4582
+ if (this.size - n < 25) {
4583
+ var lines = [];
4584
+ this.collapse(lines);
4585
+ this.children = [new LeafChunk(lines)];
4586
+ this.children[0].parent = this;
4587
+ }
4588
+ },
4589
+ collapse: function(lines) {
4590
+ for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
4591
+ },
4592
+ insertInner: function(at, lines, height) {
4593
+ this.size += lines.length;
4594
+ this.height += height;
4595
+ for (var i = 0, e = this.children.length; i < e; ++i) {
4596
+ var child = this.children[i], sz = child.chunkSize();
4597
+ if (at <= sz) {
4598
+ child.insertInner(at, lines, height);
4599
+ if (child.lines && child.lines.length > 50) {
4600
+ while (child.lines.length > 50) {
4601
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
4602
+ var newleaf = new LeafChunk(spilled);
4603
+ child.height -= newleaf.height;
4604
+ this.children.splice(i + 1, 0, newleaf);
4605
+ newleaf.parent = this;
4606
+ }
4607
+ this.maybeSpill();
4608
+ }
4609
+ break;
4610
+ }
4611
+ at -= sz;
4612
+ }
4613
+ },
4614
+ maybeSpill: function() {
4615
+ if (this.children.length <= 10) return;
4616
+ var me = this;
4617
+ do {
4618
+ var spilled = me.children.splice(me.children.length - 5, 5);
4619
+ var sibling = new BranchChunk(spilled);
4620
+ if (!me.parent) { // Become the parent node
4621
+ var copy = new BranchChunk(me.children);
4622
+ copy.parent = me;
4623
+ me.children = [copy, sibling];
4624
+ me = copy;
4625
+ } else {
4626
+ me.size -= sibling.size;
4627
+ me.height -= sibling.height;
4628
+ var myIndex = indexOf(me.parent.children, me);
4629
+ me.parent.children.splice(myIndex + 1, 0, sibling);
4630
+ }
4631
+ sibling.parent = me.parent;
4632
+ } while (me.children.length > 10);
4633
+ me.parent.maybeSpill();
4634
+ },
4635
+ iterN: function(at, n, op) {
4636
+ for (var i = 0, e = this.children.length; i < e; ++i) {
4637
+ var child = this.children[i], sz = child.chunkSize();
4638
+ if (at < sz) {
4639
+ var used = Math.min(n, sz - at);
4640
+ if (child.iterN(at, used, op)) return true;
4641
+ if ((n -= used) == 0) break;
4642
+ at = 0;
4643
+ } else at -= sz;
4644
+ }
4645
+ }
4646
+ };
4647
+
4648
+ var nextDocId = 0;
4649
+ var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
4650
+ if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4651
+ if (firstLine == null) firstLine = 0;
4652
+
4653
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4654
+ this.first = firstLine;
4655
+ this.scrollTop = this.scrollLeft = 0;
4656
+ this.cantEdit = false;
4657
+ this.history = makeHistory();
4658
+ this.cleanGeneration = 1;
4659
+ this.frontier = firstLine;
4660
+ var start = Pos(firstLine, 0);
4661
+ this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4662
+ this.id = ++nextDocId;
4663
+ this.modeOption = mode;
4664
+
4665
+ if (typeof text == "string") text = splitLines(text);
4666
+ updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
4667
+ };
4668
+
4669
+ Doc.prototype = createObj(BranchChunk.prototype, {
4670
+ constructor: Doc,
4671
+ iter: function(from, to, op) {
4672
+ if (op) this.iterN(from - this.first, to - from, op);
4673
+ else this.iterN(this.first, this.first + this.size, from);
4674
+ },
4675
+
4676
+ insert: function(at, lines) {
4677
+ var height = 0;
4678
+ for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
4679
+ this.insertInner(at - this.first, lines, height);
4680
+ },
4681
+ remove: function(at, n) { this.removeInner(at - this.first, n); },
4682
+
4683
+ getValue: function(lineSep) {
4684
+ var lines = getLines(this, this.first, this.first + this.size);
4685
+ if (lineSep === false) return lines;
4686
+ return lines.join(lineSep || "\n");
4687
+ },
4688
+ setValue: function(code) {
4689
+ var top = Pos(this.first, 0), last = this.first + this.size - 1;
4690
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
4691
+ text: splitLines(code), origin: "setValue"},
4692
+ {head: top, anchor: top}, true);
4693
+ },
4694
+ replaceRange: function(code, from, to, origin) {
4695
+ from = clipPos(this, from);
4696
+ to = to ? clipPos(this, to) : from;
4697
+ replaceRange(this, code, from, to, origin);
4698
+ },
4699
+ getRange: function(from, to, lineSep) {
4700
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
4701
+ if (lineSep === false) return lines;
4702
+ return lines.join(lineSep || "\n");
4703
+ },
4704
+
4705
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
4706
+ setLine: function(line, text) {
4707
+ if (isLine(this, line))
4708
+ replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
4709
+ },
4710
+ removeLine: function(line) {
4711
+ if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
4712
+ else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
4713
+ },
4714
+
4715
+ getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4716
+ getLineNumber: function(line) {return lineNo(line);},
4717
+
4718
+ getLineHandleVisualStart: function(line) {
4719
+ if (typeof line == "number") line = getLine(this, line);
4720
+ return visualLine(this, line);
4721
+ },
4722
+
4723
+ lineCount: function() {return this.size;},
4724
+ firstLine: function() {return this.first;},
4725
+ lastLine: function() {return this.first + this.size - 1;},
4726
+
4727
+ clipPos: function(pos) {return clipPos(this, pos);},
4728
+
4729
+ getCursor: function(start) {
4730
+ var sel = this.sel, pos;
4731
+ if (start == null || start == "head") pos = sel.head;
4732
+ else if (start == "anchor") pos = sel.anchor;
4733
+ else if (start == "end" || start === false) pos = sel.to;
4734
+ else pos = sel.from;
4735
+ return copyPos(pos);
4736
+ },
4737
+ somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
4738
+
4739
+ setCursor: docOperation(function(line, ch, extend) {
4740
+ var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
4741
+ if (extend) extendSelection(this, pos);
4742
+ else setSelection(this, pos, pos);
4743
+ }),
4744
+ setSelection: docOperation(function(anchor, head) {
4745
+ setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
4746
+ }),
4747
+ extendSelection: docOperation(function(from, to) {
4748
+ extendSelection(this, clipPos(this, from), to && clipPos(this, to));
4749
+ }),
4750
+
4751
+ getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
4752
+ replaceSelection: function(code, collapse, origin) {
4753
+ makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
4754
+ },
4755
+ undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
4756
+ redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
4757
+
4758
+ setExtending: function(val) {this.sel.extend = val;},
4759
+
4760
+ historySize: function() {
4761
+ var hist = this.history;
4762
+ return {undo: hist.done.length, redo: hist.undone.length};
4763
+ },
4764
+ clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4765
+
4766
+ markClean: function() {
4767
+ this.cleanGeneration = this.changeGeneration();
4768
+ },
4769
+ changeGeneration: function() {
4770
+ this.history.lastOp = this.history.lastOrigin = null;
4771
+ return this.history.generation;
4772
+ },
4773
+ isClean: function (gen) {
4774
+ return this.history.generation == (gen || this.cleanGeneration);
4775
+ },
4776
+
4777
+ getHistory: function() {
4778
+ return {done: copyHistoryArray(this.history.done),
4779
+ undone: copyHistoryArray(this.history.undone)};
4780
+ },
4781
+ setHistory: function(histData) {
4782
+ var hist = this.history = makeHistory(this.history.maxGeneration);
4783
+ hist.done = histData.done.slice(0);
4784
+ hist.undone = histData.undone.slice(0);
4785
+ },
4786
+
4787
+ markText: function(from, to, options) {
4788
+ return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
4789
+ },
4790
+ setBookmark: function(pos, options) {
4791
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4792
+ insertLeft: options && options.insertLeft};
4793
+ pos = clipPos(this, pos);
4794
+ return markText(this, pos, pos, realOpts, "bookmark");
4795
+ },
4796
+ findMarksAt: function(pos) {
4797
+ pos = clipPos(this, pos);
4798
+ var markers = [], spans = getLine(this, pos.line).markedSpans;
4799
+ if (spans) for (var i = 0; i < spans.length; ++i) {
4800
+ var span = spans[i];
4801
+ if ((span.from == null || span.from <= pos.ch) &&
4802
+ (span.to == null || span.to >= pos.ch))
4803
+ markers.push(span.marker.parent || span.marker);
4804
+ }
4805
+ return markers;
4806
+ },
4807
+ getAllMarks: function() {
4808
+ var markers = [];
4809
+ this.iter(function(line) {
4810
+ var sps = line.markedSpans;
4811
+ if (sps) for (var i = 0; i < sps.length; ++i)
4812
+ if (sps[i].from != null) markers.push(sps[i].marker);
4813
+ });
4814
+ return markers;
4815
+ },
4816
+
4817
+ posFromIndex: function(off) {
4818
+ var ch, lineNo = this.first;
4819
+ this.iter(function(line) {
4820
+ var sz = line.text.length + 1;
4821
+ if (sz > off) { ch = off; return true; }
4822
+ off -= sz;
4823
+ ++lineNo;
4824
+ });
4825
+ return clipPos(this, Pos(lineNo, ch));
4826
+ },
4827
+ indexFromPos: function (coords) {
4828
+ coords = clipPos(this, coords);
4829
+ var index = coords.ch;
4830
+ if (coords.line < this.first || coords.ch < 0) return 0;
4831
+ this.iter(this.first, coords.line, function (line) {
4832
+ index += line.text.length + 1;
4833
+ });
4834
+ return index;
4835
+ },
4836
+
4837
+ copy: function(copyHistory) {
4838
+ var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
4839
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
4840
+ doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
4841
+ shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
4842
+ if (copyHistory) {
4843
+ doc.history.undoDepth = this.history.undoDepth;
4844
+ doc.setHistory(this.getHistory());
4845
+ }
4846
+ return doc;
4847
+ },
4848
+
4849
+ linkedDoc: function(options) {
4850
+ if (!options) options = {};
4851
+ var from = this.first, to = this.first + this.size;
4852
+ if (options.from != null && options.from > from) from = options.from;
4853
+ if (options.to != null && options.to < to) to = options.to;
4854
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
4855
+ if (options.sharedHist) copy.history = this.history;
4856
+ (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
4857
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
4858
+ return copy;
4859
+ },
4860
+ unlinkDoc: function(other) {
4861
+ if (other instanceof CodeMirror) other = other.doc;
4862
+ if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
4863
+ var link = this.linked[i];
4864
+ if (link.doc != other) continue;
4865
+ this.linked.splice(i, 1);
4866
+ other.unlinkDoc(this);
4867
+ break;
4868
+ }
4869
+ // If the histories were shared, split them again
4870
+ if (other.history == this.history) {
4871
+ var splitIds = [other.id];
4872
+ linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
4873
+ other.history = makeHistory();
4874
+ other.history.done = copyHistoryArray(this.history.done, splitIds);
4875
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds);
4876
+ }
4877
+ },
4878
+ iterLinkedDocs: function(f) {linkedDocs(this, f);},
4879
+
4880
+ getMode: function() {return this.mode;},
4881
+ getEditor: function() {return this.cm;}
4882
+ });
4883
+
4884
+ Doc.prototype.eachLine = Doc.prototype.iter;
4885
+
4886
+ // The Doc methods that should be available on CodeMirror instances
4887
+ var dontDelegate = "iter insert remove copy getEditor".split(" ");
4888
+ for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
4889
+ CodeMirror.prototype[prop] = (function(method) {
4890
+ return function() {return method.apply(this.doc, arguments);};
4891
+ })(Doc.prototype[prop]);
4892
+
4893
+ eventMixin(Doc);
4894
+
4895
+ function linkedDocs(doc, f, sharedHistOnly) {
4896
+ function propagate(doc, skip, sharedHist) {
4897
+ if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
4898
+ var rel = doc.linked[i];
4899
+ if (rel.doc == skip) continue;
4900
+ var shared = sharedHist && rel.sharedHist;
4901
+ if (sharedHistOnly && !shared) continue;
4902
+ f(rel.doc, shared);
4903
+ propagate(rel.doc, doc, shared);
4904
+ }
4905
+ }
4906
+ propagate(doc, null, true);
4907
+ }
4908
+
4909
+ function attachDoc(cm, doc) {
4910
+ if (doc.cm) throw new Error("This document is already in use.");
4911
+ cm.doc = doc;
4912
+ doc.cm = cm;
4913
+ estimateLineHeights(cm);
4914
+ loadMode(cm);
4915
+ if (!cm.options.lineWrapping) computeMaxLength(cm);
4916
+ cm.options.mode = doc.modeOption;
4917
+ regChange(cm);
4918
+ }
4919
+
4920
+ // LINE UTILITIES
4921
+
4922
+ function getLine(chunk, n) {
4923
+ n -= chunk.first;
4924
+ while (!chunk.lines) {
4925
+ for (var i = 0;; ++i) {
4926
+ var child = chunk.children[i], sz = child.chunkSize();
4927
+ if (n < sz) { chunk = child; break; }
4928
+ n -= sz;
4929
+ }
4930
+ }
4931
+ return chunk.lines[n];
4932
+ }
4933
+
4934
+ function getBetween(doc, start, end) {
4935
+ var out = [], n = start.line;
4936
+ doc.iter(start.line, end.line + 1, function(line) {
4937
+ var text = line.text;
4938
+ if (n == end.line) text = text.slice(0, end.ch);
4939
+ if (n == start.line) text = text.slice(start.ch);
4940
+ out.push(text);
4941
+ ++n;
4942
+ });
4943
+ return out;
4944
+ }
4945
+ function getLines(doc, from, to) {
4946
+ var out = [];
4947
+ doc.iter(from, to, function(line) { out.push(line.text); });
4948
+ return out;
4949
+ }
4950
+
4951
+ function updateLineHeight(line, height) {
4952
+ var diff = height - line.height;
4953
+ for (var n = line; n; n = n.parent) n.height += diff;
4954
+ }
4955
+
4956
+ function lineNo(line) {
4957
+ if (line.parent == null) return null;
4958
+ var cur = line.parent, no = indexOf(cur.lines, line);
4959
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
4960
+ for (var i = 0;; ++i) {
4961
+ if (chunk.children[i] == cur) break;
4962
+ no += chunk.children[i].chunkSize();
4963
+ }
4964
+ }
4965
+ return no + cur.first;
4966
+ }
4967
+
4968
+ function lineAtHeight(chunk, h) {
4969
+ var n = chunk.first;
4970
+ outer: do {
4971
+ for (var i = 0, e = chunk.children.length; i < e; ++i) {
4972
+ var child = chunk.children[i], ch = child.height;
4973
+ if (h < ch) { chunk = child; continue outer; }
4974
+ h -= ch;
4975
+ n += child.chunkSize();
4976
+ }
4977
+ return n;
4978
+ } while (!chunk.lines);
4979
+ for (var i = 0, e = chunk.lines.length; i < e; ++i) {
4980
+ var line = chunk.lines[i], lh = line.height;
4981
+ if (h < lh) break;
4982
+ h -= lh;
4983
+ }
4984
+ return n + i;
4985
+ }
4986
+
4987
+ function heightAtLine(cm, lineObj) {
4988
+ lineObj = visualLine(cm.doc, lineObj);
4989
+
4990
+ var h = 0, chunk = lineObj.parent;
4991
+ for (var i = 0; i < chunk.lines.length; ++i) {
4992
+ var line = chunk.lines[i];
4993
+ if (line == lineObj) break;
4994
+ else h += line.height;
4995
+ }
4996
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
4997
+ for (var i = 0; i < p.children.length; ++i) {
4998
+ var cur = p.children[i];
4999
+ if (cur == chunk) break;
5000
+ else h += cur.height;
5001
+ }
5002
+ }
5003
+ return h;
5004
+ }
5005
+
5006
+ function getOrder(line) {
5007
+ var order = line.order;
5008
+ if (order == null) order = line.order = bidiOrdering(line.text);
5009
+ return order;
5010
+ }
5011
+
5012
+ // HISTORY
5013
+
5014
+ function makeHistory(startGen) {
5015
+ return {
5016
+ // Arrays of history events. Doing something adds an event to
5017
+ // done and clears undo. Undoing moves events from done to
5018
+ // undone, redoing moves them in the other direction.
5019
+ done: [], undone: [], undoDepth: Infinity,
5020
+ // Used to track when changes can be merged into a single undo
5021
+ // event
5022
+ lastTime: 0, lastOp: null, lastOrigin: null,
5023
+ // Used by the isClean() method
5024
+ generation: startGen || 1, maxGeneration: startGen || 1
5025
+ };
5026
+ }
5027
+
5028
+ function attachLocalSpans(doc, change, from, to) {
5029
+ var existing = change["spans_" + doc.id], n = 0;
5030
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
5031
+ if (line.markedSpans)
5032
+ (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
5033
+ ++n;
5034
+ });
5035
+ }
5036
+
5037
+ function historyChangeFromChange(doc, change) {
5038
+ var from = { line: change.from.line, ch: change.from.ch };
5039
+ var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5040
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
5041
+ linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
5042
+ return histChange;
5043
+ }
5044
+
5045
+ function addToHistory(doc, change, selAfter, opId) {
5046
+ var hist = doc.history;
5047
+ hist.undone.length = 0;
5048
+ var time = +new Date, cur = lst(hist.done);
5049
+
5050
+ if (cur &&
5051
+ (hist.lastOp == opId ||
5052
+ hist.lastOrigin == change.origin && change.origin &&
5053
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
5054
+ change.origin.charAt(0) == "*"))) {
5055
+ // Merge this change into the last event
5056
+ var last = lst(cur.changes);
5057
+ if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
5058
+ // Optimized case for simple insertion -- don't want to add
5059
+ // new changesets for every character typed
5060
+ last.to = changeEnd(change);
5061
+ } else {
5062
+ // Add new sub-event
5063
+ cur.changes.push(historyChangeFromChange(doc, change));
5064
+ }
5065
+ cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
5066
+ } else {
5067
+ // Can not be merged, start a new event.
5068
+ cur = {changes: [historyChangeFromChange(doc, change)],
5069
+ generation: hist.generation,
5070
+ anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5071
+ anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5072
+ hist.done.push(cur);
5073
+ hist.generation = ++hist.maxGeneration;
5074
+ while (hist.done.length > hist.undoDepth)
5075
+ hist.done.shift();
5076
+ }
5077
+ hist.lastTime = time;
5078
+ hist.lastOp = opId;
5079
+ hist.lastOrigin = change.origin;
5080
+ }
5081
+
5082
+ function removeClearedSpans(spans) {
5083
+ if (!spans) return null;
5084
+ for (var i = 0, out; i < spans.length; ++i) {
5085
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
5086
+ else if (out) out.push(spans[i]);
5087
+ }
5088
+ return !out ? spans : out.length ? out : null;
5089
+ }
5090
+
5091
+ function getOldSpans(doc, change) {
5092
+ var found = change["spans_" + doc.id];
5093
+ if (!found) return null;
5094
+ for (var i = 0, nw = []; i < change.text.length; ++i)
5095
+ nw.push(removeClearedSpans(found[i]));
5096
+ return nw;
5097
+ }
5098
+
5099
+ // Used both to provide a JSON-safe object in .getHistory, and, when
5100
+ // detaching a document, to split the history in two
5101
+ function copyHistoryArray(events, newGroup) {
5102
+ for (var i = 0, copy = []; i < events.length; ++i) {
5103
+ var event = events[i], changes = event.changes, newChanges = [];
5104
+ copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
5105
+ anchorAfter: event.anchorAfter, headAfter: event.headAfter});
5106
+ for (var j = 0; j < changes.length; ++j) {
5107
+ var change = changes[j], m;
5108
+ newChanges.push({from: change.from, to: change.to, text: change.text});
5109
+ if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
5110
+ if (indexOf(newGroup, Number(m[1])) > -1) {
5111
+ lst(newChanges)[prop] = change[prop];
5112
+ delete change[prop];
5113
+ }
5114
+ }
5115
+ }
5116
+ }
5117
+ return copy;
5118
+ }
5119
+
5120
+ // Rebasing/resetting history to deal with externally-sourced changes
5121
+
5122
+ function rebaseHistSel(pos, from, to, diff) {
5123
+ if (to < pos.line) {
5124
+ pos.line += diff;
5125
+ } else if (from < pos.line) {
5126
+ pos.line = from;
5127
+ pos.ch = 0;
5128
+ }
5129
+ }
5130
+
5131
+ // Tries to rebase an array of history events given a change in the
5132
+ // document. If the change touches the same lines as the event, the
5133
+ // event, and everything 'behind' it, is discarded. If the change is
5134
+ // before the event, the event's positions are updated. Uses a
5135
+ // copy-on-write scheme for the positions, to avoid having to
5136
+ // reallocate them all on every rebase, but also avoid problems with
5137
+ // shared position objects being unsafely updated.
5138
+ function rebaseHistArray(array, from, to, diff) {
5139
+ for (var i = 0; i < array.length; ++i) {
5140
+ var sub = array[i], ok = true;
5141
+ for (var j = 0; j < sub.changes.length; ++j) {
5142
+ var cur = sub.changes[j];
5143
+ if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
5144
+ if (to < cur.from.line) {
5145
+ cur.from.line += diff;
5146
+ cur.to.line += diff;
5147
+ } else if (from <= cur.to.line) {
5148
+ ok = false;
5149
+ break;
5150
+ }
5151
+ }
5152
+ if (!sub.copied) {
5153
+ sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
5154
+ sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
5155
+ sub.copied = true;
5156
+ }
5157
+ if (!ok) {
5158
+ array.splice(0, i + 1);
5159
+ i = 0;
5160
+ } else {
5161
+ rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
5162
+ rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
5163
+ }
5164
+ }
5165
+ }
5166
+
5167
+ function rebaseHist(hist, change) {
5168
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5169
+ rebaseHistArray(hist.done, from, to, diff);
5170
+ rebaseHistArray(hist.undone, from, to, diff);
5171
+ }
5172
+
5173
+ // EVENT OPERATORS
5174
+
5175
+ function stopMethod() {e_stop(this);}
5176
+ // Ensure an event has a stop method.
5177
+ function addStop(event) {
5178
+ if (!event.stop) event.stop = stopMethod;
5179
+ return event;
5180
+ }
5181
+
5182
+ function e_preventDefault(e) {
5183
+ if (e.preventDefault) e.preventDefault();
5184
+ else e.returnValue = false;
5185
+ }
5186
+ function e_stopPropagation(e) {
5187
+ if (e.stopPropagation) e.stopPropagation();
5188
+ else e.cancelBubble = true;
5189
+ }
5190
+ function e_defaultPrevented(e) {
5191
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5192
+ }
5193
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5194
+ CodeMirror.e_stop = e_stop;
5195
+ CodeMirror.e_preventDefault = e_preventDefault;
5196
+ CodeMirror.e_stopPropagation = e_stopPropagation;
5197
+
5198
+ function e_target(e) {return e.target || e.srcElement;}
5199
+ function e_button(e) {
5200
+ var b = e.which;
5201
+ if (b == null) {
5202
+ if (e.button & 1) b = 1;
5203
+ else if (e.button & 2) b = 3;
5204
+ else if (e.button & 4) b = 2;
5205
+ }
5206
+ if (mac && e.ctrlKey && b == 1) b = 3;
5207
+ return b;
5208
+ }
5209
+
5210
+ // EVENT HANDLING
5211
+
5212
+ function on(emitter, type, f) {
5213
+ if (emitter.addEventListener)
5214
+ emitter.addEventListener(type, f, false);
5215
+ else if (emitter.attachEvent)
5216
+ emitter.attachEvent("on" + type, f);
5217
+ else {
5218
+ var map = emitter._handlers || (emitter._handlers = {});
5219
+ var arr = map[type] || (map[type] = []);
5220
+ arr.push(f);
5221
+ }
5222
+ }
5223
+
5224
+ function off(emitter, type, f) {
5225
+ if (emitter.removeEventListener)
5226
+ emitter.removeEventListener(type, f, false);
5227
+ else if (emitter.detachEvent)
5228
+ emitter.detachEvent("on" + type, f);
5229
+ else {
5230
+ var arr = emitter._handlers && emitter._handlers[type];
5231
+ if (!arr) return;
5232
+ for (var i = 0; i < arr.length; ++i)
5233
+ if (arr[i] == f) { arr.splice(i, 1); break; }
5234
+ }
5235
+ }
5236
+
5237
+ function signal(emitter, type /*, values...*/) {
5238
+ var arr = emitter._handlers && emitter._handlers[type];
5239
+ if (!arr) return;
5240
+ var args = Array.prototype.slice.call(arguments, 2);
5241
+ for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
5242
+ }
5243
+
5244
+ var delayedCallbacks, delayedCallbackDepth = 0;
5245
+ function signalLater(emitter, type /*, values...*/) {
5246
+ var arr = emitter._handlers && emitter._handlers[type];
5247
+ if (!arr) return;
5248
+ var args = Array.prototype.slice.call(arguments, 2);
5249
+ if (!delayedCallbacks) {
5250
+ ++delayedCallbackDepth;
5251
+ delayedCallbacks = [];
5252
+ setTimeout(fireDelayed, 0);
5253
+ }
5254
+ function bnd(f) {return function(){f.apply(null, args);};};
5255
+ for (var i = 0; i < arr.length; ++i)
5256
+ delayedCallbacks.push(bnd(arr[i]));
5257
+ }
5258
+
5259
+ function signalDOMEvent(cm, e, override) {
5260
+ signal(cm, override || e.type, cm, e);
5261
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
5262
+ }
5263
+
5264
+ function fireDelayed() {
5265
+ --delayedCallbackDepth;
5266
+ var delayed = delayedCallbacks;
5267
+ delayedCallbacks = null;
5268
+ for (var i = 0; i < delayed.length; ++i) delayed[i]();
5269
+ }
5270
+
5271
+ function hasHandler(emitter, type) {
5272
+ var arr = emitter._handlers && emitter._handlers[type];
5273
+ return arr && arr.length > 0;
5274
+ }
5275
+
5276
+ CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
5277
+
5278
+ function eventMixin(ctor) {
5279
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
5280
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
5281
+ }
5282
+
5283
+ // MISC UTILITIES
5284
+
5285
+ // Number of pixels added to scroller and sizer to hide scrollbar
5286
+ var scrollerCutOff = 30;
5287
+
5288
+ // Returned or thrown by various protocols to signal 'I'm not
5289
+ // handling this'.
5290
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
5291
+
5292
+ function Delayed() {this.id = null;}
5293
+ Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
5294
+
5295
+ // Counts the column offset in a string, taking tabs into account.
5296
+ // Used mostly to find indentation.
5297
+ function countColumn(string, end, tabSize, startIndex, startValue) {
5298
+ if (end == null) {
5299
+ end = string.search(/[^\s\u00a0]/);
5300
+ if (end == -1) end = string.length;
5301
+ }
5302
+ for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
5303
+ if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
5304
+ else ++n;
5305
+ }
5306
+ return n;
5307
+ }
5308
+ CodeMirror.countColumn = countColumn;
5309
+
5310
+ var spaceStrs = [""];
5311
+ function spaceStr(n) {
5312
+ while (spaceStrs.length <= n)
5313
+ spaceStrs.push(lst(spaceStrs) + " ");
5314
+ return spaceStrs[n];
5315
+ }
5316
+
5317
+ function lst(arr) { return arr[arr.length-1]; }
5318
+
5319
+ function selectInput(node) {
5320
+ if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5321
+ node.selectionStart = 0;
5322
+ node.selectionEnd = node.value.length;
5323
+ } else {
5324
+ // Suppress mysterious IE10 errors
5325
+ try { node.select(); }
5326
+ catch(_e) {}
5327
+ }
5328
+ }
5329
+
5330
+ function indexOf(collection, elt) {
5331
+ if (collection.indexOf) return collection.indexOf(elt);
5332
+ for (var i = 0, e = collection.length; i < e; ++i)
5333
+ if (collection[i] == elt) return i;
5334
+ return -1;
5335
+ }
5336
+
5337
+ function createObj(base, props) {
5338
+ function Obj() {}
5339
+ Obj.prototype = base;
5340
+ var inst = new Obj();
5341
+ if (props) copyObj(props, inst);
5342
+ return inst;
5343
+ }
5344
+
5345
+ function copyObj(obj, target) {
5346
+ if (!target) target = {};
5347
+ for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
5348
+ return target;
5349
+ }
5350
+
5351
+ function emptyArray(size) {
5352
+ for (var a = [], i = 0; i < size; ++i) a.push(undefined);
5353
+ return a;
5354
+ }
5355
+
5356
+ function bind(f) {
5357
+ var args = Array.prototype.slice.call(arguments, 1);
5358
+ return function(){return f.apply(null, args);};
5359
+ }
5360
+
5361
+ var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
5362
+ function isWordChar(ch) {
5363
+ return /\w/.test(ch) || ch > "\x80" &&
5364
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
5365
+ }
5366
+
5367
+ function isEmpty(obj) {
5368
+ for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
5369
+ return true;
5370
+ }
5371
+
5372
+ var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
5373
+
5374
+ // DOM UTILITIES
5375
+
5376
+ function elt(tag, content, className, style) {
5377
+ var e = document.createElement(tag);
5378
+ if (className) e.className = className;
5379
+ if (style) e.style.cssText = style;
5380
+ if (typeof content == "string") setTextContent(e, content);
5381
+ else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
5382
+ return e;
5383
+ }
5384
+
5385
+ function removeChildren(e) {
5386
+ for (var count = e.childNodes.length; count > 0; --count)
5387
+ e.removeChild(e.firstChild);
5388
+ return e;
5389
+ }
5390
+
5391
+ function removeChildrenAndAdd(parent, e) {
5392
+ return removeChildren(parent).appendChild(e);
5393
+ }
5394
+
5395
+ function setTextContent(e, str) {
5396
+ if (ie_lt9) {
5397
+ e.innerHTML = "";
5398
+ e.appendChild(document.createTextNode(str));
5399
+ } else e.textContent = str;
5400
+ }
5401
+
5402
+ function getRect(node) {
5403
+ return node.getBoundingClientRect();
5404
+ }
5405
+ CodeMirror.replaceGetRect = function(f) { getRect = f; };
5406
+
5407
+ // FEATURE DETECTION
5408
+
5409
+ // Detect drag-and-drop
5410
+ var dragAndDrop = function() {
5411
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
5412
+ // couldn't get it to work yet.
5413
+ if (ie_lt9) return false;
5414
+ var div = elt('div');
5415
+ return "draggable" in div || "dragDrop" in div;
5416
+ }();
5417
+
5418
+ // For a reason I have yet to figure out, some browsers disallow
5419
+ // word wrapping between certain characters *only* if a new inline
5420
+ // element is started between them. This makes it hard to reliably
5421
+ // measure the position of things, since that requires inserting an
5422
+ // extra span. This terribly fragile set of tests matches the
5423
+ // character combinations that suffer from this phenomenon on the
5424
+ // various browsers.
5425
+ function spanAffectsWrapping() { return false; }
5426
+ if (gecko) // Only for "$'"
5427
+ spanAffectsWrapping = function(str, i) {
5428
+ return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
5429
+ };
5430
+ else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
5431
+ spanAffectsWrapping = function(str, i) {
5432
+ return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5433
+ };
5434
+ else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
5435
+ spanAffectsWrapping = function(str, i) {
5436
+ if (i > 1 && str.charCodeAt(i - 1) == 45) {
5437
+ if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5438
+ if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5439
+ }
5440
+ return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5441
+ };
5442
+
5443
+ var knownScrollbarWidth;
5444
+ function scrollbarWidth(measure) {
5445
+ if (knownScrollbarWidth != null) return knownScrollbarWidth;
5446
+ var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
5447
+ removeChildrenAndAdd(measure, test);
5448
+ if (test.offsetWidth)
5449
+ knownScrollbarWidth = test.offsetHeight - test.clientHeight;
5450
+ return knownScrollbarWidth || 0;
5451
+ }
5452
+
5453
+ var zwspSupported;
5454
+ function zeroWidthElement(measure) {
5455
+ if (zwspSupported == null) {
5456
+ var test = elt("span", "\u200b");
5457
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
5458
+ if (measure.firstChild.offsetHeight != 0)
5459
+ zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
5460
+ }
5461
+ if (zwspSupported) return elt("span", "\u200b");
5462
+ else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
5463
+ }
5464
+
5465
+ // See if "".split is the broken IE version, if so, provide an
5466
+ // alternative way to split lines.
5467
+ var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
5468
+ var pos = 0, result = [], l = string.length;
5469
+ while (pos <= l) {
5470
+ var nl = string.indexOf("\n", pos);
5471
+ if (nl == -1) nl = string.length;
5472
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
5473
+ var rt = line.indexOf("\r");
5474
+ if (rt != -1) {
5475
+ result.push(line.slice(0, rt));
5476
+ pos += rt + 1;
5477
+ } else {
5478
+ result.push(line);
5479
+ pos = nl + 1;
5480
+ }
5481
+ }
5482
+ return result;
5483
+ } : function(string){return string.split(/\r\n?|\n/);};
5484
+ CodeMirror.splitLines = splitLines;
5485
+
5486
+ var hasSelection = window.getSelection ? function(te) {
5487
+ try { return te.selectionStart != te.selectionEnd; }
5488
+ catch(e) { return false; }
5489
+ } : function(te) {
5490
+ try {var range = te.ownerDocument.selection.createRange();}
5491
+ catch(e) {}
5492
+ if (!range || range.parentElement() != te) return false;
5493
+ return range.compareEndPoints("StartToEnd", range) != 0;
5494
+ };
5495
+
5496
+ var hasCopyEvent = (function() {
5497
+ var e = elt("div");
5498
+ if ("oncopy" in e) return true;
5499
+ e.setAttribute("oncopy", "return;");
5500
+ return typeof e.oncopy == 'function';
5501
+ })();
5502
+
5503
+ // KEY NAMING
5504
+
5505
+ var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
5506
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
5507
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
5508
+ 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
5509
+ 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5510
+ 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
5511
+ 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
5512
+ CodeMirror.keyNames = keyNames;
5513
+ (function() {
5514
+ // Number keys
5515
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
5516
+ // Alphabetic keys
5517
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
5518
+ // Function keys
5519
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
5520
+ })();
5521
+
5522
+ // BIDI HELPERS
5523
+
5524
+ function iterateBidiSections(order, from, to, f) {
5525
+ if (!order) return f(from, to, "ltr");
5526
+ var found = false;
5527
+ for (var i = 0; i < order.length; ++i) {
5528
+ var part = order[i];
5529
+ if (part.from < to && part.to > from || from == to && part.to == from) {
5530
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5531
+ found = true;
5532
+ }
5533
+ }
5534
+ if (!found) f(from, to, "ltr");
5535
+ }
5536
+
5537
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
5538
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
5539
+
5540
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
5541
+ function lineRight(line) {
5542
+ var order = getOrder(line);
5543
+ if (!order) return line.text.length;
5544
+ return bidiRight(lst(order));
5545
+ }
5546
+
5547
+ function lineStart(cm, lineN) {
5548
+ var line = getLine(cm.doc, lineN);
5549
+ var visual = visualLine(cm.doc, line);
5550
+ if (visual != line) lineN = lineNo(visual);
5551
+ var order = getOrder(visual);
5552
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
5553
+ return Pos(lineN, ch);
5554
+ }
5555
+ function lineEnd(cm, lineN) {
5556
+ var merged, line;
5557
+ while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
5558
+ lineN = merged.find().to.line;
5559
+ var order = getOrder(line);
5560
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
5561
+ return Pos(lineN, ch);
5562
+ }
5563
+
5564
+ function compareBidiLevel(order, a, b) {
5565
+ var linedir = order[0].level;
5566
+ if (a == linedir) return true;
5567
+ if (b == linedir) return false;
5568
+ return a < b;
5569
+ }
5570
+ var bidiOther;
5571
+ function getBidiPartAt(order, pos) {
5572
+ for (var i = 0, found; i < order.length; ++i) {
5573
+ var cur = order[i];
5574
+ if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5575
+ if (cur.from == pos || cur.to == pos) {
5576
+ if (found == null) {
5577
+ found = i;
5578
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5579
+ bidiOther = found;
5580
+ return i;
5581
+ } else {
5582
+ bidiOther = i;
5583
+ return found;
5584
+ }
5585
+ }
5586
+ }
5587
+ bidiOther = null;
5588
+ return found;
5589
+ }
5590
+
5591
+ function moveInLine(line, pos, dir, byUnit) {
5592
+ if (!byUnit) return pos + dir;
5593
+ do pos += dir;
5594
+ while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5595
+ return pos;
5596
+ }
5597
+
5598
+ // This is somewhat involved. It is needed in order to move
5599
+ // 'visually' through bi-directional text -- i.e., pressing left
5600
+ // should make the cursor go left, even when in RTL text. The
5601
+ // tricky part is the 'jumps', where RTL and LTR text touch each
5602
+ // other. This often requires the cursor offset to move more than
5603
+ // one unit, in order to visually move one unit.
5604
+ function moveVisually(line, start, dir, byUnit) {
5605
+ var bidi = getOrder(line);
5606
+ if (!bidi) return moveLogically(line, start, dir, byUnit);
5607
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5608
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5609
+
5610
+ for (;;) {
5611
+ if (target > part.from && target < part.to) return target;
5612
+ if (target == part.from || target == part.to) {
5613
+ if (getBidiPartAt(bidi, target) == pos) return target;
5614
+ part = bidi[pos += dir];
5615
+ return (dir > 0) == part.level % 2 ? part.to : part.from;
5616
+ } else {
5617
+ part = bidi[pos += dir];
5618
+ if (!part) return null;
5619
+ if ((dir > 0) == part.level % 2)
5620
+ target = moveInLine(line, part.to, -1, byUnit);
5621
+ else
5622
+ target = moveInLine(line, part.from, 1, byUnit);
5623
+ }
5624
+ }
5625
+ }
5626
+
5627
+ function moveLogically(line, start, dir, byUnit) {
5628
+ var target = start + dir;
5629
+ if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
5630
+ return target < 0 || target > line.text.length ? null : target;
5631
+ }
5632
+
5633
+ // Bidirectional ordering algorithm
5634
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
5635
+ // that this (partially) implements.
5636
+
5637
+ // One-char codes used for character types:
5638
+ // L (L): Left-to-Right
5639
+ // R (R): Right-to-Left
5640
+ // r (AL): Right-to-Left Arabic
5641
+ // 1 (EN): European Number
5642
+ // + (ES): European Number Separator
5643
+ // % (ET): European Number Terminator
5644
+ // n (AN): Arabic Number
5645
+ // , (CS): Common Number Separator
5646
+ // m (NSM): Non-Spacing Mark
5647
+ // b (BN): Boundary Neutral
5648
+ // s (B): Paragraph Separator
5649
+ // t (S): Segment Separator
5650
+ // w (WS): Whitespace
5651
+ // N (ON): Other Neutrals
5652
+
5653
+ // Returns null if characters are ordered as they appear
5654
+ // (left-to-right), or an array of sections ({from, to, level}
5655
+ // objects) in the order in which they occur visually.
5656
+ var bidiOrdering = (function() {
5657
+ // Character types for codepoints 0 to 0xff
5658
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
5659
+ // Character types for codepoints 0x600 to 0x6ff
5660
+ var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
5661
+ function charType(code) {
5662
+ if (code <= 0xff) return lowTypes.charAt(code);
5663
+ else if (0x590 <= code && code <= 0x5f4) return "R";
5664
+ else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
5665
+ else if (0x700 <= code && code <= 0x8ac) return "r";
5666
+ else return "L";
5667
+ }
5668
+
5669
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
5670
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
5671
+ // Browsers seem to always treat the boundaries of block elements as being L.
5672
+ var outerType = "L";
5673
+
5674
+ return function(str) {
5675
+ if (!bidiRE.test(str)) return false;
5676
+ var len = str.length, types = [];
5677
+ for (var i = 0, type; i < len; ++i)
5678
+ types.push(type = charType(str.charCodeAt(i)));
5679
+
5680
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
5681
+ // change the type of the NSM to the type of the previous
5682
+ // character. If the NSM is at the start of the level run, it will
5683
+ // get the type of sor.
5684
+ for (var i = 0, prev = outerType; i < len; ++i) {
5685
+ var type = types[i];
5686
+ if (type == "m") types[i] = prev;
5687
+ else prev = type;
5688
+ }
5689
+
5690
+ // W2. Search backwards from each instance of a European number
5691
+ // until the first strong type (R, L, AL, or sor) is found. If an
5692
+ // AL is found, change the type of the European number to Arabic
5693
+ // number.
5694
+ // W3. Change all ALs to R.
5695
+ for (var i = 0, cur = outerType; i < len; ++i) {
5696
+ var type = types[i];
5697
+ if (type == "1" && cur == "r") types[i] = "n";
5698
+ else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
5699
+ }
5700
+
5701
+ // W4. A single European separator between two European numbers
5702
+ // changes to a European number. A single common separator between
5703
+ // two numbers of the same type changes to that type.
5704
+ for (var i = 1, prev = types[0]; i < len - 1; ++i) {
5705
+ var type = types[i];
5706
+ if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
5707
+ else if (type == "," && prev == types[i+1] &&
5708
+ (prev == "1" || prev == "n")) types[i] = prev;
5709
+ prev = type;
5710
+ }
5711
+
5712
+ // W5. A sequence of European terminators adjacent to European
5713
+ // numbers changes to all European numbers.
5714
+ // W6. Otherwise, separators and terminators change to Other
5715
+ // Neutral.
5716
+ for (var i = 0; i < len; ++i) {
5717
+ var type = types[i];
5718
+ if (type == ",") types[i] = "N";
5719
+ else if (type == "%") {
5720
+ for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
5721
+ var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
5722
+ for (var j = i; j < end; ++j) types[j] = replace;
5723
+ i = end - 1;
5724
+ }
5725
+ }
5726
+
5727
+ // W7. Search backwards from each instance of a European number
5728
+ // until the first strong type (R, L, or sor) is found. If an L is
5729
+ // found, then change the type of the European number to L.
5730
+ for (var i = 0, cur = outerType; i < len; ++i) {
5731
+ var type = types[i];
5732
+ if (cur == "L" && type == "1") types[i] = "L";
5733
+ else if (isStrong.test(type)) cur = type;
5734
+ }
5735
+
5736
+ // N1. A sequence of neutrals takes the direction of the
5737
+ // surrounding strong text if the text on both sides has the same
5738
+ // direction. European and Arabic numbers act as if they were R in
5739
+ // terms of their influence on neutrals. Start-of-level-run (sor)
5740
+ // and end-of-level-run (eor) are used at level run boundaries.
5741
+ // N2. Any remaining neutrals take the embedding direction.
5742
+ for (var i = 0; i < len; ++i) {
5743
+ if (isNeutral.test(types[i])) {
5744
+ for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5745
+ var before = (i ? types[i-1] : outerType) == "L";
5746
+ var after = (end < len - 1 ? types[end] : outerType) == "L";
5747
+ var replace = before || after ? "L" : "R";
5748
+ for (var j = i; j < end; ++j) types[j] = replace;
5749
+ i = end - 1;
5750
+ }
5751
+ }
5752
+
5753
+ // Here we depart from the documented algorithm, in order to avoid
5754
+ // building up an actual levels array. Since there are only three
5755
+ // levels (0, 1, 2) in an implementation that doesn't take
5756
+ // explicit embedding into account, we can build up the order on
5757
+ // the fly, without following the level-based algorithm.
5758
+ var order = [], m;
5759
+ for (var i = 0; i < len;) {
5760
+ if (countsAsLeft.test(types[i])) {
5761
+ var start = i;
5762
+ for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
5763
+ order.push({from: start, to: i, level: 0});
5764
+ } else {
5765
+ var pos = i, at = order.length;
5766
+ for (++i; i < len && types[i] != "L"; ++i) {}
5767
+ for (var j = pos; j < i;) {
5768
+ if (countsAsNum.test(types[j])) {
5769
+ if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
5770
+ var nstart = j;
5771
+ for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
5772
+ order.splice(at, 0, {from: nstart, to: j, level: 2});
5773
+ pos = j;
5774
+ } else ++j;
5775
+ }
5776
+ if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
5777
+ }
5778
+ }
5779
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
5780
+ order[0].from = m[0].length;
5781
+ order.unshift({from: 0, to: m[0].length, level: 0});
5782
+ }
5783
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
5784
+ lst(order).to -= m[0].length;
5785
+ order.push({from: len - m[0].length, to: len, level: 0});
5786
+ }
5787
+ if (order[0].level != lst(order).level)
5788
+ order.push({from: len, to: len, level: order[0].level});
5789
+
5790
+ return order;
5791
+ };
5792
+ })();
5793
+
5794
+ // THE END
5795
+
5796
+ CodeMirror.version = "3.15.0";
5797
+
5798
+ return CodeMirror;
5799
+ })();
plugin-fw/assets/js/codemirror/javascript.js ADDED
@@ -0,0 +1,630 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // TODO actually recognize syntax of TypeScript constructs
2
+
3
+ CodeMirror.defineMode("javascript", function(config, parserConfig) {
4
+ var indentUnit = config.indentUnit;
5
+ var statementIndent = parserConfig.statementIndent;
6
+ var jsonMode = parserConfig.json;
7
+ var isTS = parserConfig.typescript;
8
+
9
+ // Tokenizer
10
+
11
+ var keywords = function(){
12
+ function kw(type) {return {type: type, style: "keyword"};}
13
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
14
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
15
+
16
+ var jsKeywords = {
17
+ "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
18
+ "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
19
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
20
+ "function": kw("function"), "catch": kw("catch"),
21
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
22
+ "in": operator, "typeof": operator, "instanceof": operator,
23
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
24
+ "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
25
+ "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
26
+ };
27
+
28
+ // Extend the 'normal' keywords with the TypeScript language extensions
29
+ if (isTS) {
30
+ var type = {type: "variable", style: "variable-3"};
31
+ var tsKeywords = {
32
+ // object-like things
33
+ "interface": kw("interface"),
34
+ "extends": kw("extends"),
35
+ "constructor": kw("constructor"),
36
+
37
+ // scope modifiers
38
+ "public": kw("public"),
39
+ "private": kw("private"),
40
+ "protected": kw("protected"),
41
+ "static": kw("static"),
42
+
43
+ // types
44
+ "string": type, "number": type, "bool": type, "any": type
45
+ };
46
+
47
+ for (var attr in tsKeywords) {
48
+ jsKeywords[attr] = tsKeywords[attr];
49
+ }
50
+ }
51
+
52
+ return jsKeywords;
53
+ }();
54
+
55
+ var isOperatorChar = /[+\-*&%=<>!?|~^]/;
56
+
57
+ function readRegexp(stream) {
58
+ var escaped = false, next, inSet = false;
59
+ while ((next = stream.next()) != null) {
60
+ if (!escaped) {
61
+ if (next == "/" && !inSet) return;
62
+ if (next == "[") inSet = true;
63
+ else if (inSet && next == "]") inSet = false;
64
+ }
65
+ escaped = !escaped && next == "\\";
66
+ }
67
+ }
68
+
69
+ // Used as scratch variables to communicate multiple values without
70
+ // consing up tons of objects.
71
+ var type, content;
72
+ function ret(tp, style, cont) {
73
+ type = tp; content = cont;
74
+ return style;
75
+ }
76
+ function tokenBase(stream, state) {
77
+ var ch = stream.next();
78
+ if (ch == '"' || ch == "'") {
79
+ state.tokenize = tokenString(ch);
80
+ return state.tokenize(stream, state);
81
+ } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
82
+ return ret("number", "number");
83
+ } else if (ch == "." && stream.match("..")) {
84
+ return ret("spread", "meta");
85
+ } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
86
+ return ret(ch);
87
+ } else if (ch == "=" && stream.eat(">")) {
88
+ return ret("=>", "operator");
89
+ } else if (ch == "0" && stream.eat(/x/i)) {
90
+ stream.eatWhile(/[\da-f]/i);
91
+ return ret("number", "number");
92
+ } else if (/\d/.test(ch)) {
93
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
94
+ return ret("number", "number");
95
+ } else if (ch == "/") {
96
+ if (stream.eat("*")) {
97
+ state.tokenize = tokenComment;
98
+ return tokenComment(stream, state);
99
+ } else if (stream.eat("/")) {
100
+ stream.skipToEnd();
101
+ return ret("comment", "comment");
102
+ } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
103
+ state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
104
+ readRegexp(stream);
105
+ stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
106
+ return ret("regexp", "string-2");
107
+ } else {
108
+ stream.eatWhile(isOperatorChar);
109
+ return ret("operator", "operator", stream.current());
110
+ }
111
+ } else if (ch == "`") {
112
+ state.tokenize = tokenQuasi;
113
+ return tokenQuasi(stream, state);
114
+ } else if (ch == "#") {
115
+ stream.skipToEnd();
116
+ return ret("error", "error");
117
+ } else if (isOperatorChar.test(ch)) {
118
+ stream.eatWhile(isOperatorChar);
119
+ return ret("operator", "operator", stream.current());
120
+ } else {
121
+ stream.eatWhile(/[\w\$_]/);
122
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
123
+ return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
124
+ ret("variable", "variable", word);
125
+ }
126
+ }
127
+
128
+ function tokenString(quote) {
129
+ return function(stream, state) {
130
+ var escaped = false, next;
131
+ while ((next = stream.next()) != null) {
132
+ if (next == quote && !escaped) break;
133
+ escaped = !escaped && next == "\\";
134
+ }
135
+ if (!escaped) state.tokenize = tokenBase;
136
+ return ret("string", "string");
137
+ };
138
+ }
139
+
140
+ function tokenComment(stream, state) {
141
+ var maybeEnd = false, ch;
142
+ while (ch = stream.next()) {
143
+ if (ch == "/" && maybeEnd) {
144
+ state.tokenize = tokenBase;
145
+ break;
146
+ }
147
+ maybeEnd = (ch == "*");
148
+ }
149
+ return ret("comment", "comment");
150
+ }
151
+
152
+ function tokenQuasi(stream, state) {
153
+ var escaped = false, next;
154
+ while ((next = stream.next()) != null) {
155
+ if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
156
+ state.tokenize = tokenBase;
157
+ break;
158
+ }
159
+ escaped = !escaped && next == "\\";
160
+ }
161
+ return ret("quasi", "string-2", stream.current());
162
+ }
163
+
164
+ var brackets = "([{}])";
165
+ // This is a crude lookahead trick to try and notice that we're
166
+ // parsing the argument patterns for a fat-arrow function before we
167
+ // actually hit the arrow token. It only works if the arrow is on
168
+ // the same line as the arguments and there's no strange noise
169
+ // (comments) in between. Fallback is to only notice when we hit the
170
+ // arrow, and not declare the arguments as locals for the arrow
171
+ // body.
172
+ function findFatArrow(stream, state) {
173
+ if (state.fatArrowAt) state.fatArrowAt = null;
174
+ var arrow = stream.string.indexOf("=>", stream.start);
175
+ if (arrow < 0) return;
176
+
177
+ var depth = 0, sawSomething = false;
178
+ for (var pos = arrow - 1; pos >= 0; --pos) {
179
+ var ch = stream.string.charAt(pos);
180
+ var bracket = brackets.indexOf(ch);
181
+ if (bracket >= 0 && bracket < 3) {
182
+ if (!depth) { ++pos; break; }
183
+ if (--depth == 0) break;
184
+ } else if (bracket >= 3 && bracket < 6) {
185
+ ++depth;
186
+ } else if (/[$\w]/.test(ch)) {
187
+ sawSomething = true;
188
+ } else if (sawSomething && !depth) {
189
+ ++pos;
190
+ break;
191
+ }
192
+ }
193
+ if (sawSomething && !depth) state.fatArrowAt = pos;
194
+ }
195
+
196
+ // Parser
197
+
198
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};
199
+
200
+ function JSLexical(indented, column, type, align, prev, info) {
201
+ this.indented = indented;
202
+ this.column = column;
203
+ this.type = type;
204
+ this.prev = prev;
205
+ this.info = info;
206
+ if (align != null) this.align = align;
207
+ }
208
+
209
+ function inScope(state, varname) {
210
+ for (var v = state.localVars; v; v = v.next)
211
+ if (v.name == varname) return true;
212
+ for (var cx = state.context; cx; cx = cx.prev) {
213
+ for (var v = cx.vars; v; v = v.next)
214
+ if (v.name == varname) return true;
215
+ }
216
+ }
217
+
218
+ function parseJS(state, style, type, content, stream) {
219
+ var cc = state.cc;
220
+ // Communicate our context to the combinators.
221
+ // (Less wasteful than consing up a hundred closures on every call.)
222
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
223
+
224
+ if (!state.lexical.hasOwnProperty("align"))
225
+ state.lexical.align = true;
226
+
227
+ while(true) {
228
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
229
+ if (combinator(type, content)) {
230
+ while(cc.length && cc[cc.length - 1].lex)
231
+ cc.pop()();
232
+ if (cx.marked) return cx.marked;
233
+ if (type == "variable" && inScope(state, content)) return "variable-2";
234
+ return style;
235
+ }
236
+ }
237
+ }
238
+
239
+ // Combinator utils
240
+
241
+ var cx = {state: null, column: null, marked: null, cc: null};
242
+ function pass() {
243
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
244
+ }
245
+ function cont() {
246
+ pass.apply(null, arguments);
247
+ return true;
248
+ }
249
+ function register(varname) {
250
+ function inList(list) {
251
+ for (var v = list; v; v = v.next)
252
+ if (v.name == varname) return true;
253
+ return false;
254
+ }
255
+ var state = cx.state;
256
+ if (state.context) {
257
+ cx.marked = "def";
258
+ if (inList(state.localVars)) return;
259
+ state.localVars = {name: varname, next: state.localVars};
260
+ } else {
261
+ if (inList(state.globalVars)) return;
262
+ if (parserConfig.globalVars)
263
+ state.globalVars = {name: varname, next: state.globalVars};
264
+ }
265
+ }
266
+
267
+ // Combinators
268
+
269
+ var defaultVars = {name: "this", next: {name: "arguments"}};
270
+ function pushcontext() {
271
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
272
+ cx.state.localVars = defaultVars;
273
+ }
274
+ function popcontext() {
275
+ cx.state.localVars = cx.state.context.vars;
276
+ cx.state.context = cx.state.context.prev;
277
+ }
278
+ function pushlex(type, info) {
279
+ var result = function() {
280
+ var state = cx.state, indent = state.indented;
281
+ if (state.lexical.type == "stat") indent = state.lexical.indented;
282
+ state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
283
+ };
284
+ result.lex = true;
285
+ return result;
286
+ }
287
+ function poplex() {
288
+ var state = cx.state;
289
+ if (state.lexical.prev) {
290
+ if (state.lexical.type == ")")
291
+ state.indented = state.lexical.indented;
292
+ state.lexical = state.lexical.prev;
293
+ }
294
+ }
295
+ poplex.lex = true;
296
+
297
+ function expect(wanted) {
298
+ return function(type) {
299
+ if (type == wanted) return cont();
300
+ else if (wanted == ";") return pass();
301
+ else return cont(arguments.callee);
302
+ };
303
+ }
304
+
305
+ function statement(type, value) {
306
+ if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
307
+ if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
308
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
309
+ if (type == "{") return cont(pushlex("}"), block, poplex);
310
+ if (type == ";") return cont();
311
+ if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
312
+ if (type == "function") return cont(functiondef);
313
+ if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
314
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
315
+ if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
316
+ block, poplex, poplex);
317
+ if (type == "case") return cont(expression, expect(":"));
318
+ if (type == "default") return cont(expect(":"));
319
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
320
+ statement, poplex, popcontext);
321
+ if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
322
+ if (type == "class") return cont(pushlex("form"), className, objlit, poplex);
323
+ if (type == "export") return cont(pushlex("form"), afterExport, poplex);
324
+ if (type == "import") return cont(pushlex("form"), afterImport, poplex);
325
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
326
+ }
327
+ function expression(type) {
328
+ return expressionInner(type, false);
329
+ }
330
+ function expressionNoComma(type) {
331
+ return expressionInner(type, true);
332
+ }
333
+ function expressionInner(type, noComma) {
334
+ if (cx.state.fatArrowAt == cx.stream.start) {
335
+ var body = noComma ? arrowBodyNoComma : arrowBody;
336
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
337
+ else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
338
+ }
339
+
340
+ var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
341
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
342
+ if (type == "function") return cont(functiondef);
343
+ if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
344
+ if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
345
+ if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
346
+ if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
347
+ if (type == "{") return contCommasep(objprop, "}", null, maybeop);
348
+ return cont();
349
+ }
350
+ function maybeexpression(type) {
351
+ if (type.match(/[;\}\)\],]/)) return pass();
352
+ return pass(expression);
353
+ }
354
+ function maybeexpressionNoComma(type) {
355
+ if (type.match(/[;\}\)\],]/)) return pass();
356
+ return pass(expressionNoComma);
357
+ }
358
+
359
+ function maybeoperatorComma(type, value) {
360
+ if (type == ",") return cont(expression);
361
+ return maybeoperatorNoComma(type, value, false);
362
+ }
363
+ function maybeoperatorNoComma(type, value, noComma) {
364
+ var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
365
+ var expr = noComma == false ? expression : expressionNoComma;
366
+ if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
367
+ if (type == "operator") {
368
+ if (/\+\+|--/.test(value)) return cont(me);
369
+ if (value == "?") return cont(expression, expect(":"), expr);
370
+ return cont(expr);
371
+ }
372
+ if (type == "quasi") { cx.cc.push(me); return quasi(value); }
373
+ if (type == ";") return;
374
+ if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
375
+ if (type == ".") return cont(property, me);
376
+ if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
377
+ }
378
+ function quasi(value) {
379
+ if (value.slice(value.length - 2) != "${") return cont();
380
+ return cont(expression, continueQuasi);
381
+ }
382
+ function continueQuasi(type) {
383
+ if (type == "}") {
384
+ cx.marked = "string-2";
385
+ cx.state.tokenize = tokenQuasi;
386
+ return cont();
387
+ }
388
+ }
389
+ function arrowBody(type) {
390
+ findFatArrow(cx.stream, cx.state);
391
+ if (type == "{") return pass(statement);
392
+ return pass(expression);
393
+ }
394
+ function arrowBodyNoComma(type) {
395
+ findFatArrow(cx.stream, cx.state);
396
+ if (type == "{") return pass(statement);
397
+ return pass(expressionNoComma);
398
+ }
399
+ function maybelabel(type) {
400
+ if (type == ":") return cont(poplex, statement);
401
+ return pass(maybeoperatorComma, expect(";"), poplex);
402
+ }
403
+ function property(type) {
404
+ if (type == "variable") {cx.marked = "property"; return cont();}
405
+ }
406
+ function objprop(type, value) {
407
+ if (type == "variable") {
408
+ cx.marked = "property";
409
+ if (value == "get" || value == "set") return cont(getterSetter);
410
+ } else if (type == "number" || type == "string") {
411
+ cx.marked = type + " property";
412
+ } else if (type == "[") {
413
+ return cont(expression, expect("]"), afterprop);
414
+ }
415
+ if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
416
+ }
417
+ function getterSetter(type) {
418
+ if (type != "variable") return pass(afterprop);
419
+ cx.marked = "property";
420
+ return cont(functiondef);
421
+ }
422
+ function afterprop(type) {
423
+ if (type == ":") return cont(expressionNoComma);
424
+ if (type == "(") return pass(functiondef);
425
+ }
426
+ function commasep(what, end) {
427
+ function proceed(type) {
428
+ if (type == ",") {
429
+ var lex = cx.state.lexical;
430
+ if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
431
+ return cont(what, proceed);
432
+ }
433
+ if (type == end) return cont();
434
+ return cont(expect(end));
435
+ }
436
+ return function(type) {
437
+ if (type == end) return cont();
438
+ return pass(what, proceed);
439
+ };
440
+ }
441
+ function contCommasep(what, end, info) {
442
+ for (var i = 3; i < arguments.length; i++)
443
+ cx.cc.push(arguments[i]);
444
+ return cont(pushlex(end, info), commasep(what, end), poplex);
445
+ }
446
+ function block(type) {
447
+ if (type == "}") return cont();
448
+ return pass(statement, block);
449
+ }
450
+ function maybetype(type) {
451
+ if (isTS && type == ":") return cont(typedef);
452
+ }
453
+ function typedef(type) {
454
+ if (type == "variable"){cx.marked = "variable-3"; return cont();}
455
+ }
456
+ function vardef() {
457
+ return pass(pattern, maybetype, maybeAssign, vardefCont);
458
+ }
459
+ function pattern(type, value) {
460
+ if (type == "variable") { register(value); return cont(); }
461
+ if (type == "[") return contCommasep(pattern, "]");
462
+ if (type == "{") return contCommasep(proppattern, "}");
463
+ }
464
+ function proppattern(type, value) {
465
+ if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
466
+ register(value);
467
+ return cont(maybeAssign);
468
+ }
469
+ if (type == "variable") cx.marked = "property";
470
+ return cont(expect(":"), pattern, maybeAssign);
471
+ }
472
+ function maybeAssign(_type, value) {
473
+ if (value == "=") return cont(expressionNoComma);
474
+ }
475
+ function vardefCont(type) {
476
+ if (type == ",") return cont(vardef);
477
+ }
478
+ function maybeelse(type, value) {
479
+ if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
480
+ }
481
+ function forspec(type) {
482
+ if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
483
+ }
484
+ function forspec1(type) {
485
+ if (type == "var") return cont(vardef, expect(";"), forspec2);
486
+ if (type == ";") return cont(forspec2);
487
+ if (type == "variable") return cont(formaybeinof);
488
+ return pass(expression, expect(";"), forspec2);
489
+ }
490
+ function formaybeinof(_type, value) {
491
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
492
+ return cont(maybeoperatorComma, forspec2);
493
+ }
494
+ function forspec2(type, value) {
495
+ if (type == ";") return cont(forspec3);
496
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
497
+ return pass(expression, expect(";"), forspec3);
498
+ }
499
+ function forspec3(type) {
500
+ if (type != ")") cont(expression);
501
+ }
502
+ function functiondef(type, value) {
503
+ if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
504
+ if (type == "variable") {register(value); return cont(functiondef);}
505
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
506
+ }
507
+ function funarg(type) {
508
+ if (type == "spread") return cont(funarg);
509
+ return pass(pattern, maybetype);
510
+ }
511
+ function className(type, value) {
512
+ if (type == "variable") {register(value); return cont(classNameAfter);}
513
+ }
514
+ function classNameAfter(_type, value) {
515
+ if (value == "extends") return cont(expression);
516
+ }
517
+ function objlit(type) {
518
+ if (type == "{") return contCommasep(objprop, "}");
519
+ }
520
+ function afterModule(type, value) {
521
+ if (type == "string") return cont(statement);
522
+ if (type == "variable") { register(value); return cont(maybeFrom); }
523
+ }
524
+ function afterExport(_type, value) {
525
+ if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
526
+ if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
527
+ return pass(statement);
528
+ }
529
+ function afterImport(type) {
530
+ if (type == "string") return cont();
531
+ return pass(importSpec, maybeFrom);
532
+ }
533
+ function importSpec(type, value) {
534
+ if (type == "{") return contCommasep(importSpec, "}");
535
+ if (type == "variable") register(value);
536
+ return cont();
537
+ }
538
+ function maybeFrom(_type, value) {
539
+ if (value == "from") { cx.marked = "keyword"; return cont(expression); }
540
+ }
541
+ function arrayLiteral(type) {
542
+ if (type == "]") return cont();
543
+ return pass(expressionNoComma, maybeArrayComprehension);
544
+ }
545
+ function maybeArrayComprehension(type) {
546
+ if (type == "for") return pass(comprehension, expect("]"));
547
+ if (type == ",") return cont(commasep(expressionNoComma, "]"));
548
+ return pass(commasep(expressionNoComma, "]"));
549
+ }
550
+ function comprehension(type) {
551
+ if (type == "for") return cont(forspec, comprehension);
552
+ if (type == "if") return cont(expression, comprehension);
553
+ }
554
+
555
+ // Interface
556
+
557
+ return {
558
+ startState: function(basecolumn) {
559
+ var state = {
560
+ tokenize: tokenBase,
561
+ lastType: "sof",
562
+ cc: [],
563
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
564
+ localVars: parserConfig.localVars,
565
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
566
+ indented: 0
567
+ };
568
+ if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
569
+ return state;
570
+ },
571
+
572
+ token: function(stream, state) {
573
+ if (stream.sol()) {
574
+ if (!state.lexical.hasOwnProperty("align"))
575
+ state.lexical.align = false;
576
+ state.indented = stream.indentation();
577
+ findFatArrow(stream, state);
578
+ }
579
+ if (state.tokenize != tokenComment && stream.eatSpace()) return null;
580
+ var style = state.tokenize(stream, state);
581
+ if (type == "comment") return style;
582
+ state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
583
+ return parseJS(state, style, type, content, stream);
584
+ },
585
+
586
+ indent: function(state, textAfter) {
587
+ if (state.tokenize == tokenComment) return CodeMirror.Pass;
588
+ if (state.tokenize != tokenBase) return 0;
589
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
590
+ // Kludge to prevent 'maybelse' from blocking lexical scope pops
591
+ for (var i = state.cc.length - 1; i >= 0; --i) {
592
+ var c = state.cc[i];
593
+ if (c == poplex) lexical = lexical.prev;
594
+ else if (c != maybeelse) break;
595
+ }
596
+ if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
597
+ if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
598
+ lexical = lexical.prev;
599
+ var type = lexical.type, closing = firstChar == type;
600
+
601
+ if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
602
+ else if (type == "form" && firstChar == "{") return lexical.indented;
603
+ else if (type == "form") return lexical.indented + indentUnit;
604
+ else if (type == "stat")
605
+ return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
606
+ else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
607
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
608
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
609
+ else return lexical.indented + (closing ? 0 : indentUnit);
610
+ },
611
+
612
+ electricChars: ":{}",
613
+ blockCommentStart: jsonMode ? null : "/*",
614
+ blockCommentEnd: jsonMode ? null : "*/",
615
+ lineComment: jsonMode ? null : "//",
616
+ fold: "brace",
617
+
618
+ helperType: jsonMode ? "json" : "javascript",
619
+ jsonMode: jsonMode
620
+ };
621
+ });
622
+
623
+ CodeMirror.defineMIME("text/javascript", "javascript");
624
+ CodeMirror.defineMIME("text/ecmascript", "javascript");
625
+ CodeMirror.defineMIME("application/javascript", "javascript");
626
+ CodeMirror.defineMIME("application/ecmascript", "javascript");
627
+ CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
628
+ CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
629
+ CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
630
+ CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
plugin-fw/assets/js/metabox.js ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file belongs to the YIT Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+ (function ($) {
10
+
11
+ $('.metaboxes-tab').each(function () {
12
+ $('.tabs-panel', this).hide();
13
+
14
+ var active_tab = wpCookies.get('active_metabox_tab');
15
+ if (active_tab == null) {
16
+ active_tab = $('ul.metaboxes-tabs li:first-child a', this).attr('href');
17
+ } else {
18
+ active_tab = '#' + active_tab;
19
+ }
20
+
21
+ $(active_tab).show();
22
+
23
+ $('.metaboxes-tabs a', this).click(function (e) {
24
+ if ($(this).parent().hasClass('tabs')) {
25
+ e.preventDefault();
26
+ return;
27
+ }
28
+
29
+ var t = $(this).attr('href');
30
+ $(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
31
+ $('.tabs-panel').slideUp('fast');
32
+ $(t).delay(350).slideDown('fast');
33
+
34
+ return false;
35
+ });
36
+ });
37
+
38
+ //upload
39
+ var _custom_media = true,
40
+ _orig_send_attachment = wp.media.editor.send.attachment;
41
+
42
+ $(document).on('click', '.metaboxes-tab .upload_button', function(e) {
43
+ var send_attachment_bkp = wp.media.editor.send.attachment;
44
+ var button = $(this);
45
+ var id = button.attr('id').replace('-button', '');
46
+ _custom_media = true;
47
+ wp.media.editor.send.attachment = function(props, attachment){
48
+ if ( _custom_media ) {
49
+ if( $("#"+id).is('input[type=text]') ) {
50
+ $("#"+id).val(attachment.url);
51
+ } else {
52
+ $("#"+id + '_custom').val(attachment.url);
53
+ }
54
+ } else {
55
+ return _orig_send_attachment.apply( this, [props, attachment] );
56
+ };
57
+ }
58
+
59
+ wp.media.editor.open(button);
60
+ return false;
61
+ });
62
+
63
+ $('.metaboxes-tab .add_media').on('click', function(){
64
+ _custom_media = false;
65
+ });
66
+
67
+ //colorpicker
68
+ $('.metaboxes-tab .panel-colorpicker').wpColorPicker({
69
+ onInit: function(){ console.log('test');},
70
+ change: function(event, ui){
71
+ },
72
+ clear: function(){
73
+ var input = $(this);
74
+ input.val(input.data('default-color'));
75
+ input.change();
76
+ }
77
+ });
78
+
79
+
80
+ $('.metaboxes-tab .panel-colorpicker').each( function() {
81
+ var select_label = $(this).data('variations-label');
82
+ $(this).parent().parent().find('a.wp-color-result').attr('title', select_label);
83
+ });
84
+
85
+ //datepicker
86
+ $('.metaboxes-tab .panel-datepicker').each( function() {
87
+ $(this).datepicker();
88
+ });
89
+
90
+
91
+ // select
92
+ var select_value = function() {
93
+ var value = '';
94
+
95
+ if( $(this).attr('multiple')){
96
+ $(this).children("option:selected").each(function(i,v){
97
+ if( i != 0)
98
+ value += ', ';
99
+
100
+ value += $(v).text();
101
+ });
102
+
103
+ if( value == '' ){
104
+ $(this).children().children("option:selected").each(function(i,v){
105
+ if( i != 0)
106
+ value += ', ';
107
+
108
+ value += $(v).text();
109
+ });
110
+ }
111
+ }
112
+ else{
113
+ value = $(this).children("option:selected").text();
114
+
115
+ if( value == '' )
116
+ value = $(this).children().children("option:selected").text();
117
+ }
118
+
119
+
120
+ if ( $(this).parent().find('span').length <= 0 ) {
121
+ $(this).before('<span></span>');
122
+ }
123
+
124
+ $(this).parent().children('span').replaceWith('<span>'+value +'</span>');
125
+ };
126
+ $('.metaboxes-tab .select_wrapper select').not('.chosen').each(select_value).change(select_value);
127
+
128
+ //Open select multiple
129
+ $('.metaboxes-tab .select_wrapper').click( function(e){
130
+ e.stopPropagation();
131
+ $(this).find('select[multiple]').not('.chosen').toggle();
132
+ });
133
+ //Stops click propagation on select, to prevent select hide
134
+ $('.metaboxes-tab .select_wrapper select[multiple]').not('.chosen').click( function(e){
135
+ e.stopPropagation();
136
+ });
137
+ //Hides select on window click
138
+ $(window).click(function(){
139
+ $('.metaboxes-tab .select_wrapper select[multiple]').not('.chosen').hide();
140
+ })
141
+
142
+ //on-off
143
+ $('.metaboxes-tab .onoff_container span').on('click', function(){
144
+
145
+ var input = $( this ).prev( 'input' );
146
+ var checked = input.prop( 'checked' );
147
+
148
+ if( checked ) {
149
+ input.prop( 'checked', false ).attr( 'value', 'no' ).removeClass('onoffchecked');
150
+ } else {
151
+ input.prop( 'checked', true ).attr( 'value', 'yes' ).addClass('onoffchecked');
152
+ }
153
+
154
+ input.change();
155
+ });
156
+
157
+ //chosen
158
+ $('.metaboxes-tab .chosen .select_wrapper select').chosen();
159
+
160
+
161
+ $('.metaboxes-tab .slider_container .ui-slider-horizontal').each(function(){
162
+ var val = $(this).data('val');
163
+ var minValue = $(this).data('min');
164
+ var maxValue = $(this).data('max');
165
+ var step = $(this).data('step');
166
+ var labels = $(this).data('labels');
167
+
168
+ $(this).slider({
169
+ value: val,
170
+ min: minValue,
171
+ max: maxValue,
172
+ range: 'min',
173
+ step: step,
174
+
175
+ slide: function( event, ui ) {
176
+ $(this).find('input').val( ui.value );
177
+ $(this).siblings('.feedback').find('strong' ).text( ui.value + labels );
178
+ }
179
+ });
180
+ });
181
+
182
+
183
+ var act_page_option = $('#_active_page_options-container').parent().html();
184
+ $('#_active_page_options-container').parent().remove();
185
+ $(act_page_option).insertAfter('#yit-post-setting .handlediv');
186
+ $(act_page_option).insertAfter('#yit-page-setting .handlediv');
187
+
188
+
189
+ $('#_active_page_options-container').on('click', function(){
190
+ if( $('#_active_page_options').is(":checked") ){
191
+ $('#yit-page-setting .inside .metaboxes-tab, #yit-post-setting .inside .metaboxes-tab').css( { 'opacity' : 1 , 'pointer-events' : 'auto' } );
192
+ }else{
193
+ $('#yit-page-setting .inside .metaboxes-tab, #yit-post-setting .inside .metaboxes-tab').css( { 'opacity' : 0.5 , 'pointer-events' : 'none' } );
194
+ }
195
+ }).click();
196
+
197
+
198
+ //dependencies handler
199
+ $('.metaboxes-tab [data-field]').each(function(){
200
+ var t = $(this);
201
+
202
+ var field = '#' + t.data('field'),
203
+ dep = '#' + t.data('dep'),
204
+ value = t.data('value');
205
+
206
+
207
+ dependencies_handler( field, dep, value.toString() );
208
+
209
+ $(dep).on('change', function(){
210
+ dependencies_handler( field, dep, value.toString() );
211
+ }).change();
212
+ });
213
+
214
+ //Handle dependencies.
215
+ function dependencies_handler ( id, deps, values ) {
216
+ var result = true;
217
+
218
+
219
+ //Single dependency
220
+ if( typeof( deps ) == 'string' ) {
221
+ if( deps.substr( 0, 6 ) == ':radio' )
222
+ {deps = deps + ':checked'; }
223
+
224
+ var val = $( deps ).val();
225
+
226
+ if( $(deps).attr('type') == 'checkbox'){
227
+ var thisCheck = $(deps);
228
+ if ( thisCheck.is ( ':checked' ) ) {
229
+ val = 'yes';
230
+ }
231
+ else {
232
+ val = 'no';
233
+ }
234
+ }
235
+
236
+ var values = values.split( ',' );
237
+
238
+ for( var i = 0; i < values.length; i++ ) {
239
+ if( val != values[i] )
240
+ { result = false; }
241
+ else
242
+ { result = true; break; }
243
+ }
244
+ }
245
+
246
+ if( !result ) {
247
+ $( id + '-container' ).parent().hide();
248
+ } else {
249
+ $( id + '-container' ).parent().show();
250
+ }
251
+ };
252
+
253
+ // Image gallery
254
+ $(document).on('click', '.image-gallery-button', function (e) {
255
+ var $t = $(this),
256
+ $container = $t.closest('.image-gallery'),
257
+ $image_gallery_ids = $container.find('.image_gallery_ids'),
258
+ attachment_ids = $image_gallery_ids.val(),
259
+ $gallery_images_wrapper = $container.find('ul.slides-wrapper');
260
+
261
+
262
+ // Create the media frame.
263
+ var image_gallery_frame = wp.media.frames.image_gallery = wp.media({
264
+ // Set the title of the modal.
265
+ title : $t.data('choose'),
266
+ button: {
267
+ text: $t.data('update')
268
+ },
269
+ states: [
270
+ new wp.media.controller.Library({
271
+ title : $t.data('choose'),
272
+ filterable: 'all',
273
+ multiple : true
274
+ })
275
+ ]
276
+ });
277
+
278
+ // When an image is selected, run a callback.
279
+ image_gallery_frame.on('select', function () {
280
+ var selection = image_gallery_frame.state().get('selection');
281
+ selection.map(function (attachment) {
282
+ attachment = attachment.toJSON();
283
+
284
+ if (attachment.id) {
285
+ attachment_ids = attachment_ids ? attachment_ids + "," + attachment.id : attachment.id;
286
+ $gallery_images_wrapper.append('<li class="image" data-attachment_id="' + attachment.id + '"><img src="' + attachment.sizes.thumbnail.url + '"/><ul class="actions"><li><a href="#" class="delete" title="' + $t.data('delete') + '">x</a></li></ul></li>');
287
+ }
288
+ });
289
+
290
+ $image_gallery_ids.val(attachment_ids);
291
+ });
292
+
293
+ image_gallery_frame.open();
294
+
295
+ });
296
+
297
+ // Image ordering
298
+ $('.image-gallery ul.slides-wrapper').each(function(){
299
+ var $t = $(this);
300
+ $t.sortable({
301
+ items : 'li.image',
302
+ cursor : 'move',
303
+ scrollSensitivity : 40,
304
+ forcePlaceholderSize: true,
305
+ forceHelperSize : false,
306
+ helper : 'clone',
307
+ opacity : 0.65,
308
+ start : function (event, ui) {
309
+ ui.item.css('background-color', '#f6f6f6');
310
+ },
311
+ stop : function (event, ui) {
312
+ ui.item.removeAttr('style');
313
+ },
314
+ update : function (event, ui) {
315
+ var attachment_ids = '';
316
+
317
+ $t.find('li.image').css('cursor', 'default').each(function () {
318
+ var attachment_id = $(this).attr('data-attachment_id');
319
+ attachment_ids = attachment_ids + attachment_id + ',';
320
+ });
321
+
322
+ $t.closest('.image-gallery').find('.image_gallery_ids').val(attachment_ids);
323
+ }
324
+ });
325
+ });
326
+
327
+ // Remove images
328
+ $('.image-gallery ul.slides-wrapper').on( 'click', 'a.delete', function() {
329
+
330
+ var $wrapper = $(this).closest('.image-gallery'),
331
+ $gallery = $(this).closest('.image-gallery ul.slides-wrapper'),
332
+ $image_gallery_ids = $wrapper.find('.image_gallery_ids'),
333
+ attachment_ids = '';
334
+
335
+ $(this).closest('li.image').remove();
336
+
337
+ $gallery.find('li.image').css('cursor','default').each(function() {
338
+ var attachment_id = $(this).attr( 'data-attachment_id' );
339
+ attachment_ids = attachment_ids + attachment_id + ',';
340
+ });
341
+
342
+ $image_gallery_ids.val( attachment_ids );
343
+
344
+ return false;
345
+ });
346
+
347
+
348
+
349
+
350
+ })(jQuery);
plugin-fw/assets/js/metabox.min.js ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(a){function k(b,c,d){var e=!0;if("string"==typeof c){":radio"==c.substr(0,6)&&(c+=":checked");var g=a(c).val();"checkbox"==a(c).attr("type")&&(g=a(c).is(":checked")?"yes":"no");d=d.split(",");for(c=0;c<d.length;c++)if(g!=d[c])e=!1;else{e=!0;break}}e?a(b+"-container").parent().show():a(b+"-container").parent().hide()}a(".metaboxes-tab").each(function(){a(".tabs-panel",this).hide();var b=wpCookies.get("active_metabox_tab"),b=null==b?a("ul.metaboxes-tabs li:first-child a",this).attr("href"):
2
+ "#"+b;a(b).show();a(".metaboxes-tabs a",this).click(function(b){if(a(this).parent().hasClass("tabs"))b.preventDefault();else return b=a(this).attr("href"),a(this).parent().addClass("tabs").siblings("li").removeClass("tabs"),a(".tabs-panel").slideUp("fast"),a(b).delay(350).slideDown("fast"),!1})});var h=!0,l=wp.media.editor.send.attachment;a(document).on("click",".metaboxes-tab .upload_button",function(b){b=a(this);var c=b.attr("id").replace("-button","");h=!0;wp.media.editor.send.attachment=function(b,
3
+ e){if(h)a("#"+c).is("input[type=text]")?a("#"+c).val(e.url):a("#"+c+"_custom").val(e.url);else return l.apply(this,[b,e])};wp.media.editor.open(b);return!1});a(".metaboxes-tab .add_media").on("click",function(){h=!1});a(".metaboxes-tab .panel-colorpicker").wpColorPicker({onInit:function(){console.log("test")},change:function(a,c){},clear:function(){var b=a(this);b.val(b.data("default-color"));b.change()}});a(".metaboxes-tab .panel-colorpicker").each(function(){var b=a(this).data("variations-label");
4
+ a(this).parent().parent().find("a.wp-color-result").attr("title",b)});a(".metaboxes-tab .panel-datepicker").each(function(){a(this).datepicker()});var f=function(){var b="";a(this).attr("multiple")?(a(this).children("option:selected").each(function(c,d){0!=c&&(b+=", ");b+=a(d).text()}),""==b&&a(this).children().children("option:selected").each(function(c,d){0!=c&&(b+=", ");b+=a(d).text()})):(b=a(this).children("option:selected").text(),""==b&&(b=a(this).children().children("option:selected").text()));
5
+ 0>=a(this).parent().find("span").length&&a(this).before("<span></span>");a(this).parent().children("span").replaceWith("<span>"+b+"</span>")};a(".metaboxes-tab .select_wrapper select").not(".chosen").each(f).change(f);a(".metaboxes-tab .select_wrapper").click(function(b){b.stopPropagation();a(this).find("select[multiple]").not(".chosen").toggle()});a(".metaboxes-tab .select_wrapper select[multiple]").not(".chosen").click(function(a){a.stopPropagation()});a(window).click(function(){a(".metaboxes-tab .select_wrapper select[multiple]").not(".chosen").hide()});
6
+ a(".metaboxes-tab .onoff_container span").on("click",function(){var b=a(this).prev("input");b.prop("checked")?b.prop("checked",!1).attr("value","no").removeClass("onoffchecked"):b.prop("checked",!0).attr("value","yes").addClass("onoffchecked");b.change()});a(".metaboxes-tab .chosen .select_wrapper select").chosen();a(".metaboxes-tab .slider_container .ui-slider-horizontal").each(function(){var b=a(this).data("val"),c=a(this).data("min"),d=a(this).data("max"),e=a(this).data("step"),g=a(this).data("labels");
7
+ a(this).slider({value:b,min:c,max:d,range:"min",step:e,slide:function(b,c){a(this).find("input").val(c.value);a(this).siblings(".feedback").find("strong").text(c.value+g)}})});f=a("#_active_page_options-container").parent().html();a("#_active_page_options-container").parent().remove();a(f).insertAfter("#yit-post-setting .handlediv");a(f).insertAfter("#yit-page-setting .handlediv");a("#_active_page_options-container").on("click",function(){a("#_active_page_options").is(":checked")?a("#yit-page-setting .inside .metaboxes-tab, #yit-post-setting .inside .metaboxes-tab").css({opacity:1,
8
+ "pointer-events":"auto"}):a("#yit-page-setting .inside .metaboxes-tab, #yit-post-setting .inside .metaboxes-tab").css({opacity:.5,"pointer-events":"none"})}).click();a(".metaboxes-tab [data-field]").each(function(){var b=a(this),c="#"+b.data("field"),d="#"+b.data("dep"),e=b.data("value");k(c,d,e.toString());a(d).on("change",function(){k(c,d,e.toString())}).change()});a(document).on("click",".image-gallery-button",function(b){var c=a(this);b=c.closest(".image-gallery");var d=b.find(".image_gallery_ids"),
9
+ e=d.val(),g=b.find("ul.slides-wrapper"),f=wp.media.frames.image_gallery=wp.media({title:c.data("choose"),button:{text:c.data("update")},states:[new wp.media.controller.Library({title:c.data("choose"),filterable:"all",multiple:!0})]});f.on("select",function(){f.state().get("selection").map(function(a){a=a.toJSON();a.id&&(e=e?e+","+a.id:a.id,g.append('<li class="image" data-attachment_id="'+a.id+'"><img src="'+a.sizes.thumbnail.url+'"/><ul class="actions"><li><a href="#" class="delete" title="'+c.data("delete")+
10
+ '">x</a></li></ul></li>'))});d.val(e)});f.open()});a(".image-gallery ul.slides-wrapper").each(function(){var b=a(this);b.sortable({items:"li.image",cursor:"move",scrollSensitivity:40,forcePlaceholderSize:!0,forceHelperSize:!1,helper:"clone",opacity:.65,start:function(a,b){b.item.css("background-color","#f6f6f6")},stop:function(a,b){b.item.removeAttr("style")},update:function(c,d){var e="";b.find("li.image").css("cursor","default").each(function(){var b=a(this).attr("data-attachment_id");e=e+b+","});
11
+ b.closest(".image-gallery").find(".image_gallery_ids").val(e)}})});a(".image-gallery ul.slides-wrapper").on("click","a.delete",function(){var b=a(this).closest(".image-gallery"),c=a(this).closest(".image-gallery ul.slides-wrapper"),b=b.find(".image_gallery_ids"),d="";a(this).closest("li.image").remove();c.find("li.image").css("cursor","default").each(function(){var b=a(this).attr("data-attachment_id");d=d+b+","});b.val(d);return!1})})(jQuery);
plugin-fw/assets/js/multisite-updater.js ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file belongs to the YIT Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+ (function ($) {
10
+
11
+ var plugins_menu_item = $( '#menu-plugins' ),
12
+ update = plugins_menu_item.find('.update-plugins'),
13
+ count = update.find(".update-count").text(),
14
+ registered = plugins.registered,
15
+ activated = plugins.activated;
16
+
17
+ if( count == 0 || count == ''){
18
+ var update_row = '<span class="update-plugins"><span class="plugin-count"></span></span>';
19
+ count = 0;
20
+ plugins_menu_item.find( '.wp-menu-name').append( update_row );
21
+ }
22
+
23
+ /**
24
+ * Add the plugin update rows for old plugins
25
+ */
26
+ update_plugins_row( registered, activated, count, plugins );
27
+
28
+ /**
29
+ *
30
+ * Add the update plugin rows for old plugin
31
+ *
32
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
33
+ *
34
+ * @param registered Registred plugins
35
+ * @param activated Activated plugins
36
+ * @param count Number of old plugins
37
+ * @param localize Localize strings array
38
+ *
39
+ * @return void
40
+ */
41
+ function update_plugins_row( registered, activated, count, localize ){
42
+ for( var init in registered ){
43
+ var plugin = registered[init];
44
+ for( var headers in plugin ){
45
+
46
+ if( headers == 'slug' || version_compare( plugin[headers].Version, plugin[headers].Latest, '>=' ) ) {
47
+ continue;
48
+ }
49
+
50
+ count = parseInt(count) + 1;
51
+ $(".plugin-count").empty().html(count);
52
+
53
+ var regex = new RegExp(' ', 'g'),
54
+ info = plugin[headers],
55
+ name = '' + info.Name,
56
+ id = name.replace(regex, '-').trim(),
57
+ row = '#' + id.toLowerCase();
58
+
59
+ $(row).addClass("update");
60
+
61
+ var html = '<tr class="plugin-update-tr">' +
62
+ '<td colspan="3" class="plugin-update colspanchange">' +
63
+ '<div class="update-message">' + localize.strings.new_version.replace( '%plugin_name%', name ) +
64
+ '<a class="thickbox" href="' + localize.details_url[init] + '">' + localize.strings.latest.replace( '%latest%', plugin[headers].Latest ) + '</a>';
65
+
66
+ if( typeof activated[init] == "undefined" ) {
67
+
68
+ html = html +
69
+ ' <em>' + localize.strings.unavailable + '</em>' +
70
+ localize.strings.activate.replace( '%activate_link%', localize.licence_activation_url ).replace( '%plugin_name%', name );
71
+ } else {
72
+ html = html +
73
+ '. <a href="' + localize.update_url[init] + '">' + localize.strings.update_now + '</a>';
74
+ }
75
+
76
+ if( typeof localize.changelogs[init] != 'undefined' ){
77
+ html = html + localize.changelogs[init];
78
+ }
79
+
80
+ html = html +
81
+ '</div>' +
82
+ '</td>' +
83
+ '</tr>';
84
+
85
+ $(html).insertAfter(row);
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ *
92
+ * @param v1 Version 1
93
+ * @param v2 Version 2
94
+ * @param operator Compare type
95
+ * @returns bool
96
+ *
97
+ * @see php.js library http://phpjs.org/
98
+ */
99
+ function version_compare(v1, v2, operator) {
100
+ // discuss at: http://phpjs.org/functions/version_compare/
101
+ // original by: Philippe Jausions (http://pear.php.net/user/jausions)
102
+ // original by: Aidan Lister (http://aidanlister.com/)
103
+ // reimplemented by: Kankrelune (http://www.webfaktory.info/)
104
+ // improved by: Brett Zamir (http://brett-zamir.me)
105
+ // improved by: Scott Baker
106
+ // improved by: Theriault
107
+ // example 1: version_compare('8.2.5rc', '8.2.5a');
108
+ // returns 1: 1
109
+ // example 2: version_compare('8.2.50', '8.2.52', '<');
110
+ // returns 2: true
111
+ // example 3: version_compare('5.3.0-dev', '5.3.0');
112
+ // returns 3: -1
113
+ // example 4: version_compare('4.1.0.52','4.01.0.51');
114
+ // returns 4: 1
115
+
116
+ this.php_js = this.php_js || {};
117
+ this.php_js.ENV = this.php_js.ENV || {};
118
+ // END REDUNDANT
119
+ // Important: compare must be initialized at 0.
120
+ var i = 0,
121
+ x = 0,
122
+ compare = 0,
123
+ // vm maps textual PHP versions to negatives so they're less than 0.
124
+ // PHP currently defines these as CASE-SENSITIVE. It is important to
125
+ // leave these as negatives so that they can come before numerical versions
126
+ // and as if no letters were there to begin with.
127
+ // (1alpha is < 1 and < 1.1 but > 1dev1)
128
+ // If a non-numerical value can't be mapped to this table, it receives
129
+ // -7 as its value.
130
+ vm = {
131
+ 'dev' : -6,
132
+ 'alpha': -5,
133
+ 'a' : -5,
134
+ 'beta' : -4,
135
+ 'b' : -4,
136
+ 'RC' : -3,
137
+ 'rc' : -3,
138
+ '#' : -2,
139
+ 'p' : 1,
140
+ 'pl' : 1
141
+ },
142
+ // This function will be called to prepare each version argument.
143
+ // It replaces every _, -, and + with a dot.
144
+ // It surrounds any nonsequence of numbers/dots with dots.
145
+ // It replaces sequences of dots with a single dot.
146
+ // version_compare('4..0', '4.0') == 0
147
+ // Important: A string of 0 length needs to be converted into a value
148
+ // even less than an unexisting value in vm (-7), hence [-8].
149
+ // It's also important to not strip spaces because of this.
150
+ // version_compare('', ' ') == 1
151
+ prepVersion = function (v) {
152
+ v = ('' + v)
153
+ .replace(/[_\-+]/g, '.');
154
+ v = v.replace(/([^.\d]+)/g, '.$1.')
155
+ .replace(/\.{2,}/g, '.');
156
+ return (!v.length ? [-8] : v.split('.'));
157
+ };
158
+ // This converts a version component to a number.
159
+ // Empty component becomes 0.
160
+ // Non-numerical component becomes a negative number.
161
+ // Numerical component becomes itself as an integer.
162
+ numVersion = function (v) {
163
+ return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
164
+ };
165
+ v1 = prepVersion(v1);
166
+ v2 = prepVersion(v2);
167
+ x = Math.max(v1.length, v2.length);
168
+ for (i = 0; i < x; i++) {
169
+ if (v1[i] == v2[i]) {
170
+ continue;
171
+ }
172
+ v1[i] = numVersion(v1[i]);
173
+ v2[i] = numVersion(v2[i]);
174
+ if (v1[i] < v2[i]) {
175
+ compare = -1;
176
+ break;
177
+ } else if (v1[i] > v2[i]) {
178
+ compare = 1;
179
+ break;
180
+ }
181
+ }
182
+ if (!operator) {
183
+ return compare;
184
+ }
185
+
186
+ // Important: operator is CASE-SENSITIVE.
187
+ // "No operator" seems to be treated as "<."
188
+ // Any other values seem to make the function return null.
189
+ switch (operator) {
190
+ case '>':
191
+ case 'gt':
192
+ return (compare > 0);
193
+ case '>=':
194
+ case 'ge':
195
+ return (compare >= 0);
196
+ case '<=':
197
+ case 'le':
198
+ return (compare <= 0);
199
+ case '==':
200
+ case '=':
201
+ case 'eq':
202
+ return (compare === 0);
203
+ case '<>':
204
+ case '!=':
205
+ case 'ne':
206
+ return (compare !== 0);
207
+ case '':
208
+ case '<':
209
+ case 'lt':
210
+ return (compare < 0);
211
+ default:
212
+ return null;
213
+ }
214
+ }
215
+
216
+ })(jQuery);
plugin-fw/assets/js/multisite-updater.min.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ (function(m){function n(c,d,k){this.php_js=this.php_js||{};this.php_js.ENV=this.php_js.ENV||{};var a=0,e=0,b=0,f={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},a=function(a){a=(""+a).replace(/[_\-+]/g,".");a=a.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,".");return a.length?a.split("."):[-8]};numVersion=function(a){return a?isNaN(a)?f[a]||-7:parseInt(a,10):0};c=a(c);d=a(d);e=Math.max(c.length,d.length);for(a=0;a<e;a++)if(c[a]!=d[a])if(c[a]=numVersion(c[a]),d[a]=numVersion(d[a]),
2
+ c[a]<d[a]){b=-1;break}else if(c[a]>d[a]){b=1;break}if(!k)return b;switch(k){case ">":case "gt":return 0<b;case ">=":case "ge":return 0<=b;case "<=":case "le":return 0>=b;case "==":case "=":case "eq":return 0===b;case "<>":case "!=":case "ne":return 0!==b;case "":case "<":case "lt":return 0>b;default:return null}}var l=m("#menu-plugins"),g=l.find(".update-plugins").find(".update-count").text(),p=plugins.registered,q=plugins.activated;if(0==g||""==g)g=0,l.find(".wp-menu-name").append('<span class="update-plugins"><span class="plugin-count"></span></span>');
3
+ (function(c,d,k,a){for(var e in c){var b=c[e],f;for(f in b)if("slug"!=f&&!n(b[f].Version,b[f].Latest,">=")){k=parseInt(k)+1;m(".plugin-count").empty().html(k);var g=""+b[f].Name,l="#"+g.replace(RegExp(" ","g"),"-").trim().toLowerCase();m(l).addClass("update");var h='<tr class="plugin-update-tr"><td colspan="3" class="plugin-update colspanchange"><div class="update-message">'+a.strings.new_version.replace("%plugin_name%",g)+'<a class="thickbox" href="'+a.details_url[e]+'">'+a.strings.latest.replace("%latest%",
4
+ b[f].Latest)+"</a>",h="undefined"==typeof d[e]?h+" <em>"+a.strings.unavailable+"</em>"+a.strings.activate.replace("%activate_link%",a.licence_activation_url).replace("%plugin_name%",g):h+'. <a href="'+a.update_url[e]+'">'+a.strings.update_now+"</a>";"undefined"!=typeof a.changelogs[e]&&(h+=a.changelogs[e]);h+="</div></td></tr>";m(h).insertAfter(l)}}})(p,q,g,plugins)})(jQuery);
plugin-fw/assets/js/panel.spinner.js ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Spinner for jQuery (version 0.1)
3
+ Copyright (c) 2012 Simone D'Amico
4
+ http://simonedamico.com/
5
+
6
+ Licensed under the MIT license:
7
+ http://www.opensource.org/licenses/mit-license.php
8
+
9
+ Any and all use of this script must be accompanied by this copyright/license notice in its present form.
10
+
11
+ */
12
+ (function($){
13
+ $.fn.spinner = function(params) {
14
+
15
+ //private methods
16
+ var _createButton = function( buttonClass, buttonLabel ) {
17
+ return $('<button/>', {
18
+ 'class' : buttonClass + ' spinner-button',
19
+ text : buttonLabel
20
+ });
21
+ };
22
+
23
+ var _createBody = function(input) {
24
+ //create wrapper
25
+ var wrapper = input.wrap('<div class="spinner-wrapper"></div>').parent();
26
+
27
+ //create spinner buttons
28
+ var plus = _createButton('button-plus', '+').appendTo(wrapper).show(),
29
+ minus = _createButton('button-minus', '-').appendTo(wrapper).show();
30
+
31
+ return wrapper;
32
+ };
33
+
34
+ var _buttonClick = function( e ) {
35
+ var input = e.data.input,
36
+ params = e.data.params,
37
+ button = $(this),
38
+ value = parseFloat(input.val());
39
+
40
+ if( button.hasClass('button-plus') ) {
41
+ if( params.max != null ) {
42
+ if( ( value + params.interval ) <= params.max ) {
43
+ input.val( value + params.interval );
44
+ } else {
45
+ input.val( params.max );
46
+ }
47
+ } else {
48
+ input.val( value + params.interval );
49
+ }
50
+ } else if( button.hasClass('button-minus') ) {
51
+ if( params.min != null ) {
52
+ if( ( value - params.interval ) >= params.min ) {
53
+ input.val( value - params.interval );
54
+ } else {
55
+ input.val( params.min );
56
+ }
57
+ } else {
58
+ input.val( value - params.interval );
59
+ }
60
+ }
61
+
62
+ input.change(); e.preventDefault();
63
+ };
64
+
65
+ var _validateContent = function( e ) {
66
+ var value = parseFloat( $(this).val() );
67
+
68
+ if( params.max != null && value >= params.max ) {
69
+ $(this).val(params.max);
70
+ } else if( value <= params.min || isNaN( value ) ) {
71
+ $(this).val(params.min ? params.min : 0);
72
+ } else {
73
+ $(this).val(value);
74
+ }
75
+ };
76
+
77
+
78
+ //public methods
79
+ var methods = {
80
+ init : function( params ) {
81
+
82
+ var params = $.extend({
83
+ min: null,
84
+ max: null,
85
+ interval: 1,
86
+ defaultValue: 0,
87
+ mouseWheel: true,
88
+ largeInterval: 10
89
+ }, params);
90
+
91
+ var self = this,
92
+ t = $(this),
93
+ data = t.data('spinner');
94
+
95
+ return this.each(function(){
96
+ //check if the plugin hasn't already been initialized
97
+ //and it's an input[type=text] element
98
+ if( !data && t.is(':text') ) {
99
+ //initialize the value
100
+ if( params.defaultValue ) {
101
+ t.val( params.defaultValue );
102
+ }
103
+
104
+ //create the spinner body
105
+ var wrapper = _createBody(t);
106
+
107
+ //event handlers
108
+ //var mouseWheelEventName = $.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel';
109
+
110
+ wrapper.find('.spinner-button')
111
+ .bind('click.spinner', { params: params, input: t }, _buttonClick);
112
+
113
+ t.bind('blur.spinner', _validateContent)
114
+ //.bind('keyup.spinner', _validateKey)
115
+ //.bind(mouseWheelEventName, _inputMousewheel);
116
+
117
+ //register field data
118
+ t.data('spinner', {
119
+ target: self
120
+ });
121
+ }
122
+ });
123
+ },
124
+
125
+ destroy : function( params) {
126
+ console.log('destroy', params);
127
+ }
128
+ };
129
+
130
+ //execute the plugin
131
+ if ( methods[params] ) {
132
+ return methods[params].apply( this, Array.prototype.slice.call( arguments, 1 ));
133
+ } else if ( typeof params === 'object' || ! params ) {
134
+ return methods.init.apply( this, arguments );
135
+ } else {
136
+ $.error( 'Method ' + params + ' does not exist' );
137
+ }
138
+ };
139
+ })(jQuery);
plugin-fw/assets/js/panel.spinner.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ (function(d){d.fn.spinner=function(c){var h=function(b,e){return d("<button/>",{"class":b+" spinner-button",text:e})},k=function(b){var e=b.data.input,a=b.data.params,c=d(this),f=parseFloat(e.val());c.hasClass("button-plus")?null!=a.max?f+a.interval<=a.max?e.val(f+a.interval):e.val(a.max):e.val(f+a.interval):c.hasClass("button-minus")&&(null!=a.min?f-a.interval>=a.min?e.val(f-a.interval):e.val(a.min):e.val(f-a.interval));e.change();b.preventDefault()},l=function(b){b=parseFloat(d(this).val());null!=
2
+ c.max&&b>=c.max?d(this).val(c.max):b<=c.min||isNaN(b)?d(this).val(c.min?c.min:0):d(this).val(b)},g={init:function(b){b=d.extend({min:null,max:null,interval:1,defaultValue:0,mouseWheel:!0,largeInterval:10},b);var c=this,a=d(this),g=a.data("spinner");return this.each(function(){if(!g&&a.is(":text")){b.defaultValue&&a.val(b.defaultValue);var d=a.wrap('<div class="spinner-wrapper"></div>').parent();h("button-plus","+").appendTo(d).show();h("button-minus","-").appendTo(d).show();d.find(".spinner-button").bind("click.spinner",
3
+ {params:b,input:a},k);a.bind("blur.spinner",l);a.data("spinner",{target:c})}})},destroy:function(b){console.log("destroy",b)}};if(g[c])return g[c].apply(this,Array.prototype.slice.call(arguments,1));if("object"!==typeof c&&c)d.error("Method "+c+" does not exist");else return g.init.apply(this,arguments)}})(jQuery);
plugin-fw/assets/js/yit-cpt-unlimited.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file belongs to the YIT Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+
10
+ (function($) {
11
+ "use strict";
12
+ // Author code here
13
+
14
+ // open media box
15
+ $('.wrap h2').on( 'click', 'a.multi-uploader', function(event){
16
+ event.preventDefault();
17
+
18
+ var file_frame,
19
+ button = $(this),
20
+ selected = false;
21
+
22
+ // spinner
23
+ button.next('span.spinner').css( 'display', 'inline-block' );
24
+
25
+ // If the media frame already exists, reopen it.
26
+ if ( file_frame ) {
27
+ file_frame.open();
28
+ return;
29
+ }
30
+
31
+ // Create the media frame.
32
+ file_frame = wp.media.frames.file_frame = wp.media({
33
+ title: button.data( 'uploader_title' ),
34
+ button: {
35
+ text: button.data( 'uploader_button_text' )
36
+ },
37
+ library: {
38
+ type: 'image'
39
+ },
40
+ multiple: true // Set to true to allow multiple files to be selected
41
+ });
42
+
43
+ // When an image is selected, run a callback.
44
+ file_frame.on( 'select', function() {
45
+ var selection = file_frame.state().get('selection'),
46
+ images = [];
47
+
48
+ selection.map( function( attachment ) {
49
+ attachment = attachment.toJSON();
50
+
51
+ // Do something with attachment.id and/or attachment.url here
52
+ images.push( { id: attachment.id, url: attachment.url, title: attachment.title } );
53
+ });
54
+
55
+ // make AJAX request
56
+ $.post( ajaxurl, {
57
+ images: images,
58
+ post_type: typenow,
59
+ action: 'yit_cptu_multiuploader'
60
+ }, function( data ){
61
+ location.reload();
62
+ });
63
+
64
+ button.next('span.spinner').css( 'display', 'inline-block' );
65
+
66
+ // flag
67
+ selected = true;
68
+ });
69
+
70
+ // when close
71
+ file_frame.on( 'close', function() {
72
+ if ( ! selected ) button.next('span.spinner').hide();
73
+ });
74
+
75
+ // Finally, open the modal
76
+ file_frame.open();
77
+ });
78
+
79
+ })(jQuery);
plugin-fw/assets/js/yit-cpt-unlimited.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ (function(c){c(".wrap h2").on("click","a.multi-uploader",function(f){f.preventDefault();var a,b=c(this),d=!1;b.next("span.spinner").css("display","inline-block");a||(a=wp.media.frames.file_frame=wp.media({title:b.data("uploader_title"),button:{text:b.data("uploader_button_text")},library:{type:"image"},multiple:!0}),a.on("select",function(){var e=[];a.state().get("selection").map(function(a){a=a.toJSON();e.push({id:a.id,url:a.url,title:a.title})});c.post(ajaxurl,{images:e,post_type:typenow,action:"yit_cptu_multiuploader"},
2
+ function(a){location.reload()});b.next("span.spinner").css("display","inline-block");d=!0}),a.on("close",function(){d||b.next("span.spinner").hide()}));a.open()})})(jQuery);
plugin-fw/assets/js/yit-cptu-sortable-posts.js ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file belongs to the YIT Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+
10
+ (function($) {
11
+ "use strict";
12
+ // Author code here
13
+
14
+ $("#the-list").sortable({
15
+ items : 'tr',
16
+ axis : 'y',
17
+ helper : function(e, ui) {
18
+ ui.children().children().each(function() {
19
+ $(this).width( $(this).width() );
20
+ });
21
+ return ui;
22
+ },
23
+ update : function(e, ui) {
24
+ $.post( ajaxurl, {
25
+ action: 'cpt_sort_posts',
26
+ order: $("#the-list").sortable("serialize"),
27
+ post_type: typenow
28
+ });
29
+ }
30
+ });
31
+
32
+ })(jQuery);
plugin-fw/assets/js/yit-plugin-panel.js ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file belongs to the YIT Plugin Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+
10
+
11
+ (function ($) {
12
+
13
+ // select
14
+ var select_value = function () {
15
+
16
+ var value = '';
17
+
18
+ if ($(this).attr('multiple')) {
19
+ $(this).children("option:selected").each(function (i, v) {
20
+ if (i != 0)
21
+ value += ', ';
22
+
23
+ value += $(v).text();
24
+ });
25
+
26
+ if (value == '') {
27
+ $(this).children().children("option:selected").each(function (i, v) {
28
+ if (i != 0)
29
+ value += ', ';
30
+
31
+ value += $(v).text();
32
+ });
33
+ }
34
+ }
35
+ else {
36
+ value = $(this).children("option:selected").text();
37
+
38
+ if (value == '')
39
+ value = $(this).children().children("option:selected").text();
40
+ }
41
+
42
+
43
+ if ($(this).parent().find('span').length <= 0) {
44
+ $(this).before('<span></span>');
45
+ }
46
+
47
+ $(this).parent().children('span').replaceWith('<span>' + value + '</span>');
48
+ };
49
+ $('.plugin-option .select_wrapper select').not('.chosen').each(select_value).change(select_value);
50
+
51
+ //Open select multiple
52
+ $('.plugin-option .select_wrapper').click(function (e) {
53
+ e.stopPropagation();
54
+ $(this).find('select[multiple]').not('.chosen').toggle();
55
+ });
56
+ //Stops click propagation on select, to prevent select hide
57
+ $('.plugin-option .select_wrapper select[multiple]').not('.chosen').click(function (e) {
58
+ e.stopPropagation();
59
+ });
60
+ //Hides select on window click
61
+ $(window).click(function () {
62
+ $('.plugin-option .select_wrapper select[multiple]').not('.chosen').hide();
63
+ })
64
+ //chosen
65
+ $('.plugin-option .chosen .select_wrapper select').chosen();
66
+
67
+ // on-off
68
+ $('.plugin-option .on_off_container span').on('click', function () {
69
+ var input = $(this).prev('input');
70
+ var checked = input.prop('checked');
71
+
72
+ if (checked) {
73
+ input.prop('checked', false).attr('value', 'no').removeClass('onoffchecked');
74
+ } else {
75
+ input.prop('checked', true).attr('value', 'yes').addClass('onoffchecked');
76
+ }
77
+
78
+ input.change();
79
+ });
80
+
81
+
82
+ //slider
83
+ $('.plugin-option .slider_container .ui-slider-horizontal').each(function () {
84
+ var val = $(this).data('val');
85
+ var minValue = $(this).data('min');
86
+ var maxValue = $(this).data('max');
87
+ var step = $(this).data('step');
88
+ var labels = $(this).data('labels');
89
+
90
+ $(this).slider({
91
+ value: val,
92
+ min : minValue,
93
+ max : maxValue,
94
+ range: 'min',
95
+ step : step,
96
+
97
+ slide: function (event, ui) {
98
+ $(this).find('input').val(ui.value);
99
+ $(this).siblings('.feedback').find('strong').text(ui.value + labels);
100
+ }
101
+ });
102
+ });
103
+
104
+
105
+ if (typeof wp !== 'undefined' && typeof wp.media !== 'undefined') {
106
+
107
+ //upload
108
+ var _custom_media = true,
109
+ _orig_send_attachment = wp.media.editor.send.attachment;
110
+
111
+ // preview
112
+ $('.plugin-option .upload_img_url').change(function () {
113
+ var url = $(this).val();
114
+ var re = new RegExp("(http|ftp|https)://[a-zA-Z0-9@?^=%&amp;:/~+#-_.]*.(gif|jpg|jpeg|png|ico)");
115
+
116
+ var preview = $(this).parent().siblings('.upload_img_preview');
117
+ if (re.test(url)) {
118
+ preview.html('<img src="' + url + '" style="max-width:600px; max-height:300px;" />');
119
+ } else {
120
+ preview.html('');
121
+ }
122
+ }).change();
123
+
124
+ $(document).on('click', '.plugin-option .upload_button', function (e) {
125
+ var send_attachment_bkp = wp.media.editor.send.attachment;
126
+ var button = $(this);
127
+ var id = button.attr('id').replace('-button', '');
128
+ _custom_media = true;
129
+ wp.media.editor.send.attachment = function (props, attachment) {
130
+ if (_custom_media) {
131
+ if ($("#" + id).is('input[type=text]')) {
132
+ $("#" + id).val(attachment.url);
133
+ } else {
134
+ $("#" + id + '_custom').val(attachment.url);
135
+ }
136
+
137
+ } else {
138
+ return _orig_send_attachment.apply(this, [props, attachment]);
139
+ }
140
+ ;
141
+ }
142
+
143
+ wp.media.editor.open(button);
144
+ return false;
145
+ });
146
+
147
+ }
148
+
149
+ $('.plugin-option .add_media').on('click', function () {
150
+ _custom_media = false;
151
+ });
152
+
153
+ //dependencies handler
154
+ $('[data-field]').each(function () {
155
+ var t = $(this);
156
+
157
+ var field = '#' + t.data('field'),
158
+ dep = '#' + t.data('dep'),
159
+ value = t.data('value');
160
+
161
+ $(dep).on('change',function () {
162
+ dependencies_handler(field, dep, value.toString());
163
+ }).change();
164
+ });
165
+
166
+ //Handle dependencies.
167
+ function dependencies_handler(id, deps, values) {
168
+ var result = true;
169
+
170
+ //Single dependency
171
+ if (typeof( deps ) == 'string') {
172
+ if (deps.substr(0, 6) == ':radio') {
173
+ deps = deps + ':checked';
174
+ }
175
+
176
+ var values = values.split(',');
177
+
178
+ for (var i = 0; i < values.length; i++) {
179
+
180
+ if ($(deps).val() != values[i]) {
181
+ result = false;
182
+ }
183
+ else {
184
+ result = true;
185
+ break;
186
+ }
187
+ }
188
+ }
189
+
190
+ if (!result) {
191
+ $(id + '-container').closest('tr').hide();
192
+ } else {
193
+ $(id + '-container').closest('tr').show();
194
+ }
195
+ };
196
+
197
+ //connected list
198
+ $('.rm_connectedlist').each(function () {
199
+ var ul = $(this).find('ul');
200
+ var input = $(this).find(':hidden');
201
+ var sortable = ul.sortable({
202
+ connectWith: ul,
203
+ update : function (event, ui) {
204
+ var value = {};
205
+
206
+ ul.each(function () {
207
+ var options = {};
208
+
209
+ $(this).children().each(function () {
210
+ options[ $(this).data('option') ] = $(this).text();
211
+ });
212
+
213
+ value[ $(this).data('list') ] = options;
214
+ });
215
+
216
+ input.val((JSON.stringify(value)).replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0'));
217
+ }
218
+ }).disableSelection();
219
+ });
220
+
221
+ $(document).ready(function () {
222
+
223
+ $('.yith-video-link').click(function (event) {
224
+ event.preventDefault();
225
+ var target = $(this).data('video-id');
226
+
227
+ $('.' + target).dialog({
228
+ dialogClass : 'wp-dialog yit-dialog yit-video-dialog',
229
+ modal : true,
230
+ closeOnEscape: true,
231
+ width : 'auto',
232
+ resizable : false,
233
+ draggable : false,
234
+ create : function (event, ui) {
235
+ $(this).css("maxWidth", "853px");
236
+ },
237
+ open : function (event, ui) {
238
+
239
+ $('.ui-widget-overlay').bind('click', function () {
240
+ $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close');
241
+ });
242
+
243
+ }
244
+
245
+ });
246
+
247
+ $('.ui-dialog :button').blur();
248
+
249
+ });
250
+ });
251
+
252
+ //codemirror
253
+ $(document).ready(function () {
254
+ $('.codemirror').each(function (i, v) {
255
+ var editor = CodeMirror.fromTextArea(v, {
256
+ lineNumbers : 1,
257
+ mode : 'javascript',
258
+ showCursorWhenSelecting: true
259
+ })
260
+
261
+ $(v).data('codemirrorInstance', editor);
262
+ })
263
+ })
264
+
265
+ //google analytics generation
266
+ $(document).ready(function () {
267
+ $('.google-analytic-generate').click(function () {
268
+ var editor = $('#' + $(this).data('textarea')).data('codemirrorInstance');
269
+ var gatc = $('#' + $(this).data('input')).val();
270
+ var basename = $(this).data('basename');
271
+
272
+ var text = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n";
273
+ text += "(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement( o ),\n";
274
+ text += "m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n";
275
+ text += "})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n";
276
+ text += "ga('create', '" + gatc + "', '" + basename + "');\n";
277
+ text += "ga('send', 'pageview');\n";
278
+ editor.replaceRange(
279
+ text,
280
+ editor.getCursor('start'),
281
+ editor.getCursor('end')
282
+ )
283
+ })
284
+ })
285
+
286
+ })(jQuery);
plugin-fw/assets/js/yit-plugin-panel.min.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ (function(a){var k=function(){var b="";a(this).attr("multiple")?(a(this).children("option:selected").each(function(c,e){0!=c&&(b+=", ");b+=a(e).text()}),""==b&&a(this).children().children("option:selected").each(function(c,e){0!=c&&(b+=", ");b+=a(e).text()})):(b=a(this).children("option:selected").text(),""==b&&(b=a(this).children().children("option:selected").text()));0>=a(this).parent().find("span").length&&a(this).before("<span></span>");a(this).parent().children("span").replaceWith("<span>"+b+
2
+ "</span>")};a(".plugin-option .select_wrapper select").not(".chosen").each(k).change(k);a(".plugin-option .select_wrapper").click(function(b){b.stopPropagation();a(this).find("select[multiple]").not(".chosen").toggle()});a(".plugin-option .select_wrapper select[multiple]").not(".chosen").click(function(a){a.stopPropagation()});a(window).click(function(){a(".plugin-option .select_wrapper select[multiple]").not(".chosen").hide()});a(".plugin-option .chosen .select_wrapper select").chosen();a(".plugin-option .on_off_container span").on("click",
3
+ function(){var b=a(this).prev("input");b.prop("checked")?b.prop("checked",!1).attr("value","no").removeClass("onoffchecked"):b.prop("checked",!0).attr("value","yes").addClass("onoffchecked");b.change()});a(".plugin-option .slider_container .ui-slider-horizontal").each(function(){var b=a(this).data("val"),c=a(this).data("min"),e=a(this).data("max"),d=a(this).data("step"),l=a(this).data("labels");a(this).slider({value:b,min:c,max:e,range:"min",step:d,slide:function(b,c){a(this).find("input").val(c.value);
4
+ a(this).siblings(".feedback").find("strong").text(c.value+l)}})});if("undefined"!==typeof wp&&"undefined"!==typeof wp.media){var f=!0,m=wp.media.editor.send.attachment;a(".plugin-option .upload_img_url").change(function(){var b=a(this).val(),c=a(this).parent().siblings(".upload_img_preview");/(http|ftp|https):\/\/[a-zA-Z0-9@?^=%&amp;:/~+#-_.]*.(gif|jpg|jpeg|png|ico)/.test(b)?c.html('<img src="'+b+'" style="max-width:600px; max-height:300px;" />'):c.html("")}).change();a(document).on("click",".plugin-option .upload_button",
5
+ function(b){b=a(this);var c=b.attr("id").replace("-button","");f=!0;wp.media.editor.send.attachment=function(b,d){if(f)a("#"+c).is("input[type=text]")?a("#"+c).val(d.url):a("#"+c+"_custom").val(d.url);else return m.apply(this,[b,d])};wp.media.editor.open(b);return!1})}a(".plugin-option .add_media").on("click",function(){f=!1});a("[data-field]").each(function(){var b=a(this),c="#"+b.data("field"),e="#"+b.data("dep"),d=b.data("value");a(e).on("change",function(){var b=e,g=d.toString(),f=!0;if("string"==
6
+ typeof b){":radio"==b.substr(0,6)&&(b+=":checked");for(var g=g.split(","),h=0;h<g.length;h++)if(a(b).val()!=g[h])f=!1;else{f=!0;break}}f?a(c+"-container").closest("tr").show():a(c+"-container").closest("tr").hide()}).change()});a(".rm_connectedlist").each(function(){var b=a(this).find("ul"),c=a(this).find(":hidden");b.sortable({connectWith:b,update:function(e,d){var f={};b.each(function(){var b={};a(this).children().each(function(){b[a(this).data("option")]=a(this).text()});f[a(this).data("list")]=
7
+ b});c.val(JSON.stringify(f).replace(/[\\"']/g,"\\$&").replace(/\u0000/g,"\\0"))}}).disableSelection()});a(document).ready(function(){a(".yith-video-link").click(function(b){b.preventDefault();b=a(this).data("video-id");a("."+b).dialog({dialogClass:"wp-dialog yit-dialog yit-video-dialog",modal:!0,closeOnEscape:!0,width:"auto",resizable:!1,draggable:!1,create:function(b,e){a(this).css("maxWidth","853px")},open:function(b,e){a(".ui-widget-overlay").bind("click",function(){a(this).siblings(".ui-dialog").find(".ui-dialog-content").dialog("close")})}});
8
+ a(".ui-dialog :button").blur()})});a(document).ready(function(){a(".codemirror").each(function(b,c){var e=CodeMirror.fromTextArea(c,{lineNumbers:1,mode:"javascript",showCursorWhenSelecting:!0});a(c).data("codemirrorInstance",e)})});a(document).ready(function(){a(".google-analytic-generate").click(function(){var b=a("#"+a(this).data("textarea")).data("codemirrorInstance"),c=a("#"+a(this).data("input")).val(),e=a(this).data("basename"),d;d="(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement( o ),\nm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n";
9
+ d+="})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n";d+="ga('create', '"+c+"', '"+e+"');\n";d+="ga('send', 'pageview');\n";b.replaceRange(d,b.getCursor("start"),b.getCursor("end"))})})})(jQuery);
plugin-fw/assets/js/yit-wp-pointer.js ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready( function($) {
2
+
3
+ var pointers = custom_pointer.pointers[0],
4
+ options = pointers.options,
5
+ target = $(pointers.target),
6
+ pointer_id = pointers.pointer_id;
7
+
8
+ $(target).find('.wp-submenu li a').each(function () {
9
+
10
+ var t = $(this),
11
+ href = t.attr('href');
12
+
13
+ href = href.replace('admin.php?page=', '');
14
+
15
+ if( href == pointer_id ){
16
+
17
+ var selected_plugin_row = t.add( target ),
18
+ top_level_menu = target.find( pointers.target.replace( '#', '.' ) );
19
+
20
+ target.toggleClass('wp-no-current-submenu wp-menu-open wp-has-current-submenu');
21
+
22
+ t.pointer({
23
+ pointerClass: 'yit-wp-pointer',
24
+ content : options.content,
25
+ position: options.position,
26
+ open : function () { console.log( 'here' );
27
+ selected_plugin_row.toggleClass( 'yit-pointer-selected-row' );
28
+ top_level_menu.addClass( 'yit-pointer' );
29
+ },
30
+
31
+
32
+ close : function () {
33
+ target.toggleClass('wp-no-current-submenu wp-menu-open wp-has-current-submenu');
34
+ selected_plugin_row.toggleClass( 'yit-pointer-selected-row' );
35
+ top_level_menu.removeClass( 'yit-pointer' );
36
+
37
+ $.ajax({
38
+ type : 'POST',
39
+ url : ajaxurl,
40
+ data : {
41
+ "action" : "dismiss-wp-pointer",
42
+ "pointer": pointer_id
43
+ },
44
+ success: function (response) {
45
+ }
46
+ });
47
+
48
+ }
49
+ }).pointer('open');
50
+ } else if( 'yith_default_pointer' == pointer_id ) {
51
+
52
+ var selected_plugin_row = t.add( target ),
53
+ top_level_menu = target.find( pointers.target.replace( '#', '.' )),
54
+ yit_plugins = $( pointers.target );
55
+
56
+ yit_plugins.addClass('wp-has-current-submenu');
57
+
58
+ top_level_menu.pointer({
59
+ pointerClass: 'yit-wp-pointer',
60
+ content : options.content,
61
+ position: options.position,
62
+
63
+ open : function () {
64
+ yit_plugins.addClass( 'yit-pointer-selected-row' );
65
+ },
66
+
67
+ close : function () {
68
+ yit_plugins.removeClass( 'yit-pointer-selected-row wp-has-current-submenu' );
69
+
70
+ $.ajax({
71
+ type : 'POST',
72
+ url : ajaxurl,
73
+ data : {
74
+ "action" : "dismiss-wp-pointer",
75
+ "pointer": pointer_id
76
+ },
77
+ success: function (response) {
78
+ }
79
+ });
80
+ }
81
+ }).pointer('open');
82
+ }
83
+ });
84
+ });
plugin-fw/assets/js/yit-wp-pointer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ jQuery(document).ready(function(b){var c=custom_pointer.pointers[0],d=c.options,a=b(c.target),e=c.pointer_id;b(a).find(".wp-submenu li a").each(function(){var f=b(this),h=f.attr("href"),h=h.replace("admin.php?page=","");if(h==e){var k=f.add(a),g=a.find(c.target.replace("#","."));a.toggleClass("wp-no-current-submenu wp-menu-open wp-has-current-submenu");f.pointer({pointerClass:"yit-wp-pointer",content:d.content,position:d.position,open:function(){console.log("here");k.toggleClass("yit-pointer-selected-row");
2
+ g.addClass("yit-pointer")},close:function(){a.toggleClass("wp-no-current-submenu wp-menu-open wp-has-current-submenu");k.toggleClass("yit-pointer-selected-row");g.removeClass("yit-pointer");b.ajax({type:"POST",url:ajaxurl,data:{action:"dismiss-wp-pointer",pointer:e},success:function(a){}})}}).pointer("open")}else if("yith_default_pointer"==e){var k=f.add(a),g=a.find(c.target.replace("#",".")),l=b(c.target);l.addClass("wp-has-current-submenu");g.pointer({pointerClass:"yit-wp-pointer",content:d.content,
3
+ position:d.position,open:function(){l.addClass("yit-pointer-selected-row")},close:function(){l.removeClass("yit-pointer-selected-row wp-has-current-submenu");b.ajax({type:"POST",url:ajaxurl,data:{action:"dismiss-wp-pointer",pointer:e},success:function(a){}})}}).pointer("open")}})});
plugin-fw/lib/yit-cpt-unlimited.php ADDED
@@ -0,0 +1,1775 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if (!defined('ABSPATH')) {exit('Direct access forbidden.');
11
+ }
12
+
13
+ /**
14
+ * Manage the custom post types as Portfolio, Contact Forms and similar (called CPTU)
15
+ *
16
+ * @class YIT_CPT_Unlimited
17
+ * @package Yithemes
18
+ * @since 2.0.0
19
+ * @author Your Inspiration Themes
20
+ *
21
+ */
22
+
23
+ class YIT_CPT_Unlimited {
24
+
25
+ /**
26
+ * @var string The name of main post type of CPTU
27
+ * @since 1.0
28
+ */
29
+ protected $_name = '';
30
+
31
+ /**
32
+ * @var string The prefix of each post type created by the post of main CPTU
33
+ * @since 1.0
34
+ */
35
+ protected $_prefix_cpt = '';
36
+
37
+ /**
38
+ * @var string The labels defined for the main CPTU
39
+ * @since 1.0
40
+ */
41
+ protected $_labels = '';
42
+
43
+ /**
44
+ * @var string The configuration arguments of post type
45
+ * @since 1.0
46
+ */
47
+ protected $_args = '';
48
+
49
+ /**
50
+ * @var array All post types created by the post of main CPTU
51
+ * @since 1.0
52
+ */
53
+ public $post_types = array();
54
+
55
+ /**
56
+ * @var array $layouts Array with all portfolio layouts available for this site
57
+ * @since 1.0
58
+ */
59
+ public $layouts = array();
60
+
61
+ /**
62
+ * @var string $template_path The pathname of template folder
63
+ * @since 1.0
64
+ */
65
+ protected $template_path = '';
66
+
67
+ /**
68
+ * @var string $template_url The URL of template folder
69
+ * @since 1.0
70
+ */
71
+ protected $template_url = '';
72
+
73
+ /**
74
+ * @var int $_index Unique sequential ID to differentiate same shortcodes in the same page
75
+ */
76
+ public $index = 0;
77
+
78
+ /**
79
+ * @var string $_layout Temporary attribute to load automatically the settings for each layout
80
+ * @since 1.0
81
+ */
82
+ private $_layout = '';
83
+
84
+
85
+ /**
86
+ * Constructor
87
+ *
88
+ * Accept an array of arguments to define the characteristics of CPTU to register.
89
+ *
90
+ * @since 1.0
91
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
92
+ */
93
+ public function __construct( $args = array() ) {
94
+
95
+ $defaults = array(
96
+ 'name' => '',
97
+ 'post_type_prefix' => '',
98
+ 'labels' => array(
99
+ 'main_name' => '',
100
+ 'singular' => '',
101
+ 'plural' => '',
102
+ 'menu' => ''
103
+ ),
104
+ 'manage_layouts' => false,
105
+ 'add_multiuploader' => false,
106
+ 'sortable' => false,
107
+ 'has_single' => false,
108
+ 'has_taxonomy' => false,
109
+ 'label_item_sing' => '',
110
+ 'label_item_plur' => '',
111
+ 'shortcode_name' => '',
112
+ 'shortcode_icon' => '', // URL or icon name from http://melchoyce.github.io/dashicons/
113
+ 'layout_option' => '_type' // the option ID of layout metabox
114
+ );
115
+ $this->_args = wp_parse_args( $args, $defaults );
116
+
117
+ // fix labels
118
+ if ( empty( $this->_args['labels']['main_name'] ) ) {
119
+ $this->_args['labels']['main_name'] = $this->_args['labels']['singular'];
120
+ }
121
+ if ( empty( $this->_args['labels']['menu'] ) ) {
122
+ $this->_args['labels']['menu'] = $this->_args['labels']['singular'];
123
+ }
124
+
125
+ /* populate */
126
+ $this->_name = $this->_args['name'];
127
+ $this->_prefix_cpt = $this->_args['post_type_prefix'];
128
+ $this->_labels = $this->_args['labels'];
129
+
130
+ add_action( 'init', array( $this, 'register_post_type' ) );
131
+ add_action( 'init', array( $this, 'register_cptu_post_types' ) );
132
+
133
+ add_action( 'save_post', array( $this, 'rewrite_flush') );
134
+
135
+ // admin interface
136
+ add_action( 'admin_head', array( $this, 'add_cptu_menu_item' ) );
137
+ add_action( 'admin_init', array( $this, 'add_quick_links_metaboxes' ) );
138
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_assets' ) );
139
+
140
+ // metaboxes
141
+ add_action( 'after_setup_theme', array( $this, 'add_metabox_cptu' ), 2 );
142
+ add_action( 'after_setup_theme', array( $this, 'add_metabox_item_fields' ), 2 );
143
+
144
+ // multiuploader
145
+ if ( $this->_args['add_multiuploader'] ) {
146
+ add_action( 'admin_footer', array( $this, 'add_button_multiuploader' ) );
147
+ add_action( 'wp_ajax_yit_cptu_multiuploader', array( $this, 'post_multiuploader' ) );
148
+ }
149
+
150
+ // layouts
151
+ if ( $this->_args['manage_layouts'] ) {
152
+ // get all layouts available
153
+ $this->get_layouts();
154
+ }
155
+
156
+ // single layout
157
+ if ( $this->_args['has_single'] ) {
158
+ add_action( 'yit_loop', array( $this, 'single_template' ) );
159
+ add_action( 'wp', array( $this, 'single_template_config' ) );
160
+
161
+ if ( defined('DOING_AJAX') && DOING_AJAX ) {
162
+ add_action( 'init', array( $this, 'single_template_config' ) );
163
+ }
164
+ }
165
+
166
+ // archive template
167
+ add_action( 'wp', array( $this, 'archive_template' ) );
168
+
169
+ // enqueue the assets of each layout
170
+ add_action( 'wp_enqueue_scripts', array( $this, 'frontend_assets' ) );
171
+
172
+ // add the shortcode, used to show the frontend
173
+ if ( ! empty( $this->_args['shortcode_name'] ) ) {
174
+ add_shortcode( $this->_args['shortcode_name'], array( &$this, 'add_shortcode' ) );
175
+ add_filter( 'yit_shortcode_' . $this->_args['shortcode_name'] . '_icon', array( $this, 'shortcode_icon') );
176
+ add_filter( 'yit-shortcode-plugin-init', array( $this, 'add_shortcode_to_box' ) );
177
+ }
178
+
179
+ // add sortable feature
180
+ if ( $this->_args['sortable'] ) {
181
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_sortable_assets' ) );
182
+ add_action( 'wp_ajax_cpt_sort_posts', array( $this, 'sort_posts' ) );
183
+ add_action( 'admin_init', array( $this, 'init_menu_order' ) );
184
+ add_filter( 'pre_get_posts', array( $this, 'filter_active' ) );
185
+ add_filter( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
186
+ add_filter( 'get_next_post_where', array( $this, 'sorted_next_post_where' ) );
187
+ add_filter( 'get_previous_post_where', array( $this, 'sorted_prev_post_where' ) );
188
+ add_filter( 'get_next_post_sort', array( $this, 'sorted_next_post_sort' ) );
189
+ add_filter( 'get_previous_post_sort', array( $this, 'sorted_prev_post_sort' ) );
190
+ }
191
+
192
+ // add default columns to post type table list
193
+ add_filter( 'manage_edit-' . $this->_name . '_columns', array( $this, 'cptu_define_columns' ) );
194
+ add_action( 'manage_' . $this->_name . '_posts_custom_column' , array( $this, 'cptu_change_columns' ), 10, 2 );
195
+
196
+ // add required post type for wordpress importer
197
+ add_filter( 'wp_import_post_data_raw', array( $this, 'add_importer_required_post_type' ) );
198
+ add_filter( 'wp_import_terms', array( $this, 'add_importer_required_taxonomy' ) );
199
+ add_action( 'wp_import_set_post_terms', array( $this, 'recount_terms_post' ), 10, 3 );
200
+
201
+ }
202
+
203
+ /**
204
+ * Enqueue the assets for the sortable feature
205
+ *
206
+ * @return void
207
+ * @since 1.0
208
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
209
+ */
210
+ public function admin_sortable_assets() {
211
+ global $post;
212
+
213
+ if ( ! isset( $post->post_type ) || ! $this->_is_valid( $post->post_type ) ) {
214
+ return;
215
+ }
216
+
217
+ wp_enqueue_script( 'yit-cptu-sortable-posts', YIT_CORE_PLUGIN_URL . '/assets/js/yit-cptu-sortable-posts.js', array( 'jquery', 'jquery-ui-sortable' ), '1.0', true );
218
+ }
219
+
220
+ public function init_menu_order( $post_types = array() ) {
221
+ global $wpdb;
222
+
223
+ if ( empty( $post_types ) ) {
224
+ $post_types = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT post_type FROM $wpdb->posts WHERE post_type LIKE %s", str_replace( '_', '\_', $this->_prefix_cpt ) . '%' ) );
225
+ } elseif ( ! is_array( $post_types ) ) {
226
+ $post_types = array( $post_types );
227
+ }
228
+
229
+ foreach ( $post_types as $post_type ) {
230
+ $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = '{$post_type}' AND post_status IN ('publish', 'pending', 'draft', 'private', 'future') AND menu_order = 0" );
231
+
232
+ if ( empty( $count ) ) {
233
+ continue;
234
+ }
235
+
236
+ $sql = "SELECT ID
237
+ FROM $wpdb->posts
238
+ WHERE post_type = '" . $post_type . "'
239
+ AND post_status IN ('publish', 'pending', 'draft', 'private', 'future')
240
+ ORDER BY post_date DESC
241
+ ";
242
+
243
+ $results = $wpdb->get_results( $sql );
244
+
245
+ foreach ( $results as $key => $result ) {
246
+ $wpdb->update( $wpdb->posts, array( 'menu_order' => $key + 1 ), array( 'ID' => $result->ID ) );
247
+ }
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Save the order of posts from sortable feature
253
+ *
254
+ * @return void
255
+ * @since 1.0
256
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
257
+ */
258
+ public function sort_posts() {
259
+ global $wpdb;
260
+
261
+ parse_str( $_REQUEST['order'], $data );
262
+
263
+ if ( is_array( $data ) ) {
264
+ //$this->init_menu_order( $_REQUEST['post_type'] );
265
+
266
+ $id_arr = array( );
267
+ foreach ( $data as $key => $values ) {
268
+ foreach ( $values as $position => $id ) {
269
+ $id_arr[] = $id;
270
+ }
271
+ }
272
+
273
+
274
+ $menu_order_arr = array( );
275
+ foreach ( $id_arr as $key => $id ) {
276
+ $results = $wpdb->get_results( "SELECT menu_order FROM $wpdb->posts WHERE ID = " . $id );
277
+ foreach ( $results as $result ) {
278
+ $menu_order_arr[] = $result->menu_order;
279
+ }
280
+ }
281
+
282
+ sort( $menu_order_arr );
283
+
284
+ foreach ( $data as $key => $values ) {
285
+ foreach ( $values as $position => $id ) {
286
+ $wpdb->update( $wpdb->posts, array( 'menu_order' => $menu_order_arr[$position] ), array( 'ID' => $id ) );
287
+ }
288
+ }
289
+ }
290
+
291
+ die();
292
+ }
293
+
294
+ public function filter_active( $wp_query ) {
295
+ if ( isset( $wp_query->query['suppress_filters'] ) )
296
+ $wp_query->query['suppress_filters'] = false;
297
+ if ( isset( $wp_query->query_vars['suppress_filters'] ) )
298
+ $wp_query->query_vars['suppress_filters'] = false;
299
+ return $wp_query;
300
+ }
301
+
302
+ public function pre_get_posts( $wp_query ) {
303
+ if ( is_admin() && !defined( 'DOING_AJAX' ) ) {
304
+ if ( isset( $wp_query->query['post_type'] ) ) {
305
+ $post_types = (array) $wp_query->query['post_type'];
306
+ foreach ( $post_types as $post_type ) {
307
+ if ( $this->_is_valid( $post_type ) ) {
308
+ $wp_query->set( 'orderby', 'menu_order' );
309
+ $wp_query->set( 'order', 'ASC' );
310
+ }
311
+ }
312
+ }
313
+
314
+ } else {
315
+
316
+ $active = false;
317
+
318
+ if ( isset( $wp_query->query['suppress_filters'] ) || isset( $wp_query->query['post_type'] ) ) {
319
+ $post_types = (array) $wp_query->query['post_type'];
320
+ foreach ( $post_types as $post_type ) {
321
+ if ( $this->_is_valid( $post_type ) ) {
322
+ $active = true;
323
+ }
324
+ }
325
+ }
326
+
327
+ if ( $active ) {
328
+ if ( !isset( $wp_query->query['orderby'] ) || $wp_query->query['orderby'] == 'post_date' )
329
+ $wp_query->set( 'orderby', 'menu_order' );
330
+ if ( !isset( $wp_query->query['order'] ) || $wp_query->query['order'] == 'DESC' )
331
+ $wp_query->set( 'order', 'ASC' );
332
+ }
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Filters where clause for get next post
338
+ *
339
+ * @param $where
340
+ *
341
+ * @return string
342
+ * @since 1.0
343
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
344
+ */
345
+ public function sorted_next_post_where( $where ){
346
+ global $post;
347
+ if( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['post_id'] ) ){
348
+ $post = get_post( intval( $_REQUEST['post_id'] ) );
349
+ }
350
+ else{
351
+ $post = get_post();
352
+ }
353
+
354
+ if( ! $post || ! $this->_is_valid( $post->post_type ) ){
355
+ return $where;
356
+ }
357
+
358
+ $result = str_replace( "'" . $post->post_date . "'", $post->menu_order, $where );
359
+ $result = str_replace( 'p.post_date', 'p.menu_order', $result );
360
+
361
+ return $result;
362
+ }
363
+
364
+ /**
365
+ * Filters where clause for get prev post
366
+ *
367
+ * @param $where
368
+ *
369
+ * @return string
370
+ * @since 1.0
371
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
372
+ */
373
+ public function sorted_prev_post_where( $where ){
374
+ global $post;
375
+
376
+ if( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['post_id'] ) ){
377
+ $post = get_post( intval( $_REQUEST['post_id'] ) );
378
+ }
379
+ else{
380
+ $post = get_post();
381
+ }
382
+
383
+ if( ! $post || ! $this->_is_valid( $post->post_type ) ){
384
+ return $where;
385
+ }
386
+
387
+ $result = str_replace( "'" . $post->post_date . "'", $post->menu_order, $where );
388
+ $result = str_replace( 'p.post_date', 'p.menu_order', $result );
389
+
390
+ return $result;
391
+ }
392
+
393
+ /**
394
+ * Filters sort clause for get next post
395
+ *
396
+ * @param $sort
397
+ *
398
+ * @return string
399
+ * @since 1.0
400
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
401
+ */
402
+ public function sorted_next_post_sort( $sort ){
403
+ global $post;
404
+
405
+ if( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['post_id'] ) ){
406
+ $post = get_post( intval( $_REQUEST['post_id'] ) );
407
+ }
408
+ else{
409
+ $post = get_post();
410
+ }
411
+
412
+ if( ! $post || ! $this->_is_valid( $post->post_type ) ){
413
+ return $sort;
414
+ }
415
+
416
+ $result = str_replace( 'p.post_date', 'p.menu_order', $sort );
417
+ return $result;
418
+ }
419
+
420
+ /**
421
+ * Filters sort clause for get prev post
422
+ *
423
+ * @param $sort
424
+ *
425
+ * @return string
426
+ * @since 1.0
427
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
428
+ */
429
+ public function sorted_prev_post_sort( $sort ){
430
+ global $post;
431
+
432
+ if( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['post_id'] ) ){
433
+ $post = get_post( intval( $_REQUEST['post_id'] ) );
434
+ }
435
+ else{
436
+ $post = get_post();
437
+ }
438
+
439
+ if( ! $post || ! $this->_is_valid( $post->post_type ) ){
440
+ return $sort;
441
+ }
442
+
443
+ $result = str_replace( 'p.post_date', 'p.menu_order', $sort );
444
+ return $result;
445
+ }
446
+
447
+ /**
448
+ * Register post type
449
+ *
450
+ * Register the post type for the creation of portfolios
451
+ *
452
+ * @return void
453
+ * @since 1.0
454
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
455
+ */
456
+ public function register_post_type() {
457
+ $labels = array(
458
+ 'name' => ucfirst( $this->_labels['main_name'] ),
459
+ 'singular_name' => ucfirst( $this->_labels['singular'] ),
460
+ 'add_new' => sprintf( __( 'Add %s', 'yit' ), ucfirst( $this->_labels['singular'] ) ),
461
+ 'add_new_item' => sprintf( __( 'Add New %s', 'yit' ), ucfirst( $this->_labels['singular'] ) ),
462
+ 'edit_item' => sprintf( __( 'Edit %s', 'yit' ), ucfirst( $this->_labels['singular'] ) ),
463
+ 'new_item' => sprintf( __( 'New %s', 'yit' ), ucfirst( $this->_labels['singular'] ) ),
464
+ 'all_items' => sprintf( __( 'All %s', 'yit' ), ucfirst( $this->_labels['plural'] ) ),
465
+ 'view_item' => sprintf( __( 'View %s', 'yit' ), ucfirst( $this->_labels['singular'] ) ),
466
+ 'search_items' => sprintf( __( 'Search %s', 'yit' ), ucfirst( $this->_labels['plural'] ) ),
467
+ 'not_found' => sprintf( __( 'No %s found', 'yit' ), ucfirst( $this->_labels['plural'] ) ),
468
+ 'not_found_in_trash' => sprintf( __( 'No %s found in Trash', 'yit' ), ucfirst( $this->_labels['plural'] ) ),
469
+ 'parent_item_colon' => '',
470
+ 'menu_name' => ucfirst( $this->_labels['menu'] )
471
+ );
472
+
473
+ $args = array(
474
+ 'labels' => apply_filters( 'yit_' . $this->_name . '_labels', $labels ),
475
+ 'public' => false,
476
+ 'publicly_queryable' => false,
477
+ 'show_ui' => true,
478
+ 'show_in_menu' => true,
479
+ 'query_var' => false,
480
+ 'capability_type' => 'post',
481
+ 'hierarchical' => false,
482
+ 'menu_position' => null,
483
+ 'supports' => array( 'title' )
484
+ );
485
+
486
+ if ( ! empty( $this->_args['menu_icon'] ) ) {
487
+ $args['menu_icon'] = $this->_args['menu_icon'];
488
+ }
489
+
490
+ register_post_type( $this->_name, apply_filters( 'yit_' . $this->_name . '_args', $args ) );
491
+ }
492
+
493
+ /**
494
+ * Retrieve the values configured inside the custom post type
495
+ *
496
+ * @param $post /WP_Query The post where get the arguments configured in the cpt
497
+ *
498
+ * @return array
499
+ * @since 1.0
500
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
501
+ */
502
+ protected function _cpt_args( $post ) {
503
+ if ( ! isset( $post->ID ) ) {
504
+ return;
505
+ }
506
+
507
+ $args = apply_filters( 'yit_cptu_register_post_type_args', array(
508
+ 'layout' => get_post_meta( $post->ID, $this->_args['layout_option'], true ),
509
+ 'rewrite' => get_post_meta( $post->ID, '_rewrite', true ),
510
+ 'label_singular' => ! empty( $this->_args['label_item_sing'] ) ? $this->_args['label_item_sing'] : get_post_meta( $post->ID, '_label_singular', true ),
511
+ 'label_plural' => ! empty( $this->_args['label_item_plur'] ) ? $this->_args['label_item_plur'] : get_post_meta( $post->ID, '_label_plural', true ),
512
+ 'taxonomy' => get_post_meta( $post->ID, '_taxonomy', true ),
513
+ 'taxonomy_rewrite' => get_post_meta( $post->ID, '_taxonomy_rewrite', true ),
514
+ ), $this->_name, $post );
515
+
516
+ $title = $post->post_title;
517
+
518
+ if ( empty( $args['label_singular'] ) ) {
519
+ $args['label_singular'] = $title;
520
+ }
521
+
522
+ if ( empty( $args['label_plural'] ) ) {
523
+ $args['label_plural'] = $title;
524
+ }
525
+
526
+ return $args;
527
+ }
528
+
529
+ /**
530
+ * Retrieve the post types created for this CPTU
531
+ *
532
+ * @return array The link changed
533
+ * @since 1.0
534
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
535
+ */
536
+ public function get_post_types() {
537
+ if ( ! empty( $this->post_types ) ) {
538
+ return $this->post_types;
539
+ }
540
+
541
+ $args = array(
542
+ 'post_type' => $this->_name,
543
+ 'posts_per_page' => -1,
544
+ 'post_status' => 'publish'
545
+ );
546
+ $this->post_types = get_posts( $args );
547
+
548
+ return $this->post_types;
549
+ }
550
+
551
+ /**
552
+ * Register portfolio post types
553
+ *
554
+ * Register the post types for each portfolio created by admin
555
+ *
556
+ * @return void
557
+ * @since 1.0
558
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
559
+ */
560
+ public function register_cptu_post_types() {
561
+ $post_types = $this->get_post_types();
562
+ $pts = array();
563
+
564
+ foreach ( $post_types as $pt ) {
565
+
566
+ extract( $this->_cpt_args( $pt ) );
567
+
568
+ $name = $pt->post_name;
569
+ $title = $pt->post_title;
570
+
571
+ $labels = array(
572
+ 'name' => $title,
573
+ 'singular_name' => $label_singular,
574
+ 'add_new' => sprintf( __( 'Add %s', 'yit' ), $label_singular ),
575
+ 'add_new_item' => sprintf( __( 'Add New %s', 'yit' ), $label_singular ),
576
+ 'edit_item' => sprintf( __( 'Edit %s', 'yit' ), $label_singular ),
577
+ 'new_item' => sprintf( __( 'New %s', 'yit' ), $label_singular ),
578
+ 'all_items' => sprintf( __( 'All %s', 'yit' ), $label_plural ),
579
+ 'view_item' => sprintf( __( 'View %s', 'yit' ), $label_singular ),
580
+ 'search_items' => sprintf( __( 'Search %s', 'yit' ), $label_plural ),
581
+ 'not_found' => sprintf( __( 'No %s found', 'yit' ), $label_plural ),
582
+ 'not_found_in_trash' => sprintf( __( 'No %s found in Trash', 'yit' ), $label_plural ),
583
+ 'parent_item_colon' => '',
584
+ 'menu_name' => $title
585
+ );
586
+
587
+ $args = array(
588
+ 'labels' => apply_filters( 'yit_' . $this->_prefix_cpt . $name . '_labels', $labels ),
589
+ 'public' => true,
590
+ 'publicly_queryable' => true,
591
+ 'show_ui' => true,
592
+ 'show_in_menu' => false,
593
+ 'query_var' => true,
594
+ 'capability_type' => 'post',
595
+ 'hierarchical' => false,
596
+ 'menu_position' => null,
597
+ 'supports' => array( 'title', 'editor', 'thumbnail' )
598
+ );
599
+
600
+ if ( ! $this->_args['has_single'] ) {
601
+ $args['public'] = false;
602
+ $args['publicly_queryable'] = false;
603
+ $args['query_var'] = false;
604
+ }
605
+
606
+ if ( $this->_args['manage_layouts'] && isset($this->layouts[ $layout ]) && ! $this->layouts[ $layout ]['support']['description'] ) {
607
+ unset( $args['supports'][1] ); // remove 'editor'
608
+ }
609
+
610
+ if ( ! empty( $rewrite ) ) {
611
+ $args['rewrite'] = array( 'slug' => $rewrite );
612
+ }
613
+
614
+ // register post type
615
+ $post_type = yit_avoid_duplicate( str_replace( '-', '_', substr( $this->_prefix_cpt . $name, 0, 16) ), $post_types );
616
+ register_post_type( $post_type, apply_filters( 'yit_' . $this->_prefix_cpt . $name . '_args', $args, $pt ) ); // save the post type in post meta
617
+
618
+ update_post_meta( $pt->ID, '_post_type', $post_type );
619
+ $pts[] = $post_type;
620
+
621
+ // register taxonomy
622
+ if ( $this->_args['has_taxonomy'] && ! empty( $taxonomy ) ) {
623
+
624
+ $labels = array(
625
+ 'name' => sprintf( _x( '%s Categories', 'taxonomy general name', 'yit' ), $label_singular ),
626
+ 'singular_name' => _x( 'Category', 'taxonomy singular name', 'yit' ),
627
+ 'search_items' => __( 'Search Categories', 'yit' ),
628
+ 'all_items' => __( 'All Categories', 'yit' ),
629
+ 'parent_item' => __( 'Parent Category', 'yit' ),
630
+ 'parent_item_colon' => __( 'Parent Category:', 'yit' ),
631
+ 'edit_item' => __( 'Edit Category', 'yit' ),
632
+ 'update_item' => __( 'Update Category', 'yit' ),
633
+ 'add_new_item' => __( 'Add New Category', 'yit' ),
634
+ 'new_item_name' => __( 'New Category Name', 'yit' ),
635
+ 'menu_name' => __( 'Category', 'yit' ),
636
+ );
637
+
638
+ $args = array(
639
+ 'hierarchical' => true,
640
+ 'labels' => $labels,
641
+ 'show_ui' => true,
642
+ 'show_admin_column' => true,
643
+ 'query_var' => true,
644
+ );
645
+
646
+ if ( ! empty( $taxonomy_rewrite ) ) {
647
+ $args['rewrite'] = array( 'slug' => $taxonomy_rewrite );
648
+ }
649
+
650
+ register_taxonomy( substr( $taxonomy, 0, 32 ), $post_type, $args );
651
+
652
+ }
653
+
654
+ }
655
+
656
+ wp_cache_set( 'yit_cptu_post_types', $post_types );
657
+ }
658
+
659
+ /**
660
+ * Flush Rewrite Rules
661
+ *
662
+ * rewrite rules when a cpt unlimited is saved
663
+ *
664
+ * @return void
665
+ * @since 1.0
666
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
667
+ */
668
+
669
+ public function rewrite_flush( $post ){
670
+
671
+ if ( isset( $post ) && $this->_is_valid( get_post_type( intval( $post ) ) ) ) {
672
+ flush_rewrite_rules();
673
+ }
674
+
675
+ }
676
+
677
+ /**
678
+ * Add the item for each portfolio under "Portfolios"
679
+ *
680
+ * @return void
681
+ * @since 1.0
682
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
683
+ */
684
+ public function add_cptu_menu_item() {
685
+ global $submenu, $post, $parent_file, $pagenow;
686
+
687
+ // get current post type
688
+ if ( isset( $post->post_type ) ) {
689
+ $post_type = $post->post_type;
690
+ } else if ( isset( $_REQUEST['post_type'] ) ) {
691
+ $post_type = $_REQUEST['post_type'];
692
+ } else {
693
+ return;
694
+ }
695
+
696
+ $item = 'edit.php?post_type=' . $this->_name;
697
+
698
+ // add new items
699
+ if ( strpos( $post_type, $this->_prefix_cpt ) !== false ) {
700
+ global $wpdb;
701
+ $portfolio = $wpdb->get_row( $wpdb->prepare( "SELECT p.* FROM $wpdb->postmeta AS pm INNER JOIN $wpdb->posts AS p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND pm.meta_value = %s AND p.post_type = %s", '_post_type', $post_type, $this->_name ) );
702
+
703
+ if ( ! isset( $portfolio->ID ) ) {
704
+ return;
705
+ }
706
+
707
+ $label_singular = ! empty( $this->_args['label_item_sing'] ) ? $this->_args['label_item_sing'] : get_post_meta( $portfolio->ID, '_label_singular', true );
708
+ $label_plural = ! empty( $this->_args['label_item_plur'] ) ? $this->_args['label_item_plur'] : get_post_meta( $portfolio->ID, '_label_plural', true );
709
+
710
+ if ( empty( $label_plural ) ) {
711
+ $label_plural = $portfolio->post_title;
712
+ }
713
+
714
+ if ( empty( $label_singular ) ) {
715
+ $label_singular = $portfolio->post_title;
716
+ }
717
+
718
+ $submenu[ $item ][15] = array( ucfirst( $label_plural ), 'edit_posts', 'edit.php?post_type=' . $post_type );
719
+ $submenu[ $item ][20] = array( sprintf( __('Add %s', 'yit'), ucfirst( $label_singular ) ), 'edit_posts', 'post-new.php?post_type=' . $post_type );
720
+
721
+ global $wp_taxonomies;
722
+ $taxonomy = get_post_meta( $portfolio->ID, '_taxonomy', true );
723
+ if ( isset( $wp_taxonomies[ $taxonomy ] ) ) {
724
+ $submenu[ $item ][25] = array( __('Categories', 'yit'), 'edit_posts', 'edit-tags.php?taxonomy=' . $taxonomy . '&post_type=' . $post_type );
725
+ }
726
+ }
727
+
728
+ // set the parent item inside the single of each post type
729
+ if ( $pagenow == 'post.php' && isset( $_GET['post'] ) && $this->_is_valid( get_post_type( intval( $_GET['post'] ) ) ) ) {
730
+ $parent_file = 'edit.php?post_type=' . $this->_name;
731
+ }
732
+ }
733
+
734
+ /**
735
+ * Locate folder of CPTU templates, if there isn't a layouts management
736
+ *
737
+ * @return string
738
+ * @since 1.0
739
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
740
+ */
741
+ public function template_path() {
742
+ if ( ! empty( $this->template_path ) ) {
743
+ return $this->template_path;
744
+ }
745
+
746
+ // paths
747
+ $stylesheet_path_1 = get_stylesheet_directory() . '/theme/templates/' . $this->_name . '/';
748
+ $stylesheet_path_2 = get_template_directory() . '/theme/templates/' . $this->_name . '/';
749
+ $template_path_1 = get_stylesheet_directory() . '/' . $this->_name . '/';
750
+ $template_path_2 = get_template_directory() . '/' . $this->_name . '/';
751
+ $plugin_path = $this->_args['plugin_path'] . '/templates/';
752
+
753
+ foreach ( array( 'stylesheet_path_1', 'stylesheet_path_2', 'template_path_1', 'template_path_2', 'plugin_path' ) as $var ) {
754
+ $path = ${$var};
755
+
756
+ if ( file_exists( $path ) ) {
757
+ $this->template_path = $path;
758
+ }
759
+ }
760
+
761
+ return $this->template_path;
762
+ }
763
+
764
+ /**
765
+ * Locate folder of CPTU templates, if there isn't a layouts management
766
+ *
767
+ * @return string
768
+ * @since 1.0
769
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
770
+ */
771
+ public function template_url() {
772
+ if ( ! empty( $this->template_url ) ) {
773
+ return $this->template_path;
774
+ }
775
+
776
+ $this->template_url = str_replace( array(
777
+ get_stylesheet_directory(),
778
+ get_template_directory(),
779
+ $this->_args['plugin_path']
780
+ ), array(
781
+ get_stylesheet_directory_uri(),
782
+ get_template_directory_uri(),
783
+ $this->_args['plugin_url']
784
+ ), $this->template_path() );
785
+
786
+ return $this->template_url;
787
+ }
788
+
789
+ /**
790
+ * Retrieve all layouts to manage by custom post type added in the site in this order:
791
+ * 1. Child theme (if exists)
792
+ * 2. Theme
793
+ * 3. Plugin
794
+ *
795
+ * It also load the config.php file of each layout
796
+ *
797
+ * @return void
798
+ * @since 1.0
799
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
800
+ */
801
+ public function get_layouts() {
802
+
803
+ // paths
804
+ $stylesheet_path_1 = get_stylesheet_directory() . '/theme/templates/' . $this->_name . '/';
805
+ $stylesheet_path_2 = get_template_directory() . '/theme/templates/' . $this->_name . '/';
806
+ $template_path_1 = get_stylesheet_directory() . '/' . $this->_name . '/';
807
+ $template_path_2 = get_template_directory() . '/' . $this->_name . '/';
808
+ $plugin_path = $this->_args['plugin_path'] . '/templates/';
809
+
810
+ foreach ( array( 'stylesheet_path_1', 'stylesheet_path_2', 'template_path_1', 'template_path_2', 'plugin_path' ) as $var ) {
811
+ $path = ${$var};
812
+
813
+ if ( file_exists( $path ) ) {
814
+ foreach ( scandir( $path ) as $scan ) {
815
+ if ( ! isset( $this->layouts[$scan] ) && is_dir( $path . $scan ) && ! in_array( $scan, array( '.', '..', '.svn' ) ) && $scan[0] != '_' ) {
816
+ $this->layouts[$scan] = array(
817
+ 'name' => ucfirst( str_replace( '-', ' ', $scan ) ),
818
+ 'path' => $path . $scan,
819
+ 'url' => str_replace( array(
820
+ get_stylesheet_directory(),
821
+ get_template_directory(),
822
+ $this->_args['plugin_path']
823
+ ), array(
824
+ get_stylesheet_directory_uri(),
825
+ get_template_directory_uri(),
826
+ $this->_args['plugin_url']
827
+ ), $path . $scan ),
828
+ 'css' => array(),
829
+ 'js' => array(),
830
+ 'support' => array(
831
+ 'description' => true
832
+ ),
833
+ 'columns' => array()
834
+ );
835
+
836
+ // set the vars for config.php
837
+ $layout = $scan;
838
+ $this->_layout = $layout; // temporary attribute to load automatically the configuration inside the config.php, for this layout
839
+
840
+ // TODO Fare in modo di caricare il file config.php soltanto quando realmente serve
841
+ if ( ! in_array( $scan, array( 'single' ) ) && file_exists( $path . $scan . '/config.php' ) ) {
842
+ include_once( $path . $scan . '/config.php' );
843
+ }
844
+ }
845
+ }
846
+ }
847
+
848
+ }
849
+ }
850
+
851
+ /**
852
+ * Say if you want to set description for the current layout or not. This method must be used only inside the
853
+ * config.php file of layout
854
+ *
855
+ * @param $v string 'yes' or 'no'
856
+ *
857
+ * @return void
858
+ * @since 1.0
859
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
860
+ */
861
+ public function add_description_field( $v ) {
862
+ $this->layouts[ $this->_layout ]['support']['description'] = $v == 'yes' ? true : false;
863
+ }
864
+
865
+ /**
866
+ * Add the extra fields for the specific layout type of portfolio
867
+ *
868
+ * @param array $fields The fields to add
869
+ *
870
+ * @return void
871
+ * @since 1.0
872
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
873
+ */
874
+ public function add_layout_fields( $fields = array() ) {
875
+ // change the ID
876
+ foreach ( $fields as $id => $val ) {
877
+ unset( $fields[ $id ] );
878
+ $id = $this->_layout . '_' . $id;
879
+ $fields[ $id ] = $val;
880
+ }
881
+
882
+ $this->layouts[ $this->_layout ]['fields'] = $fields;
883
+ }
884
+
885
+ /**
886
+ * Add fields to add to the metabox of each item of each post type created
887
+ *
888
+ * @param array $fields The fields to add
889
+ *
890
+ * @return void
891
+ * @since 1.0
892
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
893
+ */
894
+ public function add_item_fields( $fields = array() ) {
895
+ // change the ID
896
+ foreach ( $fields as $id => $val ) {
897
+ unset( $fields[ $id ] );
898
+ //$id = $this->_layout . '_' . $id;
899
+ $fields[ $id ] = $val;
900
+ }
901
+ $this->layouts[ $this->_layout ]['item_fields'] = $fields;
902
+ }
903
+
904
+ /**
905
+ * Add columns to the table list
906
+ *
907
+ * @param array $columns The columns to add in the table list
908
+ *
909
+ * @return void
910
+ * @since 1.0
911
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
912
+ */
913
+ public function add_table_columns( $columns ) {
914
+ $this->layouts[ $this->_layout ]['columns'] = $columns;
915
+ }
916
+
917
+ /**
918
+ * Enqueue the css files of layout
919
+ *
920
+ * @param string $handle Name of the stylesheet.
921
+ * @param string|bool $src Path to the stylesheet from the root directory of WordPress. Example: '/css/mystyle.css'.
922
+ * @param array $deps An array of registered style handles this stylesheet depends on. Default empty array.
923
+ * @param string|bool $ver String specifying the stylesheet version number, if it has one. This parameter is used
924
+ * to ensure that the correct version is sent to the client regardless of caching, and so
925
+ * should be included if a version number is available and makes sense for the stylesheet.
926
+ * @param string $media Optional. The media for which this stylesheet has been defined.
927
+ * Default 'all'. Accepts 'all', 'aural', 'braille', 'handheld', 'projection', 'print',
928
+ * 'screen', 'tty', or 'tv'.
929
+ *
930
+ * @return void
931
+ * @since 1.0
932
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
933
+ */
934
+ public function enqueue_style( $handle, $src = false, $deps = array(), $ver = false, $media = 'all' ) {
935
+ $this->layouts[ $this->_layout ]['css'][] = compact( 'handle', 'src', 'deps', 'ver', 'media' );
936
+ }
937
+
938
+ /**
939
+ * Enqueue the js files of layout
940
+ *
941
+ * @param string $handle Name of the script.
942
+ * @param string|bool $src Path to the script from the root directory of WordPress. Example: '/js/myscript.js'.
943
+ * @param array $deps An array of registered handles this script depends on. Default empty array.
944
+ * @param string|bool $ver Optional. String specifying the script version number, if it has one. This parameter
945
+ * is used to ensure that the correct version is sent to the client regardless of caching,
946
+ * and so should be included if a version number is available and makes sense for the script.
947
+ * @param bool $in_footer Optional. Whether to enqueue the script before </head> or before </body>.
948
+ * Default 'false'. Accepts 'false' or 'true'.
949
+ *
950
+ * @return void
951
+ * @since 1.0
952
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
953
+ */
954
+ public function enqueue_script( $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) {
955
+ $this->layouts[ $this->_layout ]['js'][] = compact( 'handle', 'src', 'deps', 'ver', 'in_footer' );
956
+ }
957
+
958
+ /**
959
+ * Enqueue the assets for the frontend
960
+ *
961
+ * @return void
962
+ * @since 1.0
963
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
964
+ */
965
+ public function frontend_assets() {
966
+ global $post;
967
+
968
+ // not single
969
+ if ( ! is_single() || ! isset( $post->post_type ) || ! $this->_is_valid( $post->post_type ) ) {
970
+ $posts = get_posts(array(
971
+ 'post_type' => $this->_name,
972
+ 'posts_per_page' => -1,
973
+ 'post_status' => 'publish',
974
+ 'fields' => 'ids'
975
+ ));
976
+
977
+ $enqueued = array();
978
+
979
+ foreach ( $posts as $post_id ) {
980
+ $layout = get_post_meta( $post_id, $this->_args['layout_option'], true );
981
+
982
+ if ( in_array( $layout, array( $enqueued ) ) || ! isset( $this->layouts[ $layout ]['css'] ) ) {
983
+ continue;
984
+ }
985
+
986
+ foreach ( $this->layouts[ $layout ]['css'] as $asset ) {
987
+ if ( empty( $asset ) ) {
988
+ continue;
989
+ }
990
+ yit_enqueue_style( $asset['handle'], empty( $asset['src'] ) ? false : $this->locate_url( $layout ) . $asset['src'], $asset['deps'], $asset['ver'], $asset['media'] );
991
+ }
992
+
993
+ $enqueued[] = $layout;
994
+ }
995
+ }
996
+
997
+ // load assets of single template
998
+ else {
999
+ $layout = 'single';
1000
+
1001
+ if ( ! isset( $this->layouts[ $layout ]['css'] ) ) {
1002
+ return;
1003
+ }
1004
+
1005
+ foreach ( $this->layouts[ $layout ]['css'] as $asset ) {
1006
+ if ( empty( $asset ) ) {
1007
+ continue;
1008
+ }
1009
+ yit_enqueue_style( $asset['handle'], $this->locate_url( $layout ) . $asset['src'], $asset['deps'], $asset['ver'], $asset['media'] );
1010
+ }
1011
+ }
1012
+
1013
+ }
1014
+
1015
+ /**
1016
+ * Register Metaboxes options
1017
+ *
1018
+ * Add the metabox for the portfolio settings
1019
+ *
1020
+ * @return void
1021
+ * @since 1.0
1022
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1023
+ */
1024
+ public function add_metabox_cptu() {
1025
+
1026
+ // Reorganize layouts
1027
+ if ( $this->_args['manage_layouts'] ) {
1028
+ $layouts = array();
1029
+ foreach ( $this->layouts as $layout_id => $layout ) {
1030
+ if ( 'single' == $layout_id ) {
1031
+ continue;
1032
+ }
1033
+ $layouts[ $layout_id ] = $layout['name'];
1034
+ }
1035
+
1036
+ $layouts = apply_filters( 'yit_cptu_' . $this->_name . '_layout_values', $layouts );
1037
+ }
1038
+
1039
+ $single_layouts = apply_filters( 'yit_cptu_' . $this->_name . '_single_layout_values', array() );
1040
+
1041
+ $metabox_args = array(
1042
+ 'label' => sprintf( __( '%s Settings', 'yit' ), $this->_labels['singular'] ),
1043
+ 'pages' => $this->_name, //or array( 'post-type1', 'post-type2')
1044
+ 'context' => 'normal', //('normal', 'advanced', or 'side')
1045
+ 'priority' => 'default',
1046
+ 'tabs' => array(
1047
+ 'settings' => array(
1048
+ 'label' => __( 'Settings', 'yit' ),
1049
+ 'fields' => apply_filters( 'yit_cptu_fields', array(
1050
+ 'type' => array(
1051
+ 'label' => __( 'Type', 'yit' ),
1052
+ 'desc' => __( 'Layout for this '.strtolower( $this->_labels['singular'] ) , 'yit' ),
1053
+ 'type' => 'select',
1054
+ 'options' => isset( $layouts ) ? $layouts : array(),
1055
+ 'std' => '' ),
1056
+
1057
+ 'rewrite' => array(
1058
+ 'label' => __( 'Rewrite', 'yit' ),
1059
+ 'desc' => __( 'Word used in the URL of each project (slug from post if empty)', 'yit' ),
1060
+ 'type' => 'text',
1061
+ 'std' => '' ),
1062
+
1063
+ 'label_singular' => array(
1064
+ 'label' => __( 'Label in Singular', 'yit' ),
1065
+ 'desc' => __( 'Set a label in singular (title of portfolio if empty)', 'yit' ),
1066
+ 'type' => 'text',
1067
+ 'std' => '' ),
1068
+
1069
+ 'label_plural' => array(
1070
+ 'label' => __( 'Label in Plural', 'yit' ),
1071
+ 'desc' => __( 'Set a label in plural (title of portfolio if empty)', 'yit' ),
1072
+ 'type' => 'text',
1073
+ 'std' => '' ),
1074
+
1075
+ 'taxonomy' => array(
1076
+ 'label' => __( 'Taxonomy', 'yit' ),
1077
+ 'desc' => __( 'If you want to use categories in the portfolio, set a name for taxonomy. Name should be a slug (must not contain capital letters nor spaces) and must not be more than 32 characters long (database structure restriction).', 'yit' ),
1078
+ 'type' => 'text',
1079
+ 'std' => '' ),
1080
+
1081
+ 'taxonomy_rewrite' => array(
1082
+ 'label' => __( 'Taxonomy Rewrite', 'yit' ),
1083
+ 'desc' => __( 'Set the word for each category page URL.', 'yit' ),
1084
+ 'type' => 'text',
1085
+ 'std' => '' ),
1086
+
1087
+ 'single_layout' => array(
1088
+ 'label' => __( 'Single layout', 'yit' ),
1089
+ 'desc' => __( 'Layout for single page of this portfolio', 'yit' ),
1090
+ 'type' => 'select',
1091
+ 'options' => $single_layouts,
1092
+ 'std' => '' ),
1093
+ ) )
1094
+ )
1095
+ )
1096
+
1097
+ );
1098
+
1099
+ if ( ! $this->_args['has_single'] ) {
1100
+ unset( $metabox_args['tabs']['settings']['fields']['rewrite'] );
1101
+ }
1102
+
1103
+ if ( ! $this->_args['has_taxonomy'] ) {
1104
+ unset( $metabox_args['tabs']['settings']['fields']['taxonomy'] );
1105
+ unset( $metabox_args['tabs']['settings']['fields']['taxonomy_rewrite'] );
1106
+ }
1107
+
1108
+ if ( ! empty( $this->_args['label_item_sing'] ) ) {
1109
+ unset( $metabox_args['tabs']['settings']['fields']['label_singular'] );
1110
+ }
1111
+
1112
+ if ( ! empty( $this->_args['label_item_plur'] ) ) {
1113
+ unset( $metabox_args['tabs']['settings']['fields']['label_plural'] );
1114
+ }
1115
+
1116
+ if ( $this->_args['manage_layouts'] ) {
1117
+
1118
+ if ( count( $layouts ) < 1 ) {
1119
+ unset( $metabox_args['tabs']['settings']['fields']['type'] );
1120
+ }
1121
+
1122
+ // Layouts options
1123
+ foreach ( $this->layouts as $layout => $args ) {
1124
+ if ( ! isset( $args['fields'] ) ) {
1125
+ continue;
1126
+ }
1127
+
1128
+ // Section title
1129
+ $metabox_args['tabs']['settings']['fields'][ $layout . '_title' ] = array(
1130
+ 'desc' => $args['name'] . ' ' . __( 'layout settings', 'yit' ),
1131
+ 'type' => 'title',
1132
+ 'deps' => array(
1133
+ 'ids' => '_type',
1134
+ 'values' => $layout
1135
+ )
1136
+ );
1137
+
1138
+ // Options
1139
+ foreach( $args['fields'] as $field_id => $field ) {
1140
+ $metabox_args['tabs']['settings']['fields'][ $field_id ] = $field;
1141
+ $metabox_args['tabs']['settings']['fields'][ $field_id ]['deps'] = array(
1142
+ 'ids' => '_type',
1143
+ 'values' => $layout
1144
+ );
1145
+ }
1146
+ }
1147
+ }else {
1148
+ unset( $metabox_args['tabs']['settings']['fields']['type'] );
1149
+ }
1150
+
1151
+ if( count( $single_layouts ) < 1 ){
1152
+ unset( $metabox_args['tabs']['settings']['fields']['single_layout'] );
1153
+ }
1154
+
1155
+ // undo if tab empty
1156
+ if ( empty( $metabox_args['tabs']['settings']['fields'] ) ) {
1157
+ return;
1158
+ }
1159
+
1160
+ $metabox = YIT_Metabox( $this->_name . '_cptu_settings' );
1161
+ $metabox->init( $metabox_args );
1162
+ }
1163
+
1164
+ /**
1165
+ * Register Metaboxes options
1166
+ *
1167
+ * Add the metabox for the portfolio settings
1168
+ *
1169
+ * @return void
1170
+ * @since 1.0
1171
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1172
+ */
1173
+ public function add_metabox_item_fields() {
1174
+ global $pagenow, $post_type;
1175
+
1176
+ // get the actual post type, to add the metabox only if necessary
1177
+ if ( $pagenow == 'post.php' && isset( $_REQUEST['post'] ) ) {
1178
+ $post_type = get_post_type( intval( $_REQUEST['post'] ) );
1179
+ }
1180
+ elseif( $pagenow == 'post.php' && isset( $_REQUEST['post_ID'] ) ){
1181
+ $post_type = get_post_type( intval( $_REQUEST['post_ID'] ) );
1182
+ }
1183
+ elseif ( $pagenow == 'post-new.php' && isset( $_REQUEST['post_type'] ) ) {
1184
+ $post_type = $_REQUEST['post_type'];
1185
+ } else {
1186
+ return;
1187
+ }
1188
+
1189
+ $layout = get_post_meta( $this->_get_id_by_name( $post_type ), $this->_args['layout_option'], true );
1190
+
1191
+ if ( empty( $this->layouts[ $layout ]['item_fields'] ) ) {
1192
+ return;
1193
+ }
1194
+
1195
+ $metabox_args = array(
1196
+ 'label' => __( 'Settings', 'yit' ),
1197
+ 'pages' => $post_type, //or array( 'post-type1', 'post-type2')
1198
+ 'context' => 'normal', //('normal', 'advanced', or 'side')
1199
+ 'priority' => 'default',
1200
+ 'tabs' => array(
1201
+ 'settings' => array(
1202
+ 'label' => __( 'Settings', 'yit' ),
1203
+ 'fields' => $this->layouts[ $layout ]['item_fields']
1204
+ )
1205
+ )
1206
+ );
1207
+
1208
+ $metabox = YIT_Metabox( $post_type . '_item_fields' );
1209
+ $metabox->init( $metabox_args );
1210
+
1211
+ }
1212
+
1213
+ /**
1214
+ * Add quick links inside the editing page of CPTU and Custom Post Types
1215
+ *
1216
+ * @return void
1217
+ * @since 1.0
1218
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1219
+ */
1220
+ public function add_quick_links_metaboxes() {
1221
+ // CPTU
1222
+ add_meta_box( $this->_name . '_quick_links', __( 'Quick links', 'yit' ), array( $this, 'quick_links_cptu_inner' ), $this->_name, 'side', 'high' );
1223
+
1224
+ // CPTs
1225
+ $args = array(
1226
+ 'post_type' => $this->_name,
1227
+ 'posts_per_page' => -1,
1228
+ 'post_status' => 'publish'
1229
+ );
1230
+ $post_types = get_posts( $args );
1231
+
1232
+ foreach ( $post_types as $post ) {
1233
+ $post_type = get_post_meta( $post->ID, '_post_type', true );
1234
+ extract( $this->_cpt_args( $post ) );
1235
+ add_meta_box( $post->post_type . '_quick_links', __( 'Quick links', 'yit' ), array( $this, 'quick_links_cpt_inner' ), $post_type, 'side', 'high' );
1236
+ }
1237
+ }
1238
+
1239
+ /**
1240
+ * Link to: "View Items", inside the CPTU
1241
+ *
1242
+ * @param $post
1243
+ *
1244
+ * @return void
1245
+ * @since 1.0
1246
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1247
+ */
1248
+ public function quick_links_cptu_inner( $post ) {
1249
+ extract( $this->_cpt_args( $post ) );
1250
+ ?>
1251
+ <a href="<?php echo admin_url( 'edit.php?post_type=' . get_post_meta( $post->ID, '_post_type', true ) ) ?>"><?php printf( __( 'View %s', 'yit' ), $label_plural ) ?></a>
1252
+ <?php
1253
+ }
1254
+
1255
+ /**
1256
+ * Link to: "Edit %s", inside the CPTU
1257
+ *
1258
+ * @param $post
1259
+ *
1260
+ * @return void
1261
+ * @since 1.0
1262
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1263
+ */
1264
+ public function quick_links_cpt_inner( $post ) {
1265
+ $post = get_post( $this->_get_id_by_name( $post->post_type ) );
1266
+ ?>
1267
+ <a href="<?php echo admin_url( "post.php?post={$post->ID}&action=edit" ) ?>"><?php printf( __( 'Edit %s', 'yit' ), $post->post_title ) ?></a>
1268
+ <?php
1269
+ }
1270
+
1271
+ /**
1272
+ * Define the columns to use in the list table of main sliders post type
1273
+ *
1274
+ * @param $columns array The columns used in the list table
1275
+ *
1276
+ * @return array
1277
+ * @since 1.0
1278
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1279
+ */
1280
+ public function cptu_define_columns( $columns ) {
1281
+ unset( $columns['date'] );
1282
+
1283
+ $columns['actions'] = '';
1284
+
1285
+ return $columns;
1286
+ }
1287
+
1288
+ /**
1289
+ * Change the content of each column of the table list
1290
+ *
1291
+ * @param $column string The current column
1292
+ * @param $post_id int The current post ID
1293
+ *
1294
+ * @return void
1295
+ * @since 1.0
1296
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1297
+ */
1298
+ public function cptu_change_columns( $column, $post_id ) {
1299
+ $post = get_post( $post_id );
1300
+ extract( $this->_cpt_args( $post ) );
1301
+
1302
+ switch ( $column ) {
1303
+ case 'actions' :
1304
+ echo '<a href="' . admin_url( "post.php?post={$post_id}&action=edit" ) . '" class="button-secondary">' . sprintf( __( 'Edit %s', 'yit' ), ucfirst( $this->_labels['singular'] ) ) . '</a> ';
1305
+ echo '<a href="' . admin_url( 'edit.php?post_type=' . get_post_meta( $post_id, '_post_type', true ) ) . '" class="button-secondary">' . sprintf( __( 'View %s', 'yit' ), $label_plural ) . '</a> ';
1306
+ break;
1307
+ }
1308
+ }
1309
+
1310
+ /**
1311
+ * Retrieve the path of layout specified in parameter
1312
+ *
1313
+ * @param $layout
1314
+ * @param $file string The file to find
1315
+ *
1316
+ * @return bool|string
1317
+ * @since 1.0
1318
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1319
+ */
1320
+ public function locate_file( $layout, $file = '' ) {
1321
+ if ( ! $this->_args['manage_layouts'] ) {
1322
+ return $this->template_path(). '/' . ( ! empty( $file ) ? $file . '.php' : '' );
1323
+ }
1324
+
1325
+ if ( ! isset( $this->layouts[ $layout ] ) ) {
1326
+ $layout = 'default';
1327
+ }
1328
+
1329
+ return $this->layouts[ $layout ]['path'] . '/' . ( ! empty( $file ) ? $file . '.php' : '' );
1330
+ }
1331
+
1332
+ /**
1333
+ * Retrieve the URL of layout specified in parameter
1334
+ *
1335
+ * @param $layout
1336
+ * @param $file string The file to find
1337
+ *
1338
+ * @return bool|string
1339
+ * @since 1.0
1340
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1341
+ */
1342
+ public function locate_url( $layout, $file = '' ) {
1343
+ if ( ! $this->_args['manage_layouts'] ) {
1344
+ return $this->template_url();
1345
+
1346
+ }
1347
+
1348
+ if ( ! isset( $this->layouts[ $layout ] ) ) {
1349
+ $layout = 'default';
1350
+ }
1351
+
1352
+ return $this->layouts[ $layout ]['url'] . '/' . ( ! empty( $file ) ? $file . '.php' : '' );
1353
+ }
1354
+
1355
+ /**
1356
+ * Retrieve the post ID relative to the post of post type
1357
+ *
1358
+ * @param $name string
1359
+ *
1360
+ * @return mixed
1361
+ * @since 1.0
1362
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1363
+ */
1364
+ protected function _get_id_by_name( $name ) {
1365
+ global $wpdb;
1366
+ return $wpdb->get_var( $wpdb->prepare( "SELECT pm.post_id FROM $wpdb->postmeta AS pm INNER JOIN $wpdb->posts AS p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND pm.meta_value = %s AND p.post_type = %s", '_post_type', $name, $this->_name ) );
1367
+ }
1368
+
1369
+ /**
1370
+ * Retrieve the post_type of portfolio by portfolio name
1371
+ *
1372
+ * @param $name string
1373
+ *
1374
+ * @return mixed
1375
+ * @since 1.0
1376
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1377
+ */
1378
+ protected function _get_post_type_by_name( $name ) {
1379
+ global $wpdb;
1380
+ return $wpdb->get_var( $wpdb->prepare( "SELECT pm.meta_value FROM $wpdb->postmeta AS pm INNER JOIN $wpdb->posts AS p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND p.post_name = %s AND p.post_type = %s", '_post_type', $name, $this->_name ) );
1381
+ }
1382
+
1383
+ /**
1384
+ * The shortcode used to show the frontend
1385
+ *
1386
+ * @param array $atts
1387
+ * @param null $content
1388
+ *
1389
+ * @return string|null
1390
+ * @since 1.0
1391
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1392
+ */
1393
+ public function add_shortcode( $atts, $content = null ) {
1394
+ $atts = wp_parse_args( $atts, array(
1395
+ 'name' => null,
1396
+ 'cat' => array(),
1397
+ 'posts_per_page' => false,
1398
+ 'style' => null,
1399
+ ) );
1400
+
1401
+ // don't show the slider if 'name' is empty or is 'none'
1402
+ if ( empty( $atts['name'] ) || 'none' == $atts['name'] ) return null;
1403
+
1404
+ // compatibility fix: remove prefix if exists in portfolio object
1405
+ if( function_exists( 'YIT_Portfolio' ) && method_exists( YIT_Portfolio(), 'is' ) && YIT_Portfolio()->is( $atts['name'] ) ){
1406
+ $atts['name'] = str_replace( YIT_Portfolio()->post_type_prefix, '', $atts['name'] );
1407
+ }
1408
+
1409
+ // pass vars to template
1410
+ $atts['post_type'] = $this->_get_post_type_by_name( $atts['name'] );
1411
+ $atts['layout'] = $this->_args['manage_layouts'] ? get_post_meta( $this->_get_id_by_name( $atts['post_type'] ), $this->_args['layout_option'], true ) : '';
1412
+ extract( apply_filters( 'yit_cptu_frontend_vars', $atts, $this->_name ) );
1413
+
1414
+ // add the javascript assets
1415
+ if ( $this->_args['manage_layouts'] && isset( $this->layouts[ $layout ]['js'] ) && ! empty( $this->layouts[ $layout ]['js'] ) ) {
1416
+ foreach ( $this->layouts[ $layout ]['js'] as $asset ) {
1417
+ if ( empty( $asset ) ) continue;
1418
+
1419
+ if ( empty( $asset['src'] ) ) {
1420
+ wp_enqueue_script( $asset['handle'] );
1421
+ continue;
1422
+ }
1423
+
1424
+ yit_enqueue_script( $asset['handle'], $this->locate_url( $layout ) . $asset['src'], $asset['deps'], $asset['ver'], $asset['in_footer'] );
1425
+ }
1426
+ }
1427
+
1428
+ // Unique sequential index to differentiate more cpt in the same page
1429
+ ++$this->index;
1430
+
1431
+ ob_start();
1432
+
1433
+ include( $this->locate_file( $layout, 'markup' ) );
1434
+
1435
+ return ob_get_clean();
1436
+
1437
+ }
1438
+
1439
+ /**
1440
+ * Shortcode icon
1441
+ *
1442
+ * Return the shortcode icone to display on shortcode panel
1443
+ *
1444
+ * @param $icon_url string Icone url found by yit_shortcode plugin
1445
+ *
1446
+ * @return string
1447
+ * @since 1.0.0
1448
+ * @author Antonino Scarfi' <antonio.scarfi@yithemes.it>
1449
+ */
1450
+ public function shortcode_icon( $icon_url ) {
1451
+ return ! empty( $this->_args['shortcode_icon'] ) ? $this->_args['shortcode_icon'] : $icon_url;
1452
+ }
1453
+
1454
+ /**
1455
+ * Return an array with cptu options to shortcode panel
1456
+ *
1457
+ * All definition settings to add cptu shortcode to Yit Shortcode Panel
1458
+ *
1459
+ * @param array $shortcodes
1460
+ *
1461
+ * @return array
1462
+ * @since 1.0
1463
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1464
+ */
1465
+ public function add_shortcode_to_box( $shortcodes ) {
1466
+ $post_types = array();
1467
+
1468
+ foreach ( $this->get_post_types() as $post ) {
1469
+ $post_types[ $post->post_name ] = $post->post_title;
1470
+ }
1471
+
1472
+ $args = array(
1473
+ $this->_args['shortcode_name'] => array(
1474
+ 'title' => $this->_labels['singular'],
1475
+ 'description' => sprintf( __( 'Show frontend of the %s', 'yit' ), $this->_labels['main_name'] ),
1476
+ 'tab' => 'cpt',
1477
+ 'create' => false,
1478
+ 'has_content' => false,
1479
+ 'in_visual_composer' => true,
1480
+ 'attributes' => array(
1481
+ 'name' => array(
1482
+ 'title' => __( 'Name', 'yit' ),
1483
+ 'type' => 'select',
1484
+ 'options' => $post_types,
1485
+ 'std' => ''
1486
+ ),
1487
+ )
1488
+ )
1489
+ );
1490
+
1491
+ return array_merge( $shortcodes, $args );
1492
+ }
1493
+
1494
+ /**
1495
+ * Check the post type passed in parameter, if is generated by this CPTU
1496
+ *
1497
+ * @param $post_type string The post type to check
1498
+ *
1499
+ * @return bool
1500
+ * @since 1.0
1501
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1502
+ */
1503
+ protected function _is_valid( $post_type ) {
1504
+ return (bool)( strpos( $post_type, $this->_args['post_type_prefix'] ) !== false );
1505
+ }
1506
+
1507
+ /**
1508
+ * Add as a valid post type all cptu when importing dummy data
1509
+ *
1510
+ * @param $post array The post object
1511
+ *
1512
+ * @return array
1513
+ * @since 1.0
1514
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
1515
+ */
1516
+ public function add_importer_required_post_type( $post ){
1517
+ global $wp_post_types, $wp_taxonomies;
1518
+
1519
+ if( strpos( $post['post_type'], $this->_prefix_cpt ) === FALSE ){
1520
+ return $post;
1521
+ }
1522
+
1523
+ if( ! isset( $wp_post_types[ $post['post_type'] ] ) ){
1524
+ $wp_post_types[ $post['post_type'] ] = array(
1525
+ 'name' => ''
1526
+ );
1527
+ }
1528
+
1529
+ if( ! empty( $post['terms'] ) ){
1530
+ foreach( $post['terms'] as $term ){
1531
+ if( ! isset( $wp_taxonomies[ $term['domain'] ] ) ){
1532
+ $wp_taxonomies[ $term['domain'] ] = array(
1533
+ 'name' => ''
1534
+ );
1535
+ }
1536
+ }
1537
+ }
1538
+
1539
+
1540
+ return $post;
1541
+ }
1542
+
1543
+ /**
1544
+ * Add taxonomy when importing dummy data
1545
+ *
1546
+ * @param $terms array Array of terms
1547
+ *
1548
+ * @return array
1549
+ * @since 1.0
1550
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
1551
+ */
1552
+ public function add_importer_required_taxonomy( $terms ){
1553
+ global $wp_taxonomies;
1554
+
1555
+ if( ! empty( $terms ) ){
1556
+ foreach ( $terms as $term ) {
1557
+ if( isset( $term['domain'] ) && ! isset( $wp_taxonomies[ $term['domain'] ] ) ){
1558
+ $wp_taxonomies[ $term['domain'] ] = array(
1559
+ 'name' => ''
1560
+ );
1561
+ }
1562
+ }
1563
+ }
1564
+
1565
+ return $terms;
1566
+ }
1567
+
1568
+ /**
1569
+ * Force terms recount for imported taxonomy
1570
+ *
1571
+ * @param $tt_ids array Terms ids
1572
+ * @param $ids array Post ids
1573
+ * @param $tax string Taxonomy name
1574
+ *
1575
+ * @return void
1576
+ * @since 1.0
1577
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
1578
+ */
1579
+ public function recount_terms_post( $tt_ids, $ids, $tax ){
1580
+ wp_update_term_count( $tt_ids, $tax );
1581
+ }
1582
+
1583
+ // ### ASSETS ###
1584
+
1585
+ /**
1586
+ * Enqueue the assets for the admin
1587
+ *
1588
+ * @return void
1589
+ * @since 1.0
1590
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1591
+ */
1592
+ public function admin_assets() {
1593
+ wp_enqueue_media();
1594
+ wp_enqueue_script( 'yit-cptu', YIT_CORE_PLUGIN_URL . '/assets/js/yit-cpt-unlimited.js', array('jquery'), '', true );
1595
+ }
1596
+
1597
+ /**
1598
+ * Add the button to the top of the list table page of CPTU
1599
+ *
1600
+ * @return void
1601
+ * @since 1.0
1602
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1603
+ */
1604
+ public function add_button_multiuploader() {
1605
+ global $pagenow, $post_type, $wpdb;
1606
+
1607
+ if( $pagenow != 'edit.php' ){
1608
+ return;
1609
+ }
1610
+
1611
+ $cptu = $wpdb->get_var( $wpdb->prepare( "SELECT p.post_type FROM $wpdb->postmeta AS pm INNER JOIN $wpdb->posts AS p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND pm.meta_value = %s", '_post_type', $post_type ) );
1612
+
1613
+ $post = get_post( $this->_get_id_by_name( $post_type ) );
1614
+ if ( empty( $post ) ) {
1615
+ return;
1616
+ }
1617
+ extract( $this->_cpt_args( $post ) );
1618
+
1619
+ if ( $cptu != $this->_name || ! $this->_is_valid( $post_type ) ) {
1620
+ return;
1621
+ }
1622
+ ?>
1623
+ <script>
1624
+ (function($) {
1625
+ "use strict";
1626
+ // Author code here
1627
+
1628
+ var button = $('<a />', {
1629
+ href: '#',
1630
+ class: 'multi-uploader add-new-h2',
1631
+ 'data-uploader_title': '<?php printf( __( 'Add %s by images', 'yit' ), $label_plural ) ?>',
1632
+ 'data-uploader_button_text': '<?php printf( __( 'Add %s', 'yit' ), $label_plural ) ?>'
1633
+ }).text('<?php _e( 'Add with multiupload', 'yit' ) ?>');
1634
+
1635
+ var spinner = $('<span />', {
1636
+ class: 'spinner',
1637
+ style: 'float: none;'
1638
+ });
1639
+
1640
+ button.appendTo('.wrap h2').after(spinner);
1641
+
1642
+ })(jQuery);
1643
+ </script>
1644
+ <?php
1645
+ }
1646
+
1647
+ /**
1648
+ * Add more posts by multiupload
1649
+ *
1650
+ * @return void
1651
+ * @since 1.0
1652
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1653
+ */
1654
+ public function post_multiuploader() {
1655
+ if ( ! isset( $_REQUEST['images'] ) || ! isset( $_REQUEST['post_type'] ) && $this->_is_valid( $_REQUEST['post_type'] ) ) {
1656
+ return;
1657
+ }
1658
+
1659
+ foreach ( $_REQUEST['images'] as $the ) {
1660
+
1661
+ // Create post object
1662
+ $arg = array(
1663
+ 'post_title' => $the['title'],
1664
+ 'post_type' => $_REQUEST['post_type']
1665
+ );
1666
+ $post_id = wp_insert_post( $arg );
1667
+
1668
+ set_post_thumbnail( $post_id, $the['id'] );
1669
+
1670
+ }
1671
+
1672
+ die();
1673
+ }
1674
+
1675
+
1676
+ // ###### SINGLE TEMPLATE ######
1677
+
1678
+ /**
1679
+ * Load the single template file
1680
+ *
1681
+ * @return void
1682
+ * @since 1.0
1683
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1684
+ */
1685
+ public function single_template() {
1686
+ global $post, $wpdb;
1687
+
1688
+ // if ( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['post_id'] ) ) {
1689
+ // $post = get_post( $_REQUEST['post_id'] );
1690
+ // }
1691
+
1692
+ if ( ( ( ! defined('DOING_AJAX') || ! DOING_AJAX ) && ! is_single() ) || ! isset( $post->post_type ) || ! $this->_is_valid( $post->post_type ) ) {
1693
+ return;
1694
+ }
1695
+
1696
+ // add the javascript assets
1697
+ if ( $this->_args['manage_layouts'] ) {
1698
+ foreach ( $this->layouts[ 'single' ]['js'] as $asset ) {
1699
+ yit_enqueue_script( $asset['handle'], $this->locate_url( 'single' ) . $asset['src'], $asset['deps'], $asset['ver'], $asset['in_footer'] );
1700
+ }
1701
+ }
1702
+
1703
+ $post_name = $wpdb->get_var( $wpdb->prepare( "SELECT p.post_name FROM $wpdb->postmeta AS pm INNER JOIN $wpdb->posts AS p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND pm.meta_value = %s AND p.post_type = %s", '_post_type', $post->post_type, $this->_name ) );
1704
+ extract( apply_filters( 'yit_cptu_frontend_vars', array( 'name' => $post_name ), $this->_name ) );
1705
+
1706
+ include( $this->locate_file( 'single', 'markup' ) );
1707
+ }
1708
+
1709
+ /**
1710
+ * Load a file for the configuration of single template page of portfolio
1711
+ *
1712
+ * @return void
1713
+ * @since 1.0
1714
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1715
+ */
1716
+ public function single_template_config() {
1717
+ global $post, $wpdb;
1718
+
1719
+ if ( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['post_id'] ) ) {
1720
+ $post = get_post( $_REQUEST['post_id'] );
1721
+ }
1722
+
1723
+ if ( ( ( ! defined('DOING_AJAX') || ! DOING_AJAX ) && ! is_single() ) || ! isset( $post->post_type ) || ! $this->_is_valid( $post->post_type ) ) {
1724
+ return;
1725
+ }
1726
+
1727
+ $this->_layout = 'single';
1728
+ $path = $this->locate_file( 'single', 'config' );
1729
+
1730
+ if ( file_exists( $path ) ) {
1731
+ $post_name = $wpdb->get_var( $wpdb->prepare( "SELECT p.post_name FROM $wpdb->postmeta AS pm INNER JOIN $wpdb->posts AS p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND pm.meta_value = %s AND p.post_type = %s", '_post_type', $post->post_type, $this->_name ) );
1732
+ extract( apply_filters( 'yit_cptu_frontend_vars', array( 'name' => $post_name ), $this->_name ) );
1733
+
1734
+ include( $path );
1735
+ }
1736
+ }
1737
+
1738
+
1739
+ // ########################## ARCHIVE TEMPLATE ###############################
1740
+
1741
+
1742
+ /**
1743
+ * Load the template for archive page
1744
+ *
1745
+ * @return void
1746
+ * @since 1.0
1747
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1748
+ */
1749
+ public function archive_template() {
1750
+ global $wp_query;
1751
+
1752
+
1753
+ // check if we are in archive template
1754
+ if ( !( ! is_admin() && is_archive() && isset( $wp_query->post->post_type ) && $this->_is_valid( $wp_query->post->post_type ) ) ) {
1755
+ return;
1756
+ }
1757
+
1758
+ // remove the action from loop of theme
1759
+ remove_action( 'yit_content_loop', 'yit_content_loop', 10 );
1760
+ add_action( 'yit_content_loop', array( $this, 'archive_template_loop' ), 10 );
1761
+
1762
+ }
1763
+
1764
+ /**
1765
+ * Load loop for the archive template
1766
+ *
1767
+ * @return void
1768
+ * @since 1.0
1769
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
1770
+ */
1771
+ public function archive_template_loop() {
1772
+ echo $this->add_shortcode( array( 'name' => $GLOBALS['wp_query']->post->post_type ) );
1773
+ }
1774
+
1775
+ }
plugin-fw/lib/yit-metabox.php ADDED
@@ -0,0 +1,537 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ } // Exit if accessed directly
15
+
16
+ if ( ! class_exists( 'YIT_Metabox' ) ) {
17
+ /**
18
+ * YIT Metabox
19
+ *
20
+ * the metabox can be created using this code
21
+ * <code>
22
+ * $args1 = array(
23
+ * 'label' => __( 'Metabox Label', 'yit' ),
24
+ * 'pages' => 'page', //or array( 'post-type1', 'post-type2')
25
+ * 'context' => 'normal', //('normal', 'advanced', or 'side')
26
+ * 'priority' => 'default',
27
+ * 'tabs' => array(
28
+ * 'settings' => array( //tab
29
+ * 'label' => __( 'Settings', 'yit' ),
30
+ * 'fields' => array(
31
+ * 'meta_checkbox' => array(
32
+ * 'label' => __( 'Show title', 'yit' ),
33
+ * 'desc' => __( 'Show or not the title of the page.', 'yit' ),
34
+ * 'type' => 'checkbox',
35
+ * 'private' => false,
36
+ * 'std' => '1'),
37
+ * ),
38
+ * ),
39
+ * );
40
+ *
41
+ * $metabox1 = YIT_Metabox( 'yit-metabox-id' );
42
+ * $metabox1->init( $args );
43
+ * </code>
44
+ *
45
+ * @class YIT_Metaboxes
46
+ * @package Yithemes
47
+ * @since 1.0.0
48
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
49
+ *
50
+ */
51
+
52
+ class YIT_Metabox {
53
+
54
+ /**
55
+ * @var string the id of metabox
56
+ *
57
+ * @since 1.0
58
+ */
59
+
60
+ public $id;
61
+
62
+ /**
63
+ * @var array An array where are saved all metabox settings options
64
+ *
65
+ * @since 1.0
66
+ */
67
+ private $options = array();
68
+
69
+ /**
70
+ * @var array An array where are saved all tabs of metabox
71
+ *
72
+ * @since 1.0
73
+ */
74
+ private $tabs = array();
75
+
76
+ /**
77
+ * @var object The single instance of the class
78
+ * @since 1.0
79
+ */
80
+ protected static $_instance = array();
81
+
82
+ /**
83
+ * Main Instance
84
+ *
85
+ * @static
86
+ *
87
+ * @param $id
88
+ *
89
+ * @return object Main instance
90
+ *
91
+ * @since 1.0
92
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
93
+ */
94
+ public static function instance( $id ) {
95
+ if ( ! isset( self::$_instance[$id] ) ) {
96
+ self::$_instance[$id] = new self( $id );
97
+ }
98
+ return self::$_instance[$id];
99
+ }
100
+
101
+ /**
102
+ * Constructor
103
+ *
104
+ * @param string $id
105
+ *
106
+ * @return \YIT_Metabox
107
+ * @since 1.0
108
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
109
+ */
110
+ function __construct( $id = '' ) {
111
+ $this->id = $id;
112
+
113
+ }
114
+
115
+
116
+ /**
117
+ * Init
118
+ *
119
+ * set options and tabs, add actions to register metabox, scripts and save data
120
+ *
121
+ * @param array $options
122
+ *
123
+ * @return void
124
+ * @since 1.0
125
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
126
+ */
127
+ public function init( $options = array() ) {
128
+
129
+ $this->set_options( $options );
130
+ $this->set_tabs();
131
+
132
+
133
+ add_action( 'add_meta_boxes', array( $this, 'register_metabox' ) );
134
+ add_action( 'save_post', array( $this, 'save_postdata' ) );
135
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 15 );
136
+
137
+ }
138
+
139
+ /**
140
+ * Enqueue script and styles in admin side
141
+ *
142
+ * Add style and scripts to administrator
143
+ *
144
+ * @return void
145
+ * @since 1.0
146
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
147
+ */
148
+ public function enqueue() {
149
+
150
+ wp_enqueue_media();
151
+ wp_enqueue_style( 'wp-color-picker' );
152
+ wp_enqueue_style( 'yit-plugin-metaboxes', YIT_CORE_PLUGIN_URL . '/assets/css/metaboxes.css' );
153
+ wp_enqueue_style( 'jquery-chosen', YIT_CORE_PLUGIN_URL . '/assets/css/chosen/chosen.css' );
154
+ wp_enqueue_script( 'jquery-ui-datepicker' );
155
+ wp_enqueue_script( 'yit-spinner', YIT_CORE_PLUGIN_URL . '/assets/js/panel.spinner.js', array( 'jquery' ), '0.0.1', true );
156
+ wp_enqueue_script( 'jquery-chosen', YIT_CORE_PLUGIN_URL . '/assets/js/chosen/chosen.jquery.js', array( 'jquery' ), '1.1.0', true );
157
+ wp_enqueue_script( 'yit-metabox', YIT_CORE_PLUGIN_URL . '/assets/js/metabox.js', array( 'jquery', 'wp-color-picker' ), '1.0.0', true );
158
+ wp_enqueue_style( 'jquery-ui-overcast', YIT_CORE_PLUGIN_URL . '/assets/css/overcast/jquery-ui-1.8.9.custom.css', false, '1.8.9', 'all' );
159
+
160
+ if( function_exists( 'WC' ) ){
161
+
162
+ wp_enqueue_script('ajax-chosen');
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Set Options
168
+ *
169
+ * Set the variable options
170
+ *
171
+ * @param array $options
172
+ *
173
+ * @return void
174
+ * @since 1.0
175
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
176
+ */
177
+ public function set_options( $options = array() ) {
178
+ $this->options = $options;
179
+
180
+ }
181
+
182
+ /**
183
+ * Set Tabs
184
+ *
185
+ * Set the variable tabs
186
+ *
187
+ * @internal param array $tabs
188
+ *
189
+ * @return void
190
+ * @since 1.0
191
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
192
+ */
193
+ public function set_tabs() {
194
+ if ( ! isset( $this->options['tabs'] ) ) {
195
+ return;
196
+ }
197
+ $this->tabs = $this->options['tabs'] ;
198
+ if( isset($this->tabs['settings']['fields']) ){
199
+ $this->tabs['settings']['fields'] = array_filter( $this->tabs['settings']['fields'] );
200
+ }
201
+ }
202
+
203
+
204
+ /**
205
+ * Add Tab
206
+ *
207
+ * Add a tab inside the metabox
208
+ *
209
+ * @internal param array $tabs
210
+ *
211
+ * @param array $tab the new tab to add to the metabox
212
+ * @param string $where tell where insert the tab if after or before a $refer
213
+ * @param null $refer an existent tab inside metabox
214
+ *
215
+ * @return void
216
+ * @since 1.0
217
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
218
+ */
219
+ public function add_tab( $tab, $where = 'after', $refer = null ) {
220
+ if ( ! is_null( $refer ) ) {
221
+ $ref_pos = array_search( $refer, array_keys( $this->tabs ) );
222
+ if ( $ref_pos !== false ) {
223
+ if ( $where == 'after' ) {
224
+ $this->tabs = array_slice( $this->tabs, 0, $ref_pos + 1, true ) +
225
+ $tab +
226
+ array_slice( $this->tabs, $ref_pos + 1, count( $this->tabs ) - 1, true );
227
+ }
228
+ else {
229
+ $this->tabs = array_slice( $this->tabs, 0, $ref_pos, true ) +
230
+ $tab +
231
+ array_slice( $this->tabs, $ref_pos, count( $this->tabs ), true );
232
+ }
233
+ }
234
+ }
235
+ else {
236
+ $this->tabs = array_merge( $tab, $this->tabs );
237
+ }
238
+
239
+ }
240
+
241
+ /**
242
+ * Remove Tab
243
+ *
244
+ * Remove a tab from the tabs of metabox
245
+ *
246
+ * @internal param array $tabs
247
+ *
248
+ * @param $id_tab
249
+ *
250
+ * @return void
251
+ * @since 1.0
252
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
253
+ */
254
+ public function remove_tab( $id_tab ) {
255
+ if ( isset( $this->tabs[$id_tab] ) ) {
256
+ unset ( $this->tabs[$id_tab] );
257
+ }
258
+ }
259
+
260
+
261
+ /**
262
+ * Add Field
263
+ *
264
+ * Add a field inside a tab of metabox
265
+ *
266
+ * @internal param array $tabs
267
+ *
268
+ * @param string $tab_id the id of the tabs where add the field
269
+ * @param array $args the field to add
270
+ * @param string $where tell where insert the field if after or before a $refer
271
+ * @param null $refer an existent field inside tab
272
+ *
273
+ * @return void
274
+ * @since 1.0
275
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
276
+ */
277
+ public function add_field( $tab_id, $args, $where = 'after', $refer = null ) {
278
+ if ( isset( $this->tabs[$tab_id] ) ) {
279
+
280
+ $cf = $this->tabs[$tab_id]['fields'];
281
+ if ( ! is_null( $refer ) ) {
282
+ $ref_pos = array_search( $refer, array_keys( $cf ) );
283
+ if ( $ref_pos !== false ) {
284
+ if ( $where == 'after' ) {
285
+ $this->tabs[$tab_id]['fields'] = array_slice( $cf, 0, $ref_pos + 1, true ) +
286
+ $args +
287
+ array_slice( $cf, $ref_pos, count( $cf ) - 1, true );
288
+
289
+ } elseif ( $where == 'before' ) {
290
+ $this->tabs[$tab_id]['fields'] = array_slice( $cf, 0, $ref_pos, true ) +
291
+ $args +
292
+ array_slice( $cf, $ref_pos, count( $cf ), true );
293
+
294
+ }
295
+ }
296
+ }
297
+ else {
298
+ if ( $where == 'first' ) {
299
+ $this->tabs[$tab_id]['fields'] = $args + $cf;
300
+
301
+ } else {
302
+ $this->tabs[$tab_id]['fields'] = array_merge( $this->tabs[$tab_id]['fields'], $args );
303
+ }
304
+ }
305
+
306
+ }
307
+
308
+
309
+ }
310
+
311
+ /**
312
+ * Remove Field
313
+ *
314
+ * Remove a field from the metabox, search inside the tabs and remove it if exists
315
+ *
316
+ * @param $id_field
317
+ *
318
+ * @return void
319
+ * @since 1.0
320
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
321
+ */
322
+ public function remove_field( $id_field ) {
323
+ foreach ( $this->tabs as $tab_name => $tab ) {
324
+ if ( isset( $tab['fields'][$id_field] ) ) {
325
+ unset ( $this->tabs[$tab_name]['fields'][$id_field] );
326
+ }
327
+ }
328
+ }
329
+
330
+ /**
331
+ * Reorder tabs
332
+ *
333
+ * Order the tabs and fields and set id and name to each field
334
+ *
335
+ * @internal param $id_field
336
+ *
337
+ * @return void
338
+ * @since 1.0
339
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
340
+ */
341
+ public function reorder_tabs() {
342
+ foreach ( $this->tabs as $tab_name => $tab ) {
343
+ foreach ( $tab['fields'] as $id_field => $field ) {
344
+ $this->tabs[$tab_name]['fields'][$id_field]['private'] = ( isset( $field['private'] ) ) ? $field['private'] : true;
345
+ $this->tabs[$tab_name]['fields'][$id_field]['id'] = $this->get_option_metabox_id( $id_field, $this->tabs[$tab_name]['fields'][$id_field]['private'] );
346
+ $this->tabs[$tab_name]['fields'][$id_field]['name'] = $this->get_option_metabox_name( $this->tabs[$tab_name]['fields'][$id_field]['id'] );
347
+ }
348
+ }
349
+
350
+ }
351
+
352
+
353
+ /**
354
+ * Get Option Metabox ID
355
+ *
356
+ * return the id of the field
357
+ *
358
+ * @param string $id_field
359
+ * @param bool $private if private add an _befor the id
360
+ *
361
+ * @return string
362
+ * @since 1.0
363
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
364
+ */
365
+ public function get_option_metabox_id( $id_field, $private = true ) {
366
+ if ( $private ) {
367
+ return '_' . $id_field;
368
+ }
369
+ else {
370
+ return $id_field;
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Get Option Metabox Name
376
+ *
377
+ * return the name of the field, this name will be used as attribute name of the input field
378
+ *
379
+ * @param string $id_field
380
+ * @param bool $private if private add an _befor the id
381
+ *
382
+ * @return string
383
+ * @since 1.0
384
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
385
+ */
386
+ public function get_option_metabox_name( $id_field, $private = true ) {
387
+ $db_name = apply_filters( 'yit_metaboxes_option_main_name', 'yit_metaboxes' );
388
+ $return = $db_name . '[';
389
+
390
+ if ( ! strpos( $id_field, '[' ) ) {
391
+ return $return . $id_field . ']';
392
+ }
393
+ $return .= substr( $id_field, 0, strpos( $id_field, '[' ) );
394
+ $return .= ']';
395
+ $return .= substr( $id_field, strpos( $id_field, '[' ) );
396
+
397
+ return $return;
398
+ }
399
+
400
+ /**
401
+ * Register the metabox
402
+ *
403
+ * call the wp function add_metabox to add the metabox
404
+ *
405
+ *
406
+ * @return void
407
+ * @since 1.0
408
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
409
+ */
410
+ public function register_metabox() {
411
+ add_meta_box( $this->id, $this->options['label'], array( $this, 'show' ), $this->options['pages'], $this->options['context'], $this->options['priority'] );
412
+ }
413
+
414
+ /**
415
+ * Show metabox
416
+ *
417
+ * show the html of metabox
418
+ *
419
+ *
420
+ * @return void
421
+ * @since 1.0
422
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
423
+ */
424
+ public function show() {
425
+ $this->reorder_tabs();
426
+
427
+ yit_plugin_get_template( YIT_CORE_PLUGIN_PATH, 'metaboxes/tab.php', array( 'tabs' => $this->tabs ) );
428
+ }
429
+
430
+ /**
431
+ * Save Post Data
432
+ *
433
+ * Save the post data in the database when save the post
434
+ *
435
+ * @param $post_id
436
+ *
437
+ * @return int
438
+ * @since 1.0
439
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
440
+ */
441
+ public function save_postdata( $post_id ) {
442
+
443
+
444
+
445
+ if ( ! isset( $_POST['yit_metaboxes_nonce'] ) || ! wp_verify_nonce( $_POST['yit_metaboxes_nonce'], 'metaboxes-fields-nonce' ) ) {
446
+ return $post_id;
447
+ }
448
+
449
+
450
+ if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
451
+ return $post_id;
452
+ }
453
+
454
+ if ( isset( $_POST['post_type'] ) ) {
455
+ $post_type = $_POST['post_type'];
456
+ }
457
+ else {
458
+ return $post_id;
459
+ }
460
+
461
+ if ( 'page' == $post_type ) {
462
+ if ( ! current_user_can( 'edit_page', $post_id ) ) {
463
+ return $post_id;
464
+ }
465
+ }
466
+ else {
467
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
468
+ return $post_id;
469
+ }
470
+ }
471
+
472
+ $this->reorder_tabs();
473
+
474
+
475
+ foreach ( $this->tabs as $tab ) {
476
+
477
+ foreach ( $tab['fields'] as $field ) {
478
+
479
+ if ( in_array( $field['type'], array( 'title' ) ) ) {
480
+ continue;
481
+ }
482
+
483
+ if ( isset( $_POST['yit_metaboxes'][$field['id']] ) ) {
484
+
485
+ add_post_meta( $post_id, $field['id'], $_POST['yit_metaboxes'][$field['id']], true ) || update_post_meta( $post_id, $field['id'], $_POST['yit_metaboxes'][$field['id']] );
486
+ }
487
+ elseif ( in_array( $field['type'], array( 'onoff', 'checkbox' ) ) ) {
488
+ add_post_meta( $post_id, $field['id'], '0', true ) || update_post_meta( $post_id, $field['id'], '0' );
489
+ }
490
+ else {
491
+ delete_post_meta( $post_id, $field['id'] );
492
+ }
493
+ }
494
+ }
495
+
496
+ }
497
+
498
+ /**
499
+ * Remove Fields
500
+ *
501
+ * Remove a fields list from the metabox, search inside the tabs and remove it if exists
502
+ *
503
+ * @param $id_fields
504
+ *
505
+ * @return void
506
+ * @since 2.0.0
507
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
508
+ */
509
+ public function remove_fields( $id_fields ) {
510
+ foreach ( $id_fields as $k => $field ) {
511
+ $this->remove_field( $field );
512
+ }
513
+ }
514
+ }
515
+ }
516
+
517
+ if ( ! function_exists( 'YIT_Metabox' ) ) {
518
+
519
+ /**
520
+ * Main instance of plugin
521
+ *
522
+ * @param $id
523
+ *
524
+ * @return \YIT_Metabox
525
+ * @since 1.0
526
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
527
+ */
528
+
529
+
530
+ function YIT_Metabox( $id ) {
531
+ return YIT_Metabox::instance( $id );
532
+ }
533
+ }
534
+
535
+
536
+
537
+
plugin-fw/lib/yit-plugin-common.php ADDED
@@ -0,0 +1,1034 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! class_exists( 'YIT_Plugin_Common' ) ) :
12
+
13
+ /**
14
+ * Core configuration class
15
+ *
16
+ * @since 1.0.0
17
+ */
18
+ class YIT_Plugin_Common {
19
+
20
+ /**
21
+ * Config array
22
+ *
23
+ * @var array
24
+ */
25
+ protected static $_config = array(
26
+ 'slider' => array( 'nivo', 'elegant' ),
27
+
28
+
29
+ 'awesome_icons' => array(
30
+ 'f042' => 'adjust',
31
+ 'f170' => 'adn',
32
+ 'f037' => 'align-center',
33
+ 'f039' => 'align-justify',
34
+ 'f036' => 'align-left',
35
+ 'f038' => 'align-right',
36
+ 'f0f9' => 'ambulance',
37
+ 'f13d' => 'anchor',
38
+ 'f17b' => 'android',
39
+ 'f103' => 'angle-double-down',
40
+ 'f100' => 'angle-double-left',
41
+ 'f101' => 'angle-double-right',
42
+ 'f102' => 'angle-double-up',
43
+ 'f107' => 'angle-down',
44
+ 'f104' => 'angle-left',
45
+ 'f105' => 'angle-right',
46
+ 'f106' => 'angle-up',
47
+ 'f179' => 'apple',
48
+ 'f187' => 'archive',
49
+ 'f0ab' => 'arrow-circle-down',
50
+ 'f0a8' => 'arrow-circle-left',
51
+ 'f01a' => 'arrow-circle-o-down',
52
+ 'f190' => 'arrow-circle-o-left',
53
+ 'f18e' => 'arrow-circle-o-right',
54
+ 'f01b' => 'arrow-circle-o-up',
55
+ 'f0a9' => 'arrow-circle-right',
56
+ 'f0aa' => 'arrow-circle-up',
57
+ 'f063' => 'arrow-down',
58
+ 'f060' => 'arrow-left',
59
+ 'f061' => 'arrow-right',
60
+ 'f062' => 'arrow-up',
61
+ 'f047' => 'arrows',
62
+ 'f0b2' => 'arrows-alt',
63
+ 'f07e' => 'arrows-h',
64
+ 'f07d' => 'arrows-v',
65
+ 'f069' => 'asterisk',
66
+ 'f04a' => 'backward',
67
+ 'f05e' => 'ban',
68
+ 'f080' => 'bar-chart-o',
69
+ 'f02a' => 'barcode',
70
+ 'f0c9' => 'bars',
71
+ 'f0fc' => 'beer',
72
+ 'f0f3' => 'bell',
73
+ 'f0a2' => 'bell-o',
74
+ 'f171' => 'bitbucket',
75
+ 'f172' => 'bitbucket-square',
76
+ 'f032' => 'bold',
77
+ 'f0e7' => 'bolt',
78
+ 'f02d' => 'book',
79
+ 'f02e' => 'bookmark',
80
+ 'f097' => 'bookmark-o',
81
+ 'f0b1' => 'briefcase',
82
+ 'f15a' => 'btc',
83
+ 'f188' => 'bug',
84
+ 'f0f7' => 'building-o',
85
+ 'f0a1' => 'bullhorn',
86
+ 'f140' => 'bullseye',
87
+ 'f073' => 'calendar',
88
+ 'f133' => 'calendar-o',
89
+ 'f030' => 'camera',
90
+ 'f083' => 'camera-retro',
91
+ 'f0d7' => 'caret-down',
92
+ 'f0d9' => 'caret-left',
93
+ 'f0da' => 'caret-right',
94
+ 'f150' => 'caret-square-o-down',
95
+ 'f191' => 'caret-square-o-left',
96
+ 'f152' => 'caret-square-o-right',
97
+ 'f151' => 'caret-square-o-up',
98
+ 'f0d8' => 'caret-up',
99
+ 'f0a3' => 'certificate',
100
+ 'f127' => 'chain-broken',
101
+ 'f00c' => 'check',
102
+ 'f058' => 'check-circle',
103
+ 'f05d' => 'check-circle-o',
104
+ 'f14a' => 'check-square',
105
+ 'f046' => 'check-square-o',
106
+ 'f13a' => 'chevron-circle-down',
107
+ 'f137' => 'chevron-circle-left',
108
+ 'f138' => 'chevron-circle-right',
109
+ 'f139' => 'chevron-circle-up',
110
+ 'f078' => 'chevron-down',
111
+ 'f053' => 'chevron-left',
112
+ 'f054' => 'chevron-right',
113
+ 'f077' => 'chevron-up',
114
+ 'f10c' => 'circle-o',
115
+ 'f0ea' => 'clipboard',
116
+ 'f017' => 'clock-o',
117
+ 'f0c2' => 'cloud',
118
+ 'f0ed' => 'cloud-download',
119
+ 'f0ee' => 'cloud-upload',
120
+ 'f121' => 'code',
121
+ 'f126' => 'code-fork',
122
+ 'f0f4' => 'coffee',
123
+ 'f013' => 'cog',
124
+ 'f085' => 'cogs',
125
+ 'f0db' => 'columns',
126
+ 'f075' => 'comment',
127
+ 'f0e5' => 'comment-o',
128
+ 'f086' => 'comments',
129
+ 'f0e6' => 'comments-o',
130
+ 'f14e' => 'compass',
131
+ 'f066' => 'compress',
132
+ 'f09d' => 'credit-card',
133
+ 'f125' => 'crop',
134
+ 'f05b' => 'crosshairs',
135
+ 'f13c' => 'css3',
136
+ 'f0f5' => 'cutlery',
137
+ 'f108' => 'desktop',
138
+ 'f192' => 'dot-circle-o',
139
+ 'f019' => 'download',
140
+ 'f17d' => 'dribbble',
141
+ 'f16b' => 'dropbox',
142
+ 'f052' => 'eject',
143
+ 'f141' => 'ellipsis-h',
144
+ 'f142' => 'ellipsis-v',
145
+ 'f0e0' => 'envelope',
146
+ 'f003' => 'envelope-o',
147
+ 'f12d' => 'eraser',
148
+ 'f153' => 'eur',
149
+ 'f0ec' => 'exchange',
150
+ 'f12a' => 'exclamation',
151
+ 'f06a' => 'exclamation-circle',
152
+ 'f071' => 'exclamation-triangle',
153
+ 'f065' => 'expand',
154
+ 'f08e' => 'external-link',
155
+ 'f14c' => 'external-link-square',
156
+ 'f06e' => 'eye',
157
+ 'f070' => 'eye-slash',
158
+ 'f09a' => 'facebook',
159
+ 'f082' => 'facebook-square',
160
+ 'f049' => 'fast-backward',
161
+ 'f050' => 'fast-forward',
162
+ 'f182' => 'female',
163
+ 'f0fb' => 'fighter-jet',
164
+ 'f15b' => 'file',
165
+ 'f016' => 'file-o',
166
+ 'f15c' => 'file-text',
167
+ 'f0f6' => 'file-text-o',
168
+ 'f0c5' => 'files-o',
169
+ 'f008' => 'film',
170
+ 'f0b0' => 'filter',
171
+ 'f06d' => 'fire',
172
+ 'f134' => 'fire-extinguisher',
173
+ 'f024' => 'flag',
174
+ 'f11e' => 'flag-checkered',
175
+ 'f11d' => 'flag-o',
176
+ 'f0c3' => 'flask',
177
+ 'f16e' => 'flickr',
178
+ 'f0c7' => 'floppy-o',
179
+ 'f07b' => 'folder',
180
+ 'f114' => 'folder-o',
181
+ 'f07c' => 'folder-open',
182
+ 'f115' => 'folder-open-o',
183
+ 'f031' => 'font',
184
+ 'f04e' => 'forward',
185
+ 'f180' => 'foursquare',
186
+ 'f119' => 'frown-o',
187
+ 'f11b' => 'gamepad',
188
+ 'f0e3' => 'gavel',
189
+ 'f154' => 'gbp',
190
+ 'f06b' => 'gift',
191
+ 'f09b' => 'github',
192
+ 'f113' => 'github-alt',
193
+ 'f092' => 'github-square',
194
+ 'f184' => 'gittip',
195
+ 'f000' => 'glass',
196
+ 'f0ac' => 'globe',
197
+ 'f0d5' => 'google-plus',
198
+ 'f0d4' => 'google-plus-square',
199
+ 'f0fd' => 'h-square',
200
+ 'f0a7' => 'hand-o-down',
201
+ 'f0a5' => 'hand-o-left',
202
+ 'f0a4' => 'hand-o-right',
203
+ 'f0a6' => 'hand-o-up',
204
+ 'f0a0' => 'hdd-o',
205
+ 'f025' => 'headphones',
206
+ 'f004' => 'heart',
207
+ 'f08a' => 'heart-o',
208
+ 'f015' => 'home',
209
+ 'f0f8' => 'hospital-o',
210
+ 'f13b' => 'html5',
211
+ 'f01c' => 'inbox',
212
+ 'f03c' => 'indent',
213
+ 'f129' => 'info',
214
+ 'f05a' => 'info-circle',
215
+ 'f156' => 'inr',
216
+ 'f16d' => 'instagram',
217
+ 'f033' => 'italic',
218
+ 'f157' => 'jpy',
219
+ 'f084' => 'key',
220
+ 'f11c' => 'keyboard-o',
221
+ 'f159' => 'krw',
222
+ 'f109' => 'laptop',
223
+ 'f06c' => 'leaf',
224
+ 'f094' => 'lemon-o',
225
+ 'f149' => 'level-down',
226
+ 'f148' => 'level-up',
227
+ 'f0eb' => 'lightbulb-o',
228
+ 'f0c1' => 'link',
229
+ 'f0e1' => 'linkedin',
230
+ 'f08c' => 'linkedin-square',
231
+ 'f17c' => 'linux',
232
+ 'f03a' => 'list',
233
+ 'f022' => 'list-alt',
234
+ 'f0cb' => 'list-ol',
235
+ 'f0ca' => 'list-ul',
236
+ 'f124' => 'location-arrow',
237
+ 'f023' => 'lock',
238
+ 'f175' => 'long-arrow-down',
239
+ 'f177' => 'long-arrow-left',
240
+ 'f178' => 'long-arrow-right',
241
+ 'f176' => 'long-arrow-up',
242
+ 'f0d0' => 'magic',
243
+ 'f076' => 'magnet',
244
+ 'f122' => 'mail-reply-all',
245
+ 'f183' => 'male',
246
+ 'f041' => 'map-marker',
247
+ 'f136' => 'maxcdn',
248
+ 'f0fa' => 'medkit',
249
+ 'f11a' => 'meh-o',
250
+ 'f130' => 'microphone',
251
+ 'f131' => 'microphone-slash',
252
+ 'f068' => 'minus',
253
+ 'f056' => 'minus-circle',
254
+ 'f146' => 'minus-square',
255
+ 'f147' => 'minus-square-o',
256
+ 'f10b' => 'mobile',
257
+ 'f0d6' => 'money',
258
+ 'f186' => 'moon-o',
259
+ 'f001' => 'music',
260
+ 'f03b' => 'outdent',
261
+ 'f18c' => 'pagelines',
262
+ 'f0c6' => 'paperclip',
263
+ 'f04c' => 'pause',
264
+ 'f040' => 'pencil',
265
+ 'f14b' => 'pencil-square',
266
+ 'f044' => 'pencil-square-o',
267
+ 'f095' => 'phone',
268
+ 'f098' => 'phone-square',
269
+ 'f03e' => 'picture-o',
270
+ 'f0d2' => 'pinterest',
271
+ 'f0d3' => 'pinterest-square',
272
+ 'f072' => 'plane',
273
+ 'f04b' => 'play',
274
+ 'f144' => 'play-circle',
275
+ 'f01d' => 'play-circle-o',
276
+ 'f067' => 'plus',
277
+ 'f055' => 'plus-circle',
278
+ 'f0fe' => 'plus-square',
279
+ 'f196' => 'plus-square-o',
280
+ 'f011' => 'power-off',
281
+ 'f02f' => 'print',
282
+ 'f12e' => 'puzzle-piece',
283
+ 'f029' => 'qrcode',
284
+ 'f128' => 'question',
285
+ 'f059' => 'question-circle',
286
+ 'f10d' => 'quote-left',
287
+ 'f10e' => 'quote-right',
288
+ 'f074' => 'random',
289
+ 'f021' => 'refresh',
290
+ 'f18b' => 'renren',
291
+ 'f01e' => 'repeat',
292
+ 'f112' => 'reply',
293
+ 'f122' => 'reply-all',
294
+ 'f079' => 'retweet',
295
+ 'f018' => 'road',
296
+ 'f135' => 'rocket',
297
+ 'f09e' => 'rss',
298
+ 'f143' => 'rss-square',
299
+ 'f158' => 'rub',
300
+ 'f0c4' => 'scissors',
301
+ 'f002' => 'search',
302
+ 'f010' => 'search-minus',
303
+ 'f00e' => 'search-plus',
304
+ 'f064' => 'share',
305
+ 'f14d' => 'share-square',
306
+ 'f045' => 'share-square-o',
307
+ 'f132' => 'shield',
308
+ 'f07a' => 'shopping-cart',
309
+ 'f090' => 'sign-in',
310
+ 'f08b' => 'sign-out',
311
+ 'f012' => 'signal',
312
+ 'f0e8' => 'sitemap',
313
+ 'f17e' => 'skype',
314
+ 'f118' => 'smile-o',
315
+ 'f0dc' => 'sort',
316
+ 'f15d' => 'sort-alpha-asc',
317
+ 'f15e' => 'sort-alpha-desc',
318
+ 'f160' => 'sort-amount-asc',
319
+ 'f161' => 'sort-amount-desc',
320
+ 'f0dd' => 'sort-asc',
321
+ 'f0de' => 'sort-desc',
322
+ 'f162' => 'sort-numeric-asc',
323
+ 'f163' => 'sort-numeric-desc',
324
+ 'f110' => 'spinner',
325
+ 'f0c8' => 'square',
326
+ 'f096' => 'square-o',
327
+ 'f18d' => 'stack-exchange',
328
+ 'f16c' => 'stack-overflow',
329
+ 'f005' => 'star',
330
+ 'f089' => 'star-half',
331
+ 'f123' => 'star-half-o',
332
+ 'f006' => 'star-o',
333
+ 'f048' => 'step-backward',
334
+ 'f051' => 'step-forward',
335
+ 'f0f1' => 'stethoscope',
336
+ 'f04d' => 'stop',
337
+ 'f0cc' => 'strikethrough',
338
+ 'f12c' => 'subscript',
339
+ 'f0f2' => 'suitcase',
340
+ 'f185' => 'sun-o',
341
+ 'f12b' => 'superscript',
342
+ 'f0ce' => 'table',
343
+ 'f10a' => 'tablet',
344
+ 'f0e4' => 'tachometer',
345
+ 'f02b' => 'tag',
346
+ 'f02c' => 'tags',
347
+ 'f0ae' => 'tasks',
348
+ 'f120' => 'terminal',
349
+ 'f034' => 'text-height',
350
+ 'f035' => 'text-width',
351
+ 'f00a' => 'th',
352
+ 'f009' => 'th-large',
353
+ 'f00b' => 'th-list',
354
+ 'f08d' => 'thumb-tack',
355
+ 'f165' => 'thumbs-down',
356
+ 'f088' => 'thumbs-o-down',
357
+ 'f087' => 'thumbs-o-up',
358
+ 'f164' => 'thumbs-up',
359
+ 'f145' => 'ticket',
360
+ 'f00d' => 'times',
361
+ 'f057' => 'times-circle',
362
+ 'f05c' => 'times-circle-o',
363
+ 'f043' => 'tint',
364
+ 'f014' => 'trash-o',
365
+ 'f181' => 'trello',
366
+ 'f091' => 'trophy',
367
+ 'f0d1' => 'truck',
368
+ 'f195' => 'try',
369
+ 'f173' => 'tumblr',
370
+ 'f174' => 'tumblr-square',
371
+ 'f099' => 'twitter',
372
+ 'f081' => 'twitter-square',
373
+ 'f0e9' => 'umbrella',
374
+ 'f0cd' => 'underline',
375
+ 'f0e2' => 'undo',
376
+ 'f09c' => 'unlock',
377
+ 'f13e' => 'unlock-alt',
378
+ 'f093' => 'upload',
379
+ 'f155' => 'usd',
380
+ 'f007' => 'user',
381
+ 'f0f0' => 'user-md',
382
+ 'f0c0' => 'users',
383
+ 'f03d' => 'video-camera',
384
+ 'f194' => 'vimeo-square',
385
+ 'f189' => 'vk',
386
+ 'f027' => 'volume-down',
387
+ 'f026' => 'volume-off',
388
+ 'f028' => 'volume-up',
389
+ 'f18a' => 'weibo',
390
+ 'f193' => 'wheelchair',
391
+ 'f17a' => 'windows',
392
+ 'f0ad' => 'wrench',
393
+ 'f168' => 'xing',
394
+ 'f169' => 'xing-square',
395
+ 'f167' => 'youtube',
396
+ 'f16a' => 'youtube-play',
397
+ 'f166' => 'youtube-square'
398
+ ),
399
+ 'awesome_icons2' => array(
400
+ '\f042' => 'adjust',
401
+ '\f170' => 'adn',
402
+ '\f037' => 'align-center',
403
+ '\f039' => 'align-justify',
404
+ '\f036' => 'align-left',
405
+ '\f038' => 'align-right',
406
+ '\f0f9' => 'ambulance',
407
+ '\f13d' => 'anchor',
408
+ '\f17b' => 'android',
409
+ '\f103' => 'angle-double-down',
410
+ '\f100' => 'angle-double-left',
411
+ '\f101' => 'angle-double-right',
412
+ '\f102' => 'angle-double-up',
413
+ '\f107' => 'angle-down',
414
+ '\f104' => 'angle-left',
415
+ '\f105' => 'angle-right',
416
+ '\f106' => 'angle-up',
417
+ '\f179' => 'apple',
418
+ '\f187' => 'archive',
419
+ '\f0ab' => 'arrow-circle-down',
420
+ '\f0a8' => 'arrow-circle-left',
421
+ '\f01a' => 'arrow-circle-o-down',
422
+ '\f190' => 'arrow-circle-o-left',
423
+ '\f18e' => 'arrow-circle-o-right',
424
+ '\f01b' => 'arrow-circle-o-up',
425
+ '\f0a9' => 'arrow-circle-right',
426
+ '\f0aa' => 'arrow-circle-up',
427
+ '\f063' => 'arrow-down',
428
+ '\f060' => 'arrow-left',
429
+ '\f061' => 'arrow-right',
430
+ '\f062' => 'arrow-up',
431
+ '\f047' => 'arrows',
432
+ '\f0b2' => 'arrows-alt',
433
+ '\f07e' => 'arrows-h',
434
+ '\f07d' => 'arrows-v',
435
+ '\f069' => 'asterisk',
436
+ '\f04a' => 'backward',
437
+ '\f05e' => 'ban',
438
+ '\f080' => 'bar-chart-o',
439
+ '\f02a' => 'barcode',
440
+ '\f0c9' => 'bars',
441
+ '\f0fc' => 'beer',
442
+ '\f0f3' => 'bell',
443
+ '\f0a2' => 'bell-o',
444
+ '\f171' => 'bitbucket',
445
+ '\f172' => 'bitbucket-square',
446
+ '\f032' => 'bold',
447
+ '\f0e7' => 'bolt',
448
+ '\f02d' => 'book',
449
+ '\f02e' => 'bookmark',
450
+ '\f097' => 'bookmark-o',
451
+ '\f0b1' => 'briefcase',
452
+ '\f15a' => 'btc',
453
+ '\f188' => 'bug',
454
+ '\f0f7' => 'building-o',
455
+ '\f0a1' => 'bullhorn',
456
+ '\f140' => 'bullseye',
457
+ '\f073' => 'calendar',
458
+ '\f133' => 'calendar-o',
459
+ '\f030' => 'camera',
460
+ '\f083' => 'camera-retro',
461
+ '\f0d7' => 'caret-down',
462
+ '\f0d9' => 'caret-left',
463
+ '\f0da' => 'caret-right',
464
+ '\f150' => 'caret-square-o-down',
465
+ '\f191' => 'caret-square-o-left',
466
+ '\f152' => 'caret-square-o-right',
467
+ '\f151' => 'caret-square-o-up',
468
+ '\f0d8' => 'caret-up',
469
+ '\f0a3' => 'certificate',
470
+ '\f127' => 'chain-broken',
471
+ '\f00c' => 'check',
472
+ '\f058' => 'check-circle',
473
+ '\f05d' => 'check-circle-o',
474
+ '\f14a' => 'check-square',
475
+ '\f046' => 'check-square-o',
476
+ '\f13a' => 'chevron-circle-down',
477
+ '\f137' => 'chevron-circle-left',
478
+ '\f138' => 'chevron-circle-right',
479
+ '\f139' => 'chevron-circle-up',
480
+ '\f078' => 'chevron-down',
481
+ '\f053' => 'chevron-left',
482
+ '\f054' => 'chevron-right',
483
+ '\f077' => 'chevron-up',
484
+ '\f10c' => 'circle-o',
485
+ '\f0ea' => 'clipboard',
486
+ '\f017' => 'clock-o',
487
+ '\f0c2' => 'cloud',
488
+ '\f0ed' => 'cloud-download',
489
+ '\f0ee' => 'cloud-upload',
490
+ '\f121' => 'code',
491
+ '\f126' => 'code-fork',
492
+ '\f0f4' => 'coffee',
493
+ '\f013' => 'cog',
494
+ '\f085' => 'cogs',
495
+ '\f0db' => 'columns',
496
+ '\f075' => 'comment',
497
+ '\f0e5' => 'comment-o',
498
+ '\f086' => 'comments',
499
+ '\f0e6' => 'comments-o',
500
+ '\f14e' => 'compass',
501
+ '\f066' => 'compress',
502
+ '\f09d' => 'credit-card',
503
+ '\f125' => 'crop',
504
+ '\f05b' => 'crosshairs',
505
+ '\f13c' => 'css3',
506
+ '\f0f5' => 'cutlery',
507
+ '\f108' => 'desktop',
508
+ '\f192' => 'dot-circle-o',
509
+ '\f019' => 'download',
510
+ '\f17d' => 'dribbble',
511
+ '\f16b' => 'dropbox',
512
+ '\f052' => 'eject',
513
+ '\f141' => 'ellipsis-h',
514
+ '\f142' => 'ellipsis-v',
515
+ '\f0e0' => 'envelope',
516
+ '\f003' => 'envelope-o',
517
+ '\f12d' => 'eraser',
518
+ '\f153' => 'eur',
519
+ '\f0ec' => 'exchange',
520
+ '\f12a' => 'exclamation',
521
+ '\f06a' => 'exclamation-circle',
522
+ '\f071' => 'exclamation-triangle',
523
+ '\f065' => 'expand',
524
+ '\f08e' => 'external-link',
525
+ '\f14c' => 'external-link-square',
526
+ '\f06e' => 'eye',
527
+ '\f070' => 'eye-slash',
528
+ '\f09a' => 'facebook',
529
+ '\f082' => 'facebook-square',
530
+ '\f049' => 'fast-backward',
531
+ '\f050' => 'fast-forward',
532
+ '\f182' => 'female',
533
+ '\f0fb' => 'fighter-jet',
534
+ '\f15b' => 'file',
535
+ '\f016' => 'file-o',
536
+ '\f15c' => 'file-text',
537
+ '\f0f6' => 'file-text-o',
538
+ '\f0c5' => 'files-o',
539
+ '\f008' => 'film',
540
+ '\f0b0' => 'filter',
541
+ '\f06d' => 'fire',
542
+ '\f134' => 'fire-extinguisher',
543
+ '\f024' => 'flag',
544
+ '\f11e' => 'flag-checkered',
545
+ '\f11d' => 'flag-o',
546
+ '\f0c3' => 'flask',
547
+ '\f16e' => 'flickr',
548
+ '\f0c7' => 'floppy-o',
549
+ '\f07b' => 'folder',
550
+ '\f114' => 'folder-o',
551
+ '\f07c' => 'folder-open',
552
+ '\f115' => 'folder-open-o',
553
+ '\f031' => 'font',
554
+ '\f04e' => 'forward',
555
+ '\f180' => 'foursquare',
556
+ '\f119' => 'frown-o',
557
+ '\f11b' => 'gamepad',
558
+ '\f0e3' => 'gavel',
559
+ '\f154' => 'gbp',
560
+ '\f06b' => 'gift',
561
+ '\f09b' => 'github',
562
+ '\f113' => 'github-alt',
563
+ '\f092' => 'github-square',
564
+ '\f184' => 'gittip',
565
+ '\f000' => 'glass',
566
+ '\f0ac' => 'globe',
567
+ '\f0d5' => 'google-plus',
568
+ '\f0d4' => 'google-plus-square',
569
+ '\f0fd' => 'h-square',
570
+ '\f0a7' => 'hand-o-down',
571
+ '\f0a5' => 'hand-o-left',
572
+ '\f0a4' => 'hand-o-right',
573
+ '\f0a6' => 'hand-o-up',
574
+ '\f0a0' => 'hdd-o',
575
+ '\f025' => 'headphones',
576
+ '\f004' => 'heart',
577
+ '\f08a' => 'heart-o',
578
+ '\f015' => 'home',
579
+ '\f0f8' => 'hospital-o',
580
+ '\f13b' => 'html5',
581
+ '\f01c' => 'inbox',
582
+ '\f03c' => 'indent',
583
+ '\f129' => 'info',
584
+ '\f05a' => 'info-circle',
585
+ '\f156' => 'inr',
586
+ '\f16d' => 'instagram',
587
+ '\f033' => 'italic',
588
+ '\f157' => 'jpy',
589
+ '\f084' => 'key',
590
+ '\f11c' => 'keyboard-o',
591
+ '\f159' => 'krw',
592
+ '\f109' => 'laptop',
593
+ '\f06c' => 'leaf',
594
+ '\f094' => 'lemon-o',
595
+ '\f149' => 'level-down',
596
+ '\f148' => 'level-up',
597
+ '\f0eb' => 'lightbulb-o',
598
+ '\f0c1' => 'link',
599
+ '\f0e1' => 'linkedin',
600
+ '\f08c' => 'linkedin-square',
601
+ '\f17c' => 'linux',
602
+ '\f03a' => 'list',
603
+ '\f022' => 'list-alt',
604
+ '\f0cb' => 'list-ol',
605
+ '\f0ca' => 'list-ul',
606
+ '\f124' => 'location-arrow',
607
+ '\f023' => 'lock',
608
+ '\f175' => 'long-arrow-down',
609
+ '\f177' => 'long-arrow-left',
610
+ '\f178' => 'long-arrow-right',
611
+ '\f176' => 'long-arrow-up',
612
+ '\f0d0' => 'magic',
613
+ '\f076' => 'magnet',
614
+ '\f122' => 'mail-reply-all',
615
+ '\f183' => 'male',
616
+ '\f041' => 'map-marker',
617
+ '\f136' => 'maxcdn',
618
+ '\f0fa' => 'medkit',
619
+ '\f11a' => 'meh-o',
620
+ '\f130' => 'microphone',
621
+ '\f131' => 'microphone-slash',
622
+ '\f068' => 'minus',
623
+ '\f056' => 'minus-circle',
624
+ '\f146' => 'minus-square',
625
+ '\f147' => 'minus-square-o',
626
+ '\f10b' => 'mobile',
627
+ '\f0d6' => 'money',
628
+ '\f186' => 'moon-o',
629
+ '\f001' => 'music',
630
+ '\f03b' => 'outdent',
631
+ '\f18c' => 'pagelines',
632
+ '\f0c6' => 'paperclip',
633
+ '\f04c' => 'pause',
634
+ '\f040' => 'pencil',
635
+ '\f14b' => 'pencil-square',
636
+ '\f044' => 'pencil-square-o',
637
+ '\f095' => 'phone',
638
+ '\f098' => 'phone-square',
639
+ '\f03e' => 'picture-o',
640
+ '\f0d2' => 'pinterest',
641
+ '\f0d3' => 'pinterest-square',
642
+ '\f072' => 'plane',
643
+ '\f04b' => 'play',
644
+ '\f144' => 'play-circle',
645
+ '\f01d' => 'play-circle-o',
646
+ '\f067' => 'plus',
647
+ '\f055' => 'plus-circle',
648
+ '\f0fe' => 'plus-square',
649
+ '\f196' => 'plus-square-o',
650
+ '\f011' => 'power-off',
651
+ '\f02f' => 'print',
652
+ '\f12e' => 'puzzle-piece',
653
+ '\f029' => 'qrcode',
654
+ '\f128' => 'question',
655
+ '\f059' => 'question-circle',
656
+ '\f10d' => 'quote-left',
657
+ '\f10e' => 'quote-right',
658
+ '\f074' => 'random',
659
+ '\f021' => 'refresh',
660
+ '\f18b' => 'renren',
661
+ '\f01e' => 'repeat',
662
+ '\f112' => 'reply',
663
+ '\f122' => 'reply-all',
664
+ '\f079' => 'retweet',
665
+ '\f018' => 'road',
666
+ '\f135' => 'rocket',
667
+ '\f09e' => 'rss',
668
+ '\f143' => 'rss-square',
669
+ '\f158' => 'rub',
670
+ '\f0c4' => 'scissors',
671
+ '\f002' => 'search',
672
+ '\f010' => 'search-minus',
673
+ '\f00e' => 'search-plus',
674
+ '\f064' => 'share',
675
+ '\f14d' => 'share-square',
676
+ '\f045' => 'share-square-o',
677
+ '\f132' => 'shield',
678
+ '\f07a' => 'shopping-cart',
679
+ '\f090' => 'sign-in',
680
+ '\f08b' => 'sign-out',
681
+ '\f012' => 'signal',
682
+ '\f0e8' => 'sitemap',
683
+ '\f17e' => 'skype',
684
+ '\f118' => 'smile-o',
685
+ '\f0dc' => 'sort',
686
+ '\f15d' => 'sort-alpha-asc',
687
+ '\f15e' => 'sort-alpha-desc',
688
+ '\f160' => 'sort-amount-asc',
689
+ '\f161' => 'sort-amount-desc',
690
+ '\f0dd' => 'sort-asc',
691
+ '\f0de' => 'sort-desc',
692
+ '\f162' => 'sort-numeric-asc',
693
+ '\f163' => 'sort-numeric-desc',
694
+ '\f110' => 'spinner',
695
+ '\f0c8' => 'square',
696
+ '\f096' => 'square-o',
697
+ '\f18d' => 'stack-exchange',
698
+ '\f16c' => 'stack-overflow',
699
+ '\f005' => 'star',
700
+ '\f089' => 'star-half',
701
+ '\f123' => 'star-half-o',
702
+ '\f006' => 'star-o',
703
+ '\f048' => 'step-backward',
704
+ '\f051' => 'step-forward',
705
+ '\f0f1' => 'stethoscope',
706
+ '\f04d' => 'stop',
707
+ '\f0cc' => 'strikethrough',
708
+ '\f12c' => 'subscript',
709
+ '\f0f2' => 'suitcase',
710
+ '\f185' => 'sun-o',
711
+ '\f12b' => 'superscript',
712
+ '\f0ce' => 'table',
713
+ '\f10a' => 'tablet',
714
+ '\f0e4' => 'tachometer',
715
+ '\f02b' => 'tag',
716
+ '\f02c' => 'tags',
717
+ '\f0ae' => 'tasks',
718
+ '\f120' => 'terminal',
719
+ '\f034' => 'text-height',
720
+ '\f035' => 'text-width',
721
+ '\f00a' => 'th',
722
+ '\f009' => 'th-large',
723
+ '\f00b' => 'th-list',
724
+ '\f08d' => 'thumb-tack',
725
+ '\f165' => 'thumbs-down',
726
+ '\f088' => 'thumbs-o-down',
727
+ '\f087' => 'thumbs-o-up',
728
+ '\f164' => 'thumbs-up',
729
+ '\f145' => 'ticket',
730
+ '\f00d' => 'times',
731
+ '\f057' => 'times-circle',
732
+ '\f05c' => 'times-circle-o',
733
+ '\f043' => 'tint',
734
+ '\f014' => 'trash-o',
735
+ '\f181' => 'trello',
736
+ '\f091' => 'trophy',
737
+ '\f0d1' => 'truck',
738
+ '\f195' => 'try',
739
+ '\f173' => 'tumblr',
740
+ '\f174' => 'tumblr-square',
741
+ '\f099' => 'twitter',
742
+ '\f081' => 'twitter-square',
743
+ '\f0e9' => 'umbrella',
744
+ '\f0cd' => 'underline',
745
+ '\f0e2' => 'undo',
746
+ '\f09c' => 'unlock',
747
+ '\f13e' => 'unlock-alt',
748
+ '\f093' => 'upload',
749
+ '\f155' => 'usd',
750
+ '\f007' => 'user',
751
+ '\f0f0' => 'user-md',
752
+ '\f0c0' => 'users',
753
+ '\f03d' => 'video-camera',
754
+ '\f194' => 'vimeo-square',
755
+ '\f189' => 'vk',
756
+ '\f027' => 'volume-down',
757
+ '\f026' => 'volume-off',
758
+ '\f028' => 'volume-up',
759
+ '\f18a' => 'weibo',
760
+ '\f193' => 'wheelchair',
761
+ '\f17a' => 'windows',
762
+ '\f0ad' => 'wrench',
763
+ '\f168' => 'xing',
764
+ '\f169' => 'xing-square',
765
+ '\f167' => 'youtube',
766
+ '\f16a' => 'youtube-play',
767
+ '\f166' => 'youtube-square'
768
+ ),
769
+
770
+ 'awesome_icons_socials' =>array(
771
+ 'f170' => 'adn',
772
+ 'f17b' => 'android',
773
+ 'f179' => 'apple',
774
+ 'f171' => 'bitbucket',
775
+ 'f171' => 'bitbucket-square',
776
+ 'f02e' => 'bookmark',
777
+ 'f097' => 'bookmark-o',
778
+ 'f15a' => 'btc',
779
+ 'f13c' => 'css3',
780
+ 'f17d' => 'dribble',
781
+ 'f16b' => 'dropbox',
782
+ 'f09a' => 'facebook',
783
+ 'f082' => 'facebook-square',
784
+ 'f16e' => 'flickr',
785
+ 'f180' => 'foursquare',
786
+ 'f09b'=> 'github' ,
787
+ 'f113'=> 'github-alt',
788
+ 'f092' => 'github-square',
789
+ 'f184' => 'gittip',
790
+ 'f0d5' => 'google-plus',
791
+ 'f0d4' => 'google-plus-square',
792
+ 'f13b' => 'html5',
793
+ 'f16d' => 'instagram',
794
+ 'f0e1' => 'linkedin',
795
+ 'f08c' => 'linkedin-square',
796
+ 'f17c' => 'Linux',
797
+ 'f136' => 'maxcdn',
798
+ 'f18c' => 'pagelines',
799
+ 'f0d2' => 'pinterest',
800
+ 'f0d3' => 'pinterest-square',
801
+ 'f18b' => 'renren',
802
+ 'f09e' => 'rss',
803
+ 'f17e' => 'skype',
804
+ 'f18d' => 'stack-exchange',
805
+ 'f16c' => 'stack-overflow',
806
+ 'f181' => 'trello',
807
+ 'f173' => 'tumblr',
808
+ 'f174' => 'Tumblr Square',
809
+ 'f099' => 'twitter',
810
+ 'f081' => 'twitter-square',
811
+ 'f194' => 'vimeo-square',
812
+ 'f189' => 'vk',
813
+ 'f18a' => 'weibo',
814
+ 'f17a' => 'windows',
815
+ 'f168' => 'xing',
816
+ 'f169' => 'xing-square',
817
+ 'f167' => 'youtube'
818
+ ),
819
+ 'header_backgrounds' => array(),
820
+ 'body_backgrounds' => array(),
821
+
822
+ // tags used in theme options (e.g. %tag%) to have some common informations
823
+ 'tag' => array( //'themeurl' => get_template_directory_uri()
824
+ ),
825
+
826
+ 'cycle_fx' => array(
827
+ 'blindX' => 'blindX', 'blindY' => 'blindY', 'blindZ' => 'blindZ', 'cover' => 'cover', 'curtainX' => 'curtainX',
828
+ 'curtainY' => 'curtainY', 'fade' => 'fade', 'fadeZoom' => 'fadeZoom', 'growX' => 'growX', 'growY' => 'growY',
829
+ 'scrollUp' => 'scrollUp', 'scrollDown' => 'scrollDown', 'scrollLeft' => 'scrollLeft', 'scrollRight' => 'scrollRight', 'scrollHorz' => 'scrollHorz',
830
+ 'shuffle' => 'shuffle', 'slideX' => 'slideX', 'slideY' => 'slideY', 'toss' => 'toss', 'turnUp' => 'turnUp',
831
+ 'turnLeft' => 'turnLeft', 'turnRight' => 'turnRight', 'uncover' => 'uncover', 'wipe' => 'wipe', 'zoom' => 'zoom',
832
+ 'none' => 'none', 'turnDown' => 'turnDown', 'scrollVert' => 'scrollVert'
833
+ ),
834
+
835
+ 'animate' => array(
836
+ '' => "none",
837
+ "bounce" => "bounce",
838
+ "flash" =>"flash",
839
+ "pulse" =>"pulse",
840
+ //"rubberBand"=>"rubberBand",
841
+ "shake" =>"shake",
842
+ "swing"=>"swing",
843
+ "tada" =>"tada",
844
+ "wobble"=>"wobble",
845
+ "bounceIn"=>"bounceIn",
846
+ "bounceInDown"=>"bounceInDown",
847
+ "bounceInLeft"=>"bounceInLeft",
848
+ "bounceInRight"=>"bounceInRight",
849
+ "bounceInUp"=>"bounceInUp",
850
+ "fadeIn"=>"fadeIn",
851
+ "fadeInDown"=>"fadeInDown",
852
+ "fadeInDownBig"=>"fadeInDownBig",
853
+ "fadeInLeft"=>"fadeInLeft",
854
+ "fadeInLeftBig"=>"fadeInLeftBig",
855
+ "fadeInRight"=>"fadeInRight",
856
+ "fadeInRightBig"=>"fadeInRightBig",
857
+ "fadeInUp"=>"fadeInUp",
858
+ "fadeInUpBig"=>"fadeInUpBig",
859
+ "flip"=>"flip",
860
+ "flipInX"=>"flipInX",
861
+ "flipInY"=>"flipInY",
862
+ "lightSpeedIn"=>"lightSpeedIn",
863
+ "rotateIn"=>"rotateIn",
864
+ "rotateInDownLeft"=>"rotateInDownLeft",
865
+ "rotateInDownRight"=>"rotateInDownRight",
866
+ "rotateInUpLeft"=>"rotateInUpLeft",
867
+ "rotateInUpRight"=>"rotateInUpRight",
868
+ //"slideInDown"=>"slideInDown",
869
+ //"slideInLeft"=>"slideInLeft",
870
+ //"slideInRight"=>"slideInRight",
871
+ "rollIn"=>"rollIn",
872
+ ),
873
+
874
+ 'easings' => array(
875
+ FALSE => 'none',
876
+ 'easeInQuad' => 'easeInQuad',
877
+ 'easeOutQuad' => 'easeOutQuad',
878
+ 'easeInOutQuad' => 'easeInOutQuad',
879
+ 'easeInCubic' => 'easeInCubic',
880
+ 'easeOutCubic' => 'easeOutCubic',
881
+ 'easeInOutCubic' => 'easeInOutCubic',
882
+ 'easeInQuart' => 'easeInQuart',
883
+ 'easeOutQuart' => 'easeOutQuart',
884
+ 'easeInOutQuart' => 'easeInOutQuart',
885
+ 'easeInQuint' => 'easeInQuint',
886
+ 'easeOutQuint' => 'easeOutQuint',
887
+ 'easeInOutQuint' => 'easeInOutQuint',
888
+ 'easeInSine' => 'easeInSine',
889
+ 'easeOutSine' => 'easeOutSine',
890
+ 'easeInOutSine' => 'easeInOutSine',
891
+ 'easeInExpo' => 'easeInExpo',
892
+ 'easeOutExpo' => 'easeOutExpo',
893
+ 'easeInOutExpo' => 'easeInOutExpo',
894
+ 'easeInCirc' => 'easeInCirc',
895
+ 'easeOutCirc' => 'easeOutCirc',
896
+ 'easeInOutCirc' => 'easeInOutCirc',
897
+ 'easeInElastic' => 'easeInElastic',
898
+ 'easeOutElastic' => 'easeOutElastic',
899
+ 'easeInOutElastic' => 'easeInOutElastic',
900
+ 'easeInBack' => 'easeInBack',
901
+ 'easeOutBack' => 'easeOutBack',
902
+ 'easeInOutBack' => 'easeInOutBack',
903
+ 'easeInBounce' => 'easeInBounce',
904
+ 'easeOutBounce' => 'easeOutBounce',
905
+ 'easeInOutBounce' => 'easeInOutBounce'
906
+ )
907
+ );
908
+
909
+ /**
910
+ * Get configuration array
911
+ *
912
+ * @return array
913
+ */
914
+ public static function load() {
915
+ self::_loadThemeInfo();
916
+ //ksort( self::$_config['awesome_icons'] );
917
+
918
+ return self::$_config;
919
+ }
920
+
921
+ /**
922
+ * Return theme data
923
+ *
924
+ * First the method checks if the wp_get_theme() function exists (WP 3.4.0 at least).
925
+ * If not, the method calls the deprecated function get_template_directory()
926
+ *
927
+ * @return array
928
+ */
929
+ protected static function _loadThemeInfo() {
930
+ $theme = wp_get_theme();
931
+
932
+ self::$_config['theme'] = array(
933
+ 'name' => $theme->Name,
934
+ 'description' => $theme->Description,
935
+ 'author' => $theme->Author,
936
+ 'authoruri' => $theme->{'Author URI'},
937
+ 'version' => $theme->Version,
938
+ 'template' => $theme->Template,
939
+ 'status' => $theme->Status,
940
+ 'tags' => $theme->Tags
941
+ );
942
+ }
943
+
944
+
945
+ public function init() {
946
+ self::$_config['header_backgrounds'] = apply_filters( 'yit_header_backgrounds', self::$_config['header_backgrounds'] );
947
+ self::$_config['body_backgrounds'] = apply_filters( 'yit_body_backgrounds', self::$_config['body_backgrounds'] );
948
+ }
949
+
950
+ /**
951
+ * Return the font awesome array icon
952
+ *
953
+ * @return string Array
954
+ * @access public
955
+ * @since 1.0.0
956
+ */
957
+ public static function get_awesome_icons() {
958
+ return self::$_config['awesome_icons'];
959
+ }
960
+
961
+ /**
962
+ * Return the font awesome array socials icon
963
+ *
964
+ * @return string Array
965
+ * @access public
966
+ * @since 1.0.0
967
+ */
968
+ public static function get_awesome_icons_socials() {
969
+ return self::$_config['awesome_icons_socials'];
970
+ }
971
+
972
+
973
+ /**
974
+ * Return the list of icons
975
+ *
976
+ * @return string Array
977
+ * @access public
978
+ * @since 1.0.0
979
+ */
980
+ public static function get_icon_list() {
981
+
982
+ $standard_icon_list = array(
983
+ 'FontAwesome' => self::$_config['awesome_icons2']
984
+ );
985
+
986
+ return apply_filters( 'yit_icon_list', $standard_icon_list );
987
+ }
988
+
989
+ /**
990
+ * Return the data of icon
991
+ *
992
+ * @return string Array
993
+ * @access public
994
+ * @since 1.0.0
995
+ */
996
+ public static function get_icon( $icon ) {
997
+
998
+ $icon_list = self::get_icon_list();
999
+ $icon_data = '';
1000
+ if ( $icon != '' ) {
1001
+ $ic = explode( ':', $icon );
1002
+ $icon_code = array_search( $ic[1], $icon_list[$ic[0]] );
1003
+
1004
+ if( $icon_code ){
1005
+ $icon_code = ( strpos( $icon_code, '\\' ) === 0 ) ? '&#x' . substr( $icon_code, 1 ) . ';' : $icon_code;
1006
+ }
1007
+
1008
+ $icon_data = 'data-font="' . $ic[0] . '" data-key="' . $ic[1] . '" data-icon="' . $icon_code . '"';
1009
+ }
1010
+
1011
+ return $icon_data;
1012
+ }
1013
+
1014
+
1015
+ /*
1016
+ * Return the code of the relative awesome class name
1017
+ *
1018
+ * @return string
1019
+ * @access public
1020
+ * @since 1.0.0
1021
+ */
1022
+ public static function get_awesome_icons_code_by_value($class){
1023
+ $awesome_icons=self::$_config['awesome_icons'];
1024
+ foreach($awesome_icons as $key => $value){
1025
+ if($class==$value) {
1026
+ return $key;
1027
+ }
1028
+ }
1029
+
1030
+ return "";
1031
+ }
1032
+ }
1033
+
1034
+ endif;
plugin-fw/lib/yit-plugin-gradients.php ADDED
@@ -0,0 +1,536 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Your Inspiration Themes
4
+ *
5
+ * In this files there is a collection of a functions useful for the core
6
+ * of the framework.
7
+ *
8
+ * @package WordPress
9
+ * @subpackage Your Inspiration Themes
10
+ * @author Your Inspiration Themes Team <info@yithemes.com>
11
+ *
12
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
13
+ * that is bundled with this package in the file LICENSE.txt.
14
+ * It is also available through the world-wide-web at this URL:
15
+ * http://www.gnu.org/licenses/gpl-3.0.txt
16
+ */
17
+
18
+ /**
19
+ * Handles colors
20
+ *
21
+ * @since 1.0
22
+ */
23
+ /**
24
+ * Generates CSS 3 gradients for all browsers.
25
+ *
26
+ * @since 1.0
27
+ */
28
+
29
+ if ( ! class_exists( 'YIT_Gradients' ) ) {
30
+
31
+ class YIT_Gradients {
32
+
33
+ /**
34
+ * An array of colors to use for a gradient.
35
+ *
36
+ * @var array
37
+ * @since 1.0
38
+ */
39
+ public $colors_gradient = array();
40
+
41
+ /**
42
+ * Set properties
43
+ *
44
+ * @param string $key
45
+ * @param $value
46
+ *
47
+ * @internal param array $colors_gradient
48
+ * @return void
49
+ * @since 1.0
50
+ */
51
+ public function set( $key, $value ) {
52
+ if ( property_exists( $this, $key ) ) {
53
+ $this->{$key} = $value;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Get properties
59
+ *
60
+ * @param string $key
61
+ *
62
+ * @return mixed
63
+ * @since 1.0
64
+ */
65
+ public function get( $key ) {
66
+ if ( property_exists( $this, $key ) ) {
67
+ return $this->{$key};
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Add a color to use in a gradient.
73
+ *
74
+ * @param string $color
75
+ * @param int $position
76
+ *
77
+ * @return void
78
+ * @since 1.0
79
+ */
80
+ public function add_color_gradient( $color, $position ) {
81
+ $the_color['color'] = $color;
82
+ $the_color['position'] = $position;
83
+
84
+ array_push( $this->colors_gradient, $the_color );
85
+ }
86
+
87
+ /**
88
+ * Generate the CSS code for a gradient.
89
+ *
90
+ * @param string $role
91
+ * @param string $direction
92
+ *
93
+ * @return string|bool
94
+ * @since 1.0
95
+ */
96
+ public function gradient( $role, $direction ) {
97
+ if ( ! empty( $this->colors_gradient ) ) {
98
+
99
+ $css = array(
100
+ 'old' => $this->_make_old_gradient( $this->colors_gradient[0]['color'] ), //old browser
101
+ 'ff3' => $this->_make_modern_gradient( $this->colors_gradient, $direction, 'moz' ), //firefox 3.6+
102
+ 'chr_saf4' => $this->_make_chr_saf4_gradient( $this->colors_gradient, $direction ), //chrome and safari4+
103
+ 'chr10_saf5' => $this->_make_modern_gradient( $this->colors_gradient, $direction, 'webkit' ), //chrome10+ and safari5+
104
+ 'opera' => $this->_make_modern_gradient( $this->colors_gradient, $direction, 'o' ), //opera11.10+
105
+ 'ie10' => $this->_make_modern_gradient( $this->colors_gradient, $direction, 'ms' ), //internet explorer 10+
106
+ 'w3c' => $this->_make_modern_gradient( $this->colors_gradient, $direction, 'w3c' ), //w3c
107
+ 'ie6_9' => $this->_make_ie6_gradient( $this->colors_gradient, $direction ) //ie6-9
108
+ );
109
+
110
+ $css = $role . '{' . implode( ';', $css ) . '}';
111
+
112
+ $this->colors_gradient = array();
113
+
114
+ return $css;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Reverse a gradient. This method should be used only before calling ::make_gradient(). Otherwise it will not works.
120
+ *
121
+ * @return void
122
+ * @since 1.0
123
+ */
124
+ public function reverse_gradient() {
125
+ $colors_gradient = array_reverse( $this->get( 'colors_gradient' ) );
126
+
127
+ for ( $i = 0; $i < count( $colors_gradient ); $i ++ ) {
128
+ $colors_gradient[$i]['position'] = 100 - $colors_gradient[$i]['position'];
129
+ }
130
+
131
+ $this->set( 'colors_gradient', $colors_gradient );
132
+ }
133
+
134
+ /**
135
+ * Generate the CSS code for a gradient.
136
+ *
137
+ * @param string $role
138
+ * @param string $direction
139
+ *
140
+ * @return string|bool
141
+ * @since 1.0
142
+ */
143
+ public function get_gradient( $role, $direction ) {
144
+ return $this->gradient( $role, $direction );
145
+ }
146
+
147
+ /**
148
+ * Generate the CSS code for a gradient.
149
+ *
150
+ * @param string $role
151
+ * @param string $direction
152
+ *
153
+ * @return void
154
+ * @since 1.0
155
+ */
156
+ public function the_gradient( $role, $direction ) {
157
+ echo $this->get_gradient( $role, $direction );
158
+ }
159
+
160
+ /**
161
+ * Generate the CSS code for a gradient.
162
+ *
163
+ * @param string $role
164
+ * @param string $from
165
+ * @param string $to
166
+ * @param string $direction
167
+ *
168
+ * @return string|bool
169
+ * @since 1.0
170
+ */
171
+ public function gradient_from_to( $role, $from, $to, $direction ) {
172
+
173
+ $colors = array(
174
+ array(
175
+ 'color' => $from,
176
+ 'position' => 0
177
+ ),
178
+ array(
179
+ 'color' => $to,
180
+ 'position' => 100
181
+ ),
182
+ );
183
+
184
+ $this->set( 'colors_gradient', $colors );
185
+ return $this->get_gradient( $role, $direction );
186
+ }
187
+
188
+ /**
189
+ * Generate the CSS code for a gradient.
190
+ *
191
+ * @param string $role
192
+ * @param string $color
193
+ * @param string $direction
194
+ * @param int|string $factor
195
+ *
196
+ * @return string|bool
197
+ * @since 1.0
198
+ */
199
+ public function gradient_darker( $role, $color, $direction, $factor = 30 ) {
200
+
201
+ $colors = array(
202
+ array(
203
+ 'color' => $color,
204
+ 'position' => 0
205
+ ),
206
+ array(
207
+ 'color' => $this->hex_darker( $color, $factor ),
208
+ 'position' => 100
209
+ ),
210
+ );
211
+
212
+ $this->set( 'colors_gradient', $colors );
213
+ return $this->get_gradient( $role, $direction );
214
+ }
215
+
216
+ /**
217
+ * Generate the CSS code for a gradient.
218
+ *
219
+ * @param string $role
220
+ * @param string $color
221
+ * @param string $direction
222
+ * @param int|string $factor
223
+ *
224
+ * @return string|bool
225
+ * @since 1.0
226
+ */
227
+ public function gradient_lighter( $role, $color, $direction, $factor = 30 ) {
228
+
229
+ $colors = array(
230
+ array(
231
+ 'color' => $color,
232
+ 'position' => 0
233
+ ),
234
+ array(
235
+ 'color' => $this->hex_lighter( $color, $factor ),
236
+ 'position' => 100
237
+ ),
238
+ );
239
+
240
+ $this->set( 'colors_gradient', $colors );
241
+ return $this->get_gradient( $role, $direction );
242
+ }
243
+
244
+ /**
245
+ * Generate the CSS code for a gradient that not supports gradients (add only a background color).
246
+ *
247
+ * @param $color
248
+ *
249
+ * @internal param string $role
250
+ * @return string|bool
251
+ * @access private
252
+ * @since 1.0
253
+ */
254
+ private function _make_old_gradient( $color ) {
255
+ return 'background:' . $color;
256
+ }
257
+
258
+ /**
259
+ * Generate the CSS code for a gradient in IE6-9.
260
+ *
261
+ * @param $colors
262
+ * @param $direction
263
+ *
264
+ * @internal param string $role
265
+ * @return string|bool
266
+ * @access private
267
+ * @since 1.0
268
+ */
269
+ private function _make_ie6_gradient( $colors, $direction ) {
270
+ $css = 'filter:progid:DXImageTransform.Microsoft.gradient(';
271
+ $css .= 'startColorstr=\'' . $colors[0]['color'] . '\',';
272
+ $css .= 'endColorstr=\'' . $colors[count( $colors ) - 1]['color'] . '\',';
273
+
274
+ if ( $direction == 'horizontal' ) {
275
+ $css .= 'GradientType=1';
276
+ }
277
+ else {
278
+ $css .= 'GradientType=0';
279
+ } //vertical
280
+
281
+ $css .= ')';
282
+
283
+ return $css;
284
+ }
285
+
286
+ /**
287
+ * Make the CSS 3 for a gradient in modern browsers( FF3.6+, Chrome, Safari5+, Opera11.10+, IE10+ )
288
+ *
289
+ * @param array $colors
290
+ * @param string $direction
291
+ * @param $browser
292
+ *
293
+ * @return string
294
+ * @access private
295
+ * @since 1.0
296
+ */
297
+ private function _make_modern_gradient( $colors, $direction, $browser ) {
298
+ $css = 'background:';
299
+
300
+ //Add the browser suffix
301
+ if ( $browser != 'w3c' ) {
302
+ $browser = '-' . $browser . '-';
303
+ }
304
+ else {
305
+ $browser = '';
306
+ }
307
+
308
+ switch ( $direction ) {
309
+ case 'vertical' :
310
+ $css .= $browser . 'linear-gradient(top,';
311
+ break;
312
+ case 'horizontal' :
313
+ $css .= $browser . 'linear-gradient(left,';
314
+ break;
315
+ case 'diagonal-bottom':
316
+ $css .= $browser . 'linear-gradient(-45deg,';
317
+ break;
318
+ case 'diagonal-top' :
319
+ $css .= $browser . 'linear-gradient(45deg,';
320
+ break;
321
+ case 'radial' :
322
+ $css .= $browser . 'radial-gradient(center, ellipse cover,';
323
+ break;
324
+ }
325
+
326
+ foreach ( $colors as $stop ) {
327
+ $css .= $stop['color'] . ' ' . $stop['position'] . '%, ';
328
+ }
329
+
330
+ $css = rtrim( $css );
331
+ $css = rtrim( $css, ',' );
332
+ $css .= ')';
333
+
334
+ return $css;
335
+ }
336
+
337
+ /**
338
+ * Make the CSS 3 for a gradient in Chrome and Safari 4+
339
+ *
340
+ * @param array $colors
341
+ * @param string $direction
342
+ *
343
+ * @return string
344
+ * @access private
345
+ * @since 1.0
346
+ */
347
+ private function _make_chr_saf4_gradient( $colors, $direction ) {
348
+ $css = 'background:';
349
+
350
+ switch ( $direction ) {
351
+ case 'vertical' :
352
+ $css .= '-webkit-gradient(linear,left top,left bottom,';
353
+ break;
354
+ case 'horizontal' :
355
+ $css .= '-webkit-gradient(linear,left top,right top,';
356
+ break;
357
+ case 'diagonal-bottom':
358
+ $css .= '-webkit-gradient(linear,left top,right bottom,';
359
+ break;
360
+ case 'diagonal-top' :
361
+ $css .= '-webkit-gradient(linear,left bottom,right top,';
362
+ break;
363
+ case 'radial' :
364
+ $css .= '-webkit-gradient(radial,center center, 0px, center center, 100%,';
365
+ break;
366
+ }
367
+
368
+ foreach ( $colors as $stop ) {
369
+ $css .= 'color-stop(' . $stop['position'] . '%, ' . $stop['color'] . '), ';
370
+ }
371
+
372
+ $css = rtrim( $css );
373
+ $css = rtrim( $css, ',' );
374
+ $css .= ')';
375
+
376
+ return $css;
377
+ }
378
+
379
+
380
+ /**
381
+ * Return an instance of the model called
382
+ *
383
+ * @param string $class The name of class that I want the instance
384
+ *
385
+ * @since 2.0.0
386
+ * @author Simone D'Amico <simone.damico@yithemes.com>
387
+ * @return mixed
388
+ */
389
+ public function getModel( $class ) {
390
+ return YIT_Registry::get_instance()->$class;
391
+ }
392
+
393
+
394
+ /**
395
+ * Return a color darker then $color.
396
+ *
397
+ * @param string $color
398
+ * @param int $factor
399
+ *
400
+ * @return string
401
+ * @since 1.0
402
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
403
+ */
404
+ public function hex_darker( $color, $factor = 30 ) {
405
+ $color = str_replace( '#', '', $color );
406
+
407
+ $base['R'] = hexdec( substr( $color, 0, 2 ) );
408
+ $base['G'] = hexdec( substr( $color, 2, 2 ) );
409
+ $base['B'] = hexdec( substr( $color, 4, 2 ) );
410
+
411
+ $color = '#';
412
+
413
+ foreach ( $base as $k => $v ) {
414
+ $amount = $v / 100;
415
+ $amount = round( $amount * $factor );
416
+ $new_decimal = $v - $amount;
417
+
418
+ $new_hex_component = dechex( $new_decimal );
419
+
420
+ if ( strlen( $new_hex_component ) < 2 ) {
421
+ $new_hex_component = "0" . $new_hex_component;
422
+ }
423
+
424
+ $color .= $new_hex_component;
425
+ }
426
+
427
+ return $color;
428
+ }
429
+
430
+ /**
431
+ * Return a color lighter then $color.
432
+ *
433
+ * @param string $color
434
+ * @param int $factor
435
+ *
436
+ * @return string
437
+ * @since 1.0
438
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
439
+ */
440
+ public function hex_lighter( $color, $factor = 30 ) {
441
+ $color = str_replace( '#', '', $color );
442
+
443
+ $base['R'] = hexdec( $color{0} . $color{1} );
444
+ $base['G'] = hexdec( $color{2} . $color{3} );
445
+ $base['B'] = hexdec( $color{4} . $color{5} );
446
+
447
+ $color = '#';
448
+
449
+ foreach ( $base as $k => $v ) {
450
+ $amount = 255 - $v;
451
+ $amount = $amount / 100;
452
+ $amount = round( $amount * $factor );
453
+ $new_decimal = $v + $amount;
454
+
455
+ $new_hex_component = dechex( $new_decimal );
456
+
457
+ if ( strlen( $new_hex_component ) < 2 ) {
458
+ $new_hex_component = "0" . $new_hex_component;
459
+ }
460
+
461
+ $color .= $new_hex_component;
462
+ }
463
+
464
+ return $color;
465
+ }
466
+
467
+ /**
468
+ * Detect if we must use a color darker or lighter then the background.
469
+ *
470
+ * @param string $color
471
+ * @param string $dark
472
+ * @param string $light
473
+ *
474
+ * @return string
475
+ * @since 1.0
476
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
477
+ */
478
+ public function light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) {
479
+ $hex = str_replace( '#', '', $color );
480
+
481
+ $c_r = hexdec( substr( $hex, 0, 2 ) );
482
+ $c_g = hexdec( substr( $hex, 2, 2 ) );
483
+ $c_b = hexdec( substr( $hex, 4, 2 ) );
484
+ $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
485
+
486
+ return ( $brightness > 155 ) ? $dark : $light;
487
+ }
488
+
489
+ /**
490
+ * Detect if we must use a color darker or lighter then the background.
491
+ *
492
+ * @param $hex
493
+ *
494
+ * @internal param string $color
495
+ * @return string
496
+ * @since 1.0
497
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
498
+ */
499
+ public function hex2rgb( $hex ) {
500
+ $hex = str_replace( "#", "", $hex );
501
+
502
+ if ( strlen( $hex ) == 3 ) {
503
+ $r = hexdec( substr( $hex, 0, 1 ) . substr( $hex, 0, 1 ) );
504
+ $g = hexdec( substr( $hex, 1, 1 ) . substr( $hex, 1, 1 ) );
505
+ $b = hexdec( substr( $hex, 2, 1 ) . substr( $hex, 2, 1 ) );
506
+ }
507
+ else {
508
+ $r = hexdec( substr( $hex, 0, 2 ) );
509
+ $g = hexdec( substr( $hex, 2, 2 ) );
510
+ $b = hexdec( substr( $hex, 4, 2 ) );
511
+ }
512
+ $rgb = array( $r, $g, $b );
513
+ //return implode(",", $rgb); // returns the rgb values separated by commas
514
+ return $rgb; // returns an array with the rgb values
515
+ }
516
+
517
+ /**
518
+ * Magic method for this class
519
+ *
520
+ * @param $name string The name of magic property
521
+ *
522
+ * @since 2.0.0
523
+ * @author Simone D'Amico <simone.damico@yithemes.com>
524
+ * @return mixed
525
+ */
526
+ public function __get( $name ) {
527
+ if ( $name == 'request' ) {
528
+ if ( ! $this->_request instanceof YIT_Request ) {
529
+ $this->_request = YIT_Registry::get_instance()->request;
530
+ }
531
+
532
+ return $this->_request;
533
+ }
534
+ }
535
+ }
536
+ }
plugin-fw/lib/yit-plugin-panel-wc.php ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'YIT_Plugin_Panel_WooCommerce' ) ) {
16
+ /**
17
+ * YIT Plugin Panel for WooCommerce
18
+ *
19
+ * Setting Page to Manage Plugins
20
+ *
21
+ * @class YIT_Plugin_Panel
22
+ * @package Yithemes
23
+ * @since 1.0
24
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
25
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
26
+ */
27
+
28
+ class YIT_Plugin_Panel_WooCommerce extends YIT_Plugin_Panel {
29
+
30
+ /**
31
+ * @var string version of class
32
+ */
33
+ public $version = '1.0.0';
34
+
35
+ /**
36
+ * @var array a setting list of parameters
37
+ */
38
+ public $settings = array();
39
+
40
+ /**
41
+ * @var array
42
+ */
43
+ protected $_tabs_path_files;
44
+
45
+ /**
46
+ * Constructor
47
+ *
48
+ * @since 1.0
49
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
50
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
51
+ */
52
+ public function __construct( $args = array() ) {
53
+
54
+ if ( ! empty( $args ) ) {
55
+ $this->settings = $args;
56
+ $this->_tabs_path_files = $this->get_tabs_path_files();
57
+
58
+ if( isset( $this->settings['create_menu_page'] ) && $this->settings[ 'create_menu_page'] ){
59
+ $this->add_menu_page();
60
+ }
61
+ add_action( 'admin_init', array( $this, 'set_default_options') );
62
+ add_action( 'admin_menu', array( $this, 'add_setting_page' ) );
63
+ add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_menu' ), 100 );
64
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
65
+ add_action( 'admin_init', array( $this, 'woocommerce_update_options' ) );
66
+
67
+ add_action( 'woocommerce_admin_field_boxinfo', array( $this, 'yit_boxinfo' ), 10, 1 );
68
+ add_action( 'woocommerce_admin_field_videobox', array( $this, 'yit_videobox' ), 10, 1 );
69
+
70
+ }
71
+ }
72
+
73
+
74
+ /**
75
+ * Show a tabbed panel to setting page
76
+ *
77
+ * a callback function called by add_setting_page => add_submenu_page
78
+ *
79
+ * @return void
80
+ * @since 1.0
81
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
82
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
83
+ */
84
+ public function yit_panel() {
85
+ $additional_info = array(
86
+ 'current_tab' => $this->get_current_tab(),
87
+ 'available_tabs' => $this->settings['admin-tabs'],
88
+ 'default_tab' => $this->get_available_tabs( true ), //get default tabs
89
+ 'page' => $this->settings['page']
90
+ );
91
+
92
+ $additional_info = apply_filters( 'yith_admin_tab_params', $additional_info );
93
+ $additional_info['additional_info'] = $additional_info;
94
+
95
+ extract( $additional_info );
96
+ require_once( YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/woocommerce/woocommerce-panel.php' );
97
+ }
98
+
99
+ /**
100
+ * Show a box panel with specific content in two columns as a new woocommerce type
101
+ *
102
+ *
103
+ * @return void
104
+ * @since 1.0
105
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
106
+ */
107
+ public function yit_boxinfo( $args = array() ) {
108
+ if ( !empty( $args ) ) {
109
+ extract( $args );
110
+ require_once( YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/woocommerce/woocommerce-boxinfo.php' );
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Show a box panel with specific content in two columns as a new woocommerce type
116
+ *
117
+ *
118
+ * @return void
119
+ * @since 1.0
120
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
121
+ */
122
+ public function yit_videobox( $args = array() ) {
123
+ if ( !empty( $args ) ) {
124
+ extract( $args );
125
+ require_once( YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/woocommerce/woocommerce-videobox.php' );
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Show a input fields to upload images
131
+ *
132
+ *
133
+ * @return void
134
+ * @since 1.0
135
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
136
+ */
137
+
138
+ public function yit_upload_update( $option_value ) {
139
+ return $option_value;
140
+ }
141
+
142
+ /**
143
+ * Show a input fields to upload images
144
+ *
145
+ *
146
+ * @return void
147
+ * @since 1.0
148
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
149
+ */
150
+
151
+ public function yit_upload( $args = array() ) {
152
+ if ( ! empty( $args ) ) {
153
+ $args['value'] = ( get_option($args['id'])) ? get_option($args['id']) : $args['default'];
154
+ extract( $args );
155
+
156
+ include( YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/woocommerce/woocommerce-upload.php' );
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Returns current active tab slug
162
+ *
163
+ * @return string
164
+ * @since 2.0.0
165
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
166
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
167
+ */
168
+ public function get_current_tab() {
169
+ global $pagenow;
170
+ $tabs = $this->get_available_tabs();
171
+
172
+ if ( $pagenow == 'admin.php' && isset( $_REQUEST['tab'] ) && in_array( $_REQUEST['tab'], $tabs ) ) {
173
+ return $_REQUEST['tab'];
174
+ }
175
+ else {
176
+ return $tabs[0];
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Return available tabs
182
+ *
183
+ * read all options and show sections and fields
184
+ *
185
+ * @param bool false for all tabs slug, true for current tab
186
+ *
187
+ * @return mixed Array tabs | String current tab
188
+ * @since 1.0
189
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
190
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
191
+ */
192
+ public function get_available_tabs( $default = false ) {
193
+ $tabs = array_keys( $this->settings['admin-tabs'] );
194
+ return $default ? $tabs[0] : $tabs;
195
+ }
196
+
197
+
198
+ /**
199
+ * Add sections and fields to setting panel
200
+ *
201
+ * read all options and show sections and fields
202
+ *
203
+ * @return void
204
+ * @since 1.0
205
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
206
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
207
+ */
208
+ public function add_fields() {
209
+ $yit_options = $this->get_main_array_options();
210
+ $current_tab = $this->get_current_tab();
211
+
212
+ if ( ! $current_tab ) {
213
+ return;
214
+ }
215
+
216
+ woocommerce_admin_fields( $yit_options[$current_tab] );
217
+ }
218
+
219
+ /**
220
+ * Print the panel content
221
+ *
222
+ * check if the tab is a wc options tab or custom tab and print the content
223
+ *
224
+ * @return void
225
+ * @since 1.0
226
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
227
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
228
+ */
229
+ public function print_panel_content() {
230
+ $yit_options = $this->get_main_array_options();
231
+ $current_tab = $this->get_current_tab();
232
+ $custom_tab_action = $this->is_custom_tab( $yit_options, $current_tab );
233
+
234
+ if ( $custom_tab_action ) {
235
+ $this->print_custom_tab( $custom_tab_action );
236
+ return;
237
+ }
238
+ else {
239
+ require_once( YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/woocommerce/woocommerce-form.php' );
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Update options
245
+ *
246
+ * @return void
247
+ * @since 1.0
248
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
249
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
250
+ * @see woocommerce_update_options function
251
+ * @internal fire two action (before and after update): yit_panel_wc_before_update and yit_panel_wc_after_update
252
+ */
253
+ public function woocommerce_update_options() {
254
+
255
+ if ( isset( $_POST['yit_panel_wc_options_nonce'] ) && wp_verify_nonce( $_POST['yit_panel_wc_options_nonce'], 'yit_panel_wc_options_'.$this->settings['page'] ) ) {
256
+
257
+ do_action( 'yit_panel_wc_before_update' );
258
+
259
+ $yit_options = $this->get_main_array_options();
260
+ $current_tab = $this->get_current_tab();
261
+
262
+ woocommerce_update_options( $yit_options[ $current_tab ] );
263
+
264
+ do_action( 'yit_panel_wc_after_update' );
265
+
266
+ } elseif( isset( $_REQUEST['yit-action'] ) && $_REQUEST['yit-action'] == 'wc-options-reset' ){
267
+
268
+ $yit_options = $this->get_main_array_options();
269
+ $current_tab = $this->get_current_tab();
270
+
271
+ foreach( $yit_options[ $current_tab ] as $id => $option ){
272
+ if( isset( $option['default'] ) ){
273
+ update_option( $option['id'], $option['default'] );
274
+ }
275
+ }
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Add Admin WC Style and Scripts
281
+ *
282
+ * @return void
283
+ * @since 1.0
284
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
285
+ * @author Antonio La Rocca <antonio.larocca@yithemes.com>
286
+ */
287
+ public function admin_enqueue_scripts() {
288
+ global $woocommerce;
289
+
290
+ wp_enqueue_style( 'raleway-font', '//fonts.googleapis.com/css?family=Raleway:400,500,600,700,800,100,200,300,900' );
291
+
292
+ wp_enqueue_media();
293
+ wp_enqueue_style( 'woocommerce_admin_styles', $woocommerce->plugin_url() . '/assets/css/admin.css', array(), $woocommerce->version );
294
+ wp_enqueue_style( 'yit-plugin-style', YIT_CORE_PLUGIN_URL . '/assets/css/yit-plugin-panel.css', $woocommerce->version );
295
+ wp_enqueue_style ( 'wp-jquery-ui-dialog' );
296
+
297
+
298
+ wp_enqueue_style( 'jquery-chosen', YIT_CORE_PLUGIN_URL . '/assets/css/chosen/chosen.css' );
299
+ wp_enqueue_script( 'jquery-chosen', YIT_CORE_PLUGIN_URL . '/assets/js/chosen/chosen.jquery.js', array( 'jquery' ), '1.1.0', true );
300
+ wp_enqueue_script( 'woocommerce_settings', $woocommerce->plugin_url() . '/assets/js/admin/settings.min.js', array( 'jquery', 'jquery-ui-datepicker','jquery-ui-dialog', 'jquery-ui-sortable', 'iris', 'chosen' ), $woocommerce->version, true );
301
+ wp_enqueue_script( 'yit-plugin-panel', YIT_CORE_PLUGIN_URL . '/assets/js/yit-plugin-panel.min.js', array( 'jquery', 'jquery-chosen' ), $this->version, true );
302
+ wp_localize_script( 'woocommerce_settings', 'woocommerce_settings_params', array(
303
+ 'i18n_nav_warning' => __( 'The changes you made will be lost if you leave this page.', 'yit' )
304
+ ) );
305
+ }
306
+
307
+ /**
308
+ * Default options
309
+ *
310
+ * Sets up the default options used on the settings page
311
+ *
312
+ * @access public
313
+ * @return void
314
+ * @since 1.0.0
315
+ */
316
+ public function set_default_options() {
317
+
318
+ $default_options = $this->get_main_array_options();
319
+
320
+ foreach ($default_options as $section) {
321
+ foreach ( $section as $value ) {
322
+ if ( ( isset( $value['std'] ) || isset( $value['default'] ) ) && isset( $value['id'] ) ) {
323
+ $default_value = ( isset( $value['default'] ) ) ? $value['default'] : $value['std'];
324
+
325
+ if ( $value['type'] == 'image_width' ) {
326
+ add_option($value['id'].'_width', $default_value);
327
+ add_option($value['id'].'_height', $default_value);
328
+ } else {
329
+ add_option($value['id'], $default_value);
330
+ }
331
+
332
+ }
333
+
334
+ }
335
+ }
336
+
337
+ }
338
+
339
+
340
+ }
341
+ }
plugin-fw/lib/yit-plugin-panel.php ADDED
@@ -0,0 +1,710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'YIT_Plugin_Panel' ) ) {
16
+ /**
17
+ * YIT Plugin Panel
18
+ *
19
+ * Setting Page to Manage Plugins
20
+ *
21
+ * @class YIT_Plugin_Panel
22
+ * @package Yithemes
23
+ * @since 1.0
24
+ * @author Your Inspiration Themes
25
+ */
26
+
27
+ class YIT_Plugin_Panel {
28
+
29
+ /**
30
+ * @var string version of class
31
+ */
32
+ public $version = '1.0.0';
33
+
34
+ /**
35
+ * @var array a setting list of parameters
36
+ */
37
+ public $settings = array();
38
+
39
+ /**
40
+ * @var array
41
+ */
42
+ protected $_tabs_path_files;
43
+
44
+ /**
45
+ * @var array
46
+ */
47
+ private $_main_array_options = array();
48
+
49
+ /**
50
+ * Constructor
51
+ *
52
+ * @since 1.0
53
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
54
+ */
55
+ public function __construct( $args = array() ) {
56
+
57
+ if ( ! empty( $args ) ) {
58
+
59
+ $default_args = array(
60
+ 'parent_slug' => 'edit.php?',
61
+ 'page_title' => __( 'Plugin Settings', 'yit' ),
62
+ 'menu_title' => __( 'Settings', 'yit' ),
63
+ 'capability' => 'manage_options'
64
+ );
65
+
66
+ $this->settings = wp_parse_args( $args, $default_args );
67
+ $this->_tabs_path_files = $this->get_tabs_path_files();
68
+
69
+ if ( isset( $this->settings['create_menu_page'] ) && $this->settings['create_menu_page'] ) {
70
+ $this->add_menu_page();
71
+ }
72
+
73
+ add_action( 'admin_init', array( &$this, 'register_settings' ) );
74
+ add_action( 'admin_menu', array( &$this, 'add_setting_page' ) );
75
+ add_action( 'admin_bar_menu', array( &$this, 'add_admin_bar_menu' ), 100 );
76
+ add_action( 'admin_init', array( &$this, 'add_fields' ) );
77
+
78
+
79
+ }
80
+
81
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
82
+ }
83
+
84
+ /**
85
+ * Add Menu page link
86
+ *
87
+ * @return void
88
+ * @since 1.0
89
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
90
+ */
91
+ public function add_menu_page() {
92
+ add_menu_page( 'yit_plugin_panel', __( 'YIT Plugins', 'yit' ), 'manage_options', 'yit_plugin_panel', NULL, YIT_CORE_PLUGIN_URL . '/assets/images/yithemes-icon.png', 62 );
93
+ }
94
+
95
+ /**
96
+ * Remove duplicate submenu
97
+ *
98
+ * Submenu page hack: Remove the duplicate YIT Plugin link on subpages
99
+ *
100
+ * @return void
101
+ * @since 1.0
102
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
103
+ */
104
+ public function remove_duplicate_submenu_page() {
105
+ /* === Duplicate Items Hack === */
106
+ remove_submenu_page( 'yit_plugin_panel', 'yit_plugin_panel' );
107
+ }
108
+
109
+ /**
110
+ * Enqueue script and styles in admin side
111
+ *
112
+ * Add style and scripts to administrator
113
+ *
114
+ * @return void
115
+ * @since 1.0
116
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
117
+ */
118
+ public function admin_enqueue_scripts() {
119
+ //scripts
120
+ wp_enqueue_media();
121
+ wp_enqueue_script( 'jquery-ui' );
122
+ wp_enqueue_script( 'jquery-ui-core' );
123
+ wp_enqueue_script( 'jquery-ui-slider' );
124
+ wp_enqueue_style( 'jquery-chosen', YIT_CORE_PLUGIN_URL . '/assets/css/chosen/chosen.css' );
125
+ wp_enqueue_script( 'jquery-chosen', YIT_CORE_PLUGIN_URL . '/assets/js/chosen/chosen.jquery.js', array( 'jquery' ), '1.1.0', true );
126
+ wp_enqueue_script( 'yit-plugin-panel', YIT_CORE_PLUGIN_URL . '/assets/js/yit-plugin-panel.min.js', array( 'jquery', 'jquery-chosen' ), $this->version, true );
127
+ wp_register_script( 'codemirror', YIT_CORE_PLUGIN_URL . '/assets/js/codemirror/codemirror.js', array( 'jquery' ), $this->version, true );
128
+ wp_register_script( 'codemirror-javascript', YIT_CORE_PLUGIN_URL . '/assets/js/codemirror/javascript.js', array( 'jquery', 'codemirror' ), $this->version, true );
129
+
130
+
131
+ wp_register_style( 'codemirror', YIT_CORE_PLUGIN_URL . '/assets/css/codemirror/codemirror.css' );
132
+
133
+ //styles
134
+ wp_enqueue_style( 'jquery-ui-overcast', YIT_CORE_PLUGIN_URL . '/assets/css/overcast/jquery-ui-1.8.9.custom.css', false, '1.8.9', 'all' );
135
+ wp_enqueue_style( 'yit-plugin-style', YIT_CORE_PLUGIN_URL . '/assets/css/yit-plugin-panel.css', $this->version );
136
+ wp_enqueue_style( 'raleway-font', '//fonts.googleapis.com/css?family=Raleway:400,500,600,700,800,100,200,300,900' );
137
+ }
138
+
139
+ /**
140
+ * Register Settings
141
+ *
142
+ * Generate wp-admin settings pages by registering your settings and using a few callbacks to control the output
143
+ *
144
+ * @return void
145
+ * @since 1.0
146
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
147
+ */
148
+ public function register_settings() {
149
+ register_setting( 'yit_' . $this->settings['parent'] . '_options', 'yit_' . $this->settings['parent'] . '_options', array( &$this, 'options_validate' ) );
150
+ }
151
+
152
+ /**
153
+ * Options Validate
154
+ *
155
+ * a callback function called by Register Settings function
156
+ *
157
+ * @param $input
158
+ *
159
+ * @return array validate input fields
160
+ * @since 1.0
161
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
162
+ */
163
+ public function options_validate( $input ) {
164
+
165
+ $current_tab = ! empty( $input['current_tab'] ) ? $input['current_tab'] : 'general';
166
+
167
+ $yit_options = $this->get_main_array_options();
168
+
169
+ // default
170
+ $valid_input = $this->get_options();
171
+
172
+ $submit = ( ! empty( $input['submit-general'] ) ? true : false );
173
+ $reset = ( ! empty( $input['reset-general'] ) ? true : false );
174
+
175
+ foreach ( $yit_options[$current_tab] as $section => $data ) {
176
+ foreach ( $data as $option ) {
177
+ if ( isset( $option['sanitize_call'] ) && isset( $option['id'] ) ) { //yiw_debug($option, false);
178
+ if ( is_array( $option['sanitize_call'] ) ) :
179
+ foreach ( $option['sanitize_call'] as $callback ) {
180
+ if ( is_array( $input[$option['id']] ) ) {
181
+ $valid_input[$option['id']] = array_map( $callback, $input[$option['id']] );
182
+ }
183
+ else {
184
+ $valid_input[$option['id']] = call_user_func( $callback, $input[$option['id']] );
185
+ }
186
+ }
187
+ else :
188
+ if ( is_array( $input[$option['id']] ) ) {
189
+ $valid_input[$option['id']] = array_map( $option['sanitize_call'], $input[$option['id']] );
190
+ }
191
+ else {
192
+ $valid_input[$option['id']] = call_user_func( $option['sanitize_call'], $input[$option['id']] );
193
+ }
194
+ endif;
195
+ }
196
+ else {
197
+ if ( isset( $option['id'] ) ) {
198
+ if ( isset( $input[$option['id']] ) ) {
199
+ $valid_input[$option['id']] = $input[$option['id']];
200
+ }
201
+ else {
202
+ $valid_input[$option['id']] = 'no';
203
+ }
204
+
205
+ }
206
+ }
207
+
208
+ }
209
+ }
210
+
211
+ return $valid_input;
212
+ }
213
+
214
+ /**
215
+ * Add Setting SubPage
216
+ *
217
+ * add Setting SubPage to wordpress administrator
218
+ *
219
+ * @return array validate input fields
220
+ * @since 1.0
221
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
222
+ */
223
+ public function add_setting_page() {
224
+ add_submenu_page( $this->settings['parent_slug'] . $this->settings['parent_page'], $this->settings['page_title'], $this->settings['menu_title'], $this->settings['capability'], $this->settings['page'], array( &$this, 'yit_panel' ) );
225
+ /* === Duplicate Items Hack === */
226
+ $this->remove_duplicate_submenu_page();
227
+ do_action( 'yit_after_add_settings_page' );
228
+ }
229
+
230
+ /**
231
+ * Show a tabbed panel to setting page
232
+ *
233
+ * a callback function called by add_setting_page => add_submenu_page
234
+ *
235
+ * @return void
236
+ * @since 1.0
237
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
238
+ */
239
+ public function yit_panel() {
240
+
241
+ $tabs = '';
242
+ $current_tab = $this->get_current_tab();
243
+ $yit_options = $this->get_main_array_options();
244
+
245
+ // tabs
246
+ foreach ( $this->settings['admin-tabs'] as $tab => $tab_value ) {
247
+ $active_class = ( $current_tab == $tab ) ? ' nav-tab-active' : '';
248
+ $tabs .= '<a class="nav-tab' . $active_class . '" href="?' . $this->settings['parent_page'] . '&page=' . $this->settings['page'] . '&tab=' . $tab . '">' . $tab_value . '</a>';
249
+ }
250
+ ?>
251
+ <div id="icon-themes" class="icon32"><br /></div>
252
+ <h2 class="nav-tab-wrapper">
253
+ <?php echo $tabs ?>
254
+ </h2>
255
+ <?php
256
+ $custom_tab_action = $this->is_custom_tab( $yit_options, $current_tab );
257
+ if ( $custom_tab_action ) {
258
+ $this->print_custom_tab( $custom_tab_action );
259
+ return;
260
+ }
261
+ ?>
262
+ <div id="wrap" class="plugin-option">
263
+ <?php $this->message(); ?>
264
+ <h2><?php echo $this->get_tab_title() ?></h2>
265
+ <?php if ( $this->is_show_form() ) : ?>
266
+ <form method="post" action="options.php">
267
+ <?php do_settings_sections( 'yit' ); ?>
268
+ <p>&nbsp;</p>
269
+ <?php settings_fields( 'yit_' . $this->settings['parent'] . '_options' ); ?>
270
+ <input type="hidden" name="<?php echo $this->get_name_field( 'current_tab' ) ?>" value="<?php echo esc_attr( $current_tab ) ?>" />
271
+ <input type="submit" class="button-primary" value="<?php _e( 'Save Changes', 'yit' ) ?>" style="float:left;margin-right:10px;" />
272
+ </form>
273
+ <form method="post">
274
+ <?php $warning = __( 'If you go on with this action, you will reset all options in this page.', 'yit' ) ?>
275
+ <input type="hidden" name="yit-action" value="reset" />
276
+ <input type="submit" name="yit-reset" class="button-secondary" value="<?php _e( 'Reset Defaults', 'yit' ) ?>" onclick="return confirm('<?php echo $warning . '\n' . __( 'Are you sure of it?', 'yit' ) ?>');" />
277
+ </form>
278
+ <p>&nbsp;</p>
279
+ <?php endif ?>
280
+ </div>
281
+ <?php
282
+ }
283
+
284
+ public function is_custom_tab( $options, $current_tab ) {
285
+ foreach ( $options[$current_tab] as $section => $option ) {
286
+ if ( isset( $option['type'] ) && isset( $option['action'] ) && 'custom_tab' == $option['type'] && ! empty( $option['action'] ) ) {
287
+ return $option['action'];
288
+ }
289
+ else {
290
+ return false;
291
+ }
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Fire the action to print the custom tab
297
+ *
298
+ *
299
+ * @param $action Action to fire
300
+ *
301
+ * @return void
302
+ * @since 1.0
303
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
304
+ */
305
+ public function print_custom_tab( $action ) {
306
+ do_action( $action );
307
+ }
308
+
309
+ /**
310
+ * Add sections and fields to setting panel
311
+ *
312
+ * read all options and show sections and fields
313
+ *
314
+ * @return void
315
+ * @since 1.0
316
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
317
+ */
318
+ public function add_fields() {
319
+ $yit_options = $this->get_main_array_options();
320
+ $current_tab = $this->get_current_tab();
321
+
322
+ if ( ! $current_tab ) {
323
+ return;
324
+ }
325
+ foreach ( $yit_options[$current_tab] as $section => $data ) {
326
+ add_settings_section( "yit_settings_{$current_tab}_{$section}", $this->get_section_title( $section ), $this->get_section_description( $section ), 'yit' );
327
+ foreach ( $data as $option ) {
328
+ if ( isset( $option['id'] ) && isset( $option['type'] ) && isset( $option['name'] ) ) {
329
+ add_settings_field( "yit_setting_" . $option['id'], $option['name'], array( $this, 'render_field' ), 'yit', "yit_settings_{$current_tab}_{$section}", array( 'option' => $option, 'label_for' => $this->get_id_field( $option['id'] ) ) );
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+
336
+ /**
337
+ * Add the tabs to admin bar menu
338
+ *
339
+ * set all tabs of settings page on wp admin bar
340
+ *
341
+ * @return void|array return void when capability is false
342
+ * @since 1.0
343
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
344
+ */
345
+ public function add_admin_bar_menu() {
346
+
347
+ global $wp_admin_bar;
348
+
349
+ if ( ! current_user_can( 'manage_options' ) ) {
350
+ return;
351
+ }
352
+
353
+ if ( ! empty( $this->settings['admin_tabs'] ) ) {
354
+ foreach ( $this->settings['admin-tabs'] as $item => $title ) {
355
+
356
+ $wp_admin_bar->add_menu( array(
357
+ 'parent' => $this->settings['parent'],
358
+ 'title' => $title,
359
+ 'id' => $this->settings['parent'] . '-' . $item,
360
+ 'href' => admin_url( 'themes.php' ) . '?page=' . $this->settings['parent_page'] . '&tab=' . $item
361
+ ) );
362
+ }
363
+ }
364
+ }
365
+
366
+
367
+ /**
368
+ * Get current tab
369
+ *
370
+ * get the id of tab showed, return general is the current tab is not defined
371
+ *
372
+ * @return string
373
+ * @since 1.0
374
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
375
+ */
376
+ function get_current_tab() {
377
+ $admin_tabs = array_keys( $this->settings['admin-tabs'] );
378
+
379
+ if ( ! isset( $_GET['page'] ) || $_GET['page'] != $this->settings['page'] ) {
380
+ return false;
381
+ }
382
+ if ( isset( $_REQUEST['yit_tab_options'] ) ) {
383
+ return $_REQUEST['yit_tab_options'];
384
+ }
385
+ elseif ( isset( $_GET['tab'] ) && isset( $this->_tabs_path_files[$_GET['tab']] ) ) {
386
+ return $_GET['tab'];
387
+ }
388
+ elseif ( isset( $admin_tabs[0] ) ) {
389
+ return $admin_tabs[0];
390
+ }
391
+ else {
392
+ return 'general';
393
+ }
394
+ }
395
+
396
+
397
+ /**
398
+ * Message
399
+ *
400
+ * define an array of message and show the content od message if
401
+ * is find in the query string
402
+ *
403
+ * @return void
404
+ * @since 1.0
405
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
406
+ */
407
+ public function message() {
408
+
409
+ $message = array(
410
+ 'element_exists' => $this->get_message( '<strong>' . __( 'The element you have written is already exists. Please, add another name.', 'yit' ) . '</strong>', 'error', false ),
411
+ 'saved' => $this->get_message( '<strong>' . __( 'Settings saved', 'yit' ) . '.</strong>', 'updated', false ),
412
+ 'reset' => $this->get_message( '<strong>' . __( 'Settings reset', 'yit' ) . '.</strong>', 'updated', false ),
413
+ 'delete' => $this->get_message( '<strong>' . __( 'Element deleted correctly.', 'yit' ) . '</strong>', 'updated', false ),
414
+ 'updated' => $this->get_message( '<strong>' . __( 'Element updated correctly.', 'yit' ) . '</strong>', 'updated', false ),
415
+ 'settings-updated' => $this->get_message( '<strong>' . __( 'Element updated correctly.', 'yit' ) . '</strong>', 'updated', false ),
416
+ 'imported' => $this->get_message( '<strong>' . __( 'Database imported correctly.', 'yit' ) . '</strong>', 'updated', false ),
417
+ 'no-imported' => $this->get_message( '<strong>' . __( 'An error has occurred during import. Please try again.', 'yit' ) . '</strong>', 'error', false ),
418
+ 'file-not-valid' => $this->get_message( '<strong>' . __( 'The file inserted is not valid.', 'yit' ) . '</strong>', 'error', false ),
419
+ 'cant-import' => $this->get_message( '<strong>' . __( 'Sorry, import is disabled.', 'yit' ) . '</strong>', 'error', false ),
420
+ 'ord' => $this->get_message( '<strong>' . __( 'Sorting successful.', 'yit' ) . '</strong>', 'updated', false )
421
+ );
422
+
423
+ foreach ( $message as $key => $value ) {
424
+ if ( isset( $_GET[$key] ) ) {
425
+ echo $message[$key];
426
+ }
427
+ }
428
+
429
+ }
430
+
431
+ /**
432
+ * Get Message
433
+ *
434
+ * return html code of message
435
+ *
436
+ * @param $message
437
+ * @param string $type can be 'error' or 'updated'
438
+ * @param bool $echo
439
+ *
440
+ * @return void|string
441
+ * @since 1.0
442
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
443
+ */
444
+ public function get_message( $message, $type = 'error', $echo = true ) {
445
+ $message = '<div id="message" class="' . $type . ' fade"><p>' . $message . '</p></div>';
446
+ if ( $echo ) {
447
+ echo $message;
448
+ }
449
+ return $message;
450
+ }
451
+
452
+
453
+ /**
454
+ * Get Tab Path Files
455
+ *
456
+ * return an array with filenames of tabs
457
+ *
458
+ * @return array
459
+ * @since 1.0
460
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
461
+ */
462
+ function get_tabs_path_files() {
463
+
464
+ $option_files_path = $this->settings['options-path'] . '/';
465
+
466
+ $tabs = array();
467
+
468
+ foreach ( ( array ) glob( $option_files_path . '*.php' ) as $filename ) {
469
+ preg_match( '/(.*)-options\.(.*)/', basename( $filename ), $filename_parts );
470
+ $tab = $filename_parts[1];
471
+
472
+ $tabs[$tab] = $filename;
473
+ }
474
+
475
+ return $tabs;
476
+ }
477
+
478
+ /**
479
+ * Get main array options
480
+ *
481
+ * return an array with all options defined on options-files
482
+ *
483
+ * @return array
484
+ * @since 1.0
485
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
486
+ */
487
+ function get_main_array_options() {
488
+ if ( ! empty( $this->_main_array_options ) ) {
489
+ return $this->_main_array_options;
490
+ }
491
+
492
+ foreach ( $this->settings['admin-tabs'] as $item => $v ) {
493
+ $path = $this->settings['options-path'] . '/' . $item . '-options.php';
494
+ if ( file_exists( $path ) ) {
495
+ $this->_main_array_options = array_merge( $this->_main_array_options, include $path );
496
+ }
497
+ }
498
+
499
+ return $this->_main_array_options;
500
+ }
501
+
502
+
503
+ /**
504
+ * Set an array with all default options
505
+ *
506
+ * put default options in an array
507
+ *
508
+ * @return array
509
+ * @since 1.0
510
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
511
+ */
512
+ public function get_default_options() {
513
+ $yit_options = $this->get_main_array_options();
514
+ $default_options = array();
515
+
516
+ foreach ( $yit_options as $tab => $sections ) {
517
+ foreach ( $sections as $section ) {
518
+ foreach ( $section as $id => $value ) {
519
+ if ( isset( $value['std'] ) && isset( $value['id'] ) ) {
520
+ $default_options[$value['id']] = $value['std'];
521
+ }
522
+ }
523
+ }
524
+ }
525
+
526
+ unset( $yit_options );
527
+ return $default_options;
528
+ }
529
+
530
+
531
+ /**
532
+ * Get the title of the tab
533
+ *
534
+ * return the title of tab
535
+ *
536
+ * @return string
537
+ * @since 1.0
538
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
539
+ */
540
+ function get_tab_title() {
541
+ $yit_options = $this->get_main_array_options();
542
+ $current_tab = $this->get_current_tab();
543
+
544
+ foreach ( $yit_options[$current_tab] as $sections => $data ) {
545
+ foreach ( $data as $option ) {
546
+ if ( isset( $option['type'] ) && $option['type'] == 'title' ) {
547
+ return $option['name'];
548
+ }
549
+ }
550
+ }
551
+ }
552
+
553
+ /**
554
+ * Get the title of the section
555
+ *
556
+ * return the title of section
557
+ *
558
+ * @param $section
559
+ *
560
+ * @return string
561
+ * @since 1.0
562
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
563
+ */
564
+ function get_section_title( $section ) {
565
+ $yit_options = $this->get_main_array_options();
566
+ $current_tab = $this->get_current_tab();
567
+
568
+ foreach ( $yit_options[$current_tab][$section] as $option ) {
569
+ if ( isset( $option['type'] ) && $option['type'] == 'section' ) {
570
+ return $option['name'];
571
+ }
572
+ }
573
+ }
574
+
575
+ /**
576
+ * Get the description of the section
577
+ *
578
+ * return the description of section if is set
579
+ *
580
+ * @param $section
581
+ *
582
+ * @return string
583
+ * @since 1.0
584
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
585
+ */
586
+ function get_section_description( $section ) {
587
+ $yit_options = $this->get_main_array_options();
588
+ $current_tab = $this->get_current_tab();
589
+
590
+ foreach ( $yit_options[$current_tab][$section] as $option ) {
591
+ if ( isset( $option['type'] ) && $option['type'] == 'section' && isset( $option['desc'] ) ) {
592
+ return '<p>' . $option['desc'] . '</p>';
593
+ }
594
+ }
595
+ }
596
+
597
+
598
+ /**
599
+ * Show form when necessary
600
+ *
601
+ * return true if 'showform' is not defined
602
+ *
603
+ * @return bool
604
+ * @since 1.0
605
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
606
+ */
607
+ function is_show_form() {
608
+ $yit_options = $this->get_main_array_options();
609
+ $current_tab = $this->get_current_tab();
610
+
611
+ foreach ( $yit_options[$current_tab] as $sections => $data ) {
612
+ foreach ( $data as $option ) {
613
+ if ( ! isset( $option['type'] ) || $option['type'] != 'title' ) {
614
+ continue;
615
+ }
616
+ if ( isset( $option['showform'] ) ) {
617
+ return $option['showform'];
618
+ }
619
+ else {
620
+ return true;
621
+ }
622
+ }
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Get name field
628
+ *
629
+ * return a string with the name of the input field
630
+ *
631
+ * @param string $name
632
+ *
633
+ * @return string
634
+ * @since 1.0
635
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
636
+ */
637
+ function get_name_field( $name = '' ) {
638
+ return 'yit_' . $this->settings['parent'] . '_options[' . $name . ']';
639
+ }
640
+
641
+ /**
642
+ * Get id field
643
+ *
644
+ * return a string with the id of the input field
645
+ *
646
+ * @param string $id
647
+ *
648
+ * @return string
649
+ * @since 1.0
650
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
651
+ */
652
+ function get_id_field( $id ) {
653
+ return 'yit_' . $this->settings['parent'] . '_options_' . $id;
654
+ }
655
+
656
+
657
+ /**
658
+ * Render the field showed in the setting page
659
+ *
660
+ * include the file of the option type, if file do not exists
661
+ * return a text area
662
+ *
663
+ * @param array $param
664
+ *
665
+ * @return void
666
+ * @since 1.0
667
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
668
+ */
669
+ function render_field( $param ) {
670
+
671
+ if ( ! empty( $param ) && isset( $param ['option'] ) ) {
672
+ $option = $param ['option'];
673
+ $db_options = $this->get_options();
674
+
675
+ $db_value = ( isset( $db_options[$option['id']] ) ) ? $db_options[$option['id']] : '';
676
+ if ( isset( $option['deps'] ) ) {
677
+ $deps = $option['deps'];
678
+ }
679
+ $type = YIT_CORE_PLUGIN_PATH . '/templates/panel/types/' . $option['type'] . '.php';
680
+ if ( file_exists( $type ) ) {
681
+ include $type;
682
+ }
683
+ else {
684
+ do_action( "yit_panel_{$option['type']}" );
685
+ }
686
+ }
687
+ }
688
+
689
+ /**
690
+ * Get options from db
691
+ *
692
+ * return the options from db, if the options aren't defined in the db,
693
+ * get the default options ad add the options in the db
694
+ *
695
+ * @return array
696
+ * @since 1.0
697
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
698
+ */
699
+ public function get_options() {
700
+ $options = get_option( 'yit_' . $this->settings['parent'] . '_options' );
701
+ if ( $options === false || ( isset( $_REQUEST['yit-action'] ) && $_REQUEST['yit-action'] == 'reset' ) ) {
702
+ $options = $this->get_default_options();
703
+ }
704
+ return $options;
705
+ }
706
+
707
+
708
+ }
709
+
710
+ }
plugin-fw/lib/yit-plugin-subpanel.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'YIT_Plugin_SubPanel' ) ) {
16
+ /**
17
+ * YIT Plugin Panel
18
+ *
19
+ * Setting Page to Manage Plugins
20
+ *
21
+ * @class YIT_Plugin_Panel
22
+ * @package Yithemes
23
+ * @since 1.0
24
+ * @author Your Inspiration Themes
25
+ */
26
+
27
+ class YIT_Plugin_SubPanel extends YIT_Plugin_Panel {
28
+
29
+ /**
30
+ * @var string version of class
31
+ */
32
+ public $version = '1.0.0';
33
+
34
+ /**
35
+ * @var array a setting list of parameters
36
+ */
37
+ public $settings = array();
38
+
39
+
40
+ /**
41
+ * @var array
42
+ */
43
+ private $_main_array_options = array();
44
+
45
+ /**
46
+ * Constructor
47
+ *
48
+ * @since 1.0
49
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
50
+ */
51
+
52
+ public function __construct( $args = array() ) {
53
+ if ( ! empty( $args ) ) {
54
+ $this->settings = $args;
55
+ $this->settings['parent'] = $this->settings['page'];
56
+ $this->_tabs_path_files = $this->get_tabs_path_files();
57
+
58
+ add_action( 'admin_init', array( $this, 'register_settings' ) );
59
+ add_action( 'admin_menu', array( &$this, 'add_setting_page' ) );
60
+ add_action( 'admin_bar_menu', array( &$this, 'add_admin_bar_menu' ), 100 );
61
+ add_action( 'admin_init', array( &$this, 'add_fields' ) );
62
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
63
+ }
64
+ }
65
+
66
+
67
+ /**
68
+ * Register Settings
69
+ *
70
+ * Generate wp-admin settings pages by registering your settings and using a few callbacks to control the output
71
+ *
72
+ * @return void
73
+ * @since 1.0
74
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
75
+ */
76
+ public function register_settings() {
77
+ register_setting( 'yit_' . $this->settings['page'] . '_options', 'yit_' . $this->settings['page'] . '_options', array( &$this, 'options_validate' ) );
78
+ }
79
+
80
+
81
+
82
+ /**
83
+ * Add Setting SubPage
84
+ *
85
+ * add Setting SubPage to wordpress administrator
86
+ *
87
+ * @return array validate input fields
88
+ * @since 1.0
89
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
90
+ */
91
+ public function add_setting_page() {
92
+
93
+ $logo = YIT_CORE_PLUGIN_URL . '/assets/images/yithemes-icon.png';
94
+
95
+ $admin_logo = function_exists( 'yit_get_option' ) ? yit_get_option( 'admin-logo-menu' ) : '';
96
+
97
+ if ( isset( $admin_logo ) && ! empty( $admin_logo ) && $admin_logo != '' && $admin_logo) {
98
+ $logo = $admin_logo;
99
+ }
100
+
101
+ add_menu_page( 'yit_plugin_panel', __( 'YIT Plugins', 'yit' ), 'nosuchcapability', 'yit_plugin_panel', NULL, $logo, 62 );
102
+ add_submenu_page( 'yit_plugin_panel', $this->settings['label'], $this->settings['label'], 'manage_options', $this->settings['page'], array( $this, 'yit_panel' ) );
103
+ remove_submenu_page( 'yit_plugin_panel', 'yit_plugin_panel' );
104
+
105
+ }
106
+
107
+ /**
108
+ * Show a tabbed panel to setting page
109
+ *
110
+ * a callback function called by add_setting_page => add_submenu_page
111
+ *
112
+ * @return void
113
+ * @since 1.0
114
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
115
+ */
116
+ public function yit_panel() {
117
+
118
+ $tabs = '';
119
+ $current_tab = $this->get_current_tab();
120
+
121
+ // tabs
122
+ foreach ( $this->settings['admin-tabs'] as $tab => $tab_value ) {
123
+ $active_class = ( $current_tab == $tab ) ? ' nav-tab-active' : '';
124
+ $tabs .= '<a class="nav-tab' . $active_class . '" href="?page=' . $this->settings['page'] . '&tab=' . $tab . '">' . $tab_value . '</a>';
125
+ }
126
+ ?>
127
+ <div id="icon-themes" class="icon32"><br /></div>
128
+ <h2 class="nav-tab-wrapper">
129
+ <?php echo $tabs ?>
130
+ </h2>
131
+
132
+ <div id="wrap" class="plugin-option">
133
+ <?php $this->message(); ?>
134
+ <h2><?php echo $this->get_tab_title() ?></h2>
135
+
136
+ <?php if ( $this->is_show_form() ) : ?>
137
+ <form method="post" action="options.php">
138
+ <?php do_settings_sections( 'yit' ); ?>
139
+ <p>&nbsp;</p>
140
+ <?php settings_fields( 'yit_' . $this->settings['page'] . '_options' ); ?>
141
+ <input type="hidden" name="<?php echo $this->get_name_field( 'current_tab' ) ?>" value="<?php echo esc_attr( $current_tab ) ?>" />
142
+ <input type="submit" class="button-primary" value="<?php _e( 'Save Changes', 'yit' ) ?>" style="float:left;margin-right:10px;" />
143
+ </form>
144
+ <form method="post">
145
+ <?php $warning = __( 'If you go on with this action, you will reset all options in this page.', 'yit' ) ?>
146
+ <input type="hidden" name="yit-action" value="reset" />
147
+ <input type="submit" name="yit-reset" class="button-secondary" value="<?php _e( 'Reset Defaults', 'yit' ) ?>" onclick="return confirm('<?php echo $warning . '\n' . __( 'Are you sure of it?', 'yit' ) ?>');" />
148
+ </form>
149
+ <p>&nbsp;</p>
150
+ <?php endif ?>
151
+ </div>
152
+ <?php
153
+ }
154
+
155
+
156
+
157
+ }
158
+
159
+ }
160
+
plugin-fw/lib/yit-pointers.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+ /**
15
+ *
16
+ *
17
+ * @class yit-pointers
18
+ * @package Yithemes
19
+ * @since Version 2.0.0
20
+ * @author Your Inspiration Themes
21
+ *
22
+ */
23
+ if ( ! class_exists( 'YIT_Pointers' ) ) {
24
+ /**
25
+ * YIT Pointers
26
+ *
27
+ * Initializes the new feature pointers.
28
+ *
29
+ * @class YIT_Pointers
30
+ * @package Yithemes
31
+ * @since 1.0
32
+ * @author Your Inspiration Themes
33
+ * @see WP_Internal_Pointers
34
+ */
35
+ class YIT_Pointers {
36
+
37
+ /**
38
+ * @var YIT_Upgrade The main instance
39
+ */
40
+ protected static $_instance;
41
+
42
+ /**
43
+ * @var screen id where to show pointer
44
+ */
45
+ public $screen_ids = array();
46
+
47
+ public $pointers = array();
48
+
49
+ public $special_screen = array();
50
+
51
+ protected $_plugins_registered = array();
52
+
53
+ protected $_default_pointer = array();
54
+
55
+ protected $_default_position = array( 'edge' => 'left', 'align' => 'center' );
56
+
57
+ /**
58
+ * Construct
59
+ *
60
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
61
+ * @since 1.0
62
+ */
63
+ public function __construct() {
64
+
65
+ $this->_default_pointer['plugins'] = array(
66
+ 'screen_id' => 'plugins',
67
+ 'options' => array(
68
+ 'content' => sprintf( '<h3> %s </h3> <p> %s </p> <p> %s <a href="http://yithemes.com/product-category/plugins/" target="_blank">Yithemes.com</a> %s
69
+ <a href="https://profiles.wordpress.org/yithemes/" target="_blank">Wordpress.org</a></p>',
70
+ __( 'Plugins Activated', 'yit' ),
71
+ __( 'From now on, you can find all plugin options in YIT Plugin menu.
72
+ For each plugin installed, customization settings will be available as a new entry in YIT Plugin menu.', 'yit' ),
73
+ __( 'Discover all our plugins available on:', 'yit' ),
74
+ __( 'and', 'yit' )
75
+ ),
76
+ ),
77
+ );
78
+
79
+ $this->_default_pointer['update'] = array(
80
+ 'screen_id' => 'update',
81
+ 'options' => array(
82
+ 'content' => sprintf( '<h3> %s </h3> <p> %s </p> <p> %s <a href="http://yithemes.com/product-category/plugins/" target="_blank">Yithemes.com</a> %s
83
+ <a href="https://profiles.wordpress.org/yithemes/" target="_blank">Wordpress.org</a></p>',
84
+ __( 'Plugins Upgraded', 'yit' ),
85
+ __( 'From now on, you can find all the options of your plugins in YIT Plugin menu.
86
+ Any time one of our plugins is updated, a new entry will be added to this menu.
87
+ For example, after update, plugin options (such for YITH WooCommerce Wishlist, YITH WooCommerce Ajax Search, etc.)
88
+ will be moved from previous location to YIT Plugin tab.', 'yit' ),
89
+ __( 'Discover all our plugins available on:', 'yit' ),
90
+ __( 'and', 'yit' )
91
+ ),
92
+ ),
93
+ );
94
+
95
+ $this->_default_pointer = $this->parse_args( $this->_default_pointer );
96
+
97
+ /**
98
+ * Screens that require a particular action
99
+ */
100
+ $this->special_screen = apply_filters( 'yit-pointer-special-screen', array( 'plugins', 'update' ) );
101
+
102
+ add_action( 'admin_enqueue_scripts', array( $this, 'pointer_load' ) );
103
+ add_action( 'admin_init', array( $this, 'add_pointers' ), 100 );
104
+ }
105
+
106
+ public function parse_args( $args ) {
107
+ $default = array(
108
+ 'pointer_id' => 'yith_default_pointer',
109
+ 'target' => '#toplevel_page_yit_plugin_panel',
110
+ 'init' => null
111
+ );
112
+
113
+ foreach ( $args as $id => $pointer ) {
114
+ $args[ $id ] = wp_parse_args( $pointer, $default );
115
+ $args[ $id ]['options']['position'] = $this->_default_position;
116
+ }
117
+
118
+ return $args;
119
+ }
120
+
121
+ public function add_pointers(){
122
+ if( ! empty( $this->screen_ids ) ){
123
+ foreach( $this->screen_ids as $screen_id ){
124
+ add_filter( "yit_pointers-{$screen_id}", array( $this, 'pointers' ) );
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Main plugin Instance
131
+ *
132
+ * @static
133
+ * @return object Main instance
134
+ *
135
+ * @since 1.0
136
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
137
+ */
138
+ public static function instance() {
139
+ if ( is_null( self::$_instance ) ) {
140
+ self::$_instance = new self();
141
+ }
142
+
143
+ return self::$_instance;
144
+ }
145
+
146
+ public function register( $args ) {
147
+
148
+ foreach ( $args as $id => $pointer ) {
149
+
150
+ extract( $pointer );
151
+
152
+ if ( ! isset( $screen_id ) && ! empty( $screen_id ) && ! isset( $init ) && ! empty( $init ) ) {
153
+ return;
154
+ }
155
+
156
+ if ( ! in_array( $screen_id, $this->screen_ids ) ) {
157
+ $this->screen_ids[] = $screen_id;
158
+ }
159
+
160
+ $this->pointers[$screen_id][$pointer_id] = array(
161
+ 'target' => $target,
162
+ 'options' => array(
163
+ 'content' => $content,
164
+ 'position' => $position,
165
+ ),
166
+ 'init' => isset( $init ) ? $init : false
167
+ );
168
+ }
169
+ }
170
+
171
+ public function get_plugins_init( $screen_id ) {
172
+
173
+ $registered = array();
174
+
175
+ foreach( $this->pointers[ $screen_id ] as $pointer_id => $pointer ){
176
+ $registered[ $pointer['init'] ] = $pointer_id;
177
+ }
178
+
179
+ return $registered;
180
+ }
181
+
182
+ public function pointer_load( $hook_suffix ) {
183
+
184
+ /**
185
+ * Get pointers for this screen
186
+ */
187
+ $screen = get_current_screen();
188
+ $pointers = apply_filters( "yit_pointers-{$screen->id}", array() );
189
+
190
+ if ( ! $pointers || ! is_array( $pointers ) ) {
191
+ return;
192
+ }
193
+
194
+ /**
195
+ * Get dismissed pointers
196
+ */
197
+ $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
198
+ $valid_pointers = array();
199
+ //$point_id = null;
200
+
201
+ /**
202
+ * show pointers only on plugin activate action
203
+ */
204
+ if( in_array( $screen->id, $this->special_screen ) ){
205
+
206
+ $show = false;
207
+ $registered = $this->get_plugins_init( $screen->id );
208
+ $recently_activate = get_option( 'yit_recently_activated', array() );
209
+
210
+ /**
211
+ * For "plugins" screen
212
+ */
213
+ $is_single_activate = ( isset( $_GET['activate'] ) && 'true' == $_GET['activate'] ) ? true : false;
214
+ $is_multi_activate = ( isset( $_GET['activate-multi'] ) && 'true' == $_GET['activate-multi'] ) ? true : false;
215
+
216
+ /**
217
+ * For "update" screen
218
+ *
219
+ * Single plugin update use GET method
220
+ *
221
+ * Multi update plugins with bulk action send two post args called "action" and "action2"
222
+ * action refer to first bulk action button (at the top of plugins table)
223
+ * action2 refer to last bulk action button (at the bottom of plugins table)
224
+ *
225
+ */
226
+ $is_single_upgrade = ( isset( $_GET['action'] ) && 'upgrade-plugin' == $_GET['action'] ) ? true : false;
227
+ $is_multi_upgrade = ( isset( $_POST['action'] ) && 'update-selected' == $_POST['action'] ) || ( isset( $_POST['action2'] ) && 'update-selected' == $_POST['action2'] ) ? true: false;
228
+
229
+ if( $is_single_activate || $is_single_upgrade ){
230
+
231
+ $point_id = '';
232
+
233
+ /**
234
+ * Single activation plugin
235
+ * Single update plugin
236
+ */
237
+ foreach( $registered as $init => $p_id ){
238
+ if ( in_array( $init, $recently_activate ) ) {
239
+ $point_id = $p_id;
240
+ $pointer = $pointers[ $point_id ];
241
+
242
+ /**
243
+ * Sanity check
244
+ */
245
+ if ( ! ( in_array( $point_id, $dismissed ) || empty( $pointer ) || empty( $point_id ) || empty( $pointer['target'] ) || empty( $pointer['options'] ) ) ) {
246
+ /**
247
+ * Add the pointer to $valid_pointers array
248
+ */
249
+ $pointer['pointer_id'] = $point_id;
250
+ $valid_pointers['pointers'][] = $pointer;
251
+ $show = true;
252
+ }
253
+ break;
254
+ }
255
+ }
256
+ } else if( $is_multi_activate || $is_multi_upgrade ){
257
+
258
+ /**
259
+ * Bulk Action: multi plugins activation
260
+ * Bulk Action: multi plugins update
261
+ */
262
+ $point_id = array();
263
+ $screen_id = $screen->id;
264
+
265
+ if( $is_multi_upgrade && isset( $_POST['checked'] ) && ( count( $_POST['checked'] ) > 0 ) ){
266
+ $recently_activate = $_POST['checked'];
267
+ $screen_id = 'update';
268
+ $pointers = apply_filters( "yit_pointers-{$screen_id}", array() );
269
+ }
270
+
271
+ foreach ( $registered as $init => $p_id ) {
272
+ if ( in_array( $init, $recently_activate ) ) {
273
+ $point_id[] = $p_id;
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Bulk Action: Activate Plugins
279
+ *
280
+ * count( $point_id ) is the number of YITH plugins that have registered specific pointers
281
+ * case 0 -> No pointers -> Exit
282
+ * case 1 -> Only one pointers to show -> Use the specific plugin pointer
283
+ * defautl -> Two or more plugins need to show a pointer -> use a generic pointers
284
+ *
285
+ */
286
+ switch ( count( $point_id ) ) {
287
+ case 0:
288
+ $show = false;
289
+ break;
290
+
291
+ case 1:
292
+ $point_id = array_pop( $point_id );
293
+ $pointer = $pointers[$point_id];
294
+ /**
295
+ * Sanity check
296
+ */
297
+ if ( ! ( in_array( $point_id, $dismissed ) || empty( $pointer ) || empty( $point_id ) || empty( $pointer['target'] ) || empty( $pointer['options'] ) ) ) {
298
+ /**
299
+ * Add the pointer to $valid_pointers array
300
+ */
301
+ $pointer['pointer_id'] = $point_id;
302
+ $valid_pointers['pointers'][] = $pointer;
303
+ $show = true;
304
+ }
305
+ break;
306
+
307
+ default:
308
+ $valid_pointers['pointers'][] = $this->_default_pointer[ $screen_id ];
309
+ $show = true;
310
+ break;
311
+ }
312
+ }
313
+
314
+ update_option( 'yit_recently_activated', array() );
315
+
316
+ if( ! $show ){
317
+ return;
318
+ }
319
+
320
+ } else {
321
+ /**
322
+ * Check pointers and remove dismissed ones.
323
+ */
324
+ foreach ( $pointers as $pointer_id => $pointer ) {
325
+
326
+ /**
327
+ * Sanity check
328
+ */
329
+ if ( in_array( $pointer_id, $dismissed ) || empty( $pointer ) || empty( $pointer_id ) || empty( $pointer['target'] ) || empty( $pointer['options'] ) ) {
330
+ continue;
331
+ }
332
+
333
+ $pointer['pointer_id'] = $pointer_id;
334
+
335
+ /**
336
+ * Add the pointer to $valid_pointers array
337
+ */
338
+ $valid_pointers['pointers'][] = $pointer;
339
+ }
340
+ }
341
+
342
+ /**
343
+ * No valid pointers? Stop here.
344
+ */
345
+ if ( empty( $valid_pointers ) ) {
346
+ return;
347
+ }
348
+
349
+ $script_file = function_exists( 'yit_load_js_file' ) ? yit_load_js_file( 'yit-wp-pointer.js' ) : 'yit-wp-pointer.min.js';
350
+
351
+ /**
352
+ * Enqueue wp-pointer script and style
353
+ */
354
+ wp_enqueue_style( 'wp-pointer' );
355
+ wp_enqueue_script( 'wp-pointer' );
356
+
357
+ wp_enqueue_script( 'yit-wp-pointer', YIT_CORE_PLUGIN_URL . '/assets/js/' . $script_file, array( 'wp-pointer' ), false, true );
358
+ wp_localize_script( 'yit-wp-pointer', 'custom_pointer', $valid_pointers );
359
+ }
360
+
361
+ public function pointers( $pointers ){
362
+ $screen_id = str_replace( 'yit_pointers-', '', current_filter() );
363
+ $pointers_to_add = $this->get_pointers( $screen_id );
364
+
365
+ return ! empty( $pointers_to_add ) ? array_merge( $pointers, $pointers_to_add ) : $pointers;
366
+ }
367
+
368
+ public function get_pointers( $screen_id ){
369
+ return isset( $this->pointers[ $screen_id ] ) ? $this->pointers[ $screen_id ] : array();
370
+ }
371
+ }
372
+ }
373
+
374
+ if ( ! function_exists( 'YIT_Pointers' ) ) {
375
+ /**
376
+ * Main instance of plugin
377
+ *
378
+ * @return object YIT_Pointers
379
+ * @since 1.0
380
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
381
+ */
382
+ function YIT_Pointers() {
383
+ return YIT_Pointers::instance();
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Instance a YIT_Pointers object
389
+ */
390
+ YIT_Pointers();
plugin-fw/lib/yit-upgrade.php ADDED
@@ -0,0 +1,538 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+ if ( ! class_exists( 'YIT_Upgrade' ) ) {
15
+ /**
16
+ * YIT Upgrade
17
+ *
18
+ * Notify and Update plugin
19
+ *
20
+ * @class YIT_Upgrade
21
+ * @package Yithemes
22
+ * @since 1.0
23
+ * @author Your Inspiration Themes
24
+ * @see WP_Updater Class
25
+ */
26
+
27
+ class YIT_Upgrade {
28
+
29
+ /**
30
+ * @var string XML notifier update
31
+ */
32
+ protected $_xml = 'http://update.yithemes.com/plugins/%plugin_slug%.xml';
33
+
34
+ /**
35
+ * @var string api server url
36
+ */
37
+ protected $_package_url = 'http://www.yithemes.com';
38
+
39
+ /**
40
+ * @var array The registered plugins
41
+ */
42
+ protected $_plugins = array();
43
+
44
+ /**
45
+ * @var YIT_Upgrade The main instance
46
+ */
47
+ protected static $_instance;
48
+
49
+ /**
50
+ * Construct
51
+ *
52
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
53
+ * @since 1.0
54
+ */
55
+ public function __construct() {
56
+ add_filter( 'upgrader_pre_download', array( $this, 'upgrader_pre_download') , 10, 3 );
57
+ add_action( 'update-custom_upgrade-plugin-multisite', array( $this, 'upgrade_plugin_multisite' ) );
58
+
59
+ if( is_network_admin() ){
60
+ add_action( 'admin_enqueue_scripts', array( $this, 'network_admin_enqueue_scripts' ) );
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Main plugin Instance
66
+ *
67
+ * @param $plugin_slug | string The plugin slug
68
+ * @param $plugin_init | string The plugin init file
69
+ *
70
+ * @return void
71
+ *
72
+ * @since 1.0
73
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
74
+ */
75
+ public function register( $plugin_slug, $plugin_init ) {
76
+
77
+ if( ! function_exists( 'get_plugins' ) ){
78
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
79
+ }
80
+
81
+ $plugins = get_plugins();
82
+ $plugin_info = $plugins[ $plugin_init ];
83
+
84
+ $this->_plugins[ $plugin_init ] = array(
85
+ 'info' => $plugin_info,
86
+ 'slug' => $plugin_slug,
87
+ );
88
+
89
+ /* === HOOKS === */
90
+ if( ! is_multisite() || is_plugin_active_for_network( $plugin_init ) ){
91
+ add_action( 'admin_init', array( $this, 'remove_wp_plugin_update_row' ), 15 );
92
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
93
+ } else if( is_multisite() && current_user_can( 'update_plugins' ) ) {
94
+ $xml = str_replace( '%plugin_slug%', $plugin_slug, $this->_xml );
95
+ $remote_xml = wp_remote_get( $xml );
96
+
97
+ if( ! is_wp_error( $remote_xml ) && isset( $remote_xml['response']['code'] ) && '200' == $remote_xml['response']['code'] ) {
98
+ $plugin_remote_info = new SimpleXmlElement( $remote_xml['body'] );
99
+ $this->_plugins[ $plugin_init ]['info']['Latest'] = (string) $plugin_remote_info->latest;
100
+ $this->_plugins[ $plugin_init ]['info']['changelog'] = (string) $plugin_remote_info->changelog;
101
+ add_action( 'admin_enqueue_scripts', array( $this, 'multisite_updater_script' ) );
102
+ }
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Add the multisite updater scripts
108
+ *
109
+ * @return void
110
+ *
111
+ * @since 1.0
112
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
113
+ */
114
+ public function multisite_updater_script(){
115
+
116
+ $update_url = array();
117
+ $changelogs = array();
118
+ $strings = array(
119
+ 'new_version' => __( 'There is a new version of %plugin_name% available.', 'yit' ),
120
+ 'latest' => __( 'View version %latest% details.', 'yit' ),
121
+ 'unavailable' => __( 'Automatic update is unavailable for this plugin,', 'yit' ),
122
+ 'activate' => __( 'please <a href="%activate_link%"> activate </a> your copy of %plugin_name%.', 'yit' ),
123
+ 'update_now' => __( 'Update now.', 'yit' )
124
+
125
+ );
126
+
127
+ foreach( $this->_plugins as $init => $info ){
128
+ YIT_Plugin_Licence()->check( $init );
129
+
130
+ $update_url[ $init ] = wp_nonce_url( self_admin_url('update.php?action=upgrade-plugin-multisite&plugin=') . $init, 'upgrade-plugin-multisite_' . $init );
131
+ $changelog_id = str_replace( array( '/', '.php', '.' ), array( '-', '', '-' ), $init );
132
+ $details_url[ $init ] = '#TB_inline' . add_query_arg( array( 'width' => 722, 'height' => 914, 'inlineId' => $changelog_id ) , '' );
133
+ $changelogs[ $init ] = $this->in_theme_update_message( $this->_plugins[ $init ], $this->_plugins[ $init ]['info']['changelog'], $changelog_id, false );
134
+ }
135
+
136
+ $localize_script_args = array(
137
+ 'registered' => $this->_plugins,
138
+ 'activated' => YIT_Plugin_Licence()->get_activated_products(),
139
+ 'licence_activation_url' => YIT_Plugin_Licence()->get_licence_activation_page_url(),
140
+ 'update_url' => $update_url,
141
+ 'details_url' => $details_url,
142
+ 'strings' => $strings,
143
+ 'changelogs' => $changelogs
144
+ );
145
+
146
+ yit_enqueue_script( 'yit-multisite-updater', YIT_CORE_PLUGIN_URL . '/assets/js/multisite-updater.min.js', array( 'jquery' ), false, true );
147
+
148
+ wp_localize_script( 'yit-multisite-updater', 'plugins', $localize_script_args );
149
+ }
150
+
151
+ public function network_admin_enqueue_scripts(){
152
+ yit_enqueue_style( 'yit-upgrader', YIT_CORE_PLUGIN_URL . '/assets/css/yit-upgrader.css' );
153
+ }
154
+
155
+ /**
156
+ * Call the protected method _upgrader_pre_download to retrive the zip package file
157
+ *
158
+ * @param bool $reply Whether to bail without returning the package. Default false.
159
+ * @param string $package The package file name.
160
+ * @param \WP_Upgrader $upgrader WP_Upgrader instance.
161
+ *
162
+ * @return string | The download file
163
+ *
164
+ * @since 1.0
165
+ * @see wp-admin/includes/class-wp-upgrader.php
166
+ * @access public
167
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
168
+ */
169
+ public function upgrader_pre_download( $reply, $package, $upgrader ){
170
+ return $this->_upgrader_pre_download( $reply, $package, $upgrader );
171
+ }
172
+
173
+ /**
174
+ * Retrive the zip package file
175
+ *
176
+ * @param bool $reply Whether to bail without returning the package. Default false.
177
+ * @param string $package The package file name.
178
+ * @param \WP_Upgrader $upgrader WP_Upgrader instance.
179
+ *
180
+ * @return string | The download file
181
+ *
182
+ * @since 1.0
183
+ * @see wp-admin/includes/class-wp-upgrader.php
184
+ * @access protected
185
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
186
+ */
187
+ protected function _upgrader_pre_download( $reply, $package, $upgrader ) {
188
+
189
+ /**
190
+ * It isn't YITH Premium plugins, please wordpress update it for me!
191
+ */
192
+ if( ! isset( $upgrader->skin->plugin ) ) {
193
+ return $reply;
194
+ }
195
+
196
+ $plugin_info = YIT_Plugin_Licence()->get_product( $upgrader->skin->plugin );
197
+
198
+ /**
199
+ * False ? It isn't YITH Premium plugins, please wordpress update it for me!
200
+ */
201
+ if( false === $plugin_info ) {
202
+ return $reply;
203
+ }
204
+
205
+ $licence = YIT_Plugin_Licence()->get_licence();
206
+ $product_id = $plugin_info['product_id'];
207
+ $args = array(
208
+ 'email' => $licence[ $product_id ]['email'],
209
+ 'licence_key' => $licence[$product_id]['licence_key'],
210
+ 'product_id' => $plugin_info['product_id'],
211
+ 'secret_key' => $plugin_info['secret_key'],
212
+ 'instance' => YIT_Plugin_Licence()->get_home_url(),
213
+ 'wc-api' => 'download-api',
214
+ 'request' => 'download'
215
+ );
216
+
217
+ if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) {
218
+ //Local file or remote?
219
+ return $package;
220
+ }
221
+
222
+ if ( empty( $package ) ) {
223
+ return new WP_Error( 'no_package', $upgrader->strings['no_package'] );
224
+ }
225
+
226
+ $upgrader->skin->feedback( 'downloading_package', __( 'Yithemes Repository', 'yit' ) );
227
+
228
+ $download_file = $this->_download_url( $package, $args );
229
+
230
+ /**
231
+ * Regenerate update_plugins transient
232
+ */
233
+ $this->force_regenerate_update_transient();
234
+
235
+ if ( is_wp_error( $download_file ) ) {
236
+ return new WP_Error( 'download_failed', $upgrader->strings['download_failed'], $download_file->get_error_message() );
237
+ }
238
+
239
+ return $download_file;
240
+ }
241
+
242
+ /**
243
+ * Retrive the temp filename
244
+ *
245
+ * @param string $url The package url
246
+ * @param string $body The post data fields
247
+ * @param int $timeout Execution timeout (default: 300)
248
+ *
249
+ * @return string | The temp filename
250
+ *
251
+ * @since 1.0
252
+ * @see wp-admin/includes/class-wp-upgrader.php
253
+ * @access protected
254
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
255
+ */
256
+ protected function _download_url( $url, $body, $timeout = 300 ) {
257
+
258
+ //WARNING: The file is not automatically deleted, The script must unlink() the file.
259
+ if ( ! $url ) {
260
+ return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) );
261
+ }
262
+
263
+ $tmpfname = wp_tempnam( $url );
264
+
265
+ $args = array(
266
+ 'timeout' => $timeout,
267
+ 'stream' => true,
268
+ 'filename' => $tmpfname,
269
+ 'body' => $body
270
+ );
271
+
272
+ if ( ! $tmpfname ) {
273
+ return new WP_Error( 'http_no_file', __( 'Could not create Temporary file.' ) );
274
+ }
275
+
276
+ $response = wp_safe_remote_post( $url, $args );
277
+
278
+ if ( is_wp_error( $response ) ) {
279
+ unlink( $tmpfname );
280
+ return $response;
281
+ }
282
+
283
+ if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
284
+ unlink( $tmpfname );
285
+ return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
286
+ }
287
+
288
+ $content_md5 = wp_remote_retrieve_header( $response, 'content-md5' );
289
+
290
+ if ( $content_md5 ) {
291
+ $md5_check = verify_file_md5( $tmpfname, $content_md5 );
292
+ if ( is_wp_error( $md5_check ) ) {
293
+ unlink( $tmpfname );
294
+ return $md5_check;
295
+ }
296
+ }
297
+
298
+ return $tmpfname;
299
+ }
300
+
301
+ /**
302
+ * Main plugin Instance
303
+ *
304
+ * @static
305
+ * @return object Main instance
306
+ *
307
+ * @since 1.0
308
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
309
+ */
310
+ public static function instance() {
311
+ if ( is_null( self::$_instance ) ) {
312
+ self::$_instance = new self();
313
+ }
314
+
315
+ return self::$_instance;
316
+ }
317
+
318
+ /**
319
+ * Delete the update plugins transient
320
+ *
321
+ * @return void
322
+ *
323
+ * @since 1.0
324
+ * @see update_plugins transient and pre_set_site_transient_update_plugins hooks
325
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
326
+ */
327
+ public function force_regenerate_update_transient(){
328
+ delete_site_transient( 'update_plugins' );
329
+ }
330
+
331
+ /**
332
+ * Check for plugins update
333
+ *
334
+ * If a new plugin version is available set it in the pre_set_site_transient_update_plugins hooks
335
+ *
336
+ * @param mixed $transient | update_plugins transient value
337
+ * @param bool $save | Default: false. Set true to regenerate the update_transient plugins
338
+ *
339
+ * @return mixed $transient | The new update_plugins transient value
340
+ *
341
+ * @since 1.0
342
+ * @see update_plugins transient and pre_set_site_transient_update_plugins hooks
343
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
344
+ */
345
+ public function check_update( $transient, $save = false ) {
346
+
347
+ foreach ($this->_plugins as $init => $plugin) {
348
+ $xml = str_replace('%plugin_slug%', $this->_plugins[$init]['slug'], $this->_xml);
349
+ $remote_xml = wp_remote_get($xml);
350
+
351
+ if (!is_wp_error($remote_xml) && isset($remote_xml['response']['code']) && '200' == $remote_xml['response']['code']) {
352
+
353
+
354
+ $plugin_remote_info = new SimpleXmlElement($remote_xml['body']);
355
+
356
+ if (version_compare($plugin_remote_info->latest, $plugin['info']['Version'], '>') && !isset($transient->response[$init])) {
357
+
358
+ $package = YIT_Plugin_Licence()->check($init) ? $this->_package_url : null;
359
+
360
+ $obj = new stdClass();
361
+ $obj->slug = (string)$init;
362
+ $obj->new_version = (string)$plugin_remote_info->latest;
363
+ $obj->changelog = (string)$plugin_remote_info->changelog;
364
+ $obj->package = $package;
365
+ $transient->response[$init] = $obj;
366
+ }
367
+
368
+ }
369
+ }
370
+
371
+ if( $save ) {
372
+ set_site_transient( 'update_plugins', $transient );
373
+ }
374
+
375
+ return $transient;
376
+ }
377
+
378
+ /**
379
+ * Add the plugin update row in plugin page
380
+ *
381
+ * @return void
382
+ * @fire "in_theme_update_message-{$init}" action
383
+ *
384
+ * @since 1.0
385
+ * @see after_plugin_row_{$init} action
386
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
387
+ */
388
+ public function plugin_update_row() {
389
+
390
+ $current = get_site_transient( 'update_plugins' );
391
+ $init = str_replace( 'after_plugin_row_', '', current_filter() );
392
+
393
+ if ( ! isset( $current->response[ $init ] ) ) {
394
+ return false;
395
+ }
396
+
397
+ /**
398
+ * stdClass Object
399
+ */
400
+ $r = $current->response[ $init ];
401
+
402
+ $changelog_id = str_replace( array( '/', '.php', '.' ), array( '-', '', '-' ), $init );
403
+ $details_url = '#TB_inline' . add_query_arg( array( 'width' => 722, 'height' => 914, 'inlineId' => $changelog_id ) , '' );
404
+
405
+ /**
406
+ * @see wp_plugin_update_rows() in wp-single\wp-admin\includes\update.php
407
+ */
408
+ $wp_list_table = _get_list_table( 'WP_MS_Themes_List_Table' );
409
+
410
+ if( is_network_admin() || ! is_multisite() || true ) {
411
+ echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
412
+
413
+ if( ! current_user_can( 'update_plugins' ) ){
414
+ printf( __('There is a new version of %1$s available. <a href="%2$s" class="thickbox yit-changelog-button" title="%3$s">View version %4$s details</a>.', 'yit'), $this->_plugins[ $init ]['info']['Name'], esc_url( $details_url ), esc_attr( $this->_plugins[ $init ]['info']['Name'] ), $r->new_version );
415
+ }elseif( is_plugin_active_for_network( $init ) ){
416
+ printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox yit-changelog-button" title="%3$s">View version %4$s details</a>. <em>You have to activate the plugin on a single site of the network to benefit from automatic updates.</em>', 'yit' ), $this->_plugins[ $init ]['info']['Name'], esc_url( $details_url ), esc_attr( $this->_plugins[ $init ]['info']['Name'] ), $r->new_version );
417
+ }elseif ( empty( $r->package ) ) {
418
+ printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox yit-changelog-button" title="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this plugin, please <a href="%5$s" title="Licence activation">activate</a> your copy of %6s.</em>', 'yit' ), $this->_plugins[ $init ]['info']['Name'], esc_url( $details_url ), esc_attr( $this->_plugins[ $init ]['info']['Name'] ), $r->new_version, YIT_Plugin_Licence()->get_licence_activation_page_url(), $this->_plugins[ $init ]['info']['Name'] );
419
+ } else {
420
+ printf( __('There is a new version of %1$s available. <a href="%2$s" class="thickbox yit-changelog-button" title="%3$s">View version %4$s details</a> or <a href="%5$s">update now</a>.', 'yit'), $this->_plugins[ $init ]['info']['Name'], esc_url($details_url), esc_attr( $this->_plugins[ $init ]['info']['Name'] ), $r->new_version, wp_nonce_url( self_admin_url('update.php?action=upgrade-plugin&plugin=') . $init, 'upgrade-plugin_' . $init ) );
421
+ }
422
+
423
+ /**
424
+ * Fires at the end of the update message container in each
425
+ * row of the themes list table.
426
+ *
427
+ * The dynamic portion of the hook name, `$theme_key`, refers to
428
+ * the theme slug as found in the WordPress.org themes repository.
429
+ *
430
+ * @since Wordpress 3.1.0
431
+ * }
432
+ */
433
+ do_action( "in_theme_update_message-{$init}", $this->_plugins[ $init ], $r->changelog, $changelog_id );
434
+
435
+ echo '</div></td></tr>';
436
+ }
437
+ }
438
+
439
+ /**
440
+ * Remove the standard plugin_update_row
441
+ *
442
+ * Remove the standard plugin_update_row and Add a custom plugin update row in plugin page.
443
+ *
444
+ * @return void
445
+ * @fire "in_theme_update_message-{$init}" action
446
+ *
447
+ * @since 1.0
448
+ * @see after_plugin_row_{$init} action
449
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
450
+ */
451
+ public function remove_wp_plugin_update_row() {
452
+ foreach( $this->_plugins as $init => $plugin ){
453
+ remove_action( "after_plugin_row_{$init}", 'wp_plugin_update_row', 10, 2 );
454
+ add_action( "after_plugin_row_{$init}", array( $this, 'plugin_update_row' ) );
455
+ add_action( "in_theme_update_message-{$init}", array( $this, 'in_theme_update_message' ), 10, 3 );
456
+ }
457
+ }
458
+
459
+ public function in_theme_update_message( $plugin, $changelog, $changelog_id, $echo = true ){
460
+
461
+ $res = "<div id='{$changelog_id}' class='yit-plugin-changelog-wrapper'>
462
+ <div class='yit-plugin-changelog'>
463
+ <h2 class='yit-plugin-changelog-title'>{$plugin['info']['Name']} - Changelog</h2>
464
+ <p>{$changelog}</p>
465
+ </div>
466
+ </div>";
467
+
468
+ if( $echo ){
469
+ echo $res;
470
+ }
471
+ else{
472
+ return $res;
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Auto-Update Plugin in multisite
478
+ *
479
+ * Manage the non standard upgrade-plugin-multisite action
480
+ *
481
+ * @return void
482
+ *
483
+ * @since 1.0
484
+ * @see upgrade-plugin action
485
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
486
+ */
487
+ public function upgrade_plugin_multisite(){
488
+
489
+ $plugin = isset($_REQUEST['plugin']) ? trim($_REQUEST['plugin']) : '';
490
+ $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
491
+
492
+ if( 'upgrade-plugin-multisite' != $action ){
493
+ wp_die( __( 'You can\'t update plugins for this site.', 'yit' ) );
494
+ }
495
+
496
+ if ( ! current_user_can( 'update_plugins' ) ) {
497
+ wp_die( __( 'You do not have sufficient permissions to update plugins for this site.', 'yit' ) );
498
+ }
499
+
500
+ $this->check_update( get_site_transient( 'update_plugins') , true );
501
+
502
+ check_admin_referer( 'upgrade-plugin-multisite_' . $plugin );
503
+
504
+ $title = __( 'Update Plugin' );
505
+ $parent_file = 'plugins.php';
506
+ $submenu_file = 'plugins.php';
507
+
508
+ wp_enqueue_script( 'updates' );
509
+ require_once( ABSPATH . 'wp-admin/admin-header.php' );
510
+
511
+ $nonce = 'upgrade-plugin-multisite_' . $plugin;
512
+ $url = 'update.php?action=upgrade-plugin-multisite&plugin=' . urlencode( $plugin );
513
+
514
+ $upgrader = new Plugin_Upgrader( new Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) ) );
515
+ $upgrader->upgrade( $plugin );
516
+
517
+ include( ABSPATH . 'wp-admin/admin-footer.php' );
518
+ }
519
+ }
520
+ }
521
+
522
+ if ( ! function_exists( 'YIT_Upgrade' ) ) {
523
+ /**
524
+ * Main instance of plugin
525
+ *
526
+ * @return object
527
+ * @since 1.0
528
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
529
+ */
530
+ function YIT_Upgrade() {
531
+ return YIT_Upgrade::instance();
532
+ }
533
+ }
534
+
535
+ /**
536
+ * Instance a YIT_Upgrade object
537
+ */
538
+ YIT_Upgrade();
plugin-fw/lib/yit-video.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ } // Exit if accessed directly
15
+
16
+ if ( ! class_exists( 'YIT_Video' ) ) {
17
+ /**
18
+ * YIT Video
19
+ *
20
+ * Class to manage the video from youtube and vimeo or other services
21
+ *
22
+ * @class YIT_Video
23
+ * @package Yithemes
24
+ * @since 1.0.0
25
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
26
+ *
27
+ */
28
+
29
+ class YIT_Video {
30
+
31
+ /**
32
+ * Generate the HTML for a youtube video
33
+ *
34
+ * @static
35
+ *
36
+ * @param array $args Array of arguments to configure the video to generate
37
+ *
38
+ * @return string
39
+ * @since 1.0
40
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
41
+ */
42
+ public static function youtube( $args = array() ) {
43
+ $defaults = array(
44
+ 'id' => '',
45
+ 'url' => '',
46
+ 'width' => 425,
47
+ 'height' => 356,
48
+ 'echo' => false
49
+ );
50
+ $args = wp_parse_args( $args, $defaults );
51
+ extract( $args );
52
+
53
+ // get video ID if you have only URL
54
+ if ( empty( $id ) && ! empty( $url ) ) {
55
+ $id = self::video_id_by_url( $url );
56
+ } elseif ( empty( $id ) && empty( $url ) ) {
57
+ return;
58
+ }
59
+
60
+ if( ! $echo ) ob_start();
61
+
62
+ $id = preg_replace( '/[&|&amp;]feature=([\w\-]*)/', '', $id ); ?>
63
+
64
+ <div class="post_video youtube">
65
+ <iframe wmode="transparent" width="<?php echo $width; ?>" height="<?php echo $height; ?>" src="https://www.youtube.com/embed/<?php echo $id; ?>?wmode=transparent" frameborder="0" allowfullscreen></iframe>
66
+ </div>
67
+
68
+ <?php
69
+ if( ! $echo ) return ob_get_clean();
70
+ }
71
+
72
+ /**
73
+ * Generate the HTML for a vimeo video
74
+ *
75
+ * @static
76
+ *
77
+ * @param array $args Array of arguments to configure the video to generate
78
+ *
79
+ * @return string
80
+ * @since 1.0
81
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
82
+ */
83
+ public static function vimeo( $args = array() ) {
84
+ $defaults = array(
85
+ 'id' => '',
86
+ 'url' => '',
87
+ 'width' => 425,
88
+ 'height' => 356,
89
+ 'echo' => false
90
+ );
91
+ $args = wp_parse_args( $args, $defaults );
92
+ extract( $args );
93
+
94
+ // get video ID if you have only URL
95
+ if ( empty( $id ) && ! empty( $url ) ) {
96
+ $id = self::video_id_by_url( $url );
97
+ }
98
+
99
+ if( ! $echo ) ob_start();
100
+
101
+ $id = preg_replace( '/[&|&amp;]feature=([\w\-]*)/', '', $id ) ?>
102
+
103
+ <div class="post_video vimeo">
104
+ <iframe wmode="transparent" src="http://player.vimeo.com/video/<?php echo $id; ?>?title=0&amp;byline=0&amp;portrait=0" width="<?php echo $width; ?>" height="<?php echo $height; ?>" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
105
+ </div>
106
+
107
+ <?php
108
+ if( ! $echo ) return ob_get_clean();
109
+ }
110
+
111
+ /**
112
+ * Retrieve video ID from URL
113
+ *
114
+ * @static
115
+ *
116
+ * @param array $url The URL of video
117
+ *
118
+ * @return bool|string
119
+ * @since 1.0
120
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
121
+ */
122
+ public static function video_id_by_url( $url ) {
123
+ $parsed = parse_url( esc_url( $url ) );
124
+
125
+ switch ( $parsed['host'] ) {
126
+
127
+ case 'www.youtube.com' :
128
+ case 'youtu.be' :
129
+ $id = self::youtube_id_by_url( $url );
130
+ return "youtube:$id";
131
+
132
+ case 'vimeo.com' :
133
+ preg_match( '/http:\/\/(\w+.)?vimeo\.com\/(.*)/', $url, $matches );
134
+ $id = $matches[2];
135
+ return "vimeo:$id";
136
+
137
+ default :
138
+ return false;
139
+
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Retrieve video ID from URL
145
+ *
146
+ * @static
147
+ *
148
+ * @param array $url The URL of video
149
+ *
150
+ * @return bool|string
151
+ * @since 1.0
152
+ * @author Antonino Scarfi' <antonino.scarfi@yithemes.com>
153
+ */
154
+ protected static function youtube_id_by_url( $url ) {
155
+ if ( preg_match( '/http:\/\/youtu.be/', $url, $matches) ) {
156
+ $url = parse_url($url, PHP_URL_PATH);
157
+ $url = str_replace( '/', '', $url);
158
+ return $url;
159
+
160
+ } elseif ( preg_match( '/watch/', $url, $matches) ) {
161
+ $arr = parse_url($url);
162
+ $url = str_replace( 'v=', '', $arr['query'] );
163
+ return $url;
164
+
165
+ } elseif ( preg_match( '/http:\/\/www.youtube.com\/v/', $url, $matches) ) {
166
+ $arr = parse_url($url);
167
+ $url = str_replace( '/v/', '', $arr['path'] );
168
+ return $url;
169
+
170
+ } elseif ( preg_match( '/http:\/\/www.youtube.com\/embed/', $url, $matches) ) {
171
+ $arr = parse_url($url);
172
+ $url = str_replace( '/embed/', '', $arr['path'] );
173
+ return $url;
174
+
175
+ } elseif ( preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=[0-9]/)[^&\n]+|(?<=v=)[^&\n]+#", $url, $matches) ) {
176
+ return $matches[0];
177
+
178
+ } else {
179
+ return false;
180
+ }
181
+ }
182
+
183
+ }
184
+ }
plugin-fw/licence/assets/css/yit-licence.css ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* === Plugins Upgrader === */
2
+
3
+ .yit-plugin-changelog-wrapper {
4
+ display: none;
5
+ }
6
+
7
+ .yit-plugin-changelog-title {
8
+ text-transform: uppercase;
9
+ }
10
+
11
+ .yit-plugin-changelog {
12
+ background: #fcfcfc;
13
+ height: 97%;
14
+ z-index: 999;
15
+ overflow: auto;
16
+ }
17
+
18
+ /* === Plugins Licence Activation === */
19
+
20
+ .yit-container.product-licence-activation {
21
+ font-family: 'Raleway', sans-serif;
22
+ }
23
+
24
+ .yit-container.product-licence-activation .to-active-wrapper {
25
+ margin-bottom: 60px;
26
+ }
27
+
28
+ .yit-container.product-licence-activation .to-active-wrapper form.to-active-form {
29
+ position: relative;
30
+ border-color: #e1e1e1;
31
+ border-style: solid;
32
+ border-width: 0;
33
+ }
34
+
35
+ .yit-container.product-licence-activation .to-active-wrapper form.to-active-form:first-child {
36
+ border-top-width: 1px;
37
+ }
38
+
39
+ .yit-container.product-licence-activation .to-active-wrapper form.to-active-form:last-child {
40
+ border-bottom-width: 1px;
41
+ }
42
+
43
+ .yit-container.product-licence-activation .to-active-wrapper table.to-active-table {
44
+ border-width: 0;
45
+ border-spacing: 0;
46
+ width: 100%;
47
+ }
48
+
49
+ .yit-container.product-licence-activation .message {
50
+ display: none;
51
+ line-height: normal;
52
+ background: #ffffff url(../images/licence-error.png) 15px center no-repeat;
53
+ padding-left: 65px;
54
+ padding-right: 15px;
55
+ width: 150px;
56
+ }
57
+
58
+ .yit-container.product-licence-activation .message-wrapper {
59
+ height: 75px;
60
+ display: none;
61
+ position: absolute;
62
+ top: 0;
63
+ right: -250px;
64
+ border: 1px solid #ff3838;
65
+ }
66
+
67
+ .yit-container.product-licence-activation .message-wrapper.visible {
68
+ display: table;
69
+ }
70
+
71
+ .yit-container.product-licence-activation .message {
72
+ display: table-cell;
73
+ vertical-align: middle;
74
+ }
75
+
76
+ .yit-container.product-licence-activation .arrow-left:after,
77
+ .yit-container.product-licence-activation .arrow-left:before {
78
+ content: "";
79
+ display: block;
80
+ width: 0;
81
+ height: 0;
82
+ position: absolute;
83
+ }
84
+
85
+ .yit-container.product-licence-activation .arrow-left:before {
86
+ border-top: 9px solid transparent;
87
+ border-bottom: 9px solid transparent;
88
+ border-right: 9px solid #ff3838;
89
+ top: 26px;
90
+ left: -9px;
91
+ }
92
+
93
+ .yit-container.product-licence-activation .arrow-left:after {
94
+ border-top: 8px solid transparent;
95
+ border-bottom: 8px solid transparent;
96
+ border-right: 8px solid #fff;
97
+ left: -8px;
98
+ top: 27px;
99
+ }
100
+
101
+ .yit-container.product-licence-activation h2,
102
+ .yit-container.product-licence-activation h3 {
103
+ text-transform: uppercase;
104
+ font-weight: 800;
105
+ margin-bottom: 30px;
106
+ }
107
+
108
+ .yit-container.product-licence-activation h2 {
109
+ color: #808a97;
110
+ font-size: 25px;
111
+ }
112
+ .yit-container.product-licence-activation h3 {
113
+ color: #313131;
114
+ font-size: 15px;
115
+ height: 20px;
116
+ }
117
+
118
+ .yit-container.product-licence-activation h3.to-active {
119
+ height: 20px;
120
+ position: relative;
121
+ vertical-align: top;
122
+ }
123
+
124
+ .yit-container.product-licence-activation .spinner.show{
125
+ display: inline-block;
126
+ vertical-align: middle;
127
+ float: none;
128
+ }
129
+
130
+ .yit-container.product-licence-activation h3.to-active > .spinner.show {
131
+ display: inline-block;
132
+ float: none;
133
+ top: -3px;
134
+ position: relative;
135
+ }
136
+
137
+ .yit-container.product-licence-activation .licence-check-section{
138
+ margin-bottom: 60px;
139
+ }
140
+
141
+ .yit-container.product-licence-activation span.licence-label {
142
+ font-weight: 500;
143
+ color: #606060;
144
+ margin-bottom: 30px;
145
+ }
146
+
147
+ .yit-container.product-licence-activation .button-licence {
148
+ border: 0;
149
+ font-size: 13px;
150
+ text-transform: uppercase;
151
+ background-color: #808a97;
152
+ color: #fff;
153
+ font-weight: 700;
154
+ border-radius: 3px;
155
+ cursor: pointer;
156
+ text-decoration: none;
157
+ padding: 5px 7px;
158
+ -webkit-transition: background-color 0.3s ease;
159
+ -moz-transition: background-color 0.3s ease;
160
+ -ms-transition: background-color 0.3s ease;
161
+ -o-transition: background-color 0.3s ease;
162
+ transition: background-color 0.3s ease;
163
+ }
164
+
165
+ .yit-container.product-licence-activation .button-licence:hover {
166
+ background-color: #4d5c6f;
167
+ }
168
+
169
+ .yit-container.product-licence-activation .button-licence.clicked {
170
+ cursor: not-allowed;
171
+ background-color: #e2e2e2 !important;
172
+ }
173
+
174
+ .yit-container.product-licence-activation .button-licence.licence-check {
175
+ font-weight: 400;
176
+ padding: 12px 19px;
177
+ }
178
+
179
+ .yit-container.product-licence-activation .button-licence.licence-renew {
180
+ text-decoration: none;
181
+ padding: 7px 12px;
182
+ font-size: 9px;
183
+ }
184
+
185
+ .yit-container.product-licence-activation .button-licence.licence-renew:focus {
186
+ box-shadow: none;
187
+ }
188
+
189
+ .yit-container.product-licence-activation table:not(.to-active-table) {
190
+ width: 100%;
191
+ border: 1px solid #dcdcdc;
192
+ border-spacing: 0;
193
+ border-radius: 5px;
194
+ border-collapse: separate;
195
+ overflow: hidden;
196
+ }
197
+
198
+ .yit-container.product-licence-activation table:not(.to-active-table) th {
199
+ border-bottom: 1px solid #dcdcdc;
200
+ }
201
+
202
+ .yit-container.product-licence-activation table:not(.to-active-table) td,
203
+ .yit-container.product-licence-activation table:not(.to-active-table) th {
204
+ border-right: 1px solid #dcdcdc;
205
+ }
206
+ .yit-container.product-licence-activation table td:last-child,
207
+ .yit-container.product-licence-activation table th:last-child {
208
+ border-right: 0;
209
+ }
210
+
211
+ .yit-container.product-licence-activation table thead tr {
212
+ background-color: #f6f4f4;
213
+ }
214
+
215
+ .yit-container.product-licence-activation table tbody tr {
216
+ background-color: #ffffff;
217
+ }
218
+
219
+ .yit-container.product-licence-activation table thead tr th {
220
+ font-size: 13px;
221
+ color: #313131;
222
+ text-transform: uppercase;
223
+ font-weight: bold;
224
+ }
225
+
226
+ .yit-container.product-licence-activation table thead tr,
227
+ .yit-container.product-licence-activation table tbody tr {
228
+ line-height: 60px;
229
+ }
230
+
231
+ .yit-container.product-licence-activation table tbody tr td{
232
+ text-align: center;
233
+ line-height: 20px;
234
+ padding: 10px 5px;
235
+ }
236
+
237
+ .yit-container.product-licence-activation .button-licence.licence-activation {
238
+ padding: 12px 18px;
239
+ }
240
+
241
+ .yit-container.product-licence-activation .to-active-table tr {
242
+ line-height: 75px;
243
+ }
244
+
245
+ .yit-container.product-licence-activation .to-active-table tr.product-row {
246
+ background-color: transparent;
247
+ -webkit-transition: all 0.3s ease;
248
+ -moz-transition: all 0.3s ease;
249
+ -ms-transition: all 0.3s ease;
250
+ -o-transition: all 0.3s ease;
251
+ transition: all 0.3s ease;
252
+ }
253
+
254
+ .yit-container.product-licence-activation .to-active-table tr.product-row.error {
255
+ background-color: #ffdcdc;
256
+ }
257
+
258
+ .yit-container.product-licence-activation .to-active-table td {
259
+ padding-right: 12px;
260
+ width: 33%;
261
+ }
262
+
263
+
264
+ .yit-container.product-licence-activation .to-active-table td.product-name {
265
+ color: #808a97;
266
+ font-size: 12px;
267
+ text-transform: uppercase;
268
+ font-weight: bold;
269
+ line-height: 20px;
270
+ width: 20%;
271
+ padding-left: 20px;
272
+ }
273
+
274
+ .yit-container.product-licence-activation .to-active-table td.activate-button {
275
+ width: 15%;
276
+ position: relative;
277
+ }
278
+
279
+ .yit-container.product-licence-activation input[type=text],
280
+ .yit-container.product-licence-activation input[type=email]{
281
+ -webkit-transition: all 0.3s ease;
282
+ -moz-transition: all 0.3s ease;
283
+ -ms-transition: all 0.3s ease;
284
+ -o-transition: all 0.3s ease;
285
+ transition: all 0.3s ease;
286
+
287
+ border: 1px solid #dcdcdc;
288
+ padding: 0 15px;
289
+ border-radius: 3px;
290
+ height: 41px;
291
+ width: 100%;
292
+ }
293
+
294
+ .yit-container.product-licence-activation input[type=text].require,
295
+ .yit-container.product-licence-activation input[type=email].require {
296
+ border: 1px solid #ff3838;
297
+ }
298
+
299
+ .yit-container.product-licence-activation input[type=text]:focus,
300
+ .yit-container.product-licence-activation input[type=email]:focus{
301
+ webkit-box-shadow: 0 0 1px rgba(30,140,190,.8);
302
+ box-shadow: 0 0 1px rgba(30,140,190,.8);
303
+ }
304
+
305
+ .yit-container.product-licence-activation input[type=text]{
306
+ text-transform: uppercase;
307
+ text-align: center;
308
+ }
309
+
310
+ .yit-container.product-licence-activation input[type=email] {
311
+ text-align: left;
312
+ }
313
+
314
+ .yit-container.product-licence-activation input[type=submit]:focus{
315
+ outline: 0;
316
+ }
317
+
318
+ /* === Responsive === */
319
+
320
+ @media (max-width: 767px) {}
321
+
322
+ @media (max-width: 480px) {}
323
+
324
+ @media (min-width: 768px) and (max-width: 992px) {}
325
+
326
+ @media (min-width: 980px) and (max-width: 1199px) {}
327
+
328
+ @media (min-width: 1200px) {
329
+ .yit-container.product-licence-activation{
330
+ width: 900px;
331
+ }
332
+ }
333
+
334
+ @media only screen and (-webkit-min-device-pixel-ratio: 1.5),
335
+ only screen and (-o-min-device-pixel-ratio: 3/2),
336
+ only screen and (min--moz-device-pixel-ratio: 1.5),
337
+ only screen and (min-device-pixel-ratio: 1.5) {}
plugin-fw/licence/assets/images/licence-error.png ADDED
Binary file
plugin-fw/licence/assets/js/yit-licence.js ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file belongs to the YIT Plugin Framework.
3
+ *
4
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
5
+ * that is bundled with this package in the file LICENSE.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.gnu.org/licenses/gpl-3.0.txt
8
+ */
9
+
10
+
11
+ (function ($) {
12
+
13
+ /* === Licence API === */
14
+
15
+ var licence_activation = function (button) {
16
+ button.on('click', function (e, button) {
17
+ e.preventDefault();
18
+
19
+ var t = $(this),
20
+ form_id = t.data('formid'),
21
+ form = $('#' + form_id),
22
+ data = form.serialize(),
23
+ message = $(form).find('.message'),
24
+ message_wrapper = $(form).find('.message-wrapper'),
25
+ email = form.find('.user-email'),
26
+ licence_key = form.find('.licence-key'),
27
+ email_val = form.find('.user-email').val(),
28
+ licence_key_val = form.find('.licence-key').val(),
29
+ error = false,
30
+ error_fields = new Array(),
31
+ product_row = form.find('.product-row'),
32
+ spinner = $('h3.to-active').find('.spinner');
33
+
34
+ /* Init Input Fields */
35
+ message.empty();
36
+ message_wrapper.removeClass('visible')
37
+ email.removeClass('require');
38
+ licence_key.removeClass('require');
39
+ product_row.removeClass('error');
40
+ spinner.addClass('show');
41
+ t.prop("disabled", true).addClass('clicked');
42
+
43
+ if ('' == email_val) {
44
+ error = true;
45
+ error_fields[ error_fields.length ] = 'Email';
46
+ email.addClass('require');
47
+ }
48
+
49
+ if ('' == licence_key_val) {
50
+ error = true;
51
+ error_fields[ error_fields.length ] = 'Licence Key';
52
+ licence_key.addClass('require');
53
+ }
54
+
55
+ if (false == error) {
56
+ jQuery.ajax({
57
+ type : 'POST',
58
+ url : ajaxurl,
59
+ data : data,
60
+ success: function (response) {
61
+
62
+ spinner.removeClass('show');
63
+ t.prop("disabled", false).removeClass('clicked');
64
+
65
+ if (true == response.activated) {
66
+ $('.product-licence-activation').empty().replaceWith(response.template);
67
+ licence_api();
68
+ } else if (false != response) {
69
+ message.text(response.error);
70
+ message_wrapper.addClass('visible');
71
+ product_row.addClass('error');
72
+ } else {
73
+ message.text(licence_message.server);
74
+ message_wrapper.addClass('visible');
75
+ product_row.addClass('error');
76
+ }
77
+ }
78
+ });
79
+ } else {
80
+ if (error_fields.length == 1) {
81
+ message.text(licence_message.error.replace('%field%', error_fields[0]));
82
+ message_wrapper.addClass('visible');
83
+ product_row.addClass('error');
84
+ } else {
85
+ var message_text = licence_message.errors;
86
+ for (var i = 0; i < error_fields.length; i++) {
87
+ message_text = message_text.replace('%field_' + ( i + 1) + '%', error_fields[i]);
88
+ message_wrapper.addClass('visible');
89
+ }
90
+ message.text(message_text);
91
+ message_wrapper.addClass('visible');
92
+ product_row.addClass('error');
93
+ }
94
+
95
+ spinner.removeClass('show');
96
+ t.prop("disabled", false).removeClass('clicked');
97
+ }
98
+ });
99
+ }
100
+
101
+ var licence_update = function (button) {
102
+ button.on('click', function (e) {
103
+ e.preventDefault();
104
+
105
+ var t = $(this),
106
+ form = $('#licence-check-update'),
107
+ data = form.serialize();
108
+
109
+ t.prop("disabled", true).addClass('clicked');
110
+ form.find('div.spinner').addClass('show');
111
+
112
+ jQuery.ajax({
113
+ type : 'POST',
114
+ url : ajaxurl,
115
+ data : data,
116
+ success: function (response) {
117
+ $('.product-licence-activation').empty().replaceWith(response.template);
118
+ licence_api();
119
+ }
120
+ });
121
+ });
122
+ }
123
+
124
+ var licence_api = function () {
125
+ var button = $('.licence-activation'),
126
+ check = $('.licence-check');
127
+
128
+ licence_activation(button);
129
+ licence_update(check);
130
+ }
131
+
132
+ licence_api();
133
+
134
+ $('body').on('click', '.yit-changelog-button', function (e) {
135
+ $('#TB_window').remove();
136
+
137
+ });
138
+
139
+ })(jQuery);
plugin-fw/licence/assets/js/yit-licence.min.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ (function(b){var g=function(d){d.on("click",function(u,d){u.preventDefault();var e=b(this),a=e.data("formid"),c=b("#"+a),f=c.serialize(),h=b(c).find(".message"),l=b(c).find(".message-wrapper"),r=c.find(".user-email"),t=c.find(".licence-key"),g=c.find(".user-email").val(),q=c.find(".licence-key").val(),m=!1,a=[],n=c.find(".product-row"),p=b("h3.to-active").find(".spinner");h.empty();l.removeClass("visible");r.removeClass("require");t.removeClass("require");n.removeClass("error");p.addClass("show");
2
+ e.prop("disabled",!0).addClass("clicked");""==g&&(m=!0,a[a.length]="Email",r.addClass("require"));""==q&&(m=!0,a[a.length]="Licence Key",t.addClass("require"));if(0==m)jQuery.ajax({type:"POST",url:ajaxurl,data:f,success:function(a){p.removeClass("show");e.prop("disabled",!1).removeClass("clicked");1==a.activated?(b(".product-licence-activation").empty().replaceWith(a.template),k()):(0!=a?h.text(a.error):h.text(licence_message.server),l.addClass("visible"),n.addClass("error"))}});else{if(1==a.length)h.text(licence_message.error.replace("%field%",
3
+ a[0]));else{c=licence_message.errors;for(f=0;f<a.length;f++)c=c.replace("%field_"+(f+1)+"%",a[f]),l.addClass("visible");h.text(c)}l.addClass("visible");n.addClass("error");p.removeClass("show");e.prop("disabled",!1).removeClass("clicked")}})},q=function(d){d.on("click",function(d){d.preventDefault();d=b(this);var g=b("#licence-check-update"),e=g.serialize();d.prop("disabled",!0).addClass("clicked");g.find("div.spinner").addClass("show");jQuery.ajax({type:"POST",url:ajaxurl,data:e,success:function(a){b(".product-licence-activation").empty().replaceWith(a.template);
4
+ k()}})})},k=function(){var d=b(".licence-activation"),k=b(".licence-check");g(d);q(k)};k();b("body").on("click",".yit-changelog-button",function(d){b("#TB_window").remove()})})(jQuery);
plugin-fw/licence/lib/yit-licence.php ADDED
@@ -0,0 +1,543 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'YIT_Licence' ) ) {
16
+ /**
17
+ * YIT Licence Panel
18
+ *
19
+ * Setting Page to Manage Products
20
+ *
21
+ * @class YIT_Licence
22
+ * @package Yithemes
23
+ * @since 1.0
24
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
25
+ */
26
+
27
+ abstract class YIT_Licence {
28
+
29
+ /**
30
+ * @var mixed array The registered products info
31
+ * @since 1.0
32
+ */
33
+ protected $_products = array();
34
+
35
+ /**
36
+ * @var array The settings require to add the submenu page "Activation"
37
+ * @since 1.0
38
+ */
39
+ protected $_settings = array();
40
+
41
+ /**
42
+ * @var string Option name
43
+ * @since 1.0
44
+ */
45
+ protected $_licence_option = 'yit_products_licence_activation';
46
+
47
+ /**
48
+ * @var string The yithemes api uri
49
+ * @since 1.0
50
+ */
51
+ protected $_api_uri = 'http://www.yithemes.com';
52
+
53
+ /**
54
+ * @var string The yithemes api uri query args
55
+ * @since 1.0
56
+ */
57
+ protected $_api_uri_query_args = '?wc-api=software-api&request=%request%';
58
+
59
+ /**
60
+ * Constructor
61
+ *
62
+ * @since 1.0
63
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
64
+ */
65
+ abstract public function __construct();
66
+
67
+ /**
68
+ * Premium products registration
69
+ *
70
+ * @param $init string | The products identifier
71
+ * @param $secret_key string | The secret key
72
+ * @param $product_id string | The product id
73
+ *
74
+ * @return void
75
+ *
76
+ * @since 1.0
77
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
78
+ */
79
+ abstract public function register( $init, $secret_key, $product_id );
80
+
81
+ /**
82
+ * Get protected array products
83
+ *
84
+ * @return mixed array
85
+ *
86
+ * @since 1.0
87
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
88
+ */
89
+ public function get_products() {
90
+ return $this->_products;
91
+ }
92
+
93
+ /**
94
+ * Get The home url without protocol
95
+ *
96
+ * @return string | The home url
97
+ *
98
+ * @since 1.0
99
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
100
+ */
101
+ public function get_home_url() {
102
+ return is_ssl() ? str_replace( 'https://', '', home_url() ) : str_replace( 'http://', '', home_url() );
103
+ }
104
+
105
+ /**
106
+ * Check if the request is ajax
107
+ *
108
+ * @return bool true if the request is ajax, false otherwise
109
+ *
110
+ * @since 1.0
111
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
112
+ */
113
+ public function is_ajax() {
114
+ return defined( 'DOING_AJAX' ) && DOING_AJAX ? true : false;
115
+ }
116
+
117
+ /**
118
+ * Admin Enqueue Scripts
119
+ *
120
+ * @return void
121
+ *
122
+ * @since 1.0
123
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
124
+ */
125
+ public function admin_enqueue_scripts(){
126
+
127
+ /**
128
+ * Support to YIT Framework < 2.0
129
+ */
130
+ $filename = function_exists( 'yit_load_js_file' ) ? yit_load_js_file( 'yit-licence.js' ) : 'yit-licence.js';
131
+ $script_path = defined( 'YIT_CORE_PLUGIN_URL' ) ? YIT_CORE_PLUGIN_URL : get_template_directory_uri() . '/core/plugin-fw';
132
+ $style_path = defined( 'YIT_CORE_PLUGIN_URL' ) ? YIT_CORE_PLUGIN_URL : get_template_directory_uri() . '/core/plugin-fw';
133
+
134
+ wp_enqueue_script( 'yit-licence', $script_path . '/licence/assets/js/' . $filename, array( 'jquery' ), '1.0.0', true );
135
+ wp_enqueue_style( 'yit-theme-licence', $style_path . '/licence/assets/css/yit-licence.css' );
136
+ }
137
+
138
+ /**
139
+ * Localize Scripts
140
+ *
141
+ * @return void
142
+ *
143
+ * @since 1.0
144
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
145
+ */
146
+ public function localize_script() {
147
+ wp_localize_script( 'yit-licence', 'licence_message', array(
148
+ 'error' => __( '%field% field cannot be empty', 'yit' ),
149
+ 'errors' => __( '%field_1% and %field_2% fields cannot be empty', 'yit' ),
150
+ 'server' => __( 'Unable to contact the remote server, please try again later. Thanks!', 'yit' )
151
+ )
152
+ );
153
+ }
154
+
155
+ /**
156
+ * Activate Plugins
157
+ *
158
+ * Send a request to API server to activate plugins
159
+ *
160
+ * @return void
161
+ * @use wp_send_json
162
+ *
163
+ * @since 1.0
164
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
165
+ */
166
+ public function activate() {
167
+
168
+ $product_init = $_REQUEST['product_init'];
169
+ $product = $this->get_product( $product_init );
170
+
171
+ $args = array(
172
+ 'email' => urlencode( sanitize_email( $_REQUEST['email'] ) ),
173
+ 'licence_key' => sanitize_text_field( $_REQUEST['licence_key'] ),
174
+ 'product_id' => sanitize_text_field( $product['product_id'] ),
175
+ 'secret_key' => sanitize_text_field( $product['secret_key'] ),
176
+ 'instance' => $this->get_home_url()
177
+ );
178
+
179
+ $api_uri = add_query_arg( $args, $this->get_api_uri( 'activation' ) );
180
+ $response = wp_remote_get( $api_uri );
181
+
182
+ if ( is_wp_error( $response ) ) {
183
+ $body = false;
184
+ }
185
+ else {
186
+ $body = json_decode( $response['body'] );
187
+ $body = is_object( $body ) ? get_object_vars( $body ) : false;
188
+ }
189
+
190
+ if ( $body && is_array( $body ) && isset( $body['activated'] ) && $body['activated'] ) {
191
+
192
+ $option[$product['product_id']] = array(
193
+ 'email' => urldecode( $args['email'] ),
194
+ 'licence_key' => $args['licence_key'],
195
+ 'licence_expires' => $body['licence_expires'],
196
+ 'message' => $body['message'],
197
+ 'activated' => true,
198
+ 'activation_limit' => $body['activation_limit'],
199
+ 'activation_remaining' => $body['activation_remaining'],
200
+ );
201
+
202
+ /* === Check for other plugins activation === */
203
+ $options = $this->get_licence();
204
+ $options[$product['product_id']] = $option[$product['product_id']];
205
+
206
+ update_option( $this->_licence_option, $options );
207
+
208
+ /* === Licence Activation Template === */
209
+ $body['template'] = $this->show_activation_panel();
210
+ }
211
+
212
+ wp_send_json( $body );
213
+ }
214
+
215
+ /**
216
+ * Check Plugins Licence
217
+ *
218
+ * Send a request to API server to check if plugins is activated
219
+ *
220
+ * @param string|The plugin init slug $plugin_init
221
+ *
222
+ * @return bool | true if activated, false otherwise
223
+ *
224
+ * @since 1.0
225
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
226
+ */
227
+ public function check( $product_init ) {
228
+
229
+ $status = false;
230
+ $body = false;
231
+ $product = $this->get_product( $product_init );
232
+ $licence = $this->get_licence();
233
+ $product_id = $product['product_id'];
234
+
235
+ if( ! isset( $licence[ $product_id ] ) ) {
236
+ return false;
237
+ }
238
+
239
+ $args = array(
240
+ 'email' => urlencode( $licence[$product_id]['email'] ),
241
+ 'licence_key' => $licence[$product_id]['licence_key'],
242
+ 'product_id' => $product_id,
243
+ 'secret_key' => $product['secret_key'],
244
+ 'instance' => $this->get_home_url()
245
+ );
246
+
247
+ $api_uri = add_query_arg( $args, $this->get_api_uri( 'check' ) );
248
+ $response = wp_remote_get( $api_uri );
249
+
250
+ if ( ! is_wp_error( $response ) ) {
251
+ $body = json_decode( $response['body'] );
252
+ $body = is_object( $body ) ? get_object_vars( $body ) : false;
253
+ }
254
+
255
+ if ( $body && is_array( $body ) && isset( $body['success'] ) ) {
256
+ if ( $body['success'] ) {
257
+
258
+ /**
259
+ * Code 200 -> Licence key is valid
260
+ */
261
+ $licence[ $product_id ]['status_code'] = '200';
262
+ $licence[ $product_id ]['activated'] = $body['activated'];
263
+ $licence[ $product_id ]['licence_expires'] = $body['licence_expires'];
264
+ $licence[ $product_id ]['activation_remaining'] = $body['activation_remaining'];
265
+ $licence[ $product_id ]['activation_limit'] = $body['activation_limit'];
266
+ $status = (bool) $body['activated'];
267
+ }
268
+ elseif ( isset( $body['code'] ) ) {
269
+
270
+ switch ( $body['code'] ) {
271
+
272
+ /**
273
+ * Error Code List:
274
+ *
275
+ * 100 -> Invalid Request
276
+ * 101 -> Invalid licence key
277
+ * 102 -> Software has been deactivate
278
+ * 103 -> Exceeded maximum number of activations
279
+ * 104 -> Invalid instance ID
280
+ * 105 -> Invalid security key
281
+ * 106 -> Licence key has expired
282
+ * 107 -> Licence key has be banned
283
+ *
284
+ * Only code 101, 106 and 107 have effect on DB
285
+ *
286
+ */
287
+
288
+ case '101':
289
+ case '102':
290
+ unset( $licence[ $product_id ] );
291
+ break;
292
+
293
+ case '106':
294
+ $licence[ $product_id ]['activated'] = false;
295
+ $licence[ $product_id ]['message'] = $body['additional_info'];
296
+ $licence[ $product_id ]['status_code'] = $body['code'];
297
+ $licence[ $product_id ]['licence_expires'] = $body['licence_expires'];
298
+ break;
299
+
300
+ case '107':
301
+ $licence[ $product_id ]['activated'] = false;
302
+ $licence[ $product_id ]['message'] = $body['additional_info'];
303
+ $licence[ $product_id ]['status_code'] = $body['code'];
304
+ break;
305
+ }
306
+ }
307
+
308
+ /* === Update Plugin Licence Information === */
309
+ update_option( $this->_licence_option, $licence );
310
+ }
311
+ return $status;
312
+ }
313
+
314
+ /**
315
+ * Update Plugins Information
316
+ *
317
+ * Send a request to API server to check activate plugins and update the informations
318
+ *
319
+ * @return void
320
+ * @use YIT_Theme_Licence->check()
321
+ *
322
+ * @since 1.0
323
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
324
+ */
325
+ public function update_licence_information() {
326
+ foreach ( $this->_products as $init => $info ) {
327
+ $this->check( $init );
328
+ }
329
+
330
+ /* === Regenerate Update Plugins Transient === */
331
+ //YIT_Upgrade()->force_regenerate_update_transient();
332
+
333
+ do_action( 'yit_licence_after_check' );
334
+
335
+ $response['template'] = $this->show_activation_panel();
336
+ wp_send_json( $response );
337
+ }
338
+
339
+ /**
340
+ * Include activation page template
341
+ *
342
+ * @return mixed void | string the contents of the output buffer and end output buffering.
343
+ *
344
+ * @since 1.0
345
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
346
+ */
347
+ public function show_activation_panel() {
348
+
349
+ $path = defined( 'YIT_CORE_PLUGIN_PATH' ) ? YIT_CORE_PLUGIN_PATH : get_template_directory() . '/core/plugin-fw/';
350
+
351
+ if ( $this->is_ajax() ) {
352
+ ob_start();
353
+ require_once( $path . '/licence/templates/panel/activation/activation-panel.php' );
354
+ return ob_get_clean();
355
+ }
356
+ else {
357
+ require_once( $path . '/licence/templates/panel/activation/activation-panel.php' );
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Get activated products
363
+ *
364
+ * @return array
365
+ *
366
+ * @since 1.0
367
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
368
+ */
369
+ public function get_activated_products() {
370
+ $activated_products = array();
371
+ $licence = $this->get_licence();
372
+
373
+ if ( is_array( $licence ) ) {
374
+ foreach ( $this->_products as $init => $info ) {
375
+ if ( in_array( $info['product_id'], array_keys( $licence ) ) && isset( $licence[$info['product_id']]['activated'] ) && $licence[$info['product_id']]['activated'] ) {
376
+ $product[$init] = $this->_products[$init];
377
+ $product[$init]['licence'] = $licence[$info['product_id']];
378
+ $activated_products[$init] = $product[$init];
379
+ }
380
+ }
381
+ }
382
+
383
+ return $activated_products;
384
+ }
385
+
386
+ /**
387
+ * Get to active products
388
+ *
389
+ * @return array
390
+ *
391
+ * @since 1.0
392
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
393
+ */
394
+ public function get_to_active_products() {
395
+ return array_diff_key( $this->get_products(), $this->get_activated_products() );
396
+ }
397
+
398
+ /**
399
+ * Get no active products
400
+ *
401
+ * @return array
402
+ *
403
+ * @since 1.0
404
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
405
+ */
406
+ public function get_no_active_licence_key() {
407
+ $unactive_products = $this->get_to_active_products();
408
+ $licence = $this->get_licence();
409
+ $licence_key = array();
410
+
411
+ /**
412
+ * Remove banned licence key
413
+ */
414
+ foreach ( $unactive_products as $init => $info ) {
415
+ $product_id = $unactive_products[$init]['product_id'];
416
+ if ( isset( $licence[$product_id]['activated'] ) && ! $licence[$product_id]['activated'] && isset( $licence[$product_id]['status_code'] ) ) {
417
+ $status_code = $licence[$product_id]['status_code'];
418
+
419
+ switch ( $status_code ) {
420
+ case '106':
421
+ $licence_key[$status_code][$init] = $unactive_products[$init];
422
+ $licence_key[$status_code][$init]['licence'] = $licence[$product_id];
423
+ break;
424
+
425
+ case '107':
426
+ $licence_key[$status_code][$init] = $unactive_products[$init];
427
+ $licence_key[$status_code][$init]['licence'] = $licence[$product_id];
428
+ break;
429
+ }
430
+ }
431
+ }
432
+ return $licence_key;
433
+ }
434
+
435
+ /**
436
+ * Get a specific product information
437
+ *
438
+ * @param $product_init | product init file
439
+ *
440
+ * @return mixed array
441
+ *
442
+ * @since 1.0
443
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
444
+ */
445
+ public function get_product( $init ) {
446
+ return isset( $this->_products[$init] ) ? $this->_products[$init] : false;
447
+ }
448
+
449
+ /**
450
+ * Get product product id information
451
+ *
452
+ * @param $product_init | product init file
453
+ *
454
+ * @return mixed array
455
+ *
456
+ * @since 1.0
457
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
458
+ */
459
+ public function get_product_id( $init ) {
460
+ return isset( $this->_products[$init]['product_id'] ) ? $this->_products[$init]['product_id'] : false;
461
+ }
462
+
463
+ /**
464
+ * Get Renewing uri
465
+ *
466
+ * @param $licence_key The licence key to renew
467
+ *
468
+ * @return mixed The renewing uri if licence_key exists, false otherwise
469
+ *
470
+ * @since 1.0
471
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
472
+ */
473
+ public function get_renewing_uri( $licence_key ) {
474
+ return ! empty( $licence_key ) ? str_replace( 'www.', '', $this->_api_uri ) . '?renewing_key=' . $licence_key : false;
475
+ }
476
+
477
+ /**
478
+ * Get protected yithemes api uri
479
+ *
480
+ * @param $request
481
+ *
482
+ * @return mixed array
483
+ *
484
+ * @since 1.0
485
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
486
+ */
487
+ public function get_api_uri( $request ) {
488
+ return str_replace( '%request%', $request, $this->_api_uri . $this->_api_uri_query_args );
489
+ }
490
+
491
+ /**
492
+ * Get the activation page url
493
+ *
494
+ * @return String | Activation page url
495
+ *
496
+ * @since 1.0
497
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
498
+ */
499
+ public function get_licence_activation_page_url() {
500
+ return add_query_arg( array( 'page' => $this->_settings['page'] ), admin_url( 'admin.php' ) );
501
+ }
502
+
503
+
504
+ /**
505
+ * Get the licence information
506
+ *
507
+ * @return array | licence array
508
+ *
509
+ * @since 1.0
510
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
511
+ */
512
+ public function get_licence() {
513
+ return get_option( $this->_licence_option );
514
+ }
515
+
516
+ /**
517
+ * Get the licence information
518
+ *
519
+ * @param $code string The error code
520
+ *
521
+ * @return string | Error code message
522
+ *
523
+ * @since 1.0
524
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
525
+ */
526
+ public function get_error_code_message( $code ) {
527
+
528
+ $error_strings = array(
529
+ '100' => __( 'Invalid Request', 'yit' ),
530
+ '101' => __( 'Invalid licence key', 'yit' ),
531
+ '102' => __( 'Software has been deactivate', 'yit' ),
532
+ '103' => __( 'Exceeded maximum number of activations', 'yit' ),
533
+ '104' => __( 'Invalid instance ID', 'yit' ),
534
+ '105' => __( 'Invalid security key', 'yit' ),
535
+ '106' => __( 'Licence key has expired', 'yit' ),
536
+ '107' => __( 'Licence key has been banned', 'yit' )
537
+ );
538
+
539
+ return isset( $error_strings[$code] ) ? $error_strings[$code] : false;
540
+ }
541
+
542
+ }
543
+ }
plugin-fw/licence/lib/yit-plugin-licence.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'YIT_Plugin_Licence' ) ) {
16
+ /**
17
+ * YIT Plugin Licence Panel
18
+ *
19
+ * Setting Page to Manage Plugins
20
+ *
21
+ * @class YIT_Plugin_Licence
22
+ * @package Yithemes
23
+ * @since 1.0
24
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
25
+ */
26
+
27
+ class YIT_Plugin_Licence extends YIT_Licence {
28
+
29
+ /**
30
+ * @var array The settings require to add the submenu page "Activation"
31
+ * @since 1.0
32
+ */
33
+ protected $_settings = array();
34
+
35
+ /**
36
+ * @var object The single instance of the class
37
+ * @since 1.0
38
+ */
39
+ protected static $_instance = null;
40
+
41
+ /**
42
+ * @var string Option name
43
+ * @since 1.0
44
+ */
45
+ protected $_licence_option = 'yit_plugin_licence_activation';
46
+
47
+ /**
48
+ * @var string product type
49
+ * @since 1.0
50
+ */
51
+ protected $_product_type = 'plugin';
52
+
53
+ /**
54
+ * Constructor
55
+ *
56
+ * @since 1.0
57
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
58
+ */
59
+ public function __construct() {
60
+
61
+ $this->_settings = array(
62
+ 'parent_page' => 'yit_plugin_panel',
63
+ 'page_title' => __( 'Licence Activation', 'yit' ),
64
+ 'menu_title' => __( 'Licence Activation', 'yit' ),
65
+ 'capability' => 'manage_options',
66
+ 'page' => 'yith_plugins_activation',
67
+ );
68
+
69
+ add_action( 'admin_menu', array( $this, 'add_submenu_page' ), 99 );
70
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
71
+ add_action( 'admin_enqueue_scripts', array( $this, 'localize_script' ), 15 );
72
+ add_action( "wp_ajax_activate-{$this->_product_type}", array( $this, 'activate' ) );
73
+ add_action( "wp_ajax_nopriv_activate-{$this->_product_type}", array( $this, 'activate' ) );
74
+ add_action( "wp_ajax_update_licence_information-{$this->_product_type}", array( $this, 'update_licence_information' ) );
75
+ add_action( "wp_ajax_nopriv_update_licence_information-{$this->_product_type}", array( $this, 'update_licence_information' ) );
76
+ add_action( 'yit_licence_after_check', array( $this, 'licence_after_check' ) );
77
+ }
78
+
79
+
80
+ public function licence_after_check() {
81
+ /* === Regenerate Update Plugins Transient === */
82
+ YIT_Upgrade()->force_regenerate_update_transient();
83
+ }
84
+
85
+ /**
86
+ * Main plugin Instance
87
+ *
88
+ * @static
89
+ * @return object Main instance
90
+ *
91
+ * @since 1.0
92
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
93
+ */
94
+ public static function instance() {
95
+ if ( is_null( self::$_instance ) ) {
96
+ self::$_instance = new self();
97
+ }
98
+
99
+ return self::$_instance;
100
+ }
101
+
102
+ /**
103
+ * Add "Activation" submenu page under YIT Plugins
104
+ *
105
+ * @return void
106
+ * @since 1.0
107
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
108
+ */
109
+ public function add_submenu_page() {
110
+ add_submenu_page(
111
+ $this->_settings['parent_page'],
112
+ $this->_settings['page_title'],
113
+ $this->_settings['menu_title'],
114
+ $this->_settings['capability'],
115
+ $this->_settings['page'],
116
+ array( $this, 'show_activation_panel' )
117
+ );
118
+ }
119
+
120
+ /**
121
+ * Premium plugin registration
122
+ *
123
+ * @param $plugin_init | string | The plugin init file
124
+ * @param $secret_key | string | The product secret key
125
+ * @param $product_id | string | The plugin slug (product_id)
126
+ *
127
+ * @return void
128
+ *
129
+ * @since 1.0
130
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
131
+ */
132
+ public function register( $plugin_init, $secret_key, $product_id ) {
133
+ if ( ! function_exists( 'get_plugins' ) ) {
134
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
135
+ }
136
+
137
+ $plugins = get_plugins();
138
+ $plugins[$plugin_init]['secret_key'] = $secret_key;
139
+ $plugins[$plugin_init]['product_id'] = $product_id;
140
+ $this->_products[$plugin_init] = $plugins[$plugin_init];
141
+ }
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Main instance of plugin
147
+ *
148
+ * @return object
149
+ * @since 1.0
150
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
151
+ */
152
+ if( ! function_exists( 'YIT_Plugin_Licence' ) ){
153
+ function YIT_Plugin_Licence() {
154
+ return YIT_Plugin_Licence::instance();
155
+ }
156
+ }
plugin-fw/licence/lib/yit-theme-licence.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'YIT_Theme_Licence' ) ) {
16
+ /**
17
+ * YIT Plugin Licence Panel
18
+ *
19
+ * Setting Page to Manage Plugins
20
+ *
21
+ * @class YIT_Theme_Licence
22
+ * @package Yithemes
23
+ * @since 1.0
24
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
25
+ */
26
+
27
+ class YIT_Theme_Licence extends YIT_Licence {
28
+
29
+ /**
30
+ * @var array The settings require to add the submenu page "Activation"
31
+ * @since 1.0
32
+ */
33
+ protected $_settings = array();
34
+
35
+ /**
36
+ * @var object The single instance of the class
37
+ * @since 1.0
38
+ */
39
+ protected static $_instance = null;
40
+
41
+ /**
42
+ * @var string Option name
43
+ * @since 1.0
44
+ */
45
+ protected $_licence_option = 'yit_theme_licence_activation';
46
+
47
+ /**
48
+ * @var string product type
49
+ * @since 1.0
50
+ */
51
+ protected $_product_type = 'theme';
52
+
53
+ /**
54
+ * Constructor
55
+ *
56
+ * @since 1.0
57
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
58
+ */
59
+ public function __construct() {
60
+
61
+ $this->_settings = array(
62
+ 'parent_page' => 'yit_product_panel',
63
+ 'page_title' => __( 'Licence Activation', 'yit' ),
64
+ 'menu_title' => __( 'Licence Activation', 'yit' ),
65
+ 'capability' => 'manage_options',
66
+ 'page' => 'yith_plugins_activation',
67
+ );
68
+
69
+ add_action( 'admin_menu', array( $this, 'add_submenu_page' ), 99 );
70
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
71
+ add_action( 'admin_enqueue_scripts', array( $this, 'localize_script' ), 15 );
72
+ add_action( "wp_ajax_activate-{$this->_product_type}", array( $this, 'activate' ) );
73
+ add_action( "wp_ajax_nopriv_activate-{$this->_product_type}", array( $this, 'activate' ) );
74
+ add_action( "wp_ajax_update_licence_information-{$this->_product_type}", array( $this, 'update_licence_information' ) );
75
+ add_action( "wp_ajax_nopriv_update_licence_information-{$this->_product_type}", array( $this, 'update_licence_information' ) );
76
+ }
77
+
78
+ /**
79
+ * Main plugin Instance
80
+ *
81
+ * @static
82
+ * @return object Main instance
83
+ *
84
+ * @since 1.0
85
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
86
+ */
87
+ public static function instance() {
88
+ if ( is_null( self::$_instance ) ) {
89
+ self::$_instance = new self();
90
+ }
91
+
92
+ return self::$_instance;
93
+ }
94
+
95
+ /**
96
+ * Add "Activation" submenu page under YIT Plugins
97
+ *
98
+ * @return void
99
+ * @since 1.0
100
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
101
+ */
102
+ public function add_submenu_page() {
103
+
104
+ $admin_tree = array(
105
+ 'parent_slug' => apply_filters( 'yit_licence_parent_slug', 'yit_panel'),
106
+ 'page_title' => __( 'Licence Activation', 'yit' ),
107
+ 'menu_title' => __( 'Licence Activation', 'yit' ),
108
+ 'capability' => 'manage_options',
109
+ 'menu_slug' => 'yit_panel_licence',
110
+ 'function' => 'show_activation_panel'
111
+ );
112
+
113
+ add_submenu_page( $admin_tree['parent_slug'],
114
+ sprintf( __( '%s', 'yit' ), $admin_tree['page_title'] ),
115
+ sprintf( __( '%s', 'yit' ), $admin_tree['menu_title'] ),
116
+ $admin_tree['capability'],
117
+ $admin_tree['menu_slug'],
118
+ array( $this, $admin_tree['function'] )
119
+ );
120
+ }
121
+
122
+ /**
123
+ * Premium product registration
124
+ *
125
+ * @param $product_init | string | The product init file
126
+ * @param $secret_key | string | The product secret key
127
+ * @param $product_id | string | The product slug (product_id)
128
+ *
129
+ * @return void
130
+ *
131
+ * @since 1.0
132
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
133
+ */
134
+ public function register( $product_init, $secret_key, $product_id ) {
135
+ $theme = wp_get_theme();
136
+ $products[$product_init]['Name'] = $theme->Name;
137
+ $products[$product_init]['secret_key'] = $secret_key;
138
+ $products[$product_init]['product_id'] = $product_id;
139
+ $this->_products[$product_init] = $products[$product_init];
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Main instance
146
+ *
147
+ * @return object
148
+ * @since 1.0
149
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
150
+ */
151
+ if( ! function_exists( 'YIT_Theme_Licence' ) ){
152
+ function YIT_Theme_Licence() {
153
+ return YIT_Theme_Licence::instance();
154
+ }
155
+ }
plugin-fw/licence/templates/panel/activation/activation-panel.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ $to_active_products = $this->get_to_active_products();
12
+ $activated_products = $this->get_activated_products();
13
+ $no_active_products = $this->get_no_active_licence_key();
14
+ $expired_products = isset( $no_active_products[ '106' ] ) ? $no_active_products[ '106' ] : array();
15
+ $banned_products = isset( $no_active_products[ '107' ] ) ? $no_active_products[ '107' ] : array();
16
+ ?>
17
+
18
+ <div class="yit-container product-licence-activation">
19
+ <h2><?php _e( 'Yithemes Licence Activation', 'yit' ) ?></h2>
20
+
21
+ <div class="licence-check-section">
22
+ <form method="post" id="licence-check-update" action="<?php echo admin_url( 'admin-ajax.php' ) ?>">
23
+ <span class="licence-label" style="display: block;"><?php _e( 'Have you updated your licenses? Have you asked for an extension? Update information concerning your products.', 'yit' ); ?></span>
24
+ <input type="hidden" name="action" value="update_licence_information-<?php echo $this->_product_type ?>" />
25
+ <input type="submit" name="submit" value="<?php _e( 'Update licence information', 'yit' ) ?>" class="button-licence licence-check" />
26
+ <div class="spinner"></div>
27
+ </form>
28
+ </div>
29
+
30
+ <!-- To Active Products -->
31
+
32
+
33
+ <?php if( ! empty( $to_active_products ) ) : ?>
34
+ <h3 class="to-active">
35
+ <?php _e( 'Products to be activated', 'yit' ) ?>
36
+ <span class="spinner"></span>
37
+ </h3>
38
+ <div class="to-active-wrapper">
39
+ <?php foreach( $to_active_products as $init => $info ) : ?>
40
+ <form class="to-active-form" method="post" id="<?php echo $info['product_id'] ?>" action="<?php echo admin_url( 'admin-ajax.php' ) ?>">
41
+ <table class="to-active-table">
42
+ <tbody>
43
+ <tr class="product-row">
44
+ <td class="product-name">
45
+ <?php echo $info['Name'] ?>
46
+ </td>
47
+ <td>
48
+ <input type="email" name="email" placeholder="Your email on Yithemes.com" value="" class="user-email" />
49
+ </td>
50
+ <td>
51
+ <input type="text" name="licence_key" placeholder="Licence Key" value="" class="licence-key" />
52
+ </td>
53
+ <td class="activate-button">
54
+ <input type="submit" name="submit" value="<?php _e( 'Activate', 'yit' )?>" class="button-licence licence-activation" data-formid="<?php echo $info['product_id'] ?>"/>
55
+ </td>
56
+ </tr>
57
+ <input type="hidden" name="action" value="activate-<?php echo $this->_product_type ?>" />
58
+ <input type="hidden" name="product_init" value="<?php echo $init ?>" />
59
+ </tbody>
60
+ </table>
61
+ <div class="spinner"></div>
62
+ <div class="message-wrapper">
63
+ <span class="message arrow-left"></span>
64
+ </div>
65
+ </form>
66
+ <?php endforeach; ?>
67
+ </div>
68
+ <?php endif; ?>
69
+
70
+ <!-- Activated Products -->
71
+
72
+ <?php if( ! empty( $activated_products ) ) : ?>
73
+ <h3><?php _e( 'Activated', 'yit' ) ?></h3>
74
+ <table class="expired-table">
75
+ <thead>
76
+ <tr>
77
+ <th><?php _e( 'Product Name', 'yit' ) ?></th>
78
+ <th><?php _e( 'Email', 'yit' ) ?></th>
79
+ <th><?php _e( 'Licence Key', 'yit' ) ?></th>
80
+ <th><?php _e( 'Expires', 'yit' ) ?></th>
81
+ <th><?php _e( 'Remaining', 'yit' ) ?></th>
82
+ <th><?php _e( 'Renew', 'yit' ) ?></th>
83
+ </tr>
84
+ </thead>
85
+ <tbody>
86
+ <?php foreach( $activated_products as $init => $info ) : ?>
87
+ <tr>
88
+ <td class="product-name"><?php echo $info['Name'] ?></td>
89
+ <td class="product-licence-email"><?php echo $info['licence']['email'] ?></td>
90
+ <td class="product-licence-key"><?php echo $info['licence']['licence_key'] ?></td>
91
+ <td class="product-licence-expires"><?php echo date("F j, Y", $info['licence']['licence_expires'] ); ?></td>
92
+ <td class="product-licence-remaining">
93
+ <?php printf( __( '%1s out of %2s', 'yit' ), $info['licence']['activation_remaining'], $info['licence']['activation_limit'] ); ?>
94
+ </td>
95
+ <td><a class="button-licence licence-renew" href="<?php echo $this->get_renewing_uri( $info['licence']['licence_key'] ) ?>" target="_blank"><?php _e( 'Renew', 'yit' ) ?></a></td>
96
+ </tr>
97
+ <?php endforeach; ?>
98
+ </tbody>
99
+ </table>
100
+ <?php endif;?>
101
+
102
+ <!-- Banned Products -->
103
+
104
+ <?php if( ! empty( $banned_products ) ) : ?>
105
+ <h3><?php _e( 'Banned', 'yit' ) ?></h3>
106
+ <table class="expired-table">
107
+ <thead>
108
+ <tr>
109
+ <th><?php _e( 'Product Name', 'yit' ) ?></th>
110
+ <th><?php _e( 'Email', 'yit' ) ?></th>
111
+ <th><?php _e( 'Licence Key', 'yit' ) ?></th>
112
+ </tr>
113
+ </thead>
114
+ <tbody>
115
+ <?php foreach( $banned_products as $init => $info ) : ?>
116
+ <tr>
117
+ <td class="product-name"><?php echo $info['Name'] ?></td>
118
+ <td class="product-licence-email"><?php echo $info['licence']['email'] ?></td>
119
+ <td class="product-licence-key"><?php echo $info['licence']['licence_key'] ?></td>
120
+ </tr>
121
+ <?php endforeach; ?>
122
+ </tbody>
123
+ </table>
124
+ <?php endif;?>
125
+
126
+ <!-- Expired Products -->
127
+
128
+ <?php if( ! empty( $expired_products ) ) : ?>
129
+ <h3><?php _e( 'Expired', 'yit' ) ?></h3>
130
+ <table class="expired-table">
131
+ <thead>
132
+ <tr>
133
+ <th><?php _e( 'Product Name', 'yit' ) ?></th>
134
+ <th><?php _e( 'Email', 'yit' ) ?></th>
135
+ <th><?php _e( 'Licence Key', 'yit' ) ?></th>
136
+ <th><?php _e( 'Expires', 'yit' ) ?></th>
137
+ <th><?php _e( 'Renew', 'yit' ) ?></th>
138
+ </tr>
139
+ </thead>
140
+ <tbody>
141
+ <?php foreach( $expired_products as $init => $info ) : ?>
142
+ <tr>
143
+ <td class="product-name"><?php echo $info['Name'] ?></td>
144
+ <td class="product-licence-email"><?php echo $info['licence']['email'] ?></td>
145
+ <td class="product-licence-key"><?php echo $info['licence']['licence_key'] ?></td>
146
+ <td class="product-licence-expires"><?php echo date("F j, Y", $info['licence']['licence_expires'] ); ?></td>
147
+ <td><a class="button-licence licence-renew" href="<?php echo $this->get_renewing_uri( $info['licence']['licence_key'] ) ?>" target="_blank"><?php _e( 'Renew', 'yit' ) ?></a></td>
148
+ </tr>
149
+ <?php endforeach; ?>
150
+ </tbody>
151
+ </table>
152
+ <?php endif;?>
153
+ </div>
plugin-fw/templates/metaboxes/tab.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ global $post;
16
+
17
+ do_action( 'yit_before_metaboxes_tab' ) ?>
18
+ <div class="metaboxes-tab">
19
+ <?php do_action( 'yit_before_metaboxes_labels' ) ?>
20
+ <ul class="metaboxes-tabs clearfix"<?php if ( count( $tabs ) <= 1 ) : ?> style="display:none;"<?php endif; ?>>
21
+ <?php
22
+ $i = 0;
23
+ foreach ( $tabs as $tab ) :
24
+ if ( ! isset( $tab['fields'] ) || empty( $tab['fields'] ) ) {
25
+ continue;
26
+ }
27
+ ?>
28
+ <li<?php if ( ! $i ) : ?> class="tabs"<?php endif ?>>
29
+ <a href="#<?php echo urldecode( sanitize_title( $tab['label'] ) ) ?>"><?php echo $tab['label'] ?></a></li><?php
30
+ $i ++;
31
+ endforeach;
32
+ ?>
33
+ </ul>
34
+ <?php do_action( 'yit_after_metaboxes_labels' ) ?>
35
+ <?php if( isset( $tab['label'] ) ) : ?>
36
+ <?php do_action( 'yit_before_metabox_option_' . urldecode( sanitize_title( $tab['label'] ) ) ); ?>
37
+ <?php endif ?>
38
+
39
+ <?php
40
+ // Use nonce for verification
41
+ wp_nonce_field( 'metaboxes-fields-nonce', 'yit_metaboxes_nonce' );
42
+ ?>
43
+ <?php foreach ( $tabs as $tab ) :
44
+
45
+ ?>
46
+ <div class="tabs-panel" id="<?php echo urldecode( sanitize_title( $tab['label'] ) ) ?>">
47
+ <?php
48
+ if ( ! isset( $tab['fields'] ) ) {
49
+ continue;
50
+ }
51
+
52
+ $tab['fields'] = apply_filters( 'yit_metabox_' . sanitize_title( $tab['label'] ) . '_tab_fields', $tab['fields'] );
53
+
54
+ foreach ( $tab['fields'] as $id_tab=>$field ) :
55
+ $value = yit_get_post_meta( $post->ID, $field['id'] );
56
+ $field['value'] = $value != '' ? $value : ( isset( $field['std'] ) ? $field['std'] : '' );
57
+ ?>
58
+ <div class="the-metabox <?php echo $field['type'] ?> clearfix<?php if ( empty( $field['label'] ) ) : ?> no-label<?php endif; ?>">
59
+ <?php yit_plugin_get_template( YIT_CORE_PLUGIN_PATH, '/metaboxes/types/' . $field['type'] . '.php', array( 'args' => $field ) ) ?>
60
+ </div>
61
+ <?php endforeach ?>
62
+ </div>
63
+ <?php endforeach ?>
64
+ </div>
plugin-fw/templates/metaboxes/types/ajax-products.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+ wp_enqueue_script( 'woocommerce_admin' );
15
+ extract( $args );
16
+ $is_multiple = isset( $multiple ) && $multiple;
17
+ $multiple = ( $is_multiple ) ? ' multiple' : '';
18
+ ?>
19
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
20
+
21
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
22
+
23
+ <select id="<?php echo $id ?>" name="<?php echo $name ?><?php if( $is_multiple ) echo "[]" ?>" class="ajax_chosen_select_products" multiple="multiple" data-placeholder="<?php _e('Search for a product','yit') ?>">
24
+ <?php
25
+ if ( $value ) {
26
+ foreach ( $value as $product_id ) {
27
+ $product = wc_get_product( $product_id );
28
+ if ( $product ) {
29
+ echo '<option value="' . esc_attr( $product_id ) . '" selected="selected">' . esc_html( $product->get_formatted_name() ) . '</option>';
30
+ }
31
+ }
32
+ }
33
+ ?>
34
+ </select>
35
+
36
+ <span class="desc inline"><?php echo $desc ?></span>
37
+ </div>
38
+ <script>
39
+
40
+ (function ($) {
41
+
42
+ // Ajax Chosen Product Selectors
43
+
44
+ $("select.ajax_chosen_select_products").ajaxChosen({
45
+ method: 'GET',
46
+ url: '<?php echo admin_url('admin-ajax.php') ?>',
47
+ dataType: 'json',
48
+ afterTypeDelay: 100,
49
+ data: {
50
+ action: 'woocommerce_json_search_products',
51
+ security: '<?php echo wp_create_nonce("search-products") ?>'
52
+ }
53
+ }, function (data) {
54
+ var terms = {};
55
+
56
+ $.each(data, function (i, val) {
57
+ terms[i] = val;
58
+ });
59
+
60
+ return terms;
61
+ });
62
+
63
+ })(jQuery);
64
+ </script>
plugin-fw/templates/metaboxes/types/categories.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ global $post;
16
+
17
+ extract( $args );
18
+
19
+ if ( empty( $value ) || ! is_array( $value ) )
20
+ $value = array();
21
+
22
+ $categories = yit_get_model('cpt_unlimited')->get_setting( 'categories', $post->ID );
23
+ ?>
24
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
25
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
26
+ <div class="categories-panel">
27
+ <div class="box">
28
+ <ul id="<?php echo $id ?>-category-list" class="category-list">
29
+ <?php if ( ! empty( $categories ) ) : ?>
30
+ <?php foreach ( $categories as $cat_slug => $cat_name ) : ?>
31
+ <li>
32
+ <label class="selectit"><input type="checkbox" name="<?php echo $name ?>[]" value="<?php echo esc_attr( $cat_slug ) ?>"<?php checked( in_array( $cat_slug, $value ) ) ?> /> <?php echo $cat_name ?> <a class="remove_cat" href="#">X</a></label>
33
+ </li>
34
+ <?php endforeach; ?>
35
+ <?php else : ?>
36
+ <li class="remove-after-add"><i><?php _e( 'No categories.', 'yit' ); ?></i></li>
37
+ <?php endif; ?>
38
+ </ul>
39
+ </div>
40
+ <div class="wp-hidden-children">
41
+ <h4>
42
+ <a tabindex="3" class="hide-if-no-js" href="#category-add" id="<?php echo $id ?>-category-add"><?php _e( '+ Add New Category', 'yit' ); ?></a>
43
+ </h4>
44
+ <p class="category-add-field" id="<?php echo $id ?>-category-field">
45
+ <input type="text" class="newcategory" name="newcategory" style="width:100%;" id="<?php echo $id ?>-new-category" />
46
+ <input type="button" value="<?php esc_attr_e( 'Add' ); ?>" class="add:categorychecklist:category-add button category-add-submit" id="<?php echo $id ?>-category-add-submit" />
47
+ </p>
48
+ </div>
49
+ </div>
50
+ <span class="desc inline"><?php echo $desc ?></span>
51
+ </div>
52
+ <script type="text/javascript">
53
+ jQuery(document).ready(function($){
54
+ $('#<?php echo $id ?>-category-field').hide();
55
+ $(document).on('click', '#<?php echo $id ?>-category-add', function(){
56
+ $('#<?php echo $id ?>-category-field').toggle();
57
+ return false;
58
+ });
59
+
60
+ $(document).on('click', '#<?php echo $id ?>-category-add-submit', function(){
61
+ var t = $(this);
62
+ var new_category = $('#<?php echo $id ?>-new-category').val();
63
+
64
+ var data = {
65
+ action: 'add_category_post_type',
66
+ post_id: <?php echo $post->ID; ?>,
67
+ new_category: new_category
68
+ };
69
+
70
+ $.post(ajaxurl, data, function(response) {
71
+ t.prev().val('');
72
+ var new_cat = response;
73
+
74
+ $('.remove-after-add').hide();
75
+ $('.category-list').each(function(){
76
+ var this_post_id = $(this).attr('id');
77
+ var name = '<?php echo $name ?>';
78
+ this_post_id = this_post_id.match( /([0-9]+)/gi );
79
+ name = name.replace( /[0-9]+/g, this_post_id[0] );
80
+ $(this).prepend('<li><label class="selectit"><input type="checkbox" name="'+name+'[]" value="'+new_cat.slug+'" /> '+new_cat.name+' <a class="remove_cat" href="#">X</a></label></li>');
81
+ $('#<?php echo $id ?>-category-list li:first-child .selectit input').attr('checked', true);
82
+ });
83
+ }, 'json');
84
+
85
+ });
86
+
87
+ });
88
+ </script>
plugin-fw/templates/metaboxes/types/checkbox.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+
15
+ extract( $args );
16
+ ?>
17
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
18
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
19
+ <p>
20
+ <input type="checkbox" id="<?php echo $id ?>" name="<?php echo $name ?>" value="1" <?php if( isset( $std ) ) : ?>data-std="<?php echo $std ?>" <?php endif; checked( $value, 1 ) ?> />
21
+ <span class="desc inline"><?php echo $desc ?></span>
22
+ </p>
23
+ </div>
plugin-fw/templates/metaboxes/types/chosen.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ $is_multiple = isset( $multiple ) && $multiple;
17
+ $multiple = ( $is_multiple ) ? ' multiple' : '';
18
+ ?>
19
+ <div id="<?php echo $id ?>-container" class="chosen" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
20
+
21
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
22
+
23
+ <div class="select_wrapper">
24
+ <select<?php echo $multiple ?> id="<?php echo $id ?>" class="chosen" name="<?php echo $name ?><?php if( $is_multiple ) echo "[]" ?>" <?php if ( isset( $std ) ) : ?>data-std="<?php echo ( $is_multiple )? implode(' ,', $std) : $std ?>"<?php endif ?>>
25
+ <?php foreach ( $options as $key => $item ) : ?>
26
+ <option value="<?php echo esc_attr( $key ) ?>" <?php if( $is_multiple ): selected( true, in_array( $key, $value ) ); else: selected( $key, $value ); endif; ?> ><?php echo $item ?></option>
27
+ <?php endforeach; ?>
28
+ </select>
29
+ </div>
30
+
31
+ <span class="desc inline"><?php echo $desc ?></span>
32
+ </div>
plugin-fw/templates/metaboxes/types/colorpicker.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ ?>
17
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
18
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
19
+
20
+ <input type="text" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo esc_attr( $value ) ?>" <?php if( isset( $std ) ) : ?>data-default-color="<?php echo $std ?>"<?php endif ?> class="panel-colorpicker"/>
21
+ <span class="desc inline"><?php echo $desc ?></span>
22
+ </div>
plugin-fw/templates/metaboxes/types/contactform.php ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ extract( $args );
3
+
4
+ $types = array(
5
+ 'text' => __( 'Text Input', 'yit' ),
6
+ 'checkbox' => __( 'Checkbox', 'yit' ),
7
+ 'select' => __( 'Select', 'yit' ),
8
+ 'textarea' => __( 'Textarea', 'yit' ),
9
+ 'radio' => __( 'Radio Input', 'yit' ),
10
+ 'password' => __( 'Password Field', 'yit' ),
11
+ 'file' => __( 'File Upload', 'yit' ),
12
+ );
13
+
14
+ $defaults = array(
15
+ 'order' => 0,
16
+ 'title' => '',
17
+ 'data_name' => '',
18
+ 'type' => 'text',
19
+ 'already_checked' => '',
20
+ 'options' => array(),
21
+ 'option_selected' => '',
22
+ 'error' => '',
23
+ 'required' => '',
24
+ 'is_email' => '',
25
+ 'reply_to' => '',
26
+ 'class' => '',
27
+ 'select-icon' => 'none',
28
+ 'icon' => '',
29
+ 'custom-icon' => ''
30
+ );
31
+
32
+ if ( ! is_array( $value ) ) {
33
+ $value = array();
34
+ }
35
+ foreach ( $value as $i => $v ) {
36
+ $value[$i] = wp_parse_args( $value[$i], $defaults );
37
+ }
38
+
39
+ $index = 1;
40
+
41
+
42
+ /* Select Font Awesome */
43
+
44
+ $options["select"]=array(
45
+ 'icon' => __( 'Theme Icon', 'yit' ),
46
+ 'custom' => __( 'Custom Icon', 'yit' ),
47
+ 'none' => __( 'None', 'yit' )
48
+ );
49
+
50
+ $options["icon"] = YIT_Plugin_Common::get_awesome_icons();
51
+
52
+ /* End select Font Awesome */
53
+ ?>
54
+
55
+
56
+ <p class="field-row">
57
+ <a href="" class="button-secondary add-items"><?php _e( 'Add field', 'yit' ) ?></a>
58
+ <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-loading" id="add-items-ajax-loading" alt="" />
59
+ </p>
60
+
61
+
62
+ <div class="contactform_items panel" id="panel_form">
63
+ <?php while ( $index <= count( $value ) ): ?>
64
+ <div class="contactform_item closed">
65
+ <h3>
66
+ <button type="button" class="remove_item button" rel=""><?php _e( 'Remove', 'yit' ) ?></button>
67
+ <div class="handlediv" title="<?php _e( 'Click to toggle', 'yit' ) ?>"></div>
68
+ <strong><?php echo $value[$index]['title'] ?> <?php yit_string( '(', $types[$value[$index]['type']], ')' ) ?></strong>
69
+ <input type="hidden" class="contactform_menu_order" name="<?php echo $name ?>[<?php echo $index ?>][order]" value="<?php echo esc_attr( $index ) ?>" />
70
+ </h3>
71
+ <div class="inside">
72
+
73
+ <div class="the-metabox text clearfix">
74
+ <label for="<?php echo $id ?>_title_<?php echo $index ?>"><?php _e( 'Title Field', 'yit' ) ?></label>
75
+
76
+ <p>
77
+ <input type="text" value="<?php echo esc_attr( $value[$index]['title'] ) ?>" id="<?php echo $id ?>_title_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][title]" />
78
+ <span class="desc inline"><?php _e( 'Insert title for the field.', 'yit' ) ?></span>
79
+ </p>
80
+ </div>
81
+
82
+ <div class="the-metabox text clearfix">
83
+ <label for="<?php echo $id ?>_data_name_<?php echo $index ?>"><?php _e( 'Data Name', 'yit' ) ?></label>
84
+
85
+ <p>
86
+ <input type="text" value="<?php echo esc_attr( $value[$index]['data_name'] ) ?>" id="<?php echo $id ?>_data_name_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][data_name]" />
87
+ <span class="desc inline"><?php _e( 'REQUIRED: Field identification name to be entered into email body. <strong>Note:</strong>Use only lowercase characters and underscores.', 'yit' ) ?></span>
88
+ </p>
89
+ </div>
90
+
91
+ <div class="the-metabox select clearfix text-field-type">
92
+ <label for="<?php echo $id ?>_type_<?php echo $index ?>"><?php _e( 'Type field', 'yit' ) ?></label>
93
+
94
+ <p>
95
+ <select id="<?php echo $id ?>_type_<?php echo $index ?>" name="<?php echo $name . '[' . $index . ']' ?>[type]">
96
+ <?php foreach ( $types as $type => $name_type ) : ?>
97
+ <option value="<?php echo esc_attr( $type ) ?>"<?php selected( $type, $value[$index]['type'] ) ?>><?php echo $name_type ?></option>
98
+ <?php endforeach; ?>
99
+ </select>
100
+ <span class="desc inline"><?php _e( 'Select type for this field.', 'yit' ) ?></span>
101
+ </p>
102
+ </div>
103
+
104
+ <div class="the-metabox checkbox clearfix deps_checkbox deps">
105
+ <label for="<?php echo $id ?>_already_checked_<?php echo $index ?>"><?php _e( 'Checked', 'yit' ) ?></label>
106
+
107
+ <p>
108
+ <input type="checkbox" id="<?php echo $id ?>_already_checked_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][already_checked]" value="1"<?php checked( $value[$index]['already_checked'] ) ?> />
109
+ <span class="desc inline"><?php _e( 'Select this if you want this field already checked.', 'yit' ) ?></span>
110
+ </p>
111
+ </div>
112
+
113
+ <div id="<?php echo $id ?>_addoptions" class="the-metabox addoptions clearfix deps_radio deps_select deps">
114
+ <label for=""><?php _e( 'Add options ', 'yit' ) ?></label>
115
+ <a href="#" class="add-field-option button-secondary" data-index="<?php echo $index ?>"><?php _e( 'Add option', 'yit' ) ?></a><br /><br />
116
+ <?php foreach ( $value[$index]['options'] as $key => $option ) : ?>
117
+ <p class="option">
118
+ <label><input type="radio" name="<?php echo $name ?>[<?php echo $index ?>][option_selected]" value="<?php echo esc_attr( $key ) ?>"<?php checked( $value[$index]['option_selected'], $key ) ?> /> <?php _e( 'Selected', 'yit' ) ?>
119
+ </label>
120
+ <input type="text" name="<?php echo $name ?>[<?php echo $index ?>][options][]" value="<?php echo $option ?>" style="width:200px" />
121
+ <a href="#" class="del-field-option button-secondary"><?php _e( 'Delete option', 'yit' ) ?></a>
122
+ </p>
123
+ <?php endforeach; ?>
124
+ </div>
125
+
126
+ <div class="the-metabox text clearfix">
127
+ <label for="<?php echo $id ?>_error_<?php echo $index ?>"><?php _e( 'Message Error', 'yit' ) ?></label>
128
+
129
+ <p>
130
+ <input type="text" value="<?php echo esc_attr( $value[$index]['error'] ) ?>" id="<?php echo $id ?>_error_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][error]" />
131
+ <span class="desc inline"><?php _e( 'Insert the error message for validation.', 'yit' ) ?></span>
132
+ </p>
133
+ </div>
134
+
135
+ <div class="the-metabox checkbox clearfix">
136
+ <label for="<?php echo $id ?>_required_<?php echo $index ?>"><?php _e( 'Required', 'yit' ) ?></label>
137
+
138
+ <p>
139
+ <input type="checkbox" id="<?php echo $id ?>_required_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][required]" value="1"<?php checked( $value[$index]['required'] ) ?> />
140
+ <span class="desc inline"><?php _e( 'Select this if it must be required.', 'yit' ) ?></span>
141
+ </p>
142
+ </div>
143
+
144
+ <div class="the-metabox checkbox clearfix">
145
+ <label for="<?php echo $id ?>_is_email_<?php echo $index ?>"><?php _e( 'Email', 'yit' ) ?></label>
146
+
147
+ <p>
148
+ <input type="checkbox" id="<?php echo $id ?>_is_email_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][is_email]" value="1"<?php checked( $value[$index]['is_email'] ) ?> />
149
+ <span class="desc inline"><?php _e( 'Select this if it must be a valid email.', 'yit' ) ?></span>
150
+ </p>
151
+ </div>
152
+
153
+ <div class="the-metabox checkbox clearfix">
154
+ <label for="<?php echo $id ?>_reply_to_<?php echo $index ?>"><?php _e( 'Reply To', 'yit' ) ?></label>
155
+
156
+ <p>
157
+ <input type="checkbox" id="<?php echo $id ?>_reply_to_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][reply_to]" value="1"<?php checked( $value[$index]['reply_to'] ) ?> />
158
+ <span class="desc inline"><?php _e( 'Select this if it is the email you can reply to.', 'yit' ) ?></span>
159
+ </p>
160
+ </div>
161
+
162
+ <div class="the-metabox text clearfix">
163
+ <label for="<?php echo $id ?>_class_<?php echo $index ?>"><?php _e( 'Class', 'yit' ) ?></label>
164
+
165
+ <p>
166
+ <input type="text" value="<?php echo esc_attr( $value[$index]['class'] ) ?>" id="<?php echo $id ?>_class_<?php echo $index ?>" name="<?php echo $name ?>[<?php echo $index ?>][class]" />
167
+ <span class="desc inline"><?php _e( 'Insert additional class(es) (separated by commas) for more personalization.', 'yit' ) ?></span>
168
+ </p>
169
+ </div>
170
+
171
+ <div class="the-metabox text clearfix">
172
+ <label for="<?php echo $id ?>_icon_<?php echo $index ?>"><?php _e( 'Icon', 'yit' ) ?></label>
173
+
174
+ <p>
175
+
176
+ <div class="option">
177
+
178
+ <div class="icon_type">
179
+ <select name="<?php echo $name ?>[<?php echo $index ?>][select-icon]" id="<?php echo $id ?>_icon_<?php echo $index ?>">
180
+ <?php foreach ( $options['select'] as $val => $option ) { ?>
181
+ <option value="<?php echo esc_attr( $val ) ?>"<?php selected( $value[$index]['select-icon'], $val ) ?>><?php echo $option; ?></option>
182
+ <?php } ?>
183
+ </select>
184
+ </div>
185
+
186
+
187
+
188
+ <div class="awesome_icon" style="font-family: 'FontAwesome'">
189
+ <select style="font-family: 'FontAwesome'" name="<?php echo $name ?>[<?php echo $index ?>][icon]" id="<?php echo $id ?>_icon_<?php echo $index ?>[icon]">
190
+ <?php foreach ( $options['icon'] as $option => $val ) { ?>
191
+ <option value="<?php echo esc_attr( $val ) ?>"<?php selected( $value[$index]['icon'], $val ); ?>>
192
+ <?php echo '&#x' . $option . '; ' . $val; ?>
193
+ </option>
194
+ <?php } ?>
195
+ </select>
196
+ </div>
197
+
198
+ <div class="input_wrapper custom_icon">
199
+ <input type="text" name="<?php echo $name ?>[<?php echo $index ?>][custom]" id="<?php echo $id ?>_icon_<?php echo $index ?>[custom-icon]" value="<?php echo esc_attr( $value[$index]['custom'] ); ?>" class="upload_img_url upload_custom_icon" />
200
+ <input type="button" name="<?php echo $name ?>[<?php echo $index ?>][custom]-button" value="<?php _e( 'Upload', 'yit' ) ?>" id="<?php echo $id ?>_icon_<?php echo $index ?>[custom-icon]-button" class="upload_button button" />
201
+
202
+ <div class="upload_img_preview" style="margin-top:10px;">
203
+ <?php
204
+ $file = $current_options['custom'];
205
+ if ( preg_match( '/(jpg|jpeg|png|gif|ico)$/', $file ) ) {
206
+ echo __('Image preview', 'yit') . ': ' . "<img src=\"" . YIT_CORE_ASSETS_URL . "/images/sleep.png\" data-src=\"$file\" />";
207
+ }
208
+ ?>
209
+ </div>
210
+
211
+ </div>
212
+ </div>
213
+
214
+ <span class="desc inline"><?php _e( 'Insert an icon for more personalization.', 'yit' ) ?></span>
215
+ </p>
216
+ </div>
217
+
218
+ <div class="the-metabox text clearfix">
219
+ <label for="<?php echo $id ?>_width_<?php echo $index ?>"><?php _e( 'Width', 'yit' ) ?></label>
220
+
221
+ <p>
222
+ <select id="<?php echo $id ?>_width_<?php echo $index ?>" name="<?php echo $name . '[' . $index . ']' ?>[width]">
223
+ <?php
224
+ for ( $i = 1; $i < 13; $i ++ ) {
225
+ ?>
226
+ <option value="col-sm-<?php echo $i ?>"
227
+ <?php
228
+ if ( isset( $value[$index]['width'] ) ) {
229
+ selected( 'col-sm-' . $i, $value[$index]['width'] );
230
+ }
231
+ else {
232
+ if ( $value['type'] == 'textarea' ) {
233
+ selected( 'col-sm-' . $i, 'col-sm-9' );
234
+ }
235
+ else {
236
+ selected( 'col-sm-' . $i, 'col-sm-3' );
237
+ }
238
+ }
239
+ ?>><?php echo $i ?></option>
240
+ <?php
241
+ }
242
+ ?>
243
+ </select>
244
+ <span class="desc inline"><?php _e( 'Set field length.', 'yit' ) ?></span>
245
+ </p>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ <?php
250
+ $index ++;
251
+ endwhile;
252
+ ?>
253
+
254
+ </div>
255
+
256
+ <div class="contactform_item closed" id="stamp_form" style="display:none;">
257
+ <h3>
258
+ <button type="button" class="remove_item button" rel=""><?php _e( 'Remove', 'yit' ) ?></button>
259
+ <div class="handlediv" title="<?php _e( 'Click to toggle', 'yit' ) ?>"></div>
260
+ <strong></strong>
261
+ <input disabled type="hidden" class="contactform_menu_order" name="<?php echo $name ?>[][order]" value=""/>
262
+ </h3>
263
+ <div class="inside">
264
+
265
+ <div class="the-metabox text clearfix">
266
+ <label for="<?php echo $id ?>_title"><?php _e( 'Title Field', 'yit' ) ?></label>
267
+
268
+ <p>
269
+ <input disabled type="text" value="" id="<?php echo $id ?>_title" name="<?php echo $name ?>[][title]" />
270
+ <span class="desc inline"><?php _e( 'Insert title for the field.', 'yit' ) ?></span>
271
+ </p>
272
+ </div>
273
+
274
+ <div class="the-metabox text clearfix">
275
+ <label for="<?php echo $id ?>_data_name"><?php _e( 'Data Name', 'yit' ) ?></label>
276
+
277
+ <p>
278
+ <input disabled type="text" value="" id="<?php echo $id ?>_data_name" name="<?php echo $name ?>[][data_name]" />
279
+ <span class="desc inline"><?php _e( 'REQUIRED: Field identification name to be entered into email body. <strong>Note:</strong>Use only lowercase characters and underscores.', 'yit' ) ?></span>
280
+ </p>
281
+ </div>
282
+
283
+ <div class="the-metabox select clearfix text-field-type">
284
+ <label for="<?php echo $id ?>_type"><?php _e( 'Type field', 'yit' ) ?></label>
285
+
286
+ <p>
287
+ <select disabled id="<?php echo $id ?>_type" name="<?php echo $name ?>[][type]">
288
+ <?php foreach ( $types as $type => $name_type ) : ?>
289
+ <option value="<?php echo esc_attr( $type ) ?>"><?php echo $name_type ?></option>
290
+ <?php endforeach; ?>
291
+ </select>
292
+ <span class="desc inline"><?php _e( 'Select type for this field.', 'yit' ) ?></span>
293
+ </p>
294
+ </div>
295
+
296
+ <div class="the-metabox checkbox clearfix deps_checkbox deps">
297
+ <label for="<?php echo $id ?>_already_checked"><?php _e( 'Checked', 'yit' ) ?></label>
298
+
299
+ <p>
300
+ <input disabled type="checkbox" id="<?php echo $id ?>_already_checked" name="<?php echo $name ?>[][already_checked]" value="1" />
301
+ <span class="desc inline"><?php _e( 'Select this if you want this field already checked.', 'yit' ) ?></span>
302
+ </p>
303
+ </div>
304
+
305
+ <div id="<?php echo $id ?>_addoptions" class="the-metabox addoptions clearfix deps_radio deps_select deps">
306
+ <label for=""><?php _e( 'Add options ', 'yit' ) ?></label>
307
+ <a href="#" class="add-field-option button-secondary"><?php _e( 'Add option', 'yit' ) ?></a><br /><br />
308
+
309
+ <p class="option">
310
+ <label><input disabled type="radio" name="<?php echo $name ?>[][option_selected]" value="" /> <?php _e( 'Selected', 'yit' ) ?>
311
+ </label>
312
+ <input disabled type="text" name="<?php echo $name ?>[][options][]" value="" style="width:200px" />
313
+ <a href="#" class="del-field-option button-secondary"><?php _e( 'Delete option', 'yit' ) ?></a>
314
+ </p>
315
+
316
+ </div>
317
+
318
+ <div class="the-metabox text clearfix">
319
+ <label for="<?php echo $id ?>_error"><?php _e( 'Message Error', 'yit' ) ?></label>
320
+
321
+ <p>
322
+ <input disabled type="text" value="" id="<?php echo $id ?>_error" name="<?php echo $name ?>[][error]" />
323
+ <span class="desc inline"><?php _e( 'Insert the error message for validation.', 'yit' ) ?></span>
324
+ </p>
325
+ </div>
326
+
327
+ <div class="the-metabox checkbox clearfix">
328
+ <label for="<?php echo $id ?>_required"><?php _e( 'Required', 'yit' ) ?></label>
329
+
330
+ <p>
331
+ <input disabled type="checkbox" id="<?php echo $id ?>_required" name="<?php echo $name ?>[][required]" value="1" />
332
+ <span class="desc inline"><?php _e( 'Select this if it must be required.', 'yit' ) ?></span>
333
+ </p>
334
+ </div>
335
+
336
+ <div class="the-metabox checkbox clearfix">
337
+ <label for="<?php echo $id ?>_is_email"><?php _e( 'Email', 'yit' ) ?></label>
338
+
339
+ <p>
340
+ <input disabled type="checkbox" id="<?php echo $id ?>_is_email" name="<?php echo $name ?>[][is_email]" value="1" />
341
+ <span class="desc inline"><?php _e( 'Select this if it must be a valid email.', 'yit' ) ?></span>
342
+ </p>
343
+ </div>
344
+
345
+ <div class="the-metabox checkbox clearfix">
346
+ <label for="<?php echo $id ?>_reply_to"><?php _e( 'Reply To', 'yit' ) ?></label>
347
+
348
+ <p>
349
+ <input disabled type="checkbox" id="<?php echo $id ?>_reply_to" name="<?php echo $name ?>[][reply_to]" value="1" />
350
+ <span class="desc inline"><?php _e( 'Select this if it is the email you can reply to.', 'yit' ) ?></span>
351
+ </p>
352
+ </div>
353
+
354
+ <div class="the-metabox text clearfix">
355
+ <label for="<?php echo $id ?>_class"><?php _e( 'Class', 'yit' ) ?></label>
356
+
357
+ <p>
358
+ <input disabled type="text" value="" id="<?php echo $id ?>_class" name="<?php echo $name ?>[][class]" />
359
+ <span class="desc inline"><?php _e( 'Insert additional class(es) (separated by commas) for more personalization.', 'yit' ) ?></span>
360
+ </p>
361
+ </div>
362
+
363
+ <div class="the-metabox text clearfix">
364
+ <label for="<?php echo $id ?>_icon"><?php _e( 'Icon', 'yit' ) ?></label>
365
+
366
+ <div class="option">
367
+
368
+ <div class="icon_type">
369
+ <select disabled name="<?php echo $name ?>[][select-icon]" id="<?php echo $id ?>_icon">
370
+ <?php foreach ( $options['select'] as $val => $option ) { ?>
371
+ <option value="<?php echo esc_attr( $val ) ?>"><?php echo $option; ?></option>
372
+ <?php } ?>
373
+ </select>
374
+ </div>
375
+
376
+ <div class="awesome_icon" style="font-family: 'FontAwesome'">
377
+ <select disabled style="font-family: 'FontAwesome'" name="<?php echo $name ?>[][icon]" id="<?php echo $id ?>_icon[icon]">
378
+ <?php foreach ( $options['icon'] as $option => $val ) { ?>
379
+ <option value="<?php echo esc_attr( $val ) ?>">
380
+ <?php echo '&#x' . $option . '; ' . $val; ?>
381
+ </option>
382
+ <?php } ?>
383
+ </select>
384
+ </div>
385
+
386
+ <div class="input_wrapper custom_icon">
387
+ <input disabled type="text" name="<?php echo $name ?>[][custom]" id="<?php echo $id ?>_icon[custom-icon]" value="" class="upload_img_url upload_custom_icon" />
388
+ <input disabled type="button" name="<?php echo $name ?>[][custom]-button" value="<?php _e( 'Upload', 'yit' ) ?>" id="<?php echo $id ?>_icon[custom-icon]-button" class="upload_button button" />
389
+
390
+ <div class="upload_img_preview" style="margin-top:10px;">
391
+ <?php
392
+ $file = '';
393
+ if ( preg_match( '/(jpg|jpeg|png|gif|ico)$/', $file ) ) {
394
+ echo __('Image preview', 'yit') . ': ' . "<img src=\"" . YIT_CORE_ASSETS_URL . "/images/sleep.png\" data-src=\"$file\" />";
395
+ }
396
+ ?>
397
+ </div>
398
+
399
+ </div>
400
+ </div>
401
+
402
+ <span class="desc inline"><?php _e( 'Insert an icon for more personalization.', 'yit' ) ?></span>
403
+ </div>
404
+
405
+ <div class="the-metabox text clearfix">
406
+ <label for="<?php echo $id ?>_width"><?php _e( 'Width', 'yit' ) ?></label>
407
+
408
+ <p>
409
+ <select disabled id="<?php echo $id ?>_width" name="<?php echo $name?>[][width]">
410
+ <?php
411
+ for ( $i = 1; $i < 13; $i ++ ) {
412
+ ?>
413
+ <option value="col-sm-<?php echo $i ?>"> <?php echo $i ?> </option>
414
+ <?php
415
+ }
416
+ ?>
417
+ </select>
418
+ <span class="desc inline"><?php _e( 'Set field length.', 'yit' ) ?></span>
419
+ </p>
420
+ </div>
421
+ </div>
422
+ </div>
423
+
424
+ <script>
425
+
426
+ var index = <?php echo $index ?>;
427
+
428
+ jQuery(document).ready(function ($) {
429
+
430
+ $(document).on('click', '#<?php echo $id ?>_addoptions .add-field-option', function(){
431
+ var select_index = $(this).data('index');
432
+ var option = "<p class='option'><label><input type='radio' name='<?php echo $name ?>[option_selected]' value='' /> <?php _e( 'Selected', 'yit' ) ?></label><input type='text' name='<?php echo $name ?>[" + select_index + "][options][]' style='width:200px' /> <a href='#' class='del-field-option button-secondary'><?php _e( 'Delete option', 'yit' ) ?></a></p>";
433
+
434
+ $(option).appendTo( $(this).parents('#<?php echo $id ?>_addoptions') );
435
+ return false;
436
+ });
437
+
438
+ //toggle items
439
+ $(document).on('click', '.contactform_item h3, .contactform_item .handlediv', function () {
440
+ var p = $(this).parent('.contactform_item'), id = p.attr('id');
441
+ p.toggleClass('closed');
442
+
443
+ if (!p.hasClass('closed')) {
444
+ p.find('.inside').show();
445
+ } else {
446
+ p.find('.inside').hide();
447
+ }
448
+
449
+ });
450
+
451
+ //add item
452
+ $(".add-items").click(function () {
453
+
454
+
455
+ var a = $("#stamp_form").clone();
456
+ a.appendTo("#panel_form").attr("id", "").show();
457
+
458
+ a.find("input, select").each(function(){
459
+ $(this).prop('disabled', false);
460
+ var str = $(this).attr("name");
461
+
462
+ var nam = str.replace("[]","["+ index +"]");
463
+ $(this).attr("name", nam );
464
+ });
465
+
466
+ index++;
467
+
468
+ $('body').trigger('yit_contact_form_added_item');
469
+
470
+ return false;
471
+ });
472
+
473
+ //remove item
474
+ $(document).on('click', '.remove_item', function () {
475
+ if ($('.remove_item').length > 1) {
476
+ var str = $(this).parents('.contactform_item').find("input:first-child").attr("name").match( /(.*)\[(.*)\](.*)\[(.*)\]/ );
477
+
478
+ var i = parseInt(str[2]);
479
+
480
+ $('.contactform_item:gt('+ --i +')').find("input, select").each(function(){
481
+ var str = $(this).attr("name").match( /(.*)\[(.*)\](.*)\[(.*)\]/ );
482
+ var indice = parseInt(str[2]);
483
+ var nam = $(this).attr('name').replace("[" + indice + "]", "[" + --indice + "]");
484
+ $(this).attr("name", nam );
485
+ });
486
+
487
+ $(this).parents('.contactform_item').remove();
488
+
489
+ index--;
490
+
491
+ $('body').trigger('yit_contact_form_removed_item');
492
+ }
493
+
494
+ return false;
495
+ });
496
+
497
+ //sortable
498
+ $('.contactform_items').sortable({
499
+ items:'.contactform_item',
500
+ cursor:'move',
501
+ axis:'y',
502
+ handle: 'h3',
503
+ scrollSensitivity:60,
504
+ forcePlaceholderSize: true,
505
+ helper: 'clone',
506
+ opacity: 0.65,
507
+ placeholder: 'metabox-sortable-placeholder',
508
+ start:function(event,ui){
509
+ ui.item.css('background-color','#f6f6f6');
510
+ },
511
+ stop:function(event,ui){
512
+ ui.item.removeAttr('style');
513
+
514
+
515
+ variation_row_indexes();
516
+ }
517
+ });
518
+
519
+
520
+ function variation_row_indexes() {
521
+ $('.contactform_items .contactform_item').each(function(index){
522
+ index++;
523
+ $(this).find("input,select").each(function(){
524
+ var str = $(this).attr('name').match( /(.*)\[(.*)\](.*)\[(.*)\]/ );
525
+ var nam = $(this).attr('name').replace("[" +parseInt(str[2])+ "]", "[" +index+ "]");
526
+ $(this).attr('name', nam);
527
+ });
528
+ });
529
+ }
530
+
531
+ //
532
+ var field_type_handler = function(){
533
+ var this_item = $(this);
534
+ $(this_item).on('change', '.text-field-type select', function(){
535
+ var val = $(this).val();
536
+ $('.deps', this_item).hide().filter(function(i){ return $(this).hasClass( 'deps_' + val ); }).show();
537
+ });
538
+ $('.text-field-type select').change();
539
+ };
540
+ $('.contactform_item').each(field_type_handler);
541
+
542
+
543
+ //
544
+ $(document).on('click', '.del-field-option', function(){
545
+ if( $('.option').length > 1 ) {
546
+ $(this).parents('.option').remove();
547
+ }
548
+
549
+ return false;
550
+ });
551
+
552
+ });
553
+ </script>
plugin-fw/templates/metaboxes/types/customtabs.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract($args);
16
+
17
+ $args['labels'] = array(
18
+ 'plural_name' => 'Tabs',
19
+ 'singular_name' => 'Tab',
20
+ 'item_name_sing' => 'Tab',
21
+ 'item_name_plur' => 'Tabs',
22
+ );
23
+
24
+ ?>
25
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
26
+ <div id="yit_custom_tabs" class="panel wc-metaboxes-wrapper" style="display: block;">
27
+ <p class="toolbar">
28
+ <a href="#" class="close_all"><?php _e('Close all', 'yit') ?></a><a href="#" class="expand_all"><?php _e('Expand all', 'yit') ?></a>
29
+ </p>
30
+
31
+ <div class="yit_custom_tabs wc-metaboxes ui-sortable" style="">
32
+
33
+ <?php if( !empty($value) ): ?>
34
+ <?php foreach( $value as $i=>$tab ): ?>
35
+ <div class="yit_custom_tab wc-metabox closed" rel="0">
36
+ <h3>
37
+ <button type="button" class="remove_row button"><?php _e('Remove', 'yit') ?></button>
38
+ <div class="handlediv" title="Click to toggle"></div>
39
+ <strong class="attribute_name"><?php echo $tab['name'] ?></strong>
40
+ </h3>
41
+
42
+ <table cellpadding="0" cellspacing="0" class="woocommerce_attribute_data wc-metabox-content" style="display: table;">
43
+ <tbody>
44
+ <tr>
45
+ <td class="attribute_name">
46
+ <label><?php _e('Name', 'yit') ?>:</label>
47
+ <input type="text" class="attribute_name" name="<?php echo $name ?>[<?php echo $i ?>][name]" value="<?php echo esc_attr( $tab['name'] ) ?>">
48
+ <input type="hidden" name="<?php echo $name ?>[<?php echo $i ?>][position]" class="attribute_position" value="<?php echo $i ?>">
49
+ </td>
50
+
51
+ <td rowspan="3">
52
+ <label><?php _e('Value', 'yit') ?>:</label>
53
+ <textarea name="<?php echo $name ?>[<?php echo $i ?>][value]" cols="5" rows="5" placeholder="<?php _e('Content of the tab. (HTML is supported)','yit') ?>"><?php echo $tab['value'] ?></textarea>
54
+ </td>
55
+ </tr>
56
+ </tbody>
57
+ </table>
58
+
59
+ </div>
60
+ <?php endforeach ?>
61
+ <?php endif ?>
62
+ </div>
63
+
64
+ <p class="toolbar">
65
+ <button type="button" class="button button-primary add_custom_tab"><?php _e( 'Add custom product tab', 'yit' ) ?></button>
66
+ </p>
67
+
68
+ <div class="clear"></div>
69
+ </div>
70
+ </div>
71
+
72
+ <script>
73
+ jQuery(document).ready(function($){
74
+ // Add rows
75
+ $('button.add_custom_tab').on('click', function(){
76
+
77
+ var size = $('.yit_custom_tabs .yit_custom_tab').size() + 1;
78
+
79
+ // Add custom attribute row
80
+ $('.yit_custom_tabs').append('<div class="yit_custom_tab wc-metabox">\
81
+ <h3>\
82
+ <button type="button" class="remove_row button"><?php _e('Remove', 'yit') ?></button>\
83
+ <div class="handlediv" title="Click to toggle"></div>\
84
+ <strong class="attribute_name"></strong>\
85
+ </h3>\
86
+ <table cellpadding="0" cellspacing="0" class="woocommerce_attribute_data">\
87
+ <tbody>\
88
+ <tr>\
89
+ <td class="attribute_name">\
90
+ <label><?php _e('Name', 'yit') ?>:</label>\
91
+ <input type="text" class="attribute_name" name="<?php echo $name ?>[' + size + '][name]" />\
92
+ <input type="hidden" name="<?php echo $name ?>[' + size + '][position]" class="attribute_position" value="' + size + '" />\
93
+ </td>\
94
+ <td rowspan="3">\
95
+ <label><?php _e('Value', 'yit') ?>:</label>\
96
+ <textarea name="<?php echo $name ?>[' + size + '][value]" cols="5" rows="5" placeholder="<?php echo addslashes( __('Content of the tab. (HTML is supported)','yit') ) ?>"></textarea>\
97
+ </td>\
98
+ </tr>\
99
+ </tbody>\
100
+ </table>\
101
+ </div>');
102
+
103
+ });
104
+
105
+
106
+ $('.yit_custom_tabs').on('click', 'button.remove_row', function() {
107
+ var answer = confirm("<?php _e('Do you want to remove the custom tab?', 'yit') ?>");
108
+ if (answer){
109
+ var $parent = $(this).parent().parent();
110
+
111
+ $parent.remove();
112
+ attribute_row_indexes();
113
+ }
114
+ return false;
115
+ });
116
+
117
+ // Attribute ordering
118
+ $('.yit_custom_tabs').sortable({
119
+ items:'.yit_custom_tab',
120
+ cursor:'move',
121
+ axis:'y',
122
+ handle: 'h3',
123
+ scrollSensitivity:40,
124
+ forcePlaceholderSize: true,
125
+ helper: 'clone',
126
+ opacity: 0.65,
127
+ placeholder: 'wc-metabox-sortable-placeholder',
128
+ start:function(event,ui){
129
+ ui.item.css('background-color','#f6f6f6');
130
+ },
131
+ stop:function(event,ui){
132
+ ui.item.removeAttr('style');
133
+ attribute_row_indexes();
134
+ }
135
+ });
136
+
137
+ function attribute_row_indexes() {
138
+ $('.yit_custom_tabs .yit_custom_tab').each(function(index, el){
139
+ var newVal = '[' + $(el).index('.yit_custom_tabs .yit_custom_tab') + ']';
140
+ var oldVal = '[' + $('.attribute_position', el).val() + ']';
141
+
142
+ $(':input:not(button)', el).each(function(){
143
+ var name = $(this).attr('name');
144
+ $(this).attr('name', name.replace(oldVal, newVal));
145
+ });
146
+
147
+ $('.attribute_position', el).val( $(el).index('.yit_custom_tabs .yit_custom_tab') );
148
+ });
149
+ };
150
+
151
+ });
152
+ </script>
plugin-fw/templates/metaboxes/types/datepicker.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ ?>
17
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
18
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
19
+ <input type="text" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo esc_attr( $value ) ?>" class="panel-datepicker"/>
20
+ <span class="desc inline"><?php echo $desc ?></span>
21
+ </div>
plugin-fw/templates/metaboxes/types/hidden.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ extract( $args );
17
+ ?>
18
+ <input type="hidden" id="<?php echo $id ?>" name="<?php echo $name ?>" value="<?php echo esc_attr( $val ) ?>" <?php if( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?> />
plugin-fw/templates/metaboxes/types/icon-list.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Awesome Icon Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.com>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ extract( $args );
20
+
21
+
22
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
23
+
24
+ $current_options = wp_parse_args( $args['value'], $args['std'] );
25
+ $current_icon = YIT_Icon()->get_icon_data( $current_options['icon'] );
26
+ $current_icon = YIT_Icon()->get_icon_data( $std['icon'] );
27
+
28
+ $options['icon'] = YIT_Plugin_Common::get_icon_list();
29
+
30
+ ?>
31
+
32
+
33
+
34
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>class="select_icon rm_option rm_input rm_text">
35
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
36
+
37
+ <div class="option">
38
+ <div class="select_wrapper icon_list_type clearfix">
39
+ <select name="<?php echo $name ?>[select]" id="<?php echo $id ?>[select]" <?php if ( isset( $std['select'] ) ) : ?>data-std="<?php echo $std['select']; ?>"<?php endif; ?>>
40
+ <?php foreach ( $options['select'] as $val => $option ) : ?>
41
+ <option value="<?php echo $val ?>" <?php selected( $current_options['select'], $val ); ?> ><?php echo $option ?></option>
42
+ <?php endforeach; ?>
43
+ </select>
44
+ </div>
45
+
46
+
47
+ <div class="icon-manager-wrapper">
48
+ <div class="icon-manager-text">
49
+ <div class="icon-preview" <?php echo $current_icon ?>></div>
50
+ <input type="text" id="<?php echo $id ?>[icon]" class="icon-text" name="<?php echo $name ?>[icon]" value="<?php echo $current_options['icon']; ?>" />
51
+ </div>
52
+
53
+
54
+ <div class="icon-manager">
55
+ <ul class="icon-list-wrapper">
56
+ <?php foreach ( $options['icon'] as $font => $icons ):
57
+ foreach ( $icons as $key => $icon ): ?>
58
+ <li data-font="<?php echo $font ?>" data-icon="<?php echo ( strpos( $key , '\\') === 0 ) ? '&#x'.substr( $key , 1 ) : $key ?>" data-key="<?php echo $key ?>" data-name="<?php echo $icon ?>"></li>
59
+ <?php
60
+ endforeach;
61
+ endforeach; ?>
62
+ </ul>
63
+ </div>
64
+ </div>
65
+
66
+
67
+ <div class="input_wrapper custom_icon_wrapper upload" style="clear:both;">
68
+ <input type="text" name="<?php echo $name ?>[custom]" id="<?php echo $id ?>[custom]" value="<?php echo $current_options['custom'] ?>" class="upload_img_url upload_custom_icon" />
69
+ <input type="button" value="<?php _e( 'Upload', 'yit' ) ?>" id="<?php echo $id; ?>-custom-button" class="upload_button button" />
70
+
71
+ <div class="upload_img_preview" style="margin-top:10px;">
72
+ <?php
73
+ $file = $current_options['custom'];
74
+ if ( preg_match( '/(jpg|jpeg|png|gif|ico)$/', $file ) ) {
75
+ echo __('Image preview', 'yit') . ': ' . "<img src=\"" . YIT_CORE_ASSETS_URL . "/images/sleep.png\" data-src=\"$file\" />";
76
+ }
77
+ ?>
78
+ </div>
79
+ </div>
80
+
81
+ </div>
82
+
83
+ <div class="clear"></div>
84
+
85
+
86
+ <div class="description">
87
+ <?php echo $desc ?>
88
+ <?php if( $std['select'] == 'custom' ) : ?>
89
+ <?php printf( __( '(Default: %s <img src="%s"/>)', 'yit' ), $options['select']['custom'], $std['custom'] ) ?>
90
+ <?php else: ?>
91
+ <?php printf( __( '(Default: <i %s></i> )', 'yit' ), $current_icon ) ?>
92
+ <?php endif; ?>
93
+ </div>
94
+
95
+ <div class="clear"></div>
96
+
97
+ </div>
98
+
99
+ <script>
100
+
101
+ jQuery(document).ready( function($){
102
+
103
+ $('.select_wrapper.icon_list_type').on('change', function(){
104
+
105
+ var t = $(this);
106
+ var parents = $('#' + t.parents('div.select_icon').attr('id'));
107
+ var option = $('option:selected', this).val();
108
+ var to_show = option == 'none' ? '' : option == 'icon' ? '.icon-manager-wrapper' : '.custom_icon_wrapper';
109
+
110
+ parents.find('.option > div:not(.icon_list_type)').removeClass('show').addClass('hidden');
111
+ parents.find( to_show ).removeClass( 'hidden' ).addClass( 'show' );
112
+ });
113
+
114
+ $('.select_wrapper.icon_list_type').trigger('change');
115
+
116
+ var $icon_list = $('.select_icon').find('ul.icon-list-wrapper'),
117
+ $preview = $('.icon-preview'),
118
+ $element_list = $icon_list.find('li'),
119
+ $icon_text = $('.icon-text');
120
+
121
+ $element_list.on("click", function () {
122
+ var $t = $(this);
123
+ $element_list.removeClass('active');
124
+ $t.addClass('active');
125
+ $preview.attr('data-font', $t.data('font'));
126
+ $preview.attr('data-icon', $t.data('icon'));
127
+ $preview.attr('data-name', $t.data('name'));
128
+ $preview.attr('data-key', $t.data('key'));
129
+
130
+ $icon_text.val($t.data('font') + ':' + $t.data('name'));
131
+
132
+ });
133
+ });
134
+
135
+ </script>
plugin-fw/templates/metaboxes/types/image-gallery.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( !defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ $array_id = array();
17
+ if ( !empty( $value ) ) {
18
+ $array_id = array_filter( explode( ',', $value ) );
19
+ }
20
+
21
+ ?>
22
+ <div id="<?php echo $id ?>-container" class="image-gallery" <?php if (isset( $deps )): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
23
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
24
+
25
+ <p>
26
+ <span class="desc inline"><?php echo $desc ?></span>
27
+ <ul id="<?php echo $id ?>-extra-images" class="slides-wrapper extra-images ui-sortable clearfix">
28
+ <?php if ( !empty( $array_id ) ) : ?>
29
+ <?php foreach ( $array_id as $image_id ) : ?>
30
+ <li class="image" data-attachment_id = <?php echo esc_attr($image_id) ?>>
31
+ <a href="#">
32
+ <?php yit_image( "id=$image_id&size=admin-post-type-thumbnails" ); ?>
33
+ </a>
34
+ <ul class="actions">
35
+ <li><a href="#" class="delete" title="<?php _e( 'Delete image', 'yit' ); ?>">x</a></li>
36
+ </ul>
37
+ </li>
38
+ <?php endforeach; endif; ?>
39
+ </ul>
40
+ <input type="button" data-choose="<?php _e( 'Add Images to Gallery', 'yit' ); ?>" data-update="<?php _e( 'Add to gallery', 'yit' ); ?>" value="<?php _e( 'Add images', 'yit' ) ?>" data-delete="<?php _e( 'Delete image', 'yit' ); ?>" data-text="<?php _e( 'Delete', 'yit' ); ?>" id="<?php echo $id ?>-button" class="image-gallery-button button" />
41
+ <input type="hidden" class="image_gallery_ids" id="image_gallery_ids" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ); ?>" />
42
+ </p>
43
+ </div>
plugin-fw/templates/metaboxes/types/images.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+ global $post;
15
+
16
+ extract( $args );
17
+
18
+ if ( empty( $value ) || ! is_array( $value ) )
19
+ $value = array();
20
+
21
+ //$categories = yit_get_model('cpt_unlimited')->get_setting( 'categories', $post->ID );
22
+ ?>
23
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
24
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
25
+ <span class="desc inline"><?php echo $desc ?></span>
26
+ <ul id="<?php echo $id ?>-extra-images" class="slides-wrapper extra-images ui-sortable clearfix" style="">
27
+ <?php if ( ! empty( $value ) ) : foreach ( $value as $image_id ) : ?>
28
+ <li>
29
+ <a href="#">
30
+ <?php yit_image( "id=$image_id&size=admin-post-type-thumbnails" );//echo wp_get_attachment_image( $image_id, 'admin-post-type-thumbnails' ); ?>
31
+ <input type="hidden" name="<?php echo $name ?>[]" value="<?php echo esc_attr( $image_id ) ?>" />
32
+ </a>
33
+ <a href="#" title="<?php _e( 'Delete image', 'yit' ) ?>" class="delete">X</a>
34
+ </li>
35
+ <?php endforeach; endif; ?>
36
+ </ul>
37
+ <a href="#" class="button-secondary upload-extra-images" id="<?php echo $id ?>-upload-extra-images"><?php _e( 'Upload new images', 'yit' ) ?></a>
38
+ </div>
39
+ <script type="text/javascript">
40
+ jQuery(document).ready(function($){
41
+ $('#<?php echo $id ?>-upload-extra-images').on( 'click', function(){
42
+ tb_show('', 'media-upload.php?post_id=0&TB_iframe=1&width=700');
43
+
44
+ window.send_to_editor = function(html) {
45
+
46
+ var imgurl = $('a', '<div>' + html + '</div>').attr('href');
47
+ var image_id = $('img', html).attr('class').replace(/(.*?)wp-image-/, '');
48
+
49
+ var data = {
50
+ action: 'generate_preview_image_post_type',
51
+ item_id: image_id
52
+ };
53
+
54
+ $.post(ajaxurl, data, function(response) {
55
+ var thumburl = imgurl.split('.').reverse();
56
+ var baseurl = imgurl.replace( '.' + thumburl[0], '' );
57
+ thumburl = baseurl + '-140x100.' + thumburl[0];
58
+
59
+ $('#<?php echo $id ?>-extra-images.slides-wrapper').append('<li><a href="#"><img src="'+thumburl+'" width="140" height="100" /> <input type="hidden" name="<?php echo $name ?>[]" value="'+image_id+'" /></a><a href="#" title="<?php echo addslashes( __( 'Delete image', 'yit' ) ) ?>" class="delete">X</a></li>');
60
+ });
61
+
62
+ tb_remove();
63
+
64
+ }
65
+
66
+ return false;
67
+ });
68
+
69
+ $('#<?php echo $id ?>-extra-images a.delete').on( 'click', function(){
70
+ if ( confirm( "<?php _e( 'Are you sure you want to remove this image?', 'yit' ) ?>" ) ) {
71
+ $(this).parent().remove();
72
+ }
73
+
74
+ return false;
75
+ });
76
+
77
+ // SORTABLE
78
+ $('#<?php echo $id ?>-extra-images').sortable({
79
+ axis: 'x',
80
+ stop: function(e, ui) {}
81
+ });
82
+
83
+ $('.extra-images a:not(.delete)').click(function(){ return false; });
84
+ });
85
+ </script>
plugin-fw/templates/metaboxes/types/number.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+
17
+ ?>
18
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
19
+ <div class="rm_number">
20
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
21
+ <span class="field">
22
+ <input class="number" type="text" id="<?php echo $id ?>" name="<?php echo $name ?>" <?php echo $min.' '.$max ?> value="<?php echo esc_attr( $value ) ?>" <?php if( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?>" />
23
+ <?php yit_string( '<span class="description">', $desc, '</span>' ); ?>
24
+ </span>
25
+ </div>
26
+ </div>
27
+ <script type="text/javascript" charset="utf-8">
28
+ jQuery(document).ready( function( $ ) {
29
+ $('#<?php echo $id ?>').spinner({
30
+ <?php if( isset( $min )): ?>min: <?php echo $min ?>, <?php endif ?>
31
+ <?php if( isset( $max )): ?>max: <?php echo $max ?>, <?php endif ?>
32
+ showOn: 'always',
33
+ upIconClass: "ui-icon-plus",
34
+ downIconClass: "ui-icon-minus"
35
+ });
36
+ });
37
+ </script>
plugin-fw/templates/metaboxes/types/onoff.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+
17
+ ?>
18
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?> class="rm_onoff onoff_container">
19
+
20
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
21
+ <p>
22
+ <input type="checkbox" id="<?php echo $id ?>" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ) ?>" <?php checked( $value, 'yes' ) ?> class="on_off" <?php if( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?> />
23
+ <span class="onoff">&nbsp;</span>
24
+ <span class="desc inline"><?php echo $desc ?></span>
25
+ </p>
26
+ </div>
27
+
28
+ <script type="text/javascript">
29
+ jQuery( document ).ready( function( $ ) {
30
+ $( '#<?php echo $id ?>-option span' ).click( function() {
31
+ var input = $( this ).prev( 'input' );
32
+ var checked = input.attr( 'checked' );
33
+
34
+ if( checked ) {
35
+ input.attr( 'checked', false ).attr( 'value', 0 ).removeClass('onoffchecked');
36
+ } else {
37
+ input.attr( 'checked', true ).attr( 'value', 1 ).addClass('onoffchecked');
38
+ }
39
+
40
+ input.change();
41
+ } );
42
+ } );
43
+ </script>
plugin-fw/templates/metaboxes/types/responsivesliders.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+ extract( $args );
15
+
16
+ $options = yit_get_responsive_sliders();
17
+ ?>
18
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
19
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
20
+
21
+ <div class="select_wrapper">
22
+ <select id="<?php echo $id ?>" name="<?php echo $name ?>" <?php if ( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?>>
23
+ <option></option>
24
+ <option value="none"><?php _e( 'None', 'yit' ) ?></option>
25
+ <?php foreach ( $options as $key => $item ) : ?>
26
+ <option value="<?php echo esc_attr( $key ) ?>"<?php selected( $key, $value ) ?>><?php echo $item ?></option>
27
+ <?php endforeach; ?>
28
+ </select>
29
+ </div>
30
+ <span class="desc inline"><?php echo $desc ?></span>
31
+ </div>
plugin-fw/templates/metaboxes/types/select-icon.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ extract( $args );
5
+
6
+ $current_options = wp_parse_args( $args['value'], $args['std'] );
7
+
8
+ ?>
9
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?> class="select_icon">
10
+
11
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
12
+
13
+ <div class="option">
14
+
15
+ <div class="select_wrapper icon_type">
16
+ <select id="<?php echo $id ?>[select]" name="<?php echo $name ?>[select]" <?php if ( isset( $std['select'] ) ) : ?>data-std="<?php echo $std['select']; ?>"<?php endif; ?>>
17
+ <?php foreach ( $options['select'] as $val => $option ) : ?>
18
+ <option value="<?php echo $val ?>" <?php selected( $current_options['select'], $val ); ?> ><?php echo $option ?></option>
19
+ <?php endforeach; ?>
20
+ </select>
21
+ </div>
22
+
23
+ <div class="select_wrapper awesome_icon" style="font-family: 'FontAwesome'">
24
+ <select style="font-family: 'FontAwesome'" id="<?php echo $id ?>[icon]" name="<?php echo $name ?>[icon]">
25
+ <?php foreach ( $options['icon'] as $val => $option ) : $esc_icon = ! empty( $val ) ? '&#x' . $val . '; ' : ''; ?>
26
+ <option value="<?php echo $option ?>" <?php selected( $current_options['icon'], $option ); ?> ><?php echo $esc_icon . $option; ?></option>
27
+ <?php endforeach; ?>
28
+ </select>
29
+ </div>
30
+
31
+ <div class="input_wrapper custom_icon">
32
+ <input type="text" name="<?php echo $name ?>[custom]" id="<?php echo $id ?>[custom]" value="<?php echo $current_options['custom'] ?>" class="upload_img_url upload_custom_icon" />
33
+ <input type="button" value="<?php _e( 'Upload', 'yit' ) ?>" id="<?php echo $id; ?>-custom-button" class="upload_button button" />
34
+
35
+ <div class="upload_img_preview" style="margin-top:10px;">
36
+ <?php
37
+ $file = $current_options['custom'];
38
+ if ( preg_match( '/(jpg|jpeg|png|gif|ico)$/', $file ) ) {
39
+ echo __( 'Image preview', 'yit' ) . ': ' . "<img src=\"" . YIT_CORE_ASSETS_URL . "/images/sleep.png\" data-src=\"$file\" />";
40
+ }
41
+ ?>
42
+ </div>
43
+
44
+ </div>
45
+ </div>
46
+
47
+ <div class="clear"></div>
48
+
49
+ <div class="description">
50
+ <?php echo $desc ?>
51
+ </div>
52
+
53
+ </div>
54
+
55
+ <script>
56
+
57
+ jQuery(document).ready( function($){
58
+
59
+ $('.select_wrapper.icon_type').on('change', function(){
60
+ var t = $(this);
61
+ var parents = $('#' + t.parents('div.select_icon').attr('id'));
62
+ var option = $('option:selected', this).val();
63
+ var to_show = option == 'none' ? '' : option == 'icon' ? '.awesome_icon' : '.custom_icon';
64
+
65
+ parents.find('.option > div:not(.icon_type)').addClass('hidden').removeClass( 'show' );
66
+ parents.find( to_show ).removeClass( 'hidden' ).addClass( 'show' );
67
+ });
68
+
69
+ $('.select_wrapper.icon_type').trigger('change');
70
+ });
71
+
72
+ </script>
plugin-fw/templates/metaboxes/types/select-mailchimp.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ $multiple = ( isset( $multiple ) && $multiple ) ? ' multiple' : '';
17
+ ?>
18
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
19
+
20
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
21
+
22
+ <div class="select_wrapper">
23
+ <select<?php echo $multiple ?> id="<?php echo $id ?>" name="<?php echo $name ?>" <?php if ( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?>>
24
+ <?php foreach ( $options as $key => $item ) : ?>
25
+ <option value="<?php echo $key ?>"<?php selected( $key, $value ) ?>><?php echo $item ?></option>
26
+ <?php endforeach; ?>
27
+ </select>
28
+ </div>
29
+ <input type="button" class="button-secondary <?php echo $class?>" value="<?php echo $button_name?>"/>
30
+ <span class="spinner"></span>
31
+ <span class="desc inline"><?php echo $desc ?></span>
32
+ </div>
plugin-fw/templates/metaboxes/types/select.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ $is_multiple = isset( $multiple ) && $multiple;
17
+ $multiple = ( $is_multiple ) ? ' multiple' : '';
18
+ ?>
19
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
20
+
21
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
22
+
23
+ <div class="select_wrapper">
24
+ <select<?php echo $multiple ?> id="<?php echo $id ?>" name="<?php echo $name ?><?php if( $is_multiple ) echo "[]" ?>" <?php if ( isset( $std ) ) : ?>data-std="<?php echo ( $is_multiple )? implode(' ,', $std) : $std ?>"<?php endif ?>>
25
+ <?php foreach ( $options as $key => $item ) : ?>
26
+ <option value="<?php echo esc_attr( $key ) ?>" <?php if( $is_multiple ): selected( true, in_array( $key, $value ) ); else: selected( $key, $value ); endif; ?> ><?php echo $item ?></option>
27
+ <?php endforeach; ?>
28
+ </select>
29
+ </div>
30
+
31
+ <span class="desc inline"><?php echo $desc ?></span>
32
+ </div>
plugin-fw/templates/metaboxes/types/sep.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ // doesn't do nothing, allow to stamp the container of this option with sep class:
17
+ // <div class="the-metabox sep"></div>
18
+ ?>
plugin-fw/templates/metaboxes/types/sidebar-layout.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+
17
+ $layout = ! isset( $value['layout'] ) ? 'sidebar-right' : $value['layout'];
18
+ $sidebar = ! isset( $value['sidebar'] ) ? '' : $value['sidebar'];
19
+ ?>
20
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
21
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
22
+
23
+ <p class="yit-sidebar-layout">
24
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-left' ?>" value="sidebar-left" <?php checked( $layout, 'sidebar-left' ) ?> />
25
+ <img src="<?php echo YIT_CORE_ASSETS_URL ?>/images/sideleft.png" title="<?php _e( 'Left sidebar', 'yit' ) ?>" alt="<?php _e( 'Left sidebar', 'yit' ) ?>" />
26
+
27
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-no' ?>" value="sidebar-no" <?php checked( $layout, 'sidebar-no' ) ?> />
28
+ <img src="<?php echo YIT_CORE_ASSETS_URL ?>/images/noside.png" title="<?php _e( 'No sidebar', 'yit' ) ?>" alt="<?php _e( 'No sideabr', 'yit' ) ?>" />
29
+
30
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-right' ?>" value="sidebar-right" <?php checked( $layout, 'sidebar-right' ) ?> />
31
+ <img src="<?php echo YIT_CORE_ASSETS_URL ?>/images/sideright.png" title="<?php _e( 'Right sidebar', 'yit' ) ?>" alt="<?php _e( 'Right sidebar', 'yit' ) ?>" />
32
+
33
+ <select name="<?php echo $name ?>[sidebar]" id="<?php echo $id ?>-sidebar">
34
+ <option value="-1"><?php _e( 'Choose a sidebar', 'yit' ) ?></option>
35
+ <?php foreach ( yit_registered_sidebars() as $val => $option ) { ?>
36
+ <option value="<?php echo esc_attr( $val ) ?>" <?php selected( $sidebar, $val ) ?>><?php echo $option; ?></option>
37
+ <?php } ?>
38
+ </select>
39
+ <script type="text/javascript">
40
+ jQuery(document).ready(function ($) {
41
+ $('.yit-sidebar-layout img').click(function () {
42
+ $(this).parent().children(':radio').attr('checked', false);
43
+ $(this).prev(':radio').attr('checked', true);
44
+ });
45
+
46
+ if ($('#<?php echo $id . '-no' ?>').attr('checked')) {
47
+ $('#<?php echo $id ?>-sidebar').hide();
48
+ }
49
+
50
+ $('.yit-sidebar-layout :radio').next('img').click(function () {
51
+
52
+ if ($(this).prev(':radio').val() == 'sidebar-no') {
53
+ $('#<?php echo $id ?>-sidebar').fadeOut();
54
+ } else {
55
+ $('#<?php echo $id ?>-sidebar').fadeIn();
56
+ }
57
+ });
58
+ });
59
+ </script>
60
+ </p>
61
+ </div>
plugin-fw/templates/metaboxes/types/sidebarlist.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+
17
+ $options = yit_registered_sidebars();
18
+ ?>
19
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
20
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
21
+ <div class="select_wrapper">
22
+ <select id="<?php echo $id ?>" name="<?php echo $name ?>">
23
+ <?php foreach ( $options as $key => $item ) : ?>
24
+ <option value="<?php echo esc_attr( $key ) ?>"<?php selected( $key, $value ) ?>><?php echo $item ?></option>
25
+ <?php endforeach; ?>
26
+ </select>
27
+ </div>
28
+ <span class="desc inline"><?php echo $desc ?></span>
29
+ </div>
plugin-fw/templates/metaboxes/types/sidebars.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Select Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ extract( $args );
20
+ //
21
+ //$layout = ! isset( $value['layout'] ) ? 'sidebar-right' : $value['layout'];
22
+ //$sidebar1 = ! isset( $value['sidebar1'] ) ? '-1' : $value['sidebar1'];
23
+ //$sidebar2 = ! isset( $value['sidebar2'] ) ? '-1' : $value['sidebar2'];
24
+
25
+
26
+ $layout = ! isset( $value['layout'] ) ? 'sidebar-no' : $value['layout'];
27
+ $sidebar_left = ! isset( $value['sidebar-left'] ) ? '-1' : $value['sidebar-left'];
28
+ $sidebar_right = ! isset( $value['sidebar-right'] ) ? '-1' : $value['sidebar-right'];
29
+
30
+ ?>
31
+ <div class="yit-sidebar-layout">
32
+ <div class="option">
33
+ <label for="_slider_name"><?php echo $label ?></label>
34
+
35
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-left' ?>" value="sidebar-left" <?php checked( $layout, 'sidebar-left' ) ?> />
36
+ <img src="<?php echo YIT_CORE_PLUGIN_URL ?>/assets/images/sidebar-left.png" title="<?php _e( 'Left sidebar', 'yit' ) ?>" alt="<?php _e( 'Left sidebar', 'yit' ) ?>" class="<?php echo $id . '-left' ?>" />
37
+
38
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-right' ?>" value="sidebar-right" <?php checked( $layout, 'sidebar-right' ) ?> />
39
+ <img src="<?php echo YIT_CORE_PLUGIN_URL ?>/assets/images/sidebar-right.png" title="<?php _e( 'Right sidebar', 'yit' ) ?>" alt="<?php _e( 'Right sidebar', 'yit' ) ?>" class="<?php echo $id . '-right' ?>" />
40
+
41
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-double' ?>" value="sidebar-double" <?php checked( $layout, 'sidebar-double' ) ?> />
42
+ <img src="<?php echo YIT_CORE_PLUGIN_URL ?>/assets/images/double-sidebar.png" title="<?php _e( 'No sidebar', 'yit' ) ?>" alt="<?php _e( 'No sidebar', 'yit' ) ?>" class="<?php echo $id . '-double' ?>" />
43
+
44
+ <input type="radio" name="<?php echo $name ?>[layout]" id="<?php echo $id . '-no' ?>" value="sidebar-no" <?php checked( $layout, 'sidebar-no' ) ?> />
45
+ <img src="<?php echo YIT_CORE_PLUGIN_URL ?>/assets/images/no-sidebar.png" title="<?php _e( 'No sidebar', 'yit' ) ?>" alt="<?php _e( 'No sidebar', 'yit' ) ?>" class="<?php echo $id . '-no' ?>" />
46
+ </div>
47
+ <div class="clearfix"></div>
48
+ <div class="option" id="choose-sidebars">
49
+ <div class="side">
50
+ <div class="select-mask" <?php if ( $layout != 'sidebar-double' && $layout != 'sidebar-left' ) { echo 'style="display:none"'; } ?> id="<?php echo $id ?>-sidebar-left-container">
51
+ <label for ="<?php echo $id ?>-sidebar-left"><?php _e('Left Sidebar','yit') ?></label>
52
+ <select name="<?php echo $name ?>[sidebar-left]" id="<?php echo $id ?>-sidebar-left">
53
+ <option value="-1"><?php _e( 'Choose a sidebar', 'yit' ) ?></option>
54
+ <?php foreach ( yit_registered_sidebars() as $val => $option ) { ?>
55
+ <option value="<?php echo esc_attr( $val ) ?>" <?php selected( $sidebar_left, $val ) ?>><?php echo $option; ?></option>
56
+ <?php } ?>
57
+ </select>
58
+ </div>
59
+ </div>
60
+ <div class="side" style="clear: both">
61
+ <div class="select-mask" <?php if ( $layout != 'sidebar-double' && $layout != 'sidebar-right' ) { echo 'style="display:none"'; } ?> id="<?php echo $id ?>-sidebar-right-container">
62
+ <label for ="<?php echo $id ?>-sidebar-right"><?php _e('Right Sidebar','yit') ?></label>
63
+ <select name="<?php echo $name ?>[sidebar-right]" id="<?php echo $id ?>-sidebar-right">
64
+ <option value="-1"><?php _e( 'Choose a sidebar', 'yit' ) ?></option>
65
+ <?php foreach ( yit_registered_sidebars() as $val => $option ) { ?>
66
+ <option value="<?php echo esc_attr( $val ) ?>" <?php selected( $sidebar_right, $val ) ?>><?php echo $option; ?></option>
67
+ <?php } ?>
68
+ </select>
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ </div>
74
+
75
+ <script type="text/javascript">
76
+ (function ($){
77
+
78
+ $(document).on('click', '.yit-sidebar-layout img' , function(e) {
79
+
80
+ $( this ).parent().children( ':radio' ).attr( 'checked', false );
81
+ $( this ).prev( ':radio' ).attr( 'checked', true );
82
+ });
83
+
84
+ $(document).on('click', 'img._sidebars-no' , function(e) {
85
+ $( '#_sidebars-sidebar-left-container, #_sidebars-sidebar-right-container' ).hide();
86
+ });
87
+
88
+ $(document).on('click', 'img._sidebars-left' , function(e) {
89
+ $('#_sidebars-sidebar-right-container' ).hide();
90
+ $('#_sidebars-sidebar-left-container' ).show();
91
+ });
92
+
93
+ $(document).on('click', 'img._sidebars-right' , function(e) {
94
+ $('#_sidebars-sidebar-right-container' ).show();
95
+ $('#_sidebars-sidebar-left-container' ).hide();
96
+ });
97
+
98
+ $(document).on('click', 'img._sidebars-double' , function(e) {
99
+ $( '#_sidebars-sidebar-right-container, #_sidebars-sidebar-left-container' ).show();
100
+ });
101
+
102
+ //
103
+ // $(document).on('click', '.yit-sidebar-layout img' , function() {
104
+ //
105
+ // $( this ).parent().children( ':radio' ).attr( 'checked', false );
106
+ // $( this ).prev( ':radio' ).attr( 'checked', true );
107
+ // });
108
+ //
109
+ // $('img._sidebar-no').click( function() {
110
+ // $( '#_sidebar-sidebar1-container, #_sidebar-sidebar2-container' ).hide();
111
+ // });
112
+ //
113
+ // $( 'img._sidebar-left, img._sidebar-right').click( function() {
114
+ // $('#_sidebar-sidebar2-container' ).hide();
115
+ // $('#_sidebar-sidebar1-container' ).show();
116
+ // });
117
+ //
118
+ // $('img._sidebar-double').click( function() {
119
+ // $( '#_sidebar-sidebar1-container, #_sidebar-sidebar2-container' ).show();
120
+ // });
121
+
122
+
123
+ })(jQuery);
124
+ </script>
plugin-fw/templates/metaboxes/types/simple-text.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ extract( $args );
17
+
18
+ $id = empty( $id ) ? '' : " id=\"$id\"";
19
+ ?>
20
+ <p<?php echo $id ?>><?php echo $desc ?></p>
plugin-fw/templates/metaboxes/types/slider.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ extract( $args );
17
+
18
+ if ( ! isset( $labels ) ) {
19
+ $labels = '';
20
+ }
21
+
22
+ ?>
23
+ <div id="<?php echo $id ?>-container" class="slider_container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
24
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
25
+ <div class="ui-slider">
26
+ <span class="minCaption"><?php echo $min ?></span>
27
+ <span class="maxCaption"><?php echo $max ?></span>
28
+ <span id="<?php echo $id ?>-feedback" class="feedback"><strong><?php echo $value ?></strong></span>
29
+
30
+ <div id="<?php echo $id ?>-div" data-step="<?php echo isset( $step ) ? $step : 1 ?>" data-labels="<?php echo '' ?>" data-min="<?php echo $min ?>" data-max="<?php echo $max ?>" data-val="<?php echo $value; ?>" class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all">
31
+ <input id="<?php echo $id ?>" type="hidden" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ); ?>" />
32
+ </div>
33
+ </div>
34
+ <span class="description"><?php echo $desc ?></span>
35
+ </div>
plugin-fw/templates/metaboxes/types/text-array.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+
17
+ $size = isset( $size ) ? " style=\"width:{$size}px;\"" : '';
18
+ ?>
19
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
20
+ <label for="<?php echo $id ?>"><?php echo $label ?>
21
+ <small><?php echo $desc ?></small>
22
+ </label>
23
+
24
+ <p>
25
+ <?php foreach ( $fields as $field_name => $field_label ) : ?>
26
+ <?php echo $field_label ?>:
27
+ <input type="text" name="<?php echo $name ?>[<?php echo $field_name ?>]" id="<?php echo $id ?>_<?php echo $field_name ?>" value="<?php echo isset( $value[$field_name] ) ? esc_attr( $value[$field_name] ) : '' ?>"<?php echo $size ?> /> &nbsp; &nbsp;
28
+ <?php endforeach ?>
29
+ </p>
30
+ </div>
plugin-fw/templates/metaboxes/types/text.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+ extract( $args );
15
+
16
+ ?>
17
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?> data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
18
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
19
+
20
+ <p>
21
+ <input type="text" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo esc_attr( $value ) ?>" <?php if ( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?> />
22
+ <span class="desc inline"><?php echo $desc ?></span>
23
+ </p>
24
+ </div>
plugin-fw/templates/metaboxes/types/textarea-editor.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ // wp_editor is includes since 3.3 of wordpress
17
+ if ( ! function_exists( 'wp_editor' ) ) {
18
+ include 'textarea.php';
19
+ return;
20
+ }
21
+
22
+ extract( $args );
23
+
24
+ $editor_args = array(
25
+ 'wpautop' => true, // use wpautop?
26
+ 'media_buttons' => true, // show insert/upload button(s)
27
+ 'textarea_name' => $name, // set the textarea name to something different, square brackets [] can be used here
28
+ 'textarea_rows' => 20, // rows="..."
29
+ 'tabindex' => '',
30
+ 'editor_css' => '', // intended for extra styles for both visual and HTML editors buttons, needs to include the <style> tags, can use "scoped".
31
+ 'editor_class' => '', // add extra class(es) to the editor textarea
32
+ 'teeny' => false, // output the minimal editor config used in Press This
33
+ 'dfw' => false, // replace the default fullscreen with DFW (needs specific DOM elements and css)
34
+ 'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array()
35
+ 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
36
+ );
37
+ ?>
38
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?> >
39
+ <?php if ( ! empty( $title ) ) : ?><label for="<?php echo $id ?>"><?php echo $title ?></label><?php endif; ?>
40
+ <div class="editor"><?php wp_editor( $value, $id, $editor_args ); ?></div>
41
+ <p><span class="desc"><?php echo $desc ?></span></p>
42
+ </div>
plugin-fw/templates/metaboxes/types/textarea.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ extract( $args );
17
+ ?>
18
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
19
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
20
+
21
+ <p>
22
+ <textarea id="<?php echo $id ?>" name="<?php echo $name ?>" rows="5" cols="50" <?php if ( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?>><?php echo $value ?></textarea>
23
+ <span class="desc inline"><?php echo $desc ?></span>
24
+ </p>
25
+ </div>
plugin-fw/templates/metaboxes/types/title.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // Exit if accessed directly
13
+
14
+ extract( $args );
15
+ ?>
16
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
17
+ <h3 style="margin: 0 -10px;"><?php echo $desc ?></h3>
18
+ </div>
plugin-fw/templates/metaboxes/types/typography.php ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+
17
+ $defaults = array(
18
+ 'size' => 12,
19
+ 'unit' => 'px',
20
+ 'family' => '',
21
+ 'style' => 'regular',
22
+ 'color' => '#000000'
23
+ );
24
+ $value = wp_parse_args( $value, $defaults );
25
+ ?>
26
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $deps ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?> >
27
+ <div id="<?php echo $id ?>" class="rm_typography rm_option">
28
+ <div class="option">
29
+ <label for="<?php echo $id ?>"><?php echo $label ?>
30
+ <small><?php echo $desc ?></small>
31
+ </label>
32
+
33
+ <?php if ( strpos( $style['properties'], 'font-size' ) !== false ) : ?>
34
+ <!-- Size -->
35
+ <div class="spinner_container">
36
+ <input class="number" type="text" name="<?php echo $name ?>[size]" id="<?php echo $id ?>-size" value="<?php echo esc_attr( $value['size'] ) ?>" />
37
+ </div>
38
+
39
+ <!-- Unit -->
40
+ <div class="select_wrapper font-unit">
41
+ <select name="<?php echo $name ?>[unit]" id="<?php echo $id ?>-unit">
42
+ <option value="px" <?php selected( $value['unit'], 'px' ) ?>><?php _e( 'px', 'yit' ) ?></option>
43
+ <option value="em" <?php selected( $value['unit'], 'em' ) ?>><?php _e( 'em', 'yit' ) ?></option>
44
+ <option value="pt" <?php selected( $value['unit'], 'pt' ) ?>><?php _e( 'pt', 'yit' ) ?></option>
45
+ <option value="rem" <?php selected( $value['unit'], 'rem' ) ?>><?php _e( 'rem', 'yit' ) ?></option>
46
+ </select>
47
+ </div>
48
+ <?php endif; ?>
49
+
50
+ <?php if ( strpos( $style['properties'], 'font-family' ) !== false ) : ?>
51
+ <!-- Family -->
52
+ <div class="select_wrapper font-family">
53
+ <select name="<?php echo $name ?>[family]" id="<?php echo $id ?>-family">
54
+ <?php
55
+ $web_fonts = yit_get_web_fonts();
56
+ $google_fonts = yit_get_google_fonts();
57
+
58
+ if ( ! empty( $web_fonts ) ) {
59
+ echo '<optgroup label="' . __( 'Web fonts', 'yit' ) . '">';
60
+
61
+ foreach ( $web_fonts as $font_name => $rule ) {
62
+ ?>
63
+ <option value='<?php echo esc_attr( $rule ) ?>' <?php selected( stripslashes( $value['family'] ), $rule ) ?>><?php echo $font_name ?></option>
64
+ <?php
65
+ }
66
+
67
+ echo '</optgroup>';
68
+ }
69
+
70
+ if ( ! empty( $google_fonts ) ) {
71
+ echo '<optgroup label="' . __( 'Google fonts', 'yit' ) . '">';
72
+
73
+ foreach ( $google_fonts->items as $font ) {
74
+ // $font_human = trim( stripslashes( end( array_slice( explode( ',', $font ), 0, 1 ) ) ), "'" );
75
+ // $std_human = trim( stripslashes( end( array_slice( explode( ',', $value['family'] ), 0, 1 ) ) ), "'" );
76
+
77
+ //if( isset($font->family) ):
78
+ //Only me and god know what happen on this line...
79
+ ?>
80
+ <option value="<?php echo stripslashes( $font ) ?>" <?php selected( $value['family'], $font ) ?>><?php echo $font ?></option>
81
+ <?php
82
+ //endif;
83
+ }
84
+
85
+ echo '</optgroup>';
86
+ }
87
+ ?>
88
+ </select>
89
+ </div>
90
+ <?php endif; ?>
91
+
92
+ <?php if ( strpos( $style['properties'], 'font-style' ) !== false ) : ?>
93
+ <!-- Style -->
94
+ <div class="select_wrapper font-style">
95
+ <select name="<?php echo $name ?>[style]" id="<?php echo $id ?>-style">
96
+ <option value="regular" <?php selected( $value['style'], 'regular' ) ?>><?php _e( 'Regular', 'yit' ) ?></option>
97
+ <option value="bold" <?php selected( $value['style'], 'bold' ) ?>><?php _e( 'Bold', 'yit' ) ?></option>
98
+ <option value="extra-bold" <?php selected( $std['style'], 'extra-bold' ) ?>><?php _e( 'Extra bold', 'yit' ) ?></option>
99
+ <option value="italic" <?php selected( $value['style'], 'italic' ) ?>><?php _e( 'Italic', 'yit' ) ?></option>
100
+ <option value="bold-italic" <?php selected( $value['style'], 'bold-italic' ) ?>><?php _e( 'Italic bold', 'yit' ) ?></option>
101
+ </select>
102
+ </div>
103
+ <?php endif; ?>
104
+
105
+ <?php if ( strpos( $style['properties'], 'color' ) !== false ) : ?>
106
+ <!-- Color -->
107
+ <div id="<?php echo $id ?>_container" class="colorpicker_container">
108
+ <div style="background-color: <?php echo $value['color'] ?>"></div>
109
+ </div>
110
+ <input type="text" name="<?php echo $name ?>[color]" id="<?php echo $id ?>-color" style="width:150px" value="<?php echo esc_attr( $value['color'] ) ?>" />
111
+ <?php endif; ?>
112
+ </div>
113
+ <div class="clear"></div>
114
+ <div class="font-preview">
115
+ <p>The quick brown fox jumps over the lazy dog</p>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ <script type="text/javascript" charset="utf-8">
120
+ jQuery(document).ready(function ($) {
121
+ var container = $('#<?php echo $id ?>');
122
+ var preview = container.children('.font-preview').children('p');
123
+
124
+ //Set current value, before trigger change event
125
+
126
+ //Color
127
+ preview.css('color', '<?php echo $value['color'] ?>');
128
+ //Font size
129
+ var size = $('#<?php echo $id ?>-size').val();
130
+ var unit = $('#<?php echo $id ?>-unit').val();
131
+
132
+ preview.css('font-size', size + unit);
133
+ preview.css('line-height', ( unit == 'em' || unit == 'rem' ? Number(size) + 0.4 : Number(size) + 4 ) + unit);
134
+ //Font style
135
+ var style = $('#<?php echo $id ?>-style').val();
136
+
137
+ if (style == 'italic') {
138
+ preview.css({ 'font-weight': 'normal', 'font-style': 'italic' });
139
+ } else if (style == 'bold') {
140
+ preview.css({ 'font-weight': 'bold', 'font-style': 'normal' });
141
+ } else if (style == 'extra-bold') {
142
+ preview.css({ 'font-weight': '800', 'font-style': 'normal' });
143
+ } else if (style == 'bold-italic') {
144
+ preview.css({ 'font-weight': 'bold', 'font-style': 'italic' });
145
+ } else {
146
+ preview.css({ 'font-weight': 'normal', 'font-style': 'normal' });
147
+ }
148
+
149
+ //Font Family
150
+ var group = $('#<?php echo $id ?>-family').find('option:selected').parent().attr('label');
151
+
152
+ if ($('#<?php echo $id ?>-family').length > 0) {
153
+ if (group == '<?php _e( 'Web fonts', 'yit' ) ?>') {
154
+ //Web font
155
+ preview.css('font-family', $('#<?php echo $id ?>-family').val());
156
+ } else {
157
+ //Google font
158
+ WebFontConfig = {
159
+ google: { families: [ $('#<?php echo $id ?>-family :selected').text() ] }
160
+ };
161
+ (function () {
162
+ var wf = document.createElement('script');
163
+ wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
164
+ '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
165
+ wf.type = 'text/javascript';
166
+ wf.async = 'true';
167
+
168
+ var s = document.getElementsByTagName('script')[0];
169
+ s.parentNode.insertBefore(wf, s);
170
+ })();
171
+
172
+ var preview_font = $('#<?php echo $id ?>-family').val()
173
+ preview.css('font-family', preview_font.replace(/:(.*)?/g, ''));
174
+ }
175
+ }
176
+
177
+ $('#<?php echo $id ?>-size').spinner({
178
+ <?php if( isset( $min )): ?>min: <?php echo $min ?>, <?php endif ?>
179
+ <?php if( isset( $max )): ?>max: <?php echo $max ?>, <?php endif ?>
180
+ showOn : 'always',
181
+ upIconClass : "ui-icon-plus",
182
+ downIconClass : "ui-icon-minus",
183
+ });
184
+
185
+ $('#<?php echo $id ?>_container').ColorPicker({
186
+ color : '<?php echo $value['color'] ?>',
187
+ onShow : function (colpkr) {
188
+ $(colpkr).fadeIn(500);
189
+ return false;
190
+ },
191
+ onHide : function (colpkr) {
192
+ $(colpkr).fadeOut(500);
193
+ return false;
194
+ },
195
+ onChange: function (hsb, hex, rgb) {
196
+ $('#<?php echo $id ?>_container div').css('backgroundColor', '#' + hex);
197
+ $('#<?php echo $id ?>_container').next('input').attr('value', '#' + hex);
198
+
199
+ //Preview color change
200
+ preview.css('color', '#' + hex);
201
+ }
202
+ });
203
+
204
+ //Font Size Change
205
+ $('#<?php echo $id ?>-size, #<?php echo $id ?>-unit').change(function () {
206
+ var size = $('#<?php echo $id ?>-size').val();
207
+ var unit = $('#<?php echo $id ?>-unit').val();
208
+
209
+ preview.css('font-size', size + unit);
210
+ preview.css('line-height', ( unit == 'em' || unit == 'rem' ? Number(size) + 0.4 : Number(size) + 4 ) + unit);
211
+ });
212
+
213
+ //Font Family Change
214
+ $('#<?php echo $id ?>-family').change(function () {
215
+ var group = $(this).find('option:selected').parent().attr('label');
216
+
217
+ if (group == '<?php _e( 'Web fonts', 'yit' ) ?>') {
218
+ //Web font
219
+ preview.css('font-family', $(this).val());
220
+ } else {
221
+ //Google font
222
+ WebFontConfig = {
223
+ google: { families: [ $(':selected', this).text() ] }
224
+ };
225
+ (function () {
226
+ var wf = document.createElement('script');
227
+ wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
228
+ '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
229
+ wf.type = 'text/javascript';
230
+ wf.async = 'true';
231
+ var s = document.getElementsByTagName('script')[0];
232
+ s.parentNode.insertBefore(wf, s);
233
+ })();
234
+
235
+ var preview_font = $(this).val();
236
+ preview.css('font-family', preview_font.replace(/:(.*)?/g, ''));
237
+ }
238
+ });
239
+
240
+ //Font Style Change
241
+ $('#<?php echo $id ?>-style').change(function () {
242
+ var style = $(this).val();
243
+
244
+ if (style == 'italic') {
245
+ preview.css({ 'font-weight': 'normal', 'font-style': 'italic' });
246
+ } else if (style == 'bold') {
247
+ preview.css({ 'font-weight': 'bold', 'font-style': 'normal' });
248
+ } else if (style == 'bold-italic') {
249
+ preview.css({ 'font-weight': 'bold', 'font-style': 'italic' });
250
+ } else {
251
+ preview.css({ 'font-weight': 'normal', 'font-style': 'normal' });
252
+ }
253
+ });
254
+ });
255
+ </script>
plugin-fw/templates/metaboxes/types/upload.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ extract( $args );
16
+ ?>
17
+ <div id="<?php echo $id ?>-container" <?php if ( isset($deps) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $deps['ids'] ?>" data-value="<?php echo $deps['values'] ?>" <?php endif ?>>
18
+ <label for="<?php echo $id ?>"><?php echo $label ?></label>
19
+ <p>
20
+ <input type="text" id="<?php echo $id ?>" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ) ?>" <?php if( isset( $std ) ) : ?>data-std="<?php echo $std ?>"<?php endif ?> class="upload_img_url"/>
21
+ <input type="button" class="button-secondary upload_button" id="<?php echo $id ?>-button" value="<?php _e( 'Upload', 'yit' ) ?>" />
22
+ <span class="desc inline"><?php echo $desc ?></span>
23
+ </p>
24
+ </div>
plugin-fw/templates/panel/types/chosen.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ $id = $this->get_id_field( $option['id'] );
16
+ $name = $this->get_name_field( $option['id'] );
17
+
18
+ $is_multiple = isset( $option['multiple'] ) && $option['multiple'];
19
+ $multiple = ( $is_multiple ) ? ' multiple' : '';
20
+
21
+ $db_value = ( $is_multiple && ! is_array( $db_value ) ) ? array() : $db_value;
22
+ ?>
23
+ <div id="<?php echo $id ?>-container" class="chosen yit_options rm_option rm_input rm_text" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
24
+ <div class="option">
25
+ <div class="select_wrapper">
26
+ <select name="<?php echo $name ?><?php if( $is_multiple ) echo "[]" ?>" class="chosen" id="<?php echo $id ?>" <?php echo $multiple ?> >
27
+ <?php foreach ( $option['options'] as $key => $value ) : ?>
28
+ <option value="<?php echo esc_attr( $key ) ?>"<?php ($is_multiple) ? selected( true, in_array( $key, $db_value) ) : selected( $key, $db_value ) ?>><?php echo $value ?></option>
29
+ <?php endforeach; ?>
30
+ </select>
31
+ </div>
32
+ </div>
33
+ <span class="description"><?php echo $option['desc'] ?></span>
34
+
35
+ <div class="clear"></div>
36
+ </div>
plugin-fw/templates/panel/types/connected-list.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $id = $this->get_id_field( $option['id'] );
3
+ $name = $this->get_name_field( $option['id'] );
4
+ ?>
5
+
6
+ <div id="<?php echo $id ?>-container" class="yit_options rm_option rm_input rm_text rm_connectedlist" <?php if( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
7
+ <div class="option">
8
+ <?php $yit_option = json_decode( stripslashes( $db_value ), true ); ?>
9
+ <?php $lists = is_array($yit_option) ? $yit_option : $option['lists']; ?>
10
+
11
+ <?php foreach( $lists as $list => $options ): ?>
12
+ <div class="list_container">
13
+ <h4><?php echo $option['heads'][ $list ] ?></h4>
14
+ <ul id="list_<?php echo $list ?>" class="connectedSortable" data-list="<?php echo $list ?>">
15
+ <?php foreach( $options as $value => $label ): ?>
16
+ <li data-option="<?php echo $value ?>" class="ui-state-default"><?php echo $label ?></li>
17
+ <?php endforeach ?>
18
+ </ul>
19
+ </div>
20
+ <?php endforeach ?>
21
+ <input type="hidden" name="<?php echo $name ?>" id="<?php echo $id ?>" value='<?php echo esc_attr( $db_value ) ?>' />
22
+ </div>
23
+ <div class="description">
24
+ <?php echo $option['desc'] ?>
25
+ </div>
26
+ <div class="clear"></div>
27
+ </div>
plugin-fw/templates/panel/types/layout-panel.php ADDED
File without changes
plugin-fw/templates/panel/types/on-off.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * ON-OFF Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+
26
+ ?>
27
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?> class="on_off_container yit_options rm_option rm_input rm_onoff">
28
+ <div class="option">
29
+ <input type="checkbox" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo esc_attr( $db_value ) ?>" <?php checked( $db_value, 'yes' ); ?> class="on_off<?php if ( $db_value == 'yes' ): ?> onoffchecked<?php endif ?>" />
30
+ <span>&nbsp;</span>
31
+ </div>
32
+ <span class="description"><?php echo $option['desc'] ?></span>
33
+ </div>
34
+
plugin-fw/templates/panel/types/select-mailchimp.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Select Mailchimp Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Antonio La Rocca <antonio.larocca@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
20
+ ?>
21
+
22
+ <div id="<?php echo $this->get_id_field( $option['id'] ) ?>-container" class="yit_options rm_option rm_input rm_text" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
23
+ <div class="option">
24
+ <div class="select_wrapper">
25
+ <select name="<?php echo $this->get_name_field( $option['id'] ) ?>" id="<?php echo $this->get_id_field( $option['id'] ) ?>">
26
+ <?php foreach( $option['options'] as $key => $value ) : ?>
27
+ <option value="<?php echo esc_attr( $key ) ?>"<?php selected( $key, $db_value ) ?>><?php echo $value ?></option>
28
+ <?php endforeach; ?>
29
+ </select>
30
+ </div>
31
+ <input type="button" class="button-secondary <?php echo $option['class']?>" value="<?php echo esc_attr( $option['button_name'] ) ?>"/>
32
+ <span class="spinner"></span>
33
+ </div>
34
+ <span class="description"><?php echo $option['desc'] ?></span>
35
+ <div class="clear"></div>
36
+ </div>
plugin-fw/templates/panel/types/select.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Select Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+ $id = $this->get_id_field( $option['id'] );
23
+ $name = $this->get_name_field( $option['id'] );
24
+
25
+ $is_multiple = isset( $option['multiple'] ) && $option['multiple'];
26
+ $multiple = ( $is_multiple ) ? ' multiple' : '';
27
+ ?>
28
+ <div id="<?php echo $id ?>-container" class="yit_options rm_option rm_input rm_text" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
29
+ <div class="option">
30
+ <div class="select_wrapper">
31
+ <select name="<?php echo $name ?><?php if( $is_multiple ) echo "[]" ?>" id="<?php echo $id ?>" <?php echo $multiple ?> >
32
+ <?php foreach ( $option['options'] as $key => $value ) : ?>
33
+ <option value="<?php echo esc_attr( $key ) ?>"<?php ($is_multiple) ? selected( true, in_array( $key, $db_value) ) : selected( $key, $db_value ) ?>><?php echo $value ?></option>
34
+ <?php endforeach; ?>
35
+ </select>
36
+ </div>
37
+ </div>
38
+ <span class="description"><?php echo $option['desc'] ?></span>
39
+
40
+ <div class="clear"></div>
41
+ </div>
plugin-fw/templates/panel/types/slider.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Slider Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+ ?>
26
+ <div id="<?php echo $id ?>-container" class="slider_container yit_options rm_option rm_input slider_control slider" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
27
+ <div class="option">
28
+ <div class="ui-slider">
29
+ <span class="minCaption"><?php echo $option['min'] ?></span>
30
+ <span class="maxCaption"><?php echo $option['max'] ?></span>
31
+ <span id="<?php echo $id ?>-feedback" class="feedback"><strong><?php echo $db_value ?></strong></span>
32
+
33
+ <div id="<?php echo $id ?>-div" data-step="<?php echo isset( $option['step'] ) ? $option['step'] : 1 ?>" data-labels="<?php echo '' ?>" data-min="<?php echo $option['min'] ?>" data-max="<?php echo $option['max'] ?>" data-val="<?php echo $db_value; ?>" class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all">
34
+ <input id="<?php echo $id ?>" type="hidden" name="<?php echo $name ?>" value="<?php echo esc_attr( $db_value ); ?>" />
35
+ </div>
36
+ </div>
37
+ </div>
38
+
39
+ <span class="description"><?php echo $option['desc'] ?></span>
40
+ </div>
plugin-fw/templates/panel/types/text-button.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Text Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Antonio La Rocca <antonio.larocca@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+
26
+ ?>
27
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?> class="yit_options rm_option rm_input rm_text">
28
+ <div class="option">
29
+ <input type="text" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo esc_attr( $db_value ) ?>" />
30
+ <input type="button" class="<?php echo $option['button-class']?> button button-secondary" value="<?php echo esc_attr( $option['button-name'] ) ?>" <?php if ( isset( $option['data'] ) && ! empty( $option['data'] ) ): foreach( $option['data'] as $id => $data ): ?> data-<?php echo $id?>="<?php echo $data?>" <?php endforeach; endif;?> />
31
+ </div>
32
+ <span class="description"><?php echo $option['desc'] ?></span>
33
+
34
+ <div class="clear"></div>
35
+ </div>
36
+
plugin-fw/templates/panel/types/text.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Text Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+
26
+ ?>
27
+ <div id="<?php echo $id ?>-container" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?> class="yit_options rm_option rm_input rm_text">
28
+ <div class="option">
29
+ <input type="text" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo esc_attr( $db_value ) ?>" />
30
+ </div>
31
+ <span class="description"><?php echo $option['desc'] ?></span>
32
+
33
+ <div class="clear"></div>
34
+ </div>
35
+
plugin-fw/templates/panel/types/textarea-codemirror.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Textarea Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Antonio La Rocca <antonio.larocca@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+
26
+ ?>
27
+ <div id="<?php echo $id ?>-container" class="yit_options rm_option rm_input rm_text" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
28
+ <div class="option">
29
+ <textarea name="<?php echo $name ?>" class="codemirror" id="<?php echo $id ?>" rows="8" cols="50"><?php echo $db_value ?></textarea>
30
+ </div>
31
+ <span class="description"><?php echo $option['desc'] ?></span>
32
+
33
+ <div class="clear"></div>
34
+ </div>
35
+
36
+ <?php
37
+ wp_enqueue_script('codemirror');
38
+ wp_enqueue_script('codemirror-javascript');
39
+ wp_enqueue_style('codemirror');
40
+ ?>
plugin-fw/templates/panel/types/textarea.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Textarea Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+
26
+ ?>
27
+ <div id="<?php echo $id ?>-container" class="yit_options rm_option rm_input rm_text" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
28
+ <div class="option">
29
+ <textarea name="<?php echo $name ?>" id="<?php echo $id ?>" rows="8" cols="50"><?php echo $db_value ?></textarea>
30
+ </div>
31
+ <span class="description"><?php echo $option['desc'] ?></span>
32
+
33
+ <div class="clear"></div>
34
+ </div>
35
+
plugin-fw/templates/panel/types/upload.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Upload Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+ $id = $this->get_id_field( $option['id'] );
24
+ $name = $this->get_name_field( $option['id'] );
25
+
26
+ ?>
27
+ <div id="<?php echo $id ?>-container" >
28
+ <div id="<?php echo $id ?>-container" class="yit_options rm_option rm_input rm_text rm_upload" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
29
+ <div class="option">
30
+ <input type="text" name="<?php echo $name ?>" id="<?php echo $id ?>" value="<?php echo $db_value == '1' ? '' : esc_attr( $db_value ) ?>" class="upload_img_url" />
31
+ <input type="button" value="<?php _e( 'Upload', 'yit' ) ?>" id="<?php echo $id ?>-button" class="upload_button button" />
32
+ </div>
33
+ <div class="clear"></div>
34
+ <span class="description"><?php echo $option['desc'] ?></span>
35
+ </div>
36
+ <div class="upload_img_preview" style="margin-top:10px;">
37
+ <?php
38
+ $file = $db_value;
39
+ if ( preg_match( '/(jpg|jpeg|png|gif|ico)$/', $file ) ) {
40
+ echo "<img src=\"" . $this->settings['plugin-url'] . "/plugin-fw/assets/images/sleep.png\" data-src=\"$file\" />";
41
+ }
42
+ ?>
43
+ </div>
44
+ </div>
45
+
plugin-fw/templates/panel/woocommerce/woocommerce-boxinfo.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ /**
16
+ * 'section_general_settings_boxinfo' => array(
17
+ * 'name' => __( 'General information', 'yit' ),
18
+ * 'type' => 'boxinfo',
19
+ * 'default' => array(
20
+ * 'plugin_name' => __( 'Plugin Name', 'yit' ),
21
+ * 'buy_url' => 'http://www.yithemes.com',
22
+ * 'demo_url' => 'http://plugins.yithemes.com/demo-url/'
23
+ * ),
24
+ * 'id' => 'yith_wcas_general_boxinfo'
25
+ * ),
26
+ */
27
+ ?>
28
+ <div id="<?php echo $id ?>" class="meta-box-sortables">
29
+ <div id="<?php echo $id ?>-content-panel" class="postbox " style="display: block;">
30
+ <h3><?php echo $name ?></h3>
31
+ <div class="inside">
32
+ <p>Lorem ipsum ... </p>
33
+ <p class="submit"><a href="<?php echo $default['buy_url'] ?>" class="button-primary">Buy Plugin</a></p>
34
+ </div>
35
+ </div>
36
+ </div>
plugin-fw/templates/panel/woocommerce/woocommerce-form.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="<?php echo $this->settings['page']?>_<?php echo $this->get_current_tab()?>">
2
+ <form id="plugin-fw-wc" method="post">
3
+ <?php $this->add_fields() ?>
4
+ <?php wp_nonce_field( 'yit_panel_wc_options_'.$this->settings['page'], 'yit_panel_wc_options_nonce' ); ?>
5
+ <input style="float: left; margin-right: 10px;" class="button-primary" type="submit" value="<?php _e( 'Save Changes', 'yit' )?>"/>
6
+ </form>
7
+ <form id="plugin-fw-wc-reset" method="post">
8
+ <?php $warning = __( 'If you go on with this action, you will reset all options in this page.', 'yit' ) ?>
9
+ <input type="hidden" name="yit-action" value="wc-options-reset" />
10
+ <input type="submit" name="yit-reset" class="button-secondary" value="<?php _e( 'Reset Defaults', 'yit' ) ?>" onclick="return confirm('<?php echo $warning . '\n' . __( 'Are you sure of it?', 'yit' ) ?>');" />
11
+ </form>
12
+ </div>
plugin-fw/templates/panel/woocommerce/woocommerce-panel.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php add_thickbox();?>
2
+ <div class="wrap">
3
+ <div id="icon-users" class="icon32"><br/></div>
4
+ <?php if( ! empty( $available_tabs ) ): ?>
5
+ <h2 class="nav-tab-wrapper woo-nav-tab-wrapper">
6
+ <?php foreach( $available_tabs as $id => $label ): ?>
7
+ <a href="?page=<?php echo $page ?>&tab=<?php echo $id ?>" class="nav-tab <?php echo ( $current_tab == $id ) ? 'nav-tab-active' : '' ?>"><?php echo $label ?></a>
8
+ <?php endforeach; ?>
9
+ </h2>
10
+ <?php $this->print_panel_content() ?>
11
+ <?php endif; ?>
12
+ </div>
plugin-fw/templates/panel/woocommerce/woocommerce-upload.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ /**
12
+ * Upload Plugin Admin View
13
+ *
14
+ * @package Yithemes
15
+ * @author Emanuela Castorina <emanuela.castorina@yithemes.it>
16
+ * @since 1.0.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ } // Exit if accessed directly
22
+
23
+
24
+ ?>
25
+
26
+ <tr valign="top">
27
+ <th scope="row" class="image_upload">
28
+ <label for="<?php echo $id ?>"><?php echo $name ?></label>
29
+ </th>
30
+ <td class="forminp forminp-color plugin-option">
31
+
32
+ <div id="<?php echo $id ?>-container" class="yit_options rm_option rm_input rm_text rm_upload" <?php if ( isset( $option['deps'] ) ): ?>data-field="<?php echo $id ?>" data-dep="<?php echo $this->get_id_field( $option['deps']['ids'] ) ?>" data-value="<?php echo $option['deps']['values'] ?>" <?php endif ?>>
33
+ <div class="option">
34
+ <input type="text" name="<?php echo $id ?>" id="<?php echo $id ?>" value="<?php echo $value == '1' ? '' : esc_attr( $value ) ?>" class="upload_img_url" />
35
+ <input type="button" value="<?php _e( 'Upload', 'yit' ) ?>" id="<?php echo $id ?>-button" class="upload_button button" />
36
+ </div>
37
+ <div class="clear"></div>
38
+ <span class="description"><?php echo $desc ?></span>
39
+ <div class="upload_img_preview" style="margin-top:10px;">
40
+ <?php
41
+ $file = $value;
42
+ if ( preg_match( '/(jpg|jpeg|png|gif|ico)$/', $file ) ) {
43
+ echo "<img src=\"" . YIT_CORE_PLUGIN_URL. "/assets/images/sleep.png\" data-src=\"$file\" />";
44
+ }
45
+ ?>
46
+ </div>
47
+ </div>
48
+
49
+
50
+ </td>
51
+ </tr>
52
+
plugin-fw/templates/panel/woocommerce/woocommerce-videobox.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ /**
16
+ * Example to call this template
17
+ *
18
+ * 'section_general_settings_videobox' => array(
19
+ * 'name' => __( 'Title of box', 'yit' ),
20
+ * 'type' => 'videobox',
21
+ * 'default' => array(
22
+ * 'plugin_name' => __( 'Plugin Name', 'yit' ),
23
+ * 'title_first_column' => __( 'Title first column', 'yit' ),
24
+ * 'description_first_column' => __('Lorem ipsum ... ', 'yit'),
25
+ * 'video' => array(
26
+ * 'video_id' => 'vimeo_code',
27
+ * 'video_image_url' => '#',
28
+ * 'video_description' => __( 'Lorem ipsum dolor sit amet....', 'yit' ),
29
+ * ),
30
+ * 'title_second_column' => __( 'Title first column', 'yit' ),
31
+ * 'description_second_column' => __('Lorem ipsum dolor sit amet.... ', 'yit'),
32
+ * 'button' => array(
33
+ * 'href' => 'http://www.yithemes.com',
34
+ * 'title' => 'Get Support and Pro Features'
35
+ * )
36
+ * ),
37
+ * 'id' => 'yith_wcas_general_videobox'
38
+ * ),
39
+ */
40
+ ?>
41
+ <div id="normal-sortables" class="meta-box-sortables">
42
+ <div id="<?php echo $id ?>" class="postbox ">
43
+ <h3><span><?php echo $name ?></span></h3>
44
+ <div class="inside">
45
+ <div class="yith_videobox">
46
+ <div class="column"><h2><?php echo $default['title_first_column'] ?></h2>
47
+ <?php if ( isset( $default['video'] ) && !empty( $default['video'] ) ): ?>
48
+ <a class="yith-video-link" href="#" data-video-id="yith-video-iframe">
49
+ <img src="<?php echo $default['video']['video_image_url'] ?>">
50
+ </a>
51
+
52
+ <p class="yit-video-description">
53
+ <?php echo $default['video']['video_description'] ?>
54
+ </p>
55
+
56
+ <p class="yith-video-iframe">
57
+ <iframe src="//player.vimeo.com/video/<?php echo $default['video']['video_id'] ?>?title=0&amp;byline=0&amp;portrait=0" width="853" height="480" frameborder="0"></iframe>
58
+ </p>
59
+ <?php endif ?>
60
+ <?php if ( isset( $default['image'] ) && !empty( $default['image'] ) ): ?>
61
+ <a href="<?php echo $default['image']['image_link'] ?>" target="_blank" class="yith-image-frame">
62
+ <img src="<?php echo $default['image']['image_url'] ?>">
63
+ </a>
64
+ <?php endif ?>
65
+ <?php if ( isset( $default['description_first_column'] ) && $default['description_first_column'] != '' ): ?>
66
+ <p><?php echo $default['description_first_column'] ?></p>
67
+ <?php endif ?>
68
+ </div>
69
+ <div class="column two">
70
+ <h2><?php echo $default['title_second_column'] ?>?</h2>
71
+
72
+ <p><?php echo $default['description_second_column'] ?></p>
73
+
74
+ <?php if ( isset( $default['button'] ) && !empty( $default['button'] ) ): ?>
75
+ <p>
76
+ <a class="button-primary" href="<?php echo $default['button']['href'] ?>" target="_blank"><?php echo $default['button']['title'] ?></a>
77
+ </p>
78
+ <?php endif ?>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </div>
plugin-fw/yit-deactive-plugin.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This file belongs to the YIT Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! function_exists( 'yit_deactive_free_version' ) ) {
12
+ function yit_deactive_free_version( $to_deactive, $to_active ) {
13
+
14
+ if ( ! function_exists( 'is_plugin_active' ) ) {
15
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
16
+ }
17
+
18
+ if ( defined( $to_deactive ) && is_plugin_active( constant( $to_deactive ) ) ) {
19
+ deactivate_plugins( constant( $to_deactive ) );
20
+
21
+ if( ! function_exists( 'wp_create_nonce' ) ){
22
+ header( 'Location: plugins.php');
23
+ exit();
24
+ }
25
+
26
+
27
+ global $status, $page, $s;
28
+ $redirect = 'plugins.php?action=activate&plugin=' . $to_active . '&plugin_status=' . $status . '&paged=' . $page . '&s=' . $s;
29
+ $redirect = add_query_arg( '_wpnonce', wp_create_nonce( 'activate-plugin_' . $to_active ), $redirect );
30
+
31
+ header( 'Location: ' . $redirect );
32
+ exit();
33
+ }
34
+ }
35
+ }
plugin-fw/yit-functions.php ADDED
@@ -0,0 +1,819 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ if ( ! function_exists( 'yit_plugin_locate_template' ) ) {
16
+ /**
17
+ * Locate the templates and return the path of the file found
18
+ *
19
+ * @param string $plugin_basename
20
+ * @param string $path
21
+ * @param array $var
22
+ *
23
+ * @return string
24
+ * @since 2.0.0
25
+ */
26
+ function yit_plugin_locate_template( $plugin_basename, $path, $var = NULL ) {
27
+
28
+ $template_path = '/theme/templates/' . $path;
29
+
30
+ $located = locate_template( array(
31
+ $template_path
32
+ ) );
33
+
34
+ if ( ! $located ) {
35
+ $located = $plugin_basename . '/templates/' . $path;
36
+ }
37
+
38
+ return $located;
39
+ }
40
+
41
+ }
42
+
43
+ if ( ! function_exists( 'yit_plugin_get_template' ) ) {
44
+ /**
45
+ * Retrieve a template file.
46
+ *
47
+ * @param string $plugin_basename
48
+ * @param string $path
49
+ * @param mixed $var
50
+ * @param bool $return
51
+ *
52
+ * @return string
53
+ * @since 2.0.0
54
+ */
55
+ function yit_plugin_get_template( $plugin_basename, $path, $var = null, $return = false ) {
56
+
57
+ $located = yit_plugin_locate_template( $plugin_basename, $path, $var );
58
+
59
+ if ( $var && is_array( $var ) ) {
60
+ extract( $var );
61
+ }
62
+
63
+ if ( $return ) {
64
+ ob_start();
65
+ }
66
+
67
+ // include file located
68
+ include( $located );
69
+
70
+ if ( $return ) {
71
+ return ob_get_clean();
72
+ }
73
+ }
74
+ }
75
+
76
+ if ( ! function_exists( 'yit_plugin_content' ) ) {
77
+ /**
78
+ * Return post content with read more link (if needed)
79
+ *
80
+ * @param string $what
81
+ * @param int|string $limit
82
+ * @param string $more_text
83
+ * @param string $split
84
+ * @param string $in_paragraph
85
+ *
86
+ * @return string
87
+ * @since 2.0.0
88
+ */
89
+ function yit_plugin_content( $what = 'content', $limit = 25, $more_text = '', $split = '[...]', $in_paragraph = 'true' ) {
90
+ if ( $what == 'content' ) {
91
+ $content = get_the_content( $more_text );
92
+ }
93
+ else {
94
+ if ( $what == 'excerpt' ) {
95
+ $content = get_the_excerpt();
96
+ }
97
+ else {
98
+ $content = $what;
99
+ }
100
+ }
101
+
102
+ if ( $limit == 0 ) {
103
+ if ( $what == 'excerpt' ) {
104
+ $content = apply_filters( 'the_excerpt', $content );
105
+ }
106
+ else {
107
+ $content = preg_replace( '/<img[^>]+./', '', $content ); //remove images
108
+ $content = apply_filters( 'the_content', $content );
109
+ $content = str_replace( ']]>', ']]&gt;', $content );
110
+ }
111
+
112
+ return $content;
113
+ }
114
+
115
+ // remove the tag more from the content
116
+ if ( preg_match( "/<(a)[^>]*class\s*=\s*(['\"])more-link\\2[^>]*>(.*?)<\/\\1>/", $content, $matches ) ) {
117
+
118
+ if ( strpos( $matches[0], '[button' ) ) {
119
+ $more_link = str_replace( 'href="#"', 'href="' . get_permalink() . '"', do_shortcode( $matches[3] ) );
120
+ }
121
+ else {
122
+ $more_link = $matches[0];
123
+ }
124
+
125
+ $content = str_replace( $more_link, '', $content );
126
+ $split = '';
127
+ }
128
+
129
+ if ( empty( $content ) ) {
130
+ return;
131
+ }
132
+ $content = explode( ' ', $content );
133
+
134
+ if ( ! empty( $more_text ) && ! isset( $more_link ) ) {
135
+ //array_pop( $content );
136
+ $more_link = strpos( $more_text, '<a class="btn"' ) ? $more_text : '<a class="read-more' . apply_filters( 'yit_simple_read_more_classes', ' ' ) . '" href="' . get_permalink() . '">' . $more_text . '</a>';
137
+ $split = '';
138
+ }
139
+ elseif ( ! isset( $more_link ) ) {
140
+ $more_link = '';
141
+ }
142
+
143
+ // split
144
+ if ( count( $content ) >= $limit ) {
145
+ $split_content = '';
146
+ for ( $i = 0; $i < $limit; $i ++ ) {
147
+ $split_content .= $content[$i] . ' ';
148
+ }
149
+
150
+ $content = $split_content . $split;
151
+ }
152
+ else {
153
+ $content = implode( " ", $content );
154
+ }
155
+
156
+ // TAGS UNCLOSED
157
+ $tags = array();
158
+ // get all tags opened
159
+ preg_match_all( "/(<([\w]+)[^>]*>)/", $content, $tags_opened, PREG_SET_ORDER );
160
+ foreach ( $tags_opened as $tag ) {
161
+ $tags[] = $tag[2];
162
+ }
163
+
164
+ // get all tags closed and remove it from the tags opened.. the rest will be closed at the end of the content
165
+ preg_match_all( "/(<\/([\w]+)[^>]*>)/", $content, $tags_closed, PREG_SET_ORDER );
166
+ foreach ( $tags_closed as $tag ) {
167
+ unset( $tags[array_search( $tag[2], $tags )] );
168
+ }
169
+
170
+ // close the tags
171
+ if ( ! empty( $tags ) ) {
172
+ foreach ( $tags as $tag ) {
173
+ $content .= "</$tag>";
174
+ }
175
+ }
176
+
177
+ //$content = preg_replace( '/\[.+\]/', '', $content );
178
+ if ( $in_paragraph == true ): $content .= $more_link; endif;
179
+ $content = preg_replace( '/<img[^>]+./', '', $content ); //remove images
180
+ $content = apply_filters( 'the_content', $content );
181
+ $content = str_replace( ']]>', ']]&gt;', $content ); // echo str_replace( array( '<', '>' ), array( '&lt;', '&gt;' ), $content );
182
+ if ( $in_paragraph == false ): $content .= $more_link; endif;
183
+
184
+ return $content;
185
+ }
186
+ }
187
+
188
+ if ( ! function_exists( 'yit_plugin_string' ) ) {
189
+ /**
190
+ * Simple echo a string, with a before and after string, only if the main string is not empty.
191
+ *
192
+ * @param string $before What there is before the main string
193
+ * @param string $string The main string. If it is empty or null, the functions return null.
194
+ * @param string $after What there is after the main string
195
+ * @param bool $echo If echo or only return it
196
+ *
197
+ * @return string The complete string, if the main string is not empty or null
198
+ * @since 2.0.0
199
+ */
200
+ function yit_plugin_string( $before = '', $string = '', $after = '', $echo = true ) {
201
+ $html = '';
202
+
203
+ if ( $string != '' AND ! is_null( $string ) ) {
204
+ $html = $before . $string . $after;
205
+ }
206
+
207
+ if ( $echo ) {
208
+ echo $html;
209
+ }
210
+
211
+ return $html;
212
+ }
213
+ }
214
+
215
+ if ( ! function_exists( 'yit_plugin_decode_title' ) ) {
216
+ /**
217
+ * Change some special characters to put easily html into a string
218
+ *
219
+ * E.G.
220
+ * string: This is [my title] with | a new line
221
+ * return: This is <span class="title-highlight">my title</span> with <br /> a new line
222
+ *
223
+ * @param string $title The string to convert
224
+ *
225
+ * @return string The html
226
+ *
227
+ * @since 1.0
228
+ */
229
+ function yit_plugin_decode_title( $title ) {
230
+ $replaces = apply_filters( 'yit_title_special_characters', array() );
231
+
232
+ return preg_replace( array_keys( $replaces ), array_values( $replaces ), $title );
233
+ }
234
+ }
235
+
236
+ if ( ! function_exists( 'yit_plugin_get_attachment_id' ) ) {
237
+
238
+ /**
239
+ * Return the ID of an attachment.
240
+ *
241
+ * @param string $url
242
+ *
243
+ * @return int
244
+ *
245
+ * @since 2.0.0
246
+ */
247
+
248
+ function yit_plugin_get_attachment_id( $url ) {
249
+
250
+ $upload_dir = wp_upload_dir();
251
+ $dir = trailingslashit( $upload_dir['baseurl'] );
252
+
253
+ if ( false === strpos( $url, $dir ) ) {
254
+ return false;
255
+ }
256
+
257
+ $file = basename( $url );
258
+
259
+ $query = array(
260
+ 'post_type' => 'attachment',
261
+ 'fields' => 'ids',
262
+ 'meta_query' => array(
263
+ array(
264
+ 'value' => $file,
265
+ 'compare' => 'LIKE',
266
+ )
267
+ )
268
+ );
269
+
270
+ $query['meta_query'][0]['key'] = '_wp_attached_file';
271
+ $ids = get_posts( $query );
272
+
273
+ foreach ( $ids as $id ) {
274
+ $attachment_image = wp_get_attachment_image_src( $id, 'full' );
275
+ if ( $url == str_replace( 'https://', 'http://', array_shift( $attachment_image ) ) ) {
276
+ return $id;
277
+ }
278
+ }
279
+ $query['meta_query'][0]['key'] = '_wp_attachment_metadata';
280
+ $ids = get_posts( $query );
281
+
282
+ foreach ( $ids as $id ) {
283
+
284
+ $meta = wp_get_attachment_metadata( $id );
285
+ if ( ! isset( $meta['sizes'] ) ) {
286
+ continue;
287
+ }
288
+
289
+ foreach ( (array) $meta['sizes'] as $size => $values ) {
290
+ if ( $values['file'] == $file && $url == str_replace( 'https://', 'http://', array_shift( wp_get_attachment_image_src( $id, $size ) ) ) ) {
291
+
292
+ return $id;
293
+ }
294
+ }
295
+ }
296
+
297
+ return false;
298
+ }
299
+ }
300
+
301
+ if ( ! function_exists( 'yit_enqueue_script' ) ) {
302
+ /**
303
+ * Enqueues script.
304
+ *
305
+ * Registers the script if src provided (does NOT overwrite) and enqueues.
306
+ *
307
+ * @since 2.0.0
308
+ * @author Simone D'Amico <simone.damico@yithemes.com>
309
+ * @see yit_register_script() For parameter information.
310
+ */
311
+ function yit_enqueue_script( $handle, $src, $deps = array(), $ver = false, $in_footer = true ) {
312
+
313
+ if ( function_exists( 'YIT_Asset' ) && ! is_admin() ) {
314
+ $enqueue = true;
315
+ YIT_Asset()->set( 'script', $handle, compact( 'src', 'deps', 'ver', 'in_footer', 'enqueue' ) );
316
+ }
317
+ else {
318
+ wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
319
+ }
320
+ }
321
+ }
322
+
323
+ if ( ! function_exists( 'yit_enqueue_style' ) ) {
324
+ /**
325
+ * Enqueues style.
326
+ *
327
+ * Registers the style if src provided (does NOT overwrite) and enqueues.
328
+ *
329
+ * @since 2.0.0
330
+ * @author Simone D'Amico <simone.damico@yithemes.com>
331
+ * @see yit_register_style() For parameter information.
332
+ */
333
+ function yit_enqueue_style( $handle, $src, $deps = array(), $ver = false, $media = 'all' ) {
334
+
335
+ if ( function_exists( 'YIT_Asset' ) ) {
336
+ $enqueue = true;
337
+ $who = YIT_Asset()->get_stylesheet_handle( get_stylesheet_uri(), 'style' );
338
+ $where = 'before';
339
+
340
+ if( false == $who ){
341
+ $who = '';
342
+ }
343
+
344
+ YIT_Asset()->set( 'style', $handle, compact( 'src', 'deps', 'ver', 'media', 'enqueue' ), $where, $who );
345
+ }
346
+ else {
347
+ wp_enqueue_style( $handle, $src, $deps, $ver, $media );
348
+ }
349
+ }
350
+ }
351
+
352
+ if ( ! function_exists( 'yit_get_post_meta' ) ) {
353
+ /**
354
+ * Retrieve the value of a metabox.
355
+ *
356
+ * This function retrieve the value of a metabox attached to a post. It return either a single value or an array.
357
+ *
358
+ * @param int $id Post ID.
359
+ * @param string $meta The meta key to retrieve.
360
+ *
361
+ * @return mixed Single value or array
362
+ * @since 2.0.0
363
+ */
364
+ function yit_get_post_meta( $id, $meta ) {
365
+ if ( ! strpos( $meta, '[' ) ) {
366
+ return get_post_meta( $id, $meta, true );
367
+ }
368
+
369
+ $sub_meta = explode( '[', $meta );
370
+
371
+ $meta = get_post_meta( $id, $meta, true );
372
+ for ( $i = 0; $i < count( $sub_meta ); $i ++ ) {
373
+ $meta = $meta[rtrim( $sub_meta[$i], ']' )];
374
+ }
375
+
376
+ return $meta;
377
+ }
378
+ }
379
+
380
+ if ( ! function_exists( 'yit_string' ) ) {
381
+ /**
382
+ * Simple echo a string, with a before and after string, only if the main string is not empty.
383
+ *
384
+ * @param string $before What there is before the main string
385
+ * @param string $string The main string. If it is empty or null, the functions return null.
386
+ * @param string $after What there is after the main string
387
+ * @param bool $echo If echo or only return it
388
+ *
389
+ * @return string The complete string, if the main string is not empty or null
390
+ * @since 2.0.0
391
+ */
392
+ function yit_string( $before = '', $string = '', $after = '', $echo = true ) {
393
+ $html = '';
394
+
395
+ if ( $string != '' AND ! is_null( $string ) ) {
396
+ $html = $before . $string . $after;
397
+ }
398
+
399
+ if ( $echo ) {
400
+ echo $html;
401
+ }
402
+
403
+ return $html;
404
+ }
405
+ }
406
+
407
+
408
+ if ( ! function_exists( 'yit_pagination' ) ) {
409
+ /**
410
+ * Print pagination
411
+ *
412
+ * @param string $pages
413
+ * @param int $range
414
+ *
415
+ * @return string
416
+ * @since 2.0.0
417
+ */
418
+ function yit_pagination( $pages = '', $range = 10 ) {
419
+ $showitems = ( $range * 2 ) + 1;
420
+
421
+ $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : false;
422
+ if ( $paged === false ) {
423
+ $paged = ( get_query_var( 'page' ) ) ? get_query_var( 'page' ) : false;
424
+ }
425
+ if ( $paged === false ) {
426
+ $paged = 1;
427
+ }
428
+
429
+
430
+ $html = '';
431
+
432
+ if ( $pages == '' ) {
433
+ global $wp_query;
434
+
435
+ if ( isset( $wp_query->max_num_pages ) ) {
436
+ $pages = $wp_query->max_num_pages;
437
+ }
438
+
439
+ if ( ! $pages ) {
440
+ $pages = 1;
441
+ }
442
+ }
443
+
444
+ if ( 1 != $pages ) {
445
+ $html .= "<div class='general-pagination clearfix'>";
446
+ if ( $paged > 2 ) {
447
+ $html .= sprintf( '<a class="%s" href="%s">&laquo;</a>', 'yit_pagination_first', get_pagenum_link( 1 ) );
448
+ }
449
+ if ( $paged > 1 ) {
450
+ $html .= sprintf( '<a class="%s" href="%s">&lsaquo;</a>', 'yit_pagination_previous', get_pagenum_link( $paged - 1 ) );
451
+ }
452
+
453
+ for ( $i = 1; $i <= $pages; $i ++ ) {
454
+ if ( 1 != $pages && ( ! ( $i >= $paged + $range + 1 || $i <= $paged - $range - 1 ) || $pages <= $showitems ) ) {
455
+ $class = ( $paged == $i ) ? " class='selected'" : '';
456
+ $html .= "<a href='" . get_pagenum_link( $i ) . "'$class >$i</a>";
457
+ }
458
+ }
459
+
460
+ if ( $paged < $pages ) {
461
+ $html .= sprintf( '<a class="%s" href="%s">&rsaquo;</a>', 'yit_pagination_next', get_pagenum_link( $paged + 1 ) );
462
+ }
463
+ if ( $paged < $pages - 1 ) {
464
+ $html .= sprintf( '<a class="%s" href="%s">&raquo;</a>', 'yit_pagination_last', get_pagenum_link( $pages ) );
465
+ }
466
+
467
+ $html .= "</div>\n";
468
+ }
469
+
470
+ echo apply_filters( 'yit_pagination_html', $html );
471
+ }
472
+ }
473
+
474
+ if ( ! function_exists( 'yit_registered_sidebars' ) ) {
475
+ /**
476
+ * Retrieve all registered sidebars
477
+ *
478
+ * @return array
479
+ * @since 2.0.0
480
+ */
481
+ function yit_registered_sidebars() {
482
+ global $wp_registered_sidebars;
483
+
484
+ $return = array();
485
+
486
+ if ( empty( $wp_registered_sidebars ) ) {
487
+ $return = array( '' => '' );
488
+ }
489
+
490
+ foreach ( ( array ) $wp_registered_sidebars as $the_ ) {
491
+ $return[$the_['name']] = $the_['name'];
492
+ }
493
+
494
+ ksort( $return );
495
+
496
+ return $return;
497
+ }
498
+ }
499
+
500
+ if ( ! function_exists( 'yit_layout_option' ) ) {
501
+ /**
502
+ * Retrieve a layout option
503
+ *
504
+ * @param $key
505
+ * @param bool $id
506
+ * @param string $type
507
+ * @param string $model
508
+ *
509
+ * @return array
510
+ * @since 2.0.0
511
+ */
512
+ function yit_layout_option( $key, $id = false, $type = "post", $model = "post_type" ) {
513
+
514
+ $option = '';
515
+
516
+ if ( defined( 'YIT' ) ) {
517
+ $option = YIT_Layout_Panel()->get_option( $key, $id, $type, $model );
518
+ }
519
+ else {
520
+ if ( ! $id && ( is_single() || is_page() ) ) {
521
+ global $post;
522
+ $id = $post->ID;
523
+ }
524
+ elseif ( $id != 'all' ) {
525
+ $option = get_post_meta( $id, $key );
526
+ }
527
+ }
528
+
529
+ return $option;
530
+ }
531
+ }
532
+
533
+ if ( ! function_exists( 'yit_curPageURL' ) ) {
534
+ /**
535
+ * Retrieve the current complete url
536
+ *
537
+ * @since 1.0
538
+ */
539
+ function yit_curPageURL() {
540
+ $pageURL = 'http';
541
+ if ( isset( $_SERVER["HTTPS"] ) AND $_SERVER["HTTPS"] == "on" ) {
542
+ $pageURL .= "s";
543
+ }
544
+
545
+ $pageURL .= "://";
546
+
547
+ if ( isset( $_SERVER["SERVER_PORT"] ) AND $_SERVER["SERVER_PORT"] != "80" ) {
548
+ $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
549
+ }
550
+ else {
551
+ $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
552
+ }
553
+
554
+ return $pageURL;
555
+ }
556
+ }
557
+
558
+ if ( ! function_exists( 'yit_get_excluded_categories' ) ) {
559
+ /**
560
+ *
561
+ * Retrieve the escluded categories, set on Theme Options
562
+ *
563
+ * @param int $k
564
+ *
565
+ * @return string String with all id categories excluded, separated by a comma
566
+ *
567
+ * @since 2.0.0
568
+ */
569
+
570
+ function yit_get_excluded_categories( $k = 1 ) {
571
+
572
+ global $post;
573
+
574
+ if ( ! isset( $post->ID ) ) {
575
+ return;
576
+ }
577
+
578
+ $cf_cats = get_post_meta( $post->ID, 'blog-cats', true);
579
+
580
+ if ( ! empty( $cf_cats ) ){
581
+ return $cf_cats;
582
+ }
583
+
584
+ $cats = function_exists( 'yit_get_option' ) ? yit_get_option( 'blog-excluded-cats' ) : '';
585
+
586
+
587
+ if ( ! is_array( $cats ) || empty( $cats ) || ! isset( $cats[$k] ) ) {
588
+ return;
589
+ }
590
+
591
+ $cats = array_map( 'trim', $cats[$k] );
592
+
593
+ $i = 0;
594
+ $query = '';
595
+ foreach ( $cats as $cat ) {
596
+ $query .= ",-$cat";
597
+
598
+ $i ++;
599
+ }
600
+
601
+ ltrim( ',', $query );
602
+
603
+ return $query;
604
+ }
605
+ }
606
+
607
+
608
+ if ( ! function_exists( 'yit_add_extra_theme_headers' ) ) {
609
+ add_filter( 'extra_theme_headers', 'yit_add_extra_theme_headers' );
610
+
611
+ /**
612
+ * Check the framework core version
613
+ *
614
+ * @param $headers Array
615
+ *
616
+ * @return bool
617
+ * @since 2.0.0
618
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
619
+ */
620
+ function yit_add_extra_theme_headers( $headers ) {
621
+ $headers[] = 'Core Framework Version';
622
+ return $headers;
623
+ }
624
+ }
625
+
626
+ if ( ! function_exists( 'yit_check_plugin_support' ) ) {
627
+ /**
628
+ * Check the framework core version
629
+ *
630
+ * @return bool
631
+ * @since 2.0.0
632
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
633
+ */
634
+ function yit_check_plugin_support() {
635
+ $headers['core'] = wp_get_theme()->get( 'Core Framework Version' );
636
+ $headers['author'] = wp_get_theme()->get( 'Author' );
637
+
638
+ if ( ( ! empty( $headers['core'] ) && version_compare( $headers['core'], '2.0.0', '<=' ) ) || $headers['author'] != 'Your Inspiration Themes' ) {
639
+ return true;
640
+ }
641
+ else {
642
+ return false;
643
+ }
644
+ }
645
+ }
646
+
647
+ if( !function_exists( 'yit_ie_version' ) ) {
648
+ /**
649
+ * Retrieve IE version.
650
+ *
651
+ * @return int|float
652
+ * @since 1.0.0
653
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
654
+ */
655
+ function yit_ie_version() {
656
+ preg_match('/MSIE ([0-9]\.[0-9])/',$_SERVER['HTTP_USER_AGENT'],$reg);
657
+ if ( ! isset( $reg[1] ) )
658
+ { return -1; }
659
+ else
660
+ { return floatval( $reg[1] ); }
661
+ }
662
+ }
663
+
664
+ if( ! function_exists( 'yit_avoid_duplicate' ) ) {
665
+ /**
666
+ * Check if something exists. If yes, add a -N to the value where N is a number.
667
+ *
668
+ * @param mixed $value
669
+ * @param array $array
670
+ * @param string $check
671
+ * @return mixed
672
+ * @since 2.0.0
673
+ * @author Antonino Scarf� <antonino.scarfi@yithemes.com>
674
+ */
675
+ function yit_avoid_duplicate( $value, $array, $check = 'value' ) {
676
+ $match = array();
677
+
678
+ if( !is_array( $array ) ) {
679
+ return $value;
680
+ }
681
+
682
+ if ( ( $check == 'value' && ! in_array( $value, $array ) ) || ( $check == 'key' && ! isset( $array[$value] ) ) ) {
683
+ return $value;
684
+ } else {
685
+ if ( ! preg_match( '/([a-z]+)-([0-9]+)/', $value, $match ) ) {
686
+ $i = 2;
687
+ } else {
688
+ $i = intval( $match[2] ) + 1;
689
+ $value = $match[1];
690
+ }
691
+
692
+ return yit_avoid_duplicate( $value . '-' . $i, $array, $check );
693
+ }
694
+ }
695
+ }
696
+
697
+ if( !function_exists( 'yit_title_special_characters' ) ) {
698
+ /**
699
+ * The chars used in yit_decode_title() and yit_encode_title()
700
+ *
701
+ * E.G.
702
+ * string: This is [my title] with | a new line
703
+ * return: This is <span class="highlight">my title</span> with <br /> a new line
704
+ *
705
+ * @param string $title The string to convert
706
+ * @return string The html
707
+ *
708
+ * @since 1.0
709
+ */
710
+ function yit_title_special_characters( $chars )
711
+ {
712
+ return array_merge( $chars, array(
713
+ '/[=\[](.*?)[=\]]/' => '<span class="title-highlight">$1</span>',
714
+ '/\|/' => '<br />',
715
+ ) );
716
+ }
717
+ add_filter( 'yit_title_special_characters', 'yit_title_special_characters' );
718
+ }
719
+
720
+ if( !function_exists( 'yit_decode_title' ) ) {
721
+ /**
722
+ * Change some special characters to put easily html into a string
723
+ *
724
+ * E.G.
725
+ * string: This is [my title] with | a new line
726
+ * return: This is <span class="title-highlight">my title</span> with <br /> a new line
727
+ *
728
+ * @param string $title The string to convert
729
+ * @return string The html
730
+ *
731
+ * @since 1.0
732
+ */
733
+ function yit_decode_title( $title )
734
+ {
735
+ $replaces = apply_filters( 'yit_title_special_characters', array() );
736
+
737
+ return preg_replace( array_keys( $replaces ), array_values( $replaces ), $title );
738
+ }
739
+ }
740
+
741
+ if( !function_exists( 'yit_encode_title' ) ) {
742
+ /**
743
+ * Change some special characters to put easily html into a string
744
+ *
745
+ * E.G.
746
+ * string: This is [my title] with | a new line
747
+ * return: This is <span class="title-highlight">my title</span> with <br /> a new line
748
+ *
749
+ * @param string $title The string to convert
750
+ * @return string The html
751
+ *
752
+ * @since 1.0
753
+ */
754
+ function yit_encode_title( $title )
755
+ {
756
+ $replaces = apply_filters( 'yit_title_special_characters', array() );
757
+
758
+ return preg_replace( array_values( $replaces ), array_keys( $replaces ), $title );
759
+ }
760
+ }
761
+
762
+ if( !function_exists( 'yit_remove_chars_title' ) ) {
763
+ /**
764
+ * Change some special characters to put easily html into a string
765
+ *
766
+ * E.G.
767
+ * string: This is [my title] with | a new line
768
+ * return: This is <span class="title-highlight">my title</span> with <br /> a new line
769
+ *
770
+ * @param string $title The string to convert
771
+ * @return string The html
772
+ *
773
+ * @since 1.0
774
+ */
775
+ function yit_remove_chars_title( $title )
776
+ {
777
+ $replaces = apply_filters( 'yit_title_special_characters', array() );
778
+
779
+ return preg_replace( array_keys( $replaces ), '$1', $title );
780
+ }
781
+ }
782
+
783
+ if( ! function_exists( 'is_shop_installed' ) ) {
784
+ /**
785
+ * Detect if there is a shop plugin installed
786
+ *
787
+ * @return bool
788
+ * @since 2.0.0
789
+ * @author Francesco Grasso <francesco.grasso@yithemes.com
790
+ */
791
+ function is_shop_installed() {
792
+ global $woocommerce;
793
+ if( isset( $woocommerce ) || defined( 'JIGOSHOP_VERSION' ) ) {
794
+ return true;
795
+ } else {
796
+ return false;
797
+ }
798
+ }
799
+ }
800
+
801
+ if ( ! function_exists( 'yit_load_js_file' ) ) {
802
+ /**
803
+ * Load .min.js file if WP_Debug is not defined
804
+ *
805
+ * @param $filename The file name
806
+ *
807
+ * @return string The file path
808
+ * @since 2.0.0
809
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
810
+ */
811
+ function yit_load_js_file( $filename ) {
812
+
813
+ if ( ! ( ( defined( 'WP_DEBUG' ) && WP_DEBUG ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ) ) {
814
+ $filename = str_replace( '.js', '.min.js', $filename );
815
+ }
816
+
817
+ return $filename;
818
+ }
819
+ }
plugin-fw/yit-plugin-registration-hook.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if( ! function_exists( 'yith_plugin_registration_hook' ) ){
12
+ function yith_plugin_registration_hook(){
13
+
14
+ /**
15
+ * @use activate_PLUGINNAME hook
16
+ */
17
+ $hook = str_replace( 'activate_', '', current_filter() );
18
+
19
+ $option = get_option( 'yit_recently_activated', array() );
20
+ $option[] = $hook;
21
+ update_option( 'yit_recently_activated', $option );
22
+ }
23
+ }
plugin-fw/yit-plugin.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ if( !defined('YIT_CORE_PLUGIN')) {
17
+ define( 'YIT_CORE_PLUGIN', true);
18
+ }
19
+
20
+ if( !defined('YIT_CORE_PLUGIN_PATH')) {
21
+ define( 'YIT_CORE_PLUGIN_PATH', dirname(__FILE__));
22
+ }
23
+
24
+ if( !defined('YIT_CORE_PLUGIN_URL')) {
25
+ define( 'YIT_CORE_PLUGIN_URL', untrailingslashit( plugins_url( '/', __FILE__ ) ));
26
+ }
27
+
28
+ if( ! defined( 'YIT_CORE_PLUGIN_TEMPLATE_PATH' ) ){
29
+ define ( 'YIT_CORE_PLUGIN_TEMPLATE_PATH', YIT_CORE_PLUGIN_PATH . '/templates' );
30
+ }
31
+
32
+
33
+ include_once( 'yit-functions.php' );
34
+ include_once( 'yit-plugin-registration-hook.php' );
35
+ include_once( 'lib/yit-metabox.php' );
36
+ include_once( 'lib/yit-plugin-panel.php' );
37
+ include_once( 'lib/yit-plugin-panel-wc.php' );
38
+ include_once( 'lib/yit-plugin-subpanel.php' );
39
+ include_once( 'lib/yit-plugin-common.php' );
40
+ include_once( 'lib/yit-plugin-gradients.php');
41
+ include_once( 'licence/lib/yit-licence.php');
42
+ include_once( 'licence/lib/yit-plugin-licence.php');
43
+ include_once( 'licence/lib/yit-theme-licence.php');
44
+ include_once( 'lib/yit-video.php');
45
+ include_once( 'lib/yit-upgrade.php');
46
+ include_once( 'lib/yit-pointers.php');
plugin-options/premium-landing-options.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ return array(
17
+ 'premium-landing' => array(
18
+ 'home' => array(
19
+ 'type' => 'custom_tab',
20
+ 'action' => 'yith_catalog_mode_premium'
21
+ )
22
+ )
23
+ );
plugin-options/settings-options.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file belongs to the YIT Plugin Framework.
4
+ *
5
+ * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
6
+ * that is bundled with this package in the file LICENSE.txt.
7
+ * It is also available through the world-wide-web at this URL:
8
+ * http://www.gnu.org/licenses/gpl-3.0.txt
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ } // Exit if accessed directly
14
+
15
+ $videobox = defined( 'YWCTM_PREMIUM' ) ? '' : array(
16
+ 'name' => __( 'Upgrade to the PREMIUM VERSION', 'ywctm' ),
17
+ 'type' => 'videobox',
18
+ 'default' => array(
19
+ 'plugin_name' => __( 'YITH WooCommerce Catalog Mode', 'ywctm' ),
20
+ 'title_first_column' => __( 'Discover the Advanced Features', 'ywctm' ),
21
+ 'description_first_column' => __( 'Upgrade to the PREMIUM VERSION of YITH WooCommerce Catalog Mode to benefit from all features!', 'ywctm' ),
22
+ 'video' => array(
23
+ 'video_id' => '118792418',
24
+ 'video_image_url' => YWCTM_ASSETS_URL.'/images/yith-woocommerce-catalog-mode.jpg',
25
+ 'video_description' => __( 'YITH WooCommerce Catalog Mode', 'ywctm' ),
26
+ ),
27
+ 'title_second_column' => __( 'Get Support and Pro Features', 'ywctm' ),
28
+ 'description_second_column' => __( 'By purchasing the premium version of the plugin, you will take advantage of the advanced features of the product and you will get one year of free updates and support through our platform available 24h/24.', 'ywctm' ),
29
+ 'button' => array(
30
+ 'href' => 'http://yithemes.com/themes/plugins/yith-woocommerce-catalog-mode/',
31
+ 'title' => 'Get Support and Pro Features'
32
+ )
33
+ ),
34
+ 'id' => 'ywctm_general_videobox'
35
+ );
36
+
37
+ $exclusion = ! defined( 'YWCTM_PREMIUM' ) ? '' : array (
38
+ 'name' => __( '"Add to cart" button', 'ywctm' ),
39
+ 'type' => 'checkbox',
40
+ 'desc' => __( 'Exclude selected products (See "Exclusions" tab)', 'ywctm' ),
41
+ 'id' => 'ywctm_exclude_hide_add_to_cart',
42
+ 'default' => 'no',
43
+ 'checkboxgroup' => 'end'
44
+ );
45
+
46
+ return array(
47
+ 'settings' => array(
48
+ //'section_general_settings_videobox' => $videobox,
49
+ 'catalog_mode_general_title' => array(
50
+ 'name' => __( 'General Settings', 'ywctm' ),
51
+ 'type' => 'title',
52
+ 'desc' => '',
53
+ 'id' => 'ywctm_general_title',
54
+ ),
55
+ 'catalog_mode_general_enable_plugin' => array(
56
+ 'name' => __( 'Enable YITH Woocommerce Catalog Mode', 'ywctm' ),
57
+ 'type' => 'checkbox',
58
+ 'desc' => '',
59
+ 'id' => 'ywctm_enable_plugin',
60
+ 'default' => 'yes',
61
+ ),
62
+ 'catalog_mode_general_admin_view' => array(
63
+ 'name' => __( 'Admin View', 'ywctm' ),
64
+ 'type' => 'checkbox',
65
+ 'desc' => __( 'Enable Catalog Mode also for administrators', 'ywctm'),
66
+ 'id' => 'ywctm_admin_view',
67
+ 'default' => 'yes',
68
+ ),
69
+ 'catalog_mode_general_end' => array(
70
+ 'type' => 'sectionend',
71
+ 'id' => 'ywctm_general_end'
72
+ ),
73
+ 'catalog_mode_section_title' => array(
74
+ 'name' => __( 'Catalog Mode Settings', 'ywctm' ),
75
+ 'type' => 'title',
76
+ 'desc' => '',
77
+ 'id' => 'ywctm_settings_title',
78
+ ),
79
+ 'catalog_mode_settings_disable_add_to_cart_single' => array(
80
+ 'name' => __( '"Add to cart" button', 'ywctm' ),
81
+ 'type' => 'checkbox',
82
+ 'desc' => __( 'Hide in product details page', 'ywctm' ),
83
+ 'id' => 'ywctm_hide_add_to_cart_single',
84
+ 'default' => 'no',
85
+ 'checkboxgroup' => 'start'
86
+ ),
87
+ 'catalog_mode_settings_disable_add_to_cart_loop' => array(
88
+ 'name' => __( '"Add to cart" button', 'ywctm' ),
89
+ 'type' => 'checkbox',
90
+ 'desc' => __( 'Hide in other pages', 'ywctm' ),
91
+ 'id' => 'ywctm_hide_add_to_cart_loop',
92
+ 'default' => 'no',
93
+ 'checkboxgroup' => ! defined( 'YWCTM_PREMIUM' ) ? 'end' : ''
94
+ ),
95
+ 'catalog_mode_settings_exclude_products' => $exclusion,
96
+ 'catalog_mode_settings_disable_cart_in_header' => array(
97
+ 'name' => __( '"Cart" and "Checkout" pages', 'ywctm' ),
98
+ 'type' => 'checkbox',
99
+ 'desc' => __( 'Hide', 'ywctm' ),
100
+ 'id' => 'ywctm_hide_cart_header',
101
+ 'default' => 'no',
102
+ ),
103
+ 'catalog_mode_section_end' => array(
104
+ 'type' => 'sectionend',
105
+ 'id' => 'ywctm_settings_end'
106
+ )
107
+ )
108
+
109
+ );
readme.txt ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === YITH WooCommerce Catalog Mode ===
2
+
3
+ Contributors: yithemes
4
+ Tags: woocommerce, products, themes, yit, yith, e-commerce, shop, catalog mode, catalogue mode, remove add to cart
5
+ Requires at least: 4.0
6
+ Tested up to: 4.1.1
7
+ Stable tag: 1.0.1
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ YITH WooCommerce Catalog Mode allows you to disable shop functions.
12
+
13
+ == Description ==
14
+
15
+ YITH WooCommerce Catalog Mode lets you deactivate the selling features of your e-commerce site.
16
+
17
+ With this plugin you can:
18
+ - Create a showcase of your products
19
+ - Temporarily deactivate the selling operations to perform maintenance actions in your warehouse without putting offline your site
20
+
21
+ How it works:
22
+ - You can hide the "Add to cart" button in the site pages
23
+ - You can hide the "Cart" and "Checkout page and the "Cart" widget in the site pages
24
+
25
+ Full documentation is available [here](http://yithemes.com/docs-plugins/yith-woocommerce-catalog-mode/).
26
+
27
+ == Installation ==
28
+
29
+ = Installation =
30
+
31
+ Important: before of all you have to download and activate WooCommerce plugin, which is mandatory for YITH WooCommerce Catalog Mode to be working. If WooCommerce plugin is active, you just need to activate the YITH WooCommerce Catalog Mode plugin.
32
+
33
+ 1. Unzip the downloaded zip file.
34
+ 2. Upload the plugin folder into the `wp-content/plugins/` directory of your WordPress site.
35
+ 3. Activate `YITH WooCommerce Catalog Mode` from Plugins page.
36
+
37
+ = Configuration =
38
+
39
+ YITH WooCommerce Catalog Mode will add a new tab called "Catalog Mode" inside the YIT Plugins menu item. There you are able to configure all plugin settings.
40
+
41
+ == Screenshots ==
42
+
43
+ 1. This is the settings page for the plugin, you can find it inside the YIT Plugins menu item. You can hide "add to cart" buttons and cart and checkout pages.
44
+
45
+ == Changelog ==
46
+
47
+ = 1.0.1 =
48
+
49
+ * Fixed: Minor bugs
50
+
51
+ = 1.0.0 =
52
+
53
+ * Initial release
54
+
55
+ == Support ==
56
+ Already knew it, right?! Great, but maybe you do not know that: if you're looking for how to install the plugins or how to use them within your Wordpress installations, which is the right way to ask support?
57
+ That's the way:
58
+
59
+ * Register on http://yithemes.com
60
+ * Go to Support > Get Support
61
+
62
+ == Upgrade Notice ==
63
+
64
+ Last Stable Tag 1.0.1
65
+
66
+ == Suggestions ==
67
+
68
+ If you have suggestions about how to improve YITH WooCommerce Catalog Mode, you can [write us](mailto:plugins@yithemes.com "Your Inspiration Themes") so we can bundle them into YITH WooCommerce Catalog Mode.
69
+
70
+ == Translators ==
71
+
72
+ = Available Languages =
73
+ * English
74
+
75
+ If you have created your own language pack, or have an update for an existing one, you can send [gettext PO and MO file](http://codex.wordpress.org/Translating_WordPress "Translating WordPress")
76
+ [use](http://yithemes.com/contact/ "Your Inspiration Themes") so we can bundle it into YITH WooCommerce Catalog Mode languages.
screenshot-1.jpg ADDED
Binary file