YITH WooCommerce Quick View - Version 1.17.0

Version Description

Released 05 July 2022

  • New: support for WooCommerce 6.7
  • Update: YITH plugin framework
Download this release

Release Info

Developer yithemes
Plugin Icon 128x128 YITH WooCommerce Quick View
Version 1.17.0
Comparing to
See all releases

Code changes from version 1.16.0 to 1.17.0

Files changed (36) hide show
  1. assets/css/yith-quick-view.css +159 -159
  2. includes/class.yith-wcqv-admin.php +240 -240
  3. includes/class.yith-wcqv-frontend.php +435 -435
  4. includes/class.yith-wcqv.php +164 -164
  5. init.php +160 -160
  6. languages/yith-woocommerce-quick-view-it_IT.po +585 -585
  7. languages/yith-woocommerce-quick-view.pot +274 -274
  8. license.txt +693 -693
  9. plugin-fw/LICENSE.txt +739 -739
  10. plugin-fw/assets/css/codemirror/codemirror.css +260 -260
  11. plugin-fw/assets/css/colorbox.css +65 -65
  12. plugin-fw/assets/css/elementor.css +35 -35
  13. plugin-fw/assets/css/scss/yith-plugin-ui.scss +8 -8
  14. plugin-fw/assets/css/scss/yith-plugin-ui/_tables.scss +56 -56
  15. plugin-fw/assets/css/scss/yith-plugin-ui/_taxonomy.scss +52 -52
  16. plugin-fw/assets/css/scss/yith-plugin-ui/_wp-pages.scss +87 -87
  17. plugin-fw/assets/css/scss/yith-plugin-ui/components/_action-button.scss +79 -79
  18. plugin-fw/assets/css/scss/yith-plugin-ui/components/_boxed-row.scss +14 -14
  19. plugin-fw/assets/css/scss/yith-plugin-ui/components/_buttons.scss +224 -224
  20. plugin-fw/assets/css/scss/yith-plugin-ui/components/_confirm.scss +40 -40
  21. plugin-fw/assets/css/scss/yith-plugin-ui/components/_list-table-blank-state.scss +24 -24
  22. plugin-fw/assets/css/scss/yith-plugin-ui/components/_modal.scss +127 -127
  23. plugin-fw/assets/css/scss/yith-plugin-ui/mixins/_buttons.scss +123 -123
  24. plugin-fw/assets/css/scss/yith-plugin-ui/mixins/_tables.scss +158 -158
  25. plugin-fw/assets/css/yit-upgrader.css +21 -21
  26. plugin-fw/assets/css/yith-select2-no-wc.css +740 -740
  27. plugin-fw/assets/js/codemirror/codemirror.js +5806 -5806
  28. plugin-fw/assets/js/codemirror/javascript.js +630 -630
  29. plugin-fw/assets/js/how-to.js +6 -6
  30. plugin-fw/assets/js/jquery-tiptip/jquery.tipTip.js +191 -191
  31. plugin-fw/assets/js/jquery.colorbox.js +1104 -1104
  32. plugin-fw/assets/js/jquery.colorbox.min.js +5 -5
  33. plugin-fw/assets/js/multisite-updater.js +222 -222
  34. plugin-fw/assets/js/wp-pages.js +75 -75
  35. plugin-fw/assets/js/yit-cpt-unlimited.js +79 -79
  36. plugin-fw/assets/js/yit-plugin-panel.js +201 -302
assets/css/yith-quick-view.css CHANGED
@@ -1,160 +1,160 @@
1
- /*=======================
2
- * MODAL POPUP STYLE
3
- ========================*/
4
-
5
- html.yith-quick-view-is-open,
6
- html.yith-quick-view-is-open body {
7
- overflow: hidden;
8
- }
9
-
10
- #yith-quick-view-modal {
11
- position: fixed;
12
- visibility: hidden;
13
- top: 0;
14
- left: 0;
15
- right: 0;
16
- bottom: 0;
17
- z-index: 1400;
18
- opacity: 0;
19
- text-align: center;
20
- -webkit-transition: all 0.3s;
21
- -moz-transition: all 0.3s;
22
- transition: all 0.3s;
23
- }
24
-
25
- #yith-quick-view-modal:before {
26
- content: '';
27
- display: inline-block;
28
- vertical-align: middle;
29
- height: 100%;
30
- width: 0;
31
- }
32
-
33
- #yith-quick-view-modal .yith-quick-view-overlay {
34
- position: absolute;
35
- top: 0;
36
- right: 0;
37
- bottom: 0;
38
- left: 0;
39
- background: rgba( 0, 0, 0, 0.8);
40
- }
41
-
42
- #yith-quick-view-modal .yith-wcqv-wrapper {
43
- display: inline-block;
44
- vertical-align: middle;
45
- visibility: hidden;
46
- -webkit-backface-visibility: hidden;
47
- -moz-backface-visibility: hidden;
48
- backface-visibility: hidden;
49
- text-align: left;
50
- height: 600px;
51
- width: 1000px;
52
- }
53
-
54
- #yith-quick-view-modal .yith-wcqv-main {
55
- -webkit-transform: translateY(20%);
56
- -moz-transform: translateY(20%);
57
- -ms-transform: translateY(20%);
58
- transform: translateY(20%);
59
- opacity: 0;
60
- height: 100%;
61
- -webkit-transition: all 0.3s;
62
- -moz-transition: all 0.3s;
63
- transition: all 0.3s;
64
- -webkit-box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.2);
65
- box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.2);
66
- }
67
-
68
- #yith-quick-view-modal.open,
69
- #yith-quick-view-modal.open .yith-wcqv-wrapper {
70
- visibility: visible;
71
- opacity: 1;
72
- }
73
-
74
- #yith-quick-view-modal #yith-quick-view-content {
75
- height: 100%;
76
- }
77
-
78
- #yith-quick-view-modal .yith-wcqv-main:after,
79
- #yith-quick-view-modal .yith-wcqv-main:before {
80
- content: '';
81
- display: table;
82
- clear: both;
83
- }
84
- #yith-quick-view-modal.open .yith-wcqv-main {
85
- -webkit-transform: translateY(0);
86
- -moz-transform: translateY(0);
87
- -ms-transform: translateY(0);
88
- transform: translateY(0);
89
- opacity: 1;
90
- height: 100%;
91
- overflow-y: scroll;
92
- position: relative;
93
- }
94
- #yith-quick-view-close {
95
- border: 1px solid;
96
- position: absolute;
97
- top: 5px;
98
- right: 5px;
99
- width: 20px;
100
- height: 20px;
101
- text-align: center;
102
- line-height: 18px;
103
- z-index: 2;
104
- opacity: 0.5;
105
- }
106
- #yith-quick-view-close:hover {
107
- opacity: 1;
108
- transition: all 0.2s ease;
109
- -webkit-transition: all 0.2s ease;
110
- -moz-transition: all 0.2s ease;
111
- -ms-transition: all 0.2s ease;
112
- }
113
- #yith-quick-view-content div.images {
114
- width: 40%;
115
- float: left;
116
- opacity: 1 !important;
117
- margin: 0;
118
- }
119
- #yith-quick-view-content div.summary {
120
- margin: 0;
121
- padding: 15px;
122
- width: 60%;
123
- float: left;
124
- font-size: inherit;
125
- }
126
- #yith-quick-view-content div.woocommerce-product-rating:after,
127
- #yith-quick-view-content div.woocommerce-product-rating:before {
128
- content: '';
129
- display: table;
130
- clear: both;
131
- }
132
- #yith-quick-view-content div.woocommerce-product-rating a.woocommerce-review-link {
133
- display: none;
134
- }
135
- #yith-quick-view-content .onsale {
136
- top: 5px;
137
- right: auto;
138
- left: 5px;
139
- }
140
- #yith-quick-view-content figure.woocommerce-product-gallery__wrapper > div:not(:first-child) {
141
- display: none;
142
- }
143
-
144
- li.product .yith-wcqv-button .blockUI.blockOverlay:before {
145
- background: none;
146
- }
147
-
148
- @media( max-width: 480px ) {
149
- #yith-quick-view-content div.images,
150
- #yith-quick-view-content div.summary {
151
- width: 100%;
152
- float: none;
153
- }
154
- #yith-quick-view-content div.summary {
155
- margin: 0;
156
- padding: 15px;
157
- width: 100%;
158
- float: left;
159
- }
160
  }
1
+ /*=======================
2
+ * MODAL POPUP STYLE
3
+ ========================*/
4
+
5
+ html.yith-quick-view-is-open,
6
+ html.yith-quick-view-is-open body {
7
+ overflow: hidden;
8
+ }
9
+
10
+ #yith-quick-view-modal {
11
+ position: fixed;
12
+ visibility: hidden;
13
+ top: 0;
14
+ left: 0;
15
+ right: 0;
16
+ bottom: 0;
17
+ z-index: 1400;
18
+ opacity: 0;
19
+ text-align: center;
20
+ -webkit-transition: all 0.3s;
21
+ -moz-transition: all 0.3s;
22
+ transition: all 0.3s;
23
+ }
24
+
25
+ #yith-quick-view-modal:before {
26
+ content: '';
27
+ display: inline-block;
28
+ vertical-align: middle;
29
+ height: 100%;
30
+ width: 0;
31
+ }
32
+
33
+ #yith-quick-view-modal .yith-quick-view-overlay {
34
+ position: absolute;
35
+ top: 0;
36
+ right: 0;
37
+ bottom: 0;
38
+ left: 0;
39
+ background: rgba( 0, 0, 0, 0.8);
40
+ }
41
+
42
+ #yith-quick-view-modal .yith-wcqv-wrapper {
43
+ display: inline-block;
44
+ vertical-align: middle;
45
+ visibility: hidden;
46
+ -webkit-backface-visibility: hidden;
47
+ -moz-backface-visibility: hidden;
48
+ backface-visibility: hidden;
49
+ text-align: left;
50
+ height: 600px;
51
+ width: 1000px;
52
+ }
53
+
54
+ #yith-quick-view-modal .yith-wcqv-main {
55
+ -webkit-transform: translateY(20%);
56
+ -moz-transform: translateY(20%);
57
+ -ms-transform: translateY(20%);
58
+ transform: translateY(20%);
59
+ opacity: 0;
60
+ height: 100%;
61
+ -webkit-transition: all 0.3s;
62
+ -moz-transition: all 0.3s;
63
+ transition: all 0.3s;
64
+ -webkit-box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.2);
65
+ box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.2);
66
+ }
67
+
68
+ #yith-quick-view-modal.open,
69
+ #yith-quick-view-modal.open .yith-wcqv-wrapper {
70
+ visibility: visible;
71
+ opacity: 1;
72
+ }
73
+
74
+ #yith-quick-view-modal #yith-quick-view-content {
75
+ height: 100%;
76
+ }
77
+
78
+ #yith-quick-view-modal .yith-wcqv-main:after,
79
+ #yith-quick-view-modal .yith-wcqv-main:before {
80
+ content: '';
81
+ display: table;
82
+ clear: both;
83
+ }
84
+ #yith-quick-view-modal.open .yith-wcqv-main {
85
+ -webkit-transform: translateY(0);
86
+ -moz-transform: translateY(0);
87
+ -ms-transform: translateY(0);
88
+ transform: translateY(0);
89
+ opacity: 1;
90
+ height: 100%;
91
+ overflow-y: scroll;
92
+ position: relative;
93
+ }
94
+ #yith-quick-view-close {
95
+ border: 1px solid;
96
+ position: absolute;
97
+ top: 5px;
98
+ right: 5px;
99
+ width: 20px;
100
+ height: 20px;
101
+ text-align: center;
102
+ line-height: 18px;
103
+ z-index: 2;
104
+ opacity: 0.5;
105
+ }
106
+ #yith-quick-view-close:hover {
107
+ opacity: 1;
108
+ transition: all 0.2s ease;
109
+ -webkit-transition: all 0.2s ease;
110
+ -moz-transition: all 0.2s ease;
111
+ -ms-transition: all 0.2s ease;
112
+ }
113
+ #yith-quick-view-content div.images {
114
+ width: 40%;
115
+ float: left;
116
+ opacity: 1 !important;
117
+ margin: 0;
118
+ }
119
+ #yith-quick-view-content div.summary {
120
+ margin: 0;
121
+ padding: 15px;
122
+ width: 60%;
123
+ float: left;
124
+ font-size: inherit;
125
+ }
126
+ #yith-quick-view-content div.woocommerce-product-rating:after,
127
+ #yith-quick-view-content div.woocommerce-product-rating:before {
128
+ content: '';
129
+ display: table;
130
+ clear: both;
131
+ }
132
+ #yith-quick-view-content div.woocommerce-product-rating a.woocommerce-review-link {
133
+ display: none;
134
+ }
135
+ #yith-quick-view-content .onsale {
136
+ top: 5px;
137
+ right: auto;
138
+ left: 5px;
139
+ }
140
+ #yith-quick-view-content figure.woocommerce-product-gallery__wrapper > div:not(:first-child) {
141
+ display: none;
142
+ }
143
+
144
+ li.product .yith-wcqv-button .blockUI.blockOverlay:before {
145
+ background: none;
146
+ }
147
+
148
+ @media( max-width: 480px ) {
149
+ #yith-quick-view-content div.images,
150
+ #yith-quick-view-content div.summary {
151
+ width: 100%;
152
+ float: none;
153
+ }
154
+ #yith-quick-view-content div.summary {
155
+ margin: 0;
156
+ padding: 15px;
157
+ width: 100%;
158
+ float: left;
159
+ }
160
  }
includes/class.yith-wcqv-admin.php CHANGED
@@ -1,240 +1,240 @@
1
- <?php
2
- /**
3
- * Admin class
4
- *
5
- * @author YITH
6
- * @package YITH WooCommerce Quick View
7
- * @version 1.1.1
8
- */
9
-
10
- defined( 'YITH_WCQV' ) || exit; // Exit if accessed directly.
11
-
12
- if ( ! class_exists( 'YITH_WCQV_Admin' ) ) {
13
- /**
14
- * Admin class.
15
- * The class manage all the admin behaviors.
16
- *
17
- * @since 1.0.0
18
- */
19
- class YITH_WCQV_Admin {
20
-
21
- /**
22
- * Single instance of the class
23
- *
24
- * @since 1.0.0
25
- * @var YITH_WCQV_Admin
26
- */
27
- protected static $instance;
28
-
29
- /**
30
- * Plugin options
31
- *
32
- * @since 1.0.0
33
- * @var array
34
- * @access public
35
- */
36
- public $options = array();
37
-
38
- /**
39
- * Plugin version
40
- *
41
- * @since 1.0.0
42
- * @var string
43
- */
44
- public $version = YITH_WCQV_VERSION;
45
-
46
- /**
47
- * Panel Object
48
- *
49
- * @since 1.0.0
50
- * @var object $panel
51
- */
52
- protected $panel;
53
-
54
- /**
55
- * Premium tab template file name
56
- *
57
- * @since 1.0.0
58
- * @var string $premium
59
- */
60
- protected $premium = 'premium.php';
61
-
62
- /**
63
- * Premium version landing link
64
- *
65
- * @since 1.0.0
66
- * @var string
67
- */
68
- protected $premium_landing = 'https://yithemes.com/themes/plugins/yith-woocommerce-quick-view/';
69
-
70
- /**
71
- * Quick View panel page
72
- *
73
- * @since 1.0.0
74
- * @var string
75
- */
76
- protected $panel_page = 'yith_wcqv_panel';
77
-
78
- /**
79
- * Returns single instance of the class
80
- *
81
- * @since 1.0.0
82
- * @return YITH_WCQV_Admin
83
- */
84
- public static function get_instance() {
85
- if ( is_null( self::$instance ) ) {
86
- self::$instance = new self();
87
- }
88
-
89
- return self::$instance;
90
- }
91
-
92
- /**
93
- * Constructor
94
- *
95
- * @access public
96
- * @since 1.0.0
97
- */
98
- public function __construct() {
99
-
100
- // Add panel options.
101
- add_action( 'admin_menu', array( $this, 'register_panel' ), 5 );
102
-
103
- // Add action links.
104
- add_filter( 'plugin_action_links_' . plugin_basename( YITH_WCQV_DIR . '/' . basename( YITH_WCQV_FILE ) ), array( $this, 'action_links' ) );
105
- add_filter( 'yith_show_plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 5 );
106
-
107
- add_action( 'yith_quick_view_premium', array( $this, 'premium_tab' ) );
108
-
109
- // YITH WCQV Loaded!
110
- do_action( 'yith_wcqv_loaded' );
111
-
112
- }
113
-
114
-
115
- /**
116
- * Add the action links to plugin admin page
117
- *
118
- * @since 1.0
119
- * @author Andrea Grillo <andrea.grillo@yithemes.com>
120
- * @param array $links An array og plugin links.
121
- *
122
- * @return array
123
- * @use plugin_action_links_{$plugin_file_name}
124
- */
125
- public function action_links( $links ) {
126
- $links = yith_add_action_links( $links, $this->panel_page, false );
127
- return $links;
128
- }
129
-
130
- /**
131
- * Add a panel under YITH Plugins tab
132
- *
133
- * @since 1.0
134
- * @author Andrea Grillo <andrea.grillo@yithemes.com>
135
- * @use /Yit_Plugin_Panel class
136
- * @return void
137
- * @see plugin-fw/lib/yit-plugin-panel.php
138
- */
139
- public function register_panel() {
140
-
141
- if ( ! empty( $this->panel ) ) {
142
- return;
143
- }
144
-
145
- $admin_tabs = array(
146
- 'settings' => __( 'Settings', 'yith-woocommerce-quick-view' ),
147
- 'premium' => __( 'Premium Version', 'yith-woocommerce-quick-view' ),
148
- );
149
-
150
- $args = array(
151
- 'create_menu_page' => true,
152
- 'parent_slug' => '',
153
- 'page_title' => 'YITH WooCommerce Quick View',
154
- 'menu_title' => 'Quick View',
155
- 'capability' => 'manage_options',
156
- 'parent' => '',
157
- 'parent_page' => 'yith_plugin_panel',
158
- 'page' => $this->panel_page,
159
- 'admin-tabs' => $admin_tabs,
160
- 'options-path' => YITH_WCQV_DIR . '/plugin-options',
161
- 'class' => yith_set_wrapper_class(),
162
- 'plugin_slug' => YITH_WCQV_SLUG,
163
- );
164
-
165
- /* === Fixed: not updated theme === */
166
- if ( ! class_exists( 'YIT_Plugin_Panel_WooCommerce' ) ) {
167
- require_once 'plugin-fw/lib/yit-plugin-panel-wc.php';
168
- }
169
-
170
- $this->panel = new YIT_Plugin_Panel_WooCommerce( $args );
171
- }
172
-
173
- /**
174
- * Premium Tab Template
175
- *
176
- * Load the premium tab template on admin page
177
- *
178
- * @since 1.0
179
- * @author Andrea Grillo <andrea.grillo@yithemes.com>
180
- * @return void
181
- */
182
- public function premium_tab() {
183
- $premium_tab_template = YITH_WCQV_TEMPLATE_PATH . '/admin/' . $this->premium;
184
- if ( file_exists( $premium_tab_template ) ) {
185
- include_once $premium_tab_template;
186
- }
187
-
188
- }
189
-
190
- /**
191
- * Plugin Row Meta
192
- *
193
- * @since 1.0
194
- * @author Andrea Grillo <andrea.grillo@yithemes.com>
195
- * @use plugin_row_meta
196
- * @param array $new_row_meta_args An array of plugin row meta.
197
- * @param string[] $plugin_meta An array of the plugin's metadata,
198
- * including the version, author,
199
- * author URI, and plugin URI.
200
- * @param string $plugin_file Path to the plugin file relative to the plugins directory.
201
- * @param array $plugin_data An array of plugin data.
202
- * @param string $status Status of the plugin. Defaults are 'All', 'Active',
203
- * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
204
- * 'Drop-ins', 'Search', 'Paused'.
205
- *
206
- * @return array
207
- */
208
- public function plugin_row_meta( $new_row_meta_args, $plugin_meta, $plugin_file, $plugin_data, $status ) {
209
- if ( defined( 'YITH_WCQV_INIT' ) && YITH_WCQV_INIT === $plugin_file ) {
210
- $new_row_meta_args['slug'] = YITH_WCQV_SLUG;
211
-
212
- if ( defined( 'YITH_WCQV_PREMIUM' ) ) {
213
- $new_row_meta_args['is_premium'] = true;
214
- }
215
- }
216
- return $new_row_meta_args;
217
- }
218
-
219
- /**
220
- * Get the premium landing uri
221
- *
222
- * @since 1.0.0
223
- * @author Andrea Grillo <andrea.grillo@yithemes.com>
224
- * @return string The premium landing link
225
- */
226
- public function get_premium_landing_uri() {
227
- return apply_filters( 'yith_plugin_fw_premium_landing_uri', $this->premium_landing, YITH_WCQV_SLUG );
228
- }
229
-
230
- }
231
- }
232
- /**
233
- * Unique access to instance of YITH_WCQV_Admin class
234
- *
235
- * @since 1.0.0
236
- * @return YITH_WCQV_Admin
237
- */
238
- function YITH_WCQV_Admin() { // phpcs:ignore
239
- return YITH_WCQV_Admin::get_instance();
240
- }
1
+ <?php
2
+ /**
3
+ * Admin class
4
+ *
5
+ * @author YITH
6
+ * @package YITH WooCommerce Quick View
7
+ * @version 1.1.1
8
+ */
9
+
10
+ defined( 'YITH_WCQV' ) || exit; // Exit if accessed directly.
11
+
12
+ if ( ! class_exists( 'YITH_WCQV_Admin' ) ) {
13
+ /**
14
+ * Admin class.
15
+ * The class manage all the admin behaviors.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ class YITH_WCQV_Admin {
20
+
21
+ /**
22
+ * Single instance of the class
23
+ *
24
+ * @since 1.0.0
25
+ * @var YITH_WCQV_Admin
26
+ */
27
+ protected static $instance;
28
+
29
+ /**
30
+ * Plugin options
31
+ *
32
+ * @since 1.0.0
33
+ * @var array
34
+ * @access public
35
+ */
36
+ public $options = array();
37
+
38
+ /**
39
+ * Plugin version
40
+ *
41
+ * @since 1.0.0
42
+ * @var string
43
+ */
44
+ public $version = YITH_WCQV_VERSION;
45
+
46
+ /**
47
+ * Panel Object
48
+ *
49
+ * @since 1.0.0
50
+ * @var object $panel
51
+ */
52
+ protected $panel;
53
+
54
+ /**
55
+ * Premium tab template file name
56
+ *
57
+ * @since 1.0.0
58
+ * @var string $premium
59
+ */
60
+ protected $premium = 'premium.php';
61
+
62
+ /**
63
+ * Premium version landing link
64
+ *
65
+ * @since 1.0.0
66
+ * @var string
67
+ */
68
+ protected $premium_landing = 'https://yithemes.com/themes/plugins/yith-woocommerce-quick-view/';
69
+
70
+ /**
71
+ * Quick View panel page
72
+ *
73
+ * @since 1.0.0
74
+ * @var string
75
+ */
76
+ protected $panel_page = 'yith_wcqv_panel';
77
+
78
+ /**
79
+ * Returns single instance of the class
80
+ *
81
+ * @since 1.0.0
82
+ * @return YITH_WCQV_Admin
83
+ */
84
+ public static function get_instance() {
85
+ if ( is_null( self::$instance ) ) {
86
+ self::$instance = new self();
87
+ }
88
+
89
+ return self::$instance;
90
+ }
91
+
92
+ /**
93
+ * Constructor
94
+ *
95
+ * @access public
96
+ * @since 1.0.0
97
+ */
98
+ public function __construct() {
99
+
100
+ // Add panel options.
101
+ add_action( 'admin_menu', array( $this, 'register_panel' ), 5 );
102
+
103
+ // Add action links.
104
+ add_filter( 'plugin_action_links_' . plugin_basename( YITH_WCQV_DIR . '/' . basename( YITH_WCQV_FILE ) ), array( $this, 'action_links' ) );
105
+ add_filter( 'yith_show_plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 5 );
106
+
107
+ add_action( 'yith_quick_view_premium', array( $this, 'premium_tab' ) );
108
+
109
+ // YITH WCQV Loaded!
110
+ do_action( 'yith_wcqv_loaded' );
111
+
112
+ }
113
+
114
+
115
+ /**
116
+ * Add the action links to plugin admin page
117
+ *
118
+ * @since 1.0
119
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
120
+ * @param array $links An array og plugin links.
121
+ *
122
+ * @return array
123
+ * @use plugin_action_links_{$plugin_file_name}
124
+ */
125
+ public function action_links( $links ) {
126
+ $links = yith_add_action_links( $links, $this->panel_page, false );
127
+ return $links;
128
+ }
129
+
130
+ /**
131
+ * Add a panel under YITH Plugins tab
132
+ *
133
+ * @since 1.0
134
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
135
+ * @use /Yit_Plugin_Panel class
136
+ * @return void
137
+ * @see plugin-fw/lib/yit-plugin-panel.php
138
+ */
139
+ public function register_panel() {
140
+
141
+ if ( ! empty( $this->panel ) ) {
142
+ return;
143
+ }
144
+
145
+ $admin_tabs = array(
146
+ 'settings' => __( 'Settings', 'yith-woocommerce-quick-view' ),
147
+ 'premium' => __( 'Premium Version', 'yith-woocommerce-quick-view' ),
148
+ );
149
+
150
+ $args = array(
151
+ 'create_menu_page' => true,
152
+ 'parent_slug' => '',
153
+ 'page_title' => 'YITH WooCommerce Quick View',
154
+ 'menu_title' => 'Quick View',
155
+ 'capability' => 'manage_options',
156
+ 'parent' => '',
157
+ 'parent_page' => 'yith_plugin_panel',
158
+ 'page' => $this->panel_page,
159
+ 'admin-tabs' => $admin_tabs,
160
+ 'options-path' => YITH_WCQV_DIR . '/plugin-options',
161
+ 'class' => yith_set_wrapper_class(),
162
+ 'plugin_slug' => YITH_WCQV_SLUG,
163
+ );
164
+
165
+ /* === Fixed: not updated theme === */
166
+ if ( ! class_exists( 'YIT_Plugin_Panel_WooCommerce' ) ) {
167
+ require_once 'plugin-fw/lib/yit-plugin-panel-wc.php';
168
+ }
169
+
170
+ $this->panel = new YIT_Plugin_Panel_WooCommerce( $args );
171
+ }
172
+
173
+ /**
174
+ * Premium Tab Template
175
+ *
176
+ * Load the premium tab template on admin page
177
+ *
178
+ * @since 1.0
179
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
180
+ * @return void
181
+ */
182
+ public function premium_tab() {
183
+ $premium_tab_template = YITH_WCQV_TEMPLATE_PATH . '/admin/' . $this->premium;
184
+ if ( file_exists( $premium_tab_template ) ) {
185
+ include_once $premium_tab_template;
186
+ }
187
+
188
+ }
189
+
190
+ /**
191
+ * Plugin Row Meta
192
+ *
193
+ * @since 1.0
194
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
195
+ * @use plugin_row_meta
196
+ * @param array $new_row_meta_args An array of plugin row meta.
197
+ * @param string[] $plugin_meta An array of the plugin's metadata,
198
+ * including the version, author,
199
+ * author URI, and plugin URI.
200
+ * @param string $plugin_file Path to the plugin file relative to the plugins directory.
201
+ * @param array $plugin_data An array of plugin data.
202
+ * @param string $status Status of the plugin. Defaults are 'All', 'Active',
203
+ * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
204
+ * 'Drop-ins', 'Search', 'Paused'.
205
+ *
206
+ * @return array
207
+ */
208
+ public function plugin_row_meta( $new_row_meta_args, $plugin_meta, $plugin_file, $plugin_data, $status ) {
209
+ if ( defined( 'YITH_WCQV_INIT' ) && YITH_WCQV_INIT === $plugin_file ) {
210
+ $new_row_meta_args['slug'] = YITH_WCQV_SLUG;
211
+
212
+ if ( defined( 'YITH_WCQV_PREMIUM' ) ) {
213
+ $new_row_meta_args['is_premium'] = true;
214
+ }
215
+ }
216
+ return $new_row_meta_args;
217
+ }
218
+
219
+ /**
220
+ * Get the premium landing uri
221
+ *
222
+ * @since 1.0.0
223
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
224
+ * @return string The premium landing link
225
+ */
226
+ public function get_premium_landing_uri() {
227
+ return apply_filters( 'yith_plugin_fw_premium_landing_uri', $this->premium_landing, YITH_WCQV_SLUG );
228
+ }
229
+
230
+ }
231
+ }
232
+ /**
233
+ * Unique access to instance of YITH_WCQV_Admin class
234
+ *
235
+ * @since 1.0.0
236
+ * @return YITH_WCQV_Admin
237
+ */
238
+ function YITH_WCQV_Admin() { // phpcs:ignore
239
+ return YITH_WCQV_Admin::get_instance();
240
+ }
includes/class.yith-wcqv-frontend.php CHANGED
@@ -1,435 +1,435 @@
1
- <?php
2
- /**
3
- * Frontend class
4
- *
5
- * @author YITH
6
- * @package YITH WooCommerce Quick View
7
- * @version 1.1.1
8
- */
9
-
10
- defined( 'YITH_WCQV' ) || exit; // Exit if accessed directly.
11
-
12
- if ( ! class_exists( 'YITH_WCQV_Frontend' ) ) {
13
- /**
14
- * Admin class.
15
- * The class manage all the Frontend behaviors.
16
- *
17
- * @since 1.0.0
18
- */
19
- class YITH_WCQV_Frontend {
20
-
21
- /**
22
- * Single instance of the class
23
- *
24
- * @since 1.0.0
25
- * @var YITH_WCQV_Frontend
26
- */
27
- protected static $instance;
28
-
29
- /**
30
- * Plugin version
31
- *
32
- * @since 1.0.0
33
- * @var string
34
- */
35
- public $version = YITH_WCQV_VERSION;
36
-
37
- /**
38
- * Returns single instance of the class
39
- *
40
- * @since 1.0.0
41
- * @return YITH_WCQV_Frontend
42
- */
43
- public static function get_instance() {
44
- if ( is_null( self::$instance ) ) {
45
- self::$instance = new self();
46
- }
47
-
48
- return self::$instance;
49
- }
50
-
51
- /**
52
- * Constructor
53
- *
54
- * @access public
55
- * @since 1.0.0
56
- */
57
- public function __construct() {
58
-
59
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles_scripts' ) );
60
-
61
- // Enqueue gift card script.
62
- if ( defined( 'YITH_YWGC_FILE' ) ) {
63
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_gift_card_script' ) );
64
- }
65
-
66
- // Quick view AJAX.
67
- add_action( 'wp_ajax_yith_load_product_quick_view', array( $this, 'yith_load_product_quick_view_ajax' ) );
68
- add_action( 'wp_ajax_nopriv_yith_load_product_quick_view', array( $this, 'yith_load_product_quick_view_ajax' ) );
69
-
70
- // Load modal template.
71
- add_action( 'wp_footer', array( $this, 'yith_quick_view' ) );
72
-
73
- // Load action for product template.
74
- $this->yith_quick_view_action_template();
75
- // Add quick view button.
76
- add_action( 'init', array( $this, 'add_button' ) );
77
-
78
- add_shortcode( 'yith_quick_view', array( $this, 'quick_view_shortcode' ) );
79
- add_filter( 'woocommerce_add_to_cart_form_action', array( $this, 'avoid_redirect_to_single_page' ), 10, 1 );
80
- }
81
-
82
- /**
83
- * Enqueue styles and scripts
84
- *
85
- * @access public
86
- * @since 1.0.0
87
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
88
- * @return void
89
- */
90
- public function enqueue_styles_scripts() {
91
-
92
- $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
93
-
94
- wp_register_script( 'yith-wcqv-frontend', YITH_WCQV_ASSETS_URL . '/js/frontend' . $suffix . '.js', array( 'jquery' ), $this->version, true );
95
- wp_enqueue_script( 'yith-wcqv-frontend' );
96
- wp_enqueue_style( 'yith-quick-view', YITH_WCQV_ASSETS_URL . '/css/yith-quick-view.css', array(), $this->version );
97
-
98
- $background_modal = get_option( 'yith-wcqv-background-modal', '#ffffff' );
99
- $close_color = get_option( 'yith-wcqv-close-color', '#cdcdcd' );
100
- $close_color_hover = get_option( 'yith-wcqv-close-color-hover', '#ff0000' );
101
-
102
- $inline_style = "
103
- #yith-quick-view-modal .yith-wcqv-main{background:{$background_modal};}
104
- #yith-quick-view-close{color:{$close_color};}
105
- #yith-quick-view-close:hover{color:{$close_color_hover};}";
106
-
107
- wp_add_inline_style( 'yith-quick-view', $inline_style );
108
- }
109
-
110
-
111
- /**
112
- * Enqueue scripts for YITH WooCommerce Gift Cards
113
- *
114
- * @access public
115
- * @since 1.0.0
116
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
117
- * @return void
118
- */
119
- public function enqueue_gift_card_script() {
120
- if ( ! wp_script_is( 'ywgc-frontend' ) && apply_filters( 'yith_load_gift_card_script_pages_for_quick_view', is_shop() ) && version_compare( YITH_YWGC_VERSION, '3.0.0', '<' ) ) {
121
- wp_register_script( 'ywgc-frontend', YITH_YWGC_URL . 'assets/js/' . yit_load_js_file( 'ywgc-frontend.js' ), array( 'jquery', 'woocommerce' ), YITH_YWGC_VERSION, true );
122
- wp_enqueue_script( 'ywgc-frontend' );
123
- } elseif ( ! wp_script_is( 'ywgc-frontend' ) && apply_filters( 'yith_load_gift_card_script_pages_for_quick_view', is_shop() ) ) {
124
- wp_register_script( 'ywgc-frontend', YITH_YWGC_URL . 'assets/js/' . yit_load_js_file( 'ywgc-frontend.js' ), array( 'jquery', 'woocommerce', 'jquery-ui-datepicker', 'accounting' ), YITH_YWGC_VERSION, true );
125
-
126
- wp_localize_script(
127
- 'ywgc-frontend',
128
- 'ywgc_data',
129
- array(
130
- 'loader' => apply_filters( 'yith_gift_cards_loader', YITH_YWGC_ASSETS_URL . '/images/loading.gif' ),
131
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
132
- 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
133
- 'notice_target' => apply_filters( 'yith_ywgc_gift_card_notice_target', 'div.woocommerce' ),
134
- )
135
- );
136
-
137
- wp_enqueue_script( 'ywgc-frontend' );
138
- }
139
- }
140
-
141
- /**
142
- * Add quick view button hooks
143
- *
144
- * @since 1.5.0
145
- * @author Francesco Licandro
146
- * @return void
147
- */
148
- public function add_button() {
149
- if ( $this->is_proteo_add_to_cart_hover() ) {
150
- add_action( 'yith_proteo_products_loop_add_to_cart_actions', array( $this, 'yith_add_quick_view_button' ), 55 );
151
- } else {
152
- add_action( 'woocommerce_after_shop_loop_item', array( $this, 'yith_add_quick_view_button' ), 15 );
153
- }
154
-
155
- add_action( 'yith_wcwl_table_after_product_name', array( $this, 'add_quick_view_button_wishlist' ), 15 );
156
- }
157
-
158
-
159
- /**
160
- * Check if current theme is YITH Proteo and if the add to cart button is visible on image hover
161
- *
162
- * @since 1.6.7
163
- * @author Francesco Licandro
164
- * @return boolean
165
- */
166
- public function is_proteo_add_to_cart_hover() {
167
- return defined( 'YITH_PROTEO_VERSION' ) && 'hover' === get_theme_mod( 'yith_proteo_products_loop_add_to_cart_position', 'classic' );
168
- }
169
-
170
- /**
171
- * Add quick view button in wc product loop
172
- *
173
- * @access public
174
- * @since 1.0.0
175
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
176
- * @param integer|string $product_id The product id.
177
- * @param string $label The button label.
178
- * @param boolean $return True to return, false to echo.
179
- * @return string|void
180
- */
181
- public function yith_add_quick_view_button( $product_id = 0, $label = '', $return = false ) {
182
-
183
- global $product;
184
-
185
- if ( ! $product_id && $product instanceof WC_Product ) {
186
- $product_id = $product->get_id();
187
- }
188
-
189
- if ( ! apply_filters( 'yith_wcqv_show_quick_view_button', true, $product_id ) ) {
190
- return;
191
- }
192
-
193
- $button = '';
194
- if ( $product_id ) {
195
- if ( ! $label ) {
196
- $label = $this->get_button_label();
197
- }
198
-
199
- $button = '<a href="#" class="button yith-wcqv-button" data-product_id="' . esc_attr( $product_id ) . '">' . $label . '</a>';
200
- $button = apply_filters( 'yith_add_quick_view_button_html', $button, $label, $product );
201
- }
202
-
203
- if ( $return ) {
204
- return $button;
205
- }
206
-
207
- echo $button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
208
- }
209
-
210
- /**
211
- * Add quick view button in wishlist
212
- *
213
- * @since 1.5.1
214
- * @author Francesco Licandro
215
- * @param YITH_WCWL_Wishlist_Item $item THe wishlist item.
216
- * @return string|void
217
- */
218
- public function add_quick_view_button_wishlist( $item ) {
219
- if ( $item instanceof YITH_WCWL_Wishlist_Item ) {
220
- $this->yith_add_quick_view_button( $item->get_product_id() );
221
- }
222
- }
223
-
224
- /**
225
- * Enqueue scripts and pass variable to js used in quick view
226
- *
227
- * @access public
228
- * @since 1.0.0
229
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
230
- * @return bool
231
- */
232
- public function yith_woocommerce_quick_view() {
233
-
234
- wp_enqueue_script( 'wc-add-to-cart-variation' );
235
- if ( version_compare( WC()->version, '3.0.0', '>=' ) ) {
236
- if ( current_theme_supports( 'wc-product-gallery-zoom' ) ) {
237
- wp_enqueue_script( 'zoom' );
238
- }
239
- if ( current_theme_supports( 'wc-product-gallery-lightbox' ) ) {
240
- wp_enqueue_script( 'photoswipe-ui-default' );
241
- wp_enqueue_style( 'photoswipe-default-skin' );
242
- if ( has_action( 'wp_footer', 'woocommerce_photoswipe' ) === false ) {
243
- add_action( 'wp_footer', 'woocommerce_photoswipe', 15 );
244
- }
245
- }
246
- wp_enqueue_script( 'wc-single-product' );
247
- }
248
-
249
- // Enqueue WC Color and Label Variations style and script.
250
- wp_enqueue_script( 'yith_wccl_frontend' );
251
- wp_enqueue_style( 'yith_wccl_frontend' );
252
-
253
- // Allow user to load custom style and scripts!
254
- do_action( 'yith_quick_view_custom_style_scripts' );
255
-
256
- wp_localize_script(
257
- 'yith-wcqv-frontend',
258
- 'yith_qv',
259
- array(
260
- 'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ),
261
- 'loader' => apply_filters( 'yith_quick_view_loader_gif', YITH_WCQV_ASSETS_URL . '/image/qv-loader.gif' ),
262
- 'lang' => defined( 'ICL_LANGUAGE_CODE' ) ? ICL_LANGUAGE_CODE : '',
263
- )
264
- );
265
-
266
- return true;
267
- }
268
-
269
- /**
270
- * Ajax action to load product in quick view
271
- *
272
- * @access public
273
- * @since 1.0.0
274
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
275
- * @return void
276
- */
277
- public function yith_load_product_quick_view_ajax() {
278
- // phpcs:disable WordPress.Security.NonceVerification.Recommended
279
- if ( ! isset( $_REQUEST['product_id'] ) ) {
280
- die();
281
- }
282
-
283
- global $sitepress;
284
-
285
- $product_id = intval( $_REQUEST['product_id'] );
286
- $attributes = array();
287
-
288
- /**
289
- * WPML Suppot: Localize Ajax Call
290
- */
291
- $lang = isset( $_REQUEST['lang'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['lang'] ) ) : '';
292
- if ( defined( 'ICL_LANGUAGE_CODE' ) && $lang && isset( $sitepress ) ) {
293
- $sitepress->switch_lang( $lang, true );
294
- }
295
-
296
- // Set the main wp query for the product.
297
- wp( 'p=' . $product_id . '&post_type=product' );
298
-
299
- // Remove product thumbnails gallery.
300
- remove_action( 'woocommerce_product_thumbnails', 'woocommerce_show_product_thumbnails', 20 );
301
- // Change template for variable products.
302
- if ( isset( $GLOBALS['yith_wccl'] ) ) {
303
- $GLOBALS['yith_wccl']->obj = new YITH_WCCL_Frontend();
304
- $GLOBALS['yith_wccl']->obj->override();
305
- } elseif ( defined( 'YITH_WCCL_PREMIUM' ) && YITH_WCCL_PREMIUM && class_exists( 'YITH_WCCL_Frontend' ) ) {
306
- $attributes = YITH_WCCL_Frontend()->create_attributes_json( $product_id, true );
307
- }
308
- ob_start();
309
- wc_get_template( 'yith-quick-view-content.php', array(), '', YITH_WCQV_DIR . 'templates/' );
310
- $html = ob_get_contents(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
311
- ob_end_clean();
312
-
313
- wp_send_json(
314
- array(
315
- 'html' => $html,
316
- 'prod_attr' => $attributes,
317
- )
318
- );
319
-
320
- die();
321
- // phpcs:enable WordPress.Security.NonceVerification.Recommended
322
- }
323
-
324
- /**
325
- * Load quick view template
326
- *
327
- * @access public
328
- * @since 1.0.0
329
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
330
- * @return void
331
- */
332
- public function yith_quick_view() {
333
- $this->yith_woocommerce_quick_view();
334
- wc_get_template( 'yith-quick-view.php', array(), '', YITH_WCQV_DIR . 'templates/' );
335
- }
336
-
337
- /**
338
- * Load wc action for quick view product template
339
- *
340
- * @access public
341
- * @since 1.0.0
342
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
343
- * @return void
344
- */
345
- public function yith_quick_view_action_template() {
346
-
347
- // Image.
348
- add_action( 'yith_wcqv_product_image', 'woocommerce_show_product_sale_flash', 10 );
349
- add_action( 'yith_wcqv_product_image', 'woocommerce_show_product_images', 20 );
350
-
351
- // Summary.
352
- add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_title', 5 );
353
- add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_rating', 10 );
354
- add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_price', 15 );
355
- add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_excerpt', 20 );
356
- add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_add_to_cart', 25 );
357
- add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_meta', 30 );
358
- }
359
-
360
- /**
361
- * Get Quick View button label
362
- *
363
- * @since 1.2.0
364
- * @author Francesco Licandro
365
- * @return string
366
- */
367
- public function get_button_label() {
368
- $label = get_option( 'yith-wcqv-button-label' );
369
- $label = call_user_func( '__', $label, 'yith-woocommerce-quick-view' );
370
-
371
- return apply_filters( 'yith_wcqv_button_label', esc_html( $label ) );
372
- }
373
-
374
- /**
375
- * Quick View shortcode button
376
- *
377
- * @access public
378
- * @since 1.0.7
379
- * @author Francesco Licandro
380
- * @param array $atts An array of shortcode attributes.
381
- * @return string
382
- */
383
- public function quick_view_shortcode( $atts ) {
384
-
385
- $atts = shortcode_atts(
386
- array(
387
- 'product_id' => 0,
388
- 'label' => '',
389
- ),
390
- $atts
391
- );
392
-
393
- extract( $atts ); // phpcs:ignore
394
-
395
- return $this->yith_add_quick_view_button( intval( $product_id ), $label, true );
396
- }
397
-
398
- /**
399
- * Check if is quick view
400
- *
401
- * @access public
402
- * @since 1.3.1
403
- * @author Francesco Licandro <francesco.licandro@yithemes.com>
404
- * @return bool
405
- */
406
- public function yith_is_quick_view() {
407
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended
408
- return ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && 'yith_load_product_quick_view' === $_REQUEST['action'] );
409
- }
410
-
411
- /**
412
- * Avoid redirect to single product page on add to cart action in quick view
413
- *
414
- * @since 1.3.1
415
- * @author Francesco Licandro
416
- * @param string $value The redirect url value.
417
- * @return string
418
- */
419
- public function avoid_redirect_to_single_page( $value ) {
420
- if ( $this->yith_is_quick_view() ) {
421
- return '';
422
- }
423
- return $value;
424
- }
425
- }
426
- }
427
- /**
428
- * Unique access to instance of YITH_WCQV_Frontend class
429
- *
430
- * @since 1.0.0
431
- * @return YITH_WCQV_Frontend
432
- */
433
- function YITH_WCQV_Frontend() { // phpcs:ignore
434
- return YITH_WCQV_Frontend::get_instance();
435
- }
1
+ <?php
2
+ /**
3
+ * Frontend class
4
+ *
5
+ * @author YITH
6
+ * @package YITH WooCommerce Quick View
7
+ * @version 1.1.1
8
+ */
9
+
10
+ defined( 'YITH_WCQV' ) || exit; // Exit if accessed directly.
11
+
12
+ if ( ! class_exists( 'YITH_WCQV_Frontend' ) ) {
13
+ /**
14
+ * Admin class.
15
+ * The class manage all the Frontend behaviors.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ class YITH_WCQV_Frontend {
20
+
21
+ /**
22
+ * Single instance of the class
23
+ *
24
+ * @since 1.0.0
25
+ * @var YITH_WCQV_Frontend
26
+ */
27
+ protected static $instance;
28
+
29
+ /**
30
+ * Plugin version
31
+ *
32
+ * @since 1.0.0
33
+ * @var string
34
+ */
35
+ public $version = YITH_WCQV_VERSION;
36
+
37
+ /**
38
+ * Returns single instance of the class
39
+ *
40
+ * @since 1.0.0
41
+ * @return YITH_WCQV_Frontend
42
+ */
43
+ public static function get_instance() {
44
+ if ( is_null( self::$instance ) ) {
45
+ self::$instance = new self();
46
+ }
47
+
48
+ return self::$instance;
49
+ }
50
+
51
+ /**
52
+ * Constructor
53
+ *
54
+ * @access public
55
+ * @since 1.0.0
56
+ */
57
+ public function __construct() {
58
+
59
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles_scripts' ) );
60
+
61
+ // Enqueue gift card script.
62
+ if ( defined( 'YITH_YWGC_FILE' ) ) {
63
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_gift_card_script' ) );
64
+ }
65
+
66
+ // Quick view AJAX.
67
+ add_action( 'wp_ajax_yith_load_product_quick_view', array( $this, 'yith_load_product_quick_view_ajax' ) );
68
+ add_action( 'wp_ajax_nopriv_yith_load_product_quick_view', array( $this, 'yith_load_product_quick_view_ajax' ) );
69
+
70
+ // Load modal template.
71
+ add_action( 'wp_footer', array( $this, 'yith_quick_view' ) );
72
+
73
+ // Load action for product template.
74
+ $this->yith_quick_view_action_template();
75
+ // Add quick view button.
76
+ add_action( 'init', array( $this, 'add_button' ) );
77
+
78
+ add_shortcode( 'yith_quick_view', array( $this, 'quick_view_shortcode' ) );
79
+ add_filter( 'woocommerce_add_to_cart_form_action', array( $this, 'avoid_redirect_to_single_page' ), 10, 1 );
80
+ }
81
+
82
+ /**
83
+ * Enqueue styles and scripts
84
+ *
85
+ * @access public
86
+ * @since 1.0.0
87
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
88
+ * @return void
89
+ */
90
+ public function enqueue_styles_scripts() {
91
+
92
+ $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
93
+
94
+ wp_register_script( 'yith-wcqv-frontend', YITH_WCQV_ASSETS_URL . '/js/frontend' . $suffix . '.js', array( 'jquery' ), $this->version, true );
95
+ wp_enqueue_script( 'yith-wcqv-frontend' );
96
+ wp_enqueue_style( 'yith-quick-view', YITH_WCQV_ASSETS_URL . '/css/yith-quick-view.css', array(), $this->version );
97
+
98
+ $background_modal = get_option( 'yith-wcqv-background-modal', '#ffffff' );
99
+ $close_color = get_option( 'yith-wcqv-close-color', '#cdcdcd' );
100
+ $close_color_hover = get_option( 'yith-wcqv-close-color-hover', '#ff0000' );
101
+
102
+ $inline_style = "
103
+ #yith-quick-view-modal .yith-wcqv-main{background:{$background_modal};}
104
+ #yith-quick-view-close{color:{$close_color};}
105
+ #yith-quick-view-close:hover{color:{$close_color_hover};}";
106
+
107
+ wp_add_inline_style( 'yith-quick-view', $inline_style );
108
+ }
109
+
110
+
111
+ /**
112
+ * Enqueue scripts for YITH WooCommerce Gift Cards
113
+ *
114
+ * @access public
115
+ * @since 1.0.0
116
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
117
+ * @return void
118
+ */
119
+ public function enqueue_gift_card_script() {
120
+ if ( ! wp_script_is( 'ywgc-frontend' ) && apply_filters( 'yith_load_gift_card_script_pages_for_quick_view', is_shop() ) && version_compare( YITH_YWGC_VERSION, '3.0.0', '<' ) ) {
121
+ wp_register_script( 'ywgc-frontend', YITH_YWGC_URL . 'assets/js/' . yit_load_js_file( 'ywgc-frontend.js' ), array( 'jquery', 'woocommerce' ), YITH_YWGC_VERSION, true );
122
+ wp_enqueue_script( 'ywgc-frontend' );
123
+ } elseif ( ! wp_script_is( 'ywgc-frontend' ) && apply_filters( 'yith_load_gift_card_script_pages_for_quick_view', is_shop() ) ) {
124
+ wp_register_script( 'ywgc-frontend', YITH_YWGC_URL . 'assets/js/' . yit_load_js_file( 'ywgc-frontend.js' ), array( 'jquery', 'woocommerce', 'jquery-ui-datepicker', 'accounting' ), YITH_YWGC_VERSION, true );
125
+
126
+ wp_localize_script(
127
+ 'ywgc-frontend',
128
+ 'ywgc_data',
129
+ array(
130
+ 'loader' => apply_filters( 'yith_gift_cards_loader', YITH_YWGC_ASSETS_URL . '/images/loading.gif' ),
131
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
132
+ 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
133
+ 'notice_target' => apply_filters( 'yith_ywgc_gift_card_notice_target', 'div.woocommerce' ),
134
+ )
135
+ );
136
+
137
+ wp_enqueue_script( 'ywgc-frontend' );
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Add quick view button hooks
143
+ *
144
+ * @since 1.5.0
145
+ * @author Francesco Licandro
146
+ * @return void
147
+ */
148
+ public function add_button() {
149
+ if ( $this->is_proteo_add_to_cart_hover() ) {
150
+ add_action( 'yith_proteo_products_loop_add_to_cart_actions', array( $this, 'yith_add_quick_view_button' ), 55 );
151
+ } else {
152
+ add_action( 'woocommerce_after_shop_loop_item', array( $this, 'yith_add_quick_view_button' ), 15 );
153
+ }
154
+
155
+ add_action( 'yith_wcwl_table_after_product_name', array( $this, 'add_quick_view_button_wishlist' ), 15 );
156
+ }
157
+
158
+
159
+ /**
160
+ * Check if current theme is YITH Proteo and if the add to cart button is visible on image hover
161
+ *
162
+ * @since 1.6.7
163
+ * @author Francesco Licandro
164
+ * @return boolean
165
+ */
166
+ public function is_proteo_add_to_cart_hover() {
167
+ return defined( 'YITH_PROTEO_VERSION' ) && 'hover' === get_theme_mod( 'yith_proteo_products_loop_add_to_cart_position', 'classic' );
168
+ }
169
+
170
+ /**
171
+ * Add quick view button in wc product loop
172
+ *
173
+ * @access public
174
+ * @since 1.0.0
175
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
176
+ * @param integer|string $product_id The product id.
177
+ * @param string $label The button label.
178
+ * @param boolean $return True to return, false to echo.
179
+ * @return string|void
180
+ */
181
+ public function yith_add_quick_view_button( $product_id = 0, $label = '', $return = false ) {
182
+
183
+ global $product;
184
+
185
+ if ( ! $product_id && $product instanceof WC_Product ) {
186
+ $product_id = $product->get_id();
187
+ }
188
+
189
+ if ( ! apply_filters( 'yith_wcqv_show_quick_view_button', true, $product_id ) ) {
190
+ return;
191
+ }
192
+
193
+ $button = '';
194
+ if ( $product_id ) {
195
+ if ( ! $label ) {
196
+ $label = $this->get_button_label();
197
+ }
198
+
199
+ $button = '<a href="#" class="button yith-wcqv-button" data-product_id="' . esc_attr( $product_id ) . '">' . $label . '</a>';
200
+ $button = apply_filters( 'yith_add_quick_view_button_html', $button, $label, $product );
201
+ }
202
+
203
+ if ( $return ) {
204
+ return $button;
205
+ }
206
+
207
+ echo $button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
208
+ }
209
+
210
+ /**
211
+ * Add quick view button in wishlist
212
+ *
213
+ * @since 1.5.1
214
+ * @author Francesco Licandro
215
+ * @param YITH_WCWL_Wishlist_Item $item THe wishlist item.
216
+ * @return string|void
217
+ */
218
+ public function add_quick_view_button_wishlist( $item ) {
219
+ if ( $item instanceof YITH_WCWL_Wishlist_Item ) {
220
+ $this->yith_add_quick_view_button( $item->get_product_id() );
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Enqueue scripts and pass variable to js used in quick view
226
+ *
227
+ * @access public
228
+ * @since 1.0.0
229
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
230
+ * @return bool
231
+ */
232
+ public function yith_woocommerce_quick_view() {
233
+
234
+ wp_enqueue_script( 'wc-add-to-cart-variation' );
235
+ if ( version_compare( WC()->version, '3.0.0', '>=' ) ) {
236
+ if ( current_theme_supports( 'wc-product-gallery-zoom' ) ) {
237
+ wp_enqueue_script( 'zoom' );
238
+ }
239
+ if ( current_theme_supports( 'wc-product-gallery-lightbox' ) ) {
240
+ wp_enqueue_script( 'photoswipe-ui-default' );
241
+ wp_enqueue_style( 'photoswipe-default-skin' );
242
+ if ( has_action( 'wp_footer', 'woocommerce_photoswipe' ) === false ) {
243
+ add_action( 'wp_footer', 'woocommerce_photoswipe', 15 );
244
+ }
245
+ }
246
+ wp_enqueue_script( 'wc-single-product' );
247
+ }
248
+
249
+ // Enqueue WC Color and Label Variations style and script.
250
+ wp_enqueue_script( 'yith_wccl_frontend' );
251
+ wp_enqueue_style( 'yith_wccl_frontend' );
252
+
253
+ // Allow user to load custom style and scripts!
254
+ do_action( 'yith_quick_view_custom_style_scripts' );
255
+
256
+ wp_localize_script(
257
+ 'yith-wcqv-frontend',
258
+ 'yith_qv',
259
+ array(
260
+ 'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ),
261
+ 'loader' => apply_filters( 'yith_quick_view_loader_gif', YITH_WCQV_ASSETS_URL . '/image/qv-loader.gif' ),
262
+ 'lang' => defined( 'ICL_LANGUAGE_CODE' ) ? ICL_LANGUAGE_CODE : '',
263
+ )
264
+ );
265
+
266
+ return true;
267
+ }
268
+
269
+ /**
270
+ * Ajax action to load product in quick view
271
+ *
272
+ * @access public
273
+ * @since 1.0.0
274
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
275
+ * @return void
276
+ */
277
+ public function yith_load_product_quick_view_ajax() {
278
+ // phpcs:disable WordPress.Security.NonceVerification.Recommended
279
+ if ( ! isset( $_REQUEST['product_id'] ) ) {
280
+ die();
281
+ }
282
+
283
+ global $sitepress;
284
+
285
+ $product_id = intval( $_REQUEST['product_id'] );
286
+ $attributes = array();
287
+
288
+ /**
289
+ * WPML Suppot: Localize Ajax Call
290
+ */
291
+ $lang = isset( $_REQUEST['lang'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['lang'] ) ) : '';
292
+ if ( defined( 'ICL_LANGUAGE_CODE' ) && $lang && isset( $sitepress ) ) {
293
+ $sitepress->switch_lang( $lang, true );
294
+ }
295
+
296
+ // Set the main wp query for the product.
297
+ wp( 'p=' . $product_id . '&post_type=product' );
298
+
299
+ // Remove product thumbnails gallery.
300
+ remove_action( 'woocommerce_product_thumbnails', 'woocommerce_show_product_thumbnails', 20 );
301
+ // Change template for variable products.
302
+ if ( isset( $GLOBALS['yith_wccl'] ) ) {
303
+ $GLOBALS['yith_wccl']->obj = new YITH_WCCL_Frontend();
304
+ $GLOBALS['yith_wccl']->obj->override();
305
+ } elseif ( defined( 'YITH_WCCL_PREMIUM' ) && YITH_WCCL_PREMIUM && class_exists( 'YITH_WCCL_Frontend' ) ) {
306
+ $attributes = YITH_WCCL_Frontend()->create_attributes_json( $product_id, true );
307
+ }
308
+ ob_start();
309
+ wc_get_template( 'yith-quick-view-content.php', array(), '', YITH_WCQV_DIR . 'templates/' );
310
+ $html = ob_get_contents(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
311
+ ob_end_clean();
312
+
313
+ wp_send_json(
314
+ array(
315
+ 'html' => $html,
316
+ 'prod_attr' => $attributes,
317
+ )
318
+ );
319
+
320
+ die();
321
+ // phpcs:enable WordPress.Security.NonceVerification.Recommended
322
+ }
323
+
324
+ /**
325
+ * Load quick view template
326
+ *
327
+ * @access public
328
+ * @since 1.0.0
329
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
330
+ * @return void
331
+ */
332
+ public function yith_quick_view() {
333
+ $this->yith_woocommerce_quick_view();
334
+ wc_get_template( 'yith-quick-view.php', array(), '', YITH_WCQV_DIR . 'templates/' );
335
+ }
336
+
337
+ /**
338
+ * Load wc action for quick view product template
339
+ *
340
+ * @access public
341
+ * @since 1.0.0
342
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
343
+ * @return void
344
+ */
345
+ public function yith_quick_view_action_template() {
346
+
347
+ // Image.
348
+ add_action( 'yith_wcqv_product_image', 'woocommerce_show_product_sale_flash', 10 );
349
+ add_action( 'yith_wcqv_product_image', 'woocommerce_show_product_images', 20 );
350
+
351
+ // Summary.
352
+ add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_title', 5 );
353
+ add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_rating', 10 );
354
+ add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_price', 15 );
355
+ add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_excerpt', 20 );
356
+ add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_add_to_cart', 25 );
357
+ add_action( 'yith_wcqv_product_summary', 'woocommerce_template_single_meta', 30 );
358
+ }
359
+
360
+ /**
361
+ * Get Quick View button label
362
+ *
363
+ * @since 1.2.0
364
+ * @author Francesco Licandro
365
+ * @return string
366
+ */
367
+ public function get_button_label() {
368
+ $label = get_option( 'yith-wcqv-button-label' );
369
+ $label = call_user_func( '__', $label, 'yith-woocommerce-quick-view' );
370
+
371
+ return apply_filters( 'yith_wcqv_button_label', esc_html( $label ) );
372
+ }
373
+
374
+ /**
375
+ * Quick View shortcode button
376
+ *
377
+ * @access public
378
+ * @since 1.0.7
379
+ * @author Francesco Licandro
380
+ * @param array $atts An array of shortcode attributes.
381
+ * @return string
382
+ */
383
+ public function quick_view_shortcode( $atts ) {
384
+
385
+ $atts = shortcode_atts(
386
+ array(
387
+ 'product_id' => 0,
388
+ 'label' => '',
389
+ ),
390
+ $atts
391
+ );
392
+
393
+ extract( $atts ); // phpcs:ignore
394
+
395
+ return $this->yith_add_quick_view_button( intval( $product_id ), $label, true );
396
+ }
397
+
398
+ /**
399
+ * Check if is quick view
400
+ *
401
+ * @access public
402
+ * @since 1.3.1
403
+ * @author Francesco Licandro <francesco.licandro@yithemes.com>
404
+ * @return bool
405
+ */
406
+ public function yith_is_quick_view() {
407
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
408
+ return ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && 'yith_load_product_quick_view' === $_REQUEST['action'] );
409
+ }
410
+
411
+ /**
412
+ * Avoid redirect to single product page on add to cart action in quick view
413
+ *
414
+ * @since 1.3.1
415
+ * @author Francesco Licandro
416
+ * @param string $value The redirect url value.
417
+ * @return string
418
+ */
419
+ public function avoid_redirect_to_single_page( $value ) {
420
+ if ( $this->yith_is_quick_view() ) {
421
+ return '';
422
+ }
423
+ return $value;
424
+ }
425
+ }
426
+ }
427
+ /**
428
+ * Unique access to instance of YITH_WCQV_Frontend class
429
+ *
430
+ * @since 1.0.0
431
+ * @return YITH_WCQV_Frontend
432
+ */
433
+ function YITH_WCQV_Frontend() { // phpcs:ignore
434
+ return YITH_WCQV_Frontend::get_instance();
435
+ }
includes/class.yith-wcqv.php CHANGED
@@ -1,164 +1,164 @@
1
- <?php
2
- /**
3
- * Main class
4
- *
5
- * @author YITH
6
- * @package YITH WooCommerce Quick View
7
- * @version 1.0.0
8
- */
9
-
10
- defined( 'YITH_WCQV' ) || exit; // Exit if accessed directly.
11
-
12
- if ( ! class_exists( 'YITH_WCQV' ) ) {
13
- /**
14
- * YITH WooCommerce Quick View
15
- *
16
- * @since 1.0.0
17
- */
18
- class YITH_WCQV {
19
-
20
- /**
21
- * Single instance of the class
22
- *
23
- * @since 1.0.0
24
- * @var YITH_WCQV
25
- */
26
- protected static $instance;
27
-
28
- /**
29
- * Plugin version
30
- *
31
- * @since 1.0.0
32
- * @var string
33
- */
34
- public $version = YITH_WCQV_VERSION;
35
-
36
- /**
37
- * Plugin object
38
- *
39
- * @since 1.0.0
40
- * @var string
41
- */
42
- public $obj = null;
43
-
44
- /**
45
- * Returns single instance of the class
46
- *
47
- * @since 1.0.0
48
- * @return YITH_WCQV
49
- */
50
- public static function get_instance() {
51
- if ( is_null( self::$instance ) ) {
52
- self::$instance = new self();
53
- }
54
-
55
- return self::$instance;
56
- }
57
-
58
- /**
59
- * Constructor
60
- *
61
- * @since 1.0.0
62
- * @return void
63
- */
64
- public function __construct() {
65
-
66
- // Load Plugin Framework.
67
- add_action( 'after_setup_theme', array( $this, 'plugin_fw_loader' ), 1 );
68
-
69
- if ( $this->can_load() ) {
70
- if ( $this->is_admin() ) {
71
- require_once 'class.yith-wcqv-admin.php';
72
- YITH_WCQV_Admin();
73
- }
74
- if ( $this->load_frontend() ) {
75
- require_once 'class.yith-wcqv-frontend.php';
76
- YITH_WCQV_Frontend();
77
- }
78
- }
79
- }
80
-
81
- /**
82
- * Check if the plugin can load. Exit if is WooCommerce AJAX.
83
- *
84
- * @since 1.5
85
- * @author Francesco Licandro
86
- * @return boolean
87
- */
88
- public function can_load() {
89
- $action = array(
90
- 'woocommerce_get_refreshed_fragments',
91
- 'woocommerce_apply_coupon',
92
- 'woocommerce_remove_coupon',
93
- 'woocommerce_update_shipping_method',
94
- 'woocommerce_update_order_review',
95
- 'woocommerce_add_to_cart',
96
- 'woocommerce_checkout',
97
- );
98
-
99
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended
100
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], $action, true ) ) {
101
- return false;
102
- }
103
-
104
- return true;
105
- }
106
-
107
- /**
108
- * Check if context is admin
109
- *
110
- * @since 1.2.0
111
- * @author Francesco Licandro
112
- * @return boolean
113
- */
114
- public function is_admin() {
115
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended
116
- $is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['context'] ) && 'frontend' === $_REQUEST['context'] );
117
- return apply_filters( 'yith_wcqv_is_admin', is_admin() && ! $is_ajax );
118
- }
119
-
120
- /**
121
- * Check if load or not frontend
122
- *
123
- * @since 1.2.0
124
- * @author Francesco Licandro
125
- * @return boolean
126
- */
127
- public function load_frontend() {
128
- $enable = get_option( 'yith-wcqv-enable', 'yes' ) === 'yes';
129
- $enable_on_mobile = get_option( 'yith-wcqv-enable-mobile', 'yes' ) === 'yes';
130
- $is_mobile = wp_is_mobile();
131
-
132
- return apply_filters( 'yith_wcqv_load_frontend', ( ! $is_mobile && $enable ) || ( $is_mobile && $enable_on_mobile ) );
133
- }
134
-
135
-
136
- /**
137
- * Load Plugin Framework
138
- *
139
- * @since 1.0
140
- * @access public
141
- * @author Andrea Grillo <andrea.grillo@yithemes.com>
142
- * @return void
143
- */
144
- public function plugin_fw_loader() {
145
- if ( ! defined( 'YIT_CORE_PLUGIN' ) ) {
146
- global $plugin_fw_data;
147
- if ( ! empty( $plugin_fw_data ) ) {
148
- $plugin_fw_file = array_shift( $plugin_fw_data );
149
- require_once $plugin_fw_file;
150
- }
151
- }
152
- }
153
- }
154
- }
155
-
156
- /**
157
- * Unique access to instance of YITH_WCQV class
158
- *
159
- * @since 1.0.0
160
- * @return YITH_WCQV
161
- */
162
- function YITH_WCQV() { // phpcs:ignore
163
- return YITH_WCQV::get_instance();
164
- }
1
+ <?php
2
+ /**
3
+ * Main class
4
+ *
5
+ * @author YITH
6
+ * @package YITH WooCommerce Quick View
7
+ * @version 1.0.0
8
+ */
9
+
10
+ defined( 'YITH_WCQV' ) || exit; // Exit if accessed directly.
11
+
12
+ if ( ! class_exists( 'YITH_WCQV' ) ) {
13
+ /**
14
+ * YITH WooCommerce Quick View
15
+ *
16
+ * @since 1.0.0
17
+ */
18
+ class YITH_WCQV {
19
+
20
+ /**
21
+ * Single instance of the class
22
+ *
23
+ * @since 1.0.0
24
+ * @var YITH_WCQV
25
+ */
26
+ protected static $instance;
27
+
28
+ /**
29
+ * Plugin version
30
+ *
31
+ * @since 1.0.0
32
+ * @var string
33
+ */
34
+ public $version = YITH_WCQV_VERSION;
35
+
36
+ /**
37
+ * Plugin object
38
+ *
39
+ * @since 1.0.0
40
+ * @var string
41
+ */
42
+ public $obj = null;
43
+
44
+ /**
45
+ * Returns single instance of the class
46
+ *
47
+ * @since 1.0.0
48
+ * @return YITH_WCQV
49
+ */
50
+ public static function get_instance() {
51
+ if ( is_null( self::$instance ) ) {
52
+ self::$instance = new self();
53
+ }
54
+
55
+ return self::$instance;
56
+ }
57
+
58
+ /**
59
+ * Constructor
60
+ *
61
+ * @since 1.0.0
62
+ * @return void
63
+ */
64
+ public function __construct() {
65
+
66
+ // Load Plugin Framework.
67
+ add_action( 'after_setup_theme', array( $this, 'plugin_fw_loader' ), 1 );
68
+
69
+ if ( $this->can_load() ) {
70
+ if ( $this->is_admin() ) {
71
+ require_once 'class.yith-wcqv-admin.php';
72
+ YITH_WCQV_Admin();
73
+ }
74
+ if ( $this->load_frontend() ) {
75
+ require_once 'class.yith-wcqv-frontend.php';
76
+ YITH_WCQV_Frontend();
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Check if the plugin can load. Exit if is WooCommerce AJAX.
83
+ *
84
+ * @since 1.5
85
+ * @author Francesco Licandro
86
+ * @return boolean
87
+ */
88
+ public function can_load() {
89
+ $action = array(
90
+ 'woocommerce_get_refreshed_fragments',
91
+ 'woocommerce_apply_coupon',
92
+ 'woocommerce_remove_coupon',
93
+ 'woocommerce_update_shipping_method',
94
+ 'woocommerce_update_order_review',
95
+ 'woocommerce_add_to_cart',
96
+ 'woocommerce_checkout',
97
+ );
98
+
99
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
100
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], $action, true ) ) {
101
+ return false;
102
+ }
103
+
104
+ return true;
105
+ }
106
+
107
+ /**
108
+ * Check if context is admin
109
+ *
110
+ * @since 1.2.0
111
+ * @author Francesco Licandro
112
+ * @return boolean
113
+ */
114
+ public function is_admin() {
115
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
116
+ $is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['context'] ) && 'frontend' === $_REQUEST['context'] );
117
+ return apply_filters( 'yith_wcqv_is_admin', is_admin() && ! $is_ajax );
118
+ }
119
+
120
+ /**
121
+ * Check if load or not frontend
122
+ *
123
+ * @since 1.2.0
124
+ * @author Francesco Licandro
125
+ * @return boolean
126
+ */
127
+ public function load_frontend() {
128
+ $enable = get_option( 'yith-wcqv-enable', 'yes' ) === 'yes';
129
+ $enable_on_mobile = get_option( 'yith-wcqv-enable-mobile', 'yes' ) === 'yes';
130
+ $is_mobile = wp_is_mobile();
131
+
132
+ return apply_filters( 'yith_wcqv_load_frontend', ( ! $is_mobile && $enable ) || ( $is_mobile && $enable_on_mobile ) );
133
+ }
134
+
135
+
136
+ /**
137
+ * Load Plugin Framework
138
+ *
139
+ * @since 1.0
140
+ * @access public
141
+ * @author Andrea Grillo <andrea.grillo@yithemes.com>
142
+ * @return void
143
+ */
144
+ public function plugin_fw_loader() {
145
+ if ( ! defined( 'YIT_CORE_PLUGIN' ) ) {
146
+ global $plugin_fw_data;
147
+ if ( ! empty( $plugin_fw_data ) ) {
148
+ $plugin_fw_file = array_shift( $plugin_fw_data );
149
+ require_once $plugin_fw_file;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Unique access to instance of YITH_WCQV class
158
+ *
159
+ * @since 1.0.0
160
+ * @return YITH_WCQV
161
+ */
162
+ function YITH_WCQV() { // phpcs:ignore
163
+ return YITH_WCQV::get_instance();
164
+ }
init.php CHANGED
@@ -1,160 +1,160 @@
1
- <?php
2
- /**
3
- * Plugin Name: YITH WooCommerce Quick View
4
- * Plugin URI: https://yithemes.com/themes/plugins/yith-woocommerce-quick-view
5
- * Description: The <code><strong>YITH WooCommerce Quick View</strong></code> plugin allows your customers to have a quick look about products. <a href="https://yithemes.com/" target="_blank">Get more plugins for your e-commerce shop on <strong>YITH</strong></a>.
6
- * Version: 1.16.0
7
- * Author: YITH
8
- * Author URI: https://yithemes.com/
9
- * Text Domain: yith-woocommerce-quick-view
10
- * Domain Path: /languages/
11
- * WC requires at least: 6.4
12
- * WC tested up to: 6.6
13
- *
14
- * @author YITH
15
- * @package YITH WooCommerce Quick View
16
- * @version 1.16.0
17
- */
18
-
19
- /** Copyright 2015-2022 Your Inspiration Solutions (email : plugins@yithemes.com)
20
- *
21
- * This program is free software; you can redistribute it and/or modify
22
- * it under the terms of the GNU General Public License, version 2, as
23
- * published by the Free Software Foundation.
24
- *
25
- * This program is distributed in the hope that it will be useful,
26
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
- * GNU General Public License for more details.
29
- *
30
- * You should have received a copy of the GNU General Public License
31
- * along with this program; if not, write to the Free Software
32
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33
- */
34
-
35
- defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
36
-
37
- if ( ! function_exists( 'is_plugin_active' ) ) {
38
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
39
- }
40
-
41
- /**
42
- * Message if WooCommerce is not installed.
43
- *
44
- * @since 1.0.0
45
- * @author Francesco Licandro
46
- * @return void
47
- */
48
- function yith_wcqv_install_woocommerce_admin_notice() {
49
- ?>
50
- <div class="error">
51
- <p><?php esc_html_e( 'YITH WooCommerce Quick View is enabled but not effective. It requires WooCommerce in order to work.', 'yith-woocommerce-quick-view' ); ?></p>
52
- </div>
53
- <?php
54
- }
55
-
56
- /**
57
- * Message if Premium plugin is installed.
58
- *
59
- * @since 1.0.0
60
- * @author Francesco Licandro
61
- * @return void
62
- */
63
- function yith_wcqv_install_free_admin_notice() {
64
- ?>
65
- <div class="error">
66
- <p><?php esc_html_e( 'You can\'t activate the free version of YITH WooCommerce Quick View while you are using the premium one.', 'yith-woocommerce-quick-view' ); ?></p>
67
- </div>
68
- <?php
69
- }
70
-
71
- if ( ! function_exists( 'yith_plugin_registration_hook' ) ) {
72
- require_once 'plugin-fw/yit-plugin-registration-hook.php';
73
- }
74
- register_activation_hook( __FILE__, 'yith_plugin_registration_hook' );
75
-
76
-
77
- if ( ! defined( 'YITH_WCQV_VERSION' ) ) {
78
- define( 'YITH_WCQV_VERSION', '1.16.0' );
79
- }
80
-
81
- if ( ! defined( 'YITH_WCQV_FREE_INIT' ) ) {
82
- define( 'YITH_WCQV_FREE_INIT', plugin_basename( __FILE__ ) );
83
- }
84
-
85
- if ( ! defined( 'YITH_WCQV_INIT' ) ) {
86
- define( 'YITH_WCQV_INIT', plugin_basename( __FILE__ ) );
87
- }
88
-
89
- if ( ! defined( 'YITH_WCQV' ) ) {
90
- define( 'YITH_WCQV', true );
91
- }
92
-
93
- if ( ! defined( 'YITH_WCQV_FILE' ) ) {
94
- define( 'YITH_WCQV_FILE', __FILE__ );
95
- }
96
-
97
- if ( ! defined( 'YITH_WCQV_URL' ) ) {
98
- define( 'YITH_WCQV_URL', plugin_dir_url( __FILE__ ) );
99
- }
100
-
101
- if ( ! defined( 'YITH_WCQV_DIR' ) ) {
102
- define( 'YITH_WCQV_DIR', plugin_dir_path( __FILE__ ) );
103
- }
104
-
105
- if ( ! defined( 'YITH_WCQV_TEMPLATE_PATH' ) ) {
106
- define( 'YITH_WCQV_TEMPLATE_PATH', YITH_WCQV_DIR . 'templates' );
107
- }
108
-
109
- if ( ! defined( 'YITH_WCQV_ASSETS_URL' ) ) {
110
- define( 'YITH_WCQV_ASSETS_URL', YITH_WCQV_URL . 'assets' );
111
- }
112
-
113
- if ( ! defined( 'YITH_WCQV_SLUG' ) ) {
114
- define( 'YITH_WCQV_SLUG', 'yith-woocommerce-quick-view' );
115
- }
116
-
117
- /* Plugin Framework Version Check */
118
- if ( ! function_exists( 'yit_maybe_plugin_fw_loader' ) && file_exists( YITH_WCQV_DIR . 'plugin-fw/init.php' ) ) {
119
- require_once YITH_WCQV_DIR . 'plugin-fw/init.php';
120
- }
121
- yit_maybe_plugin_fw_loader( YITH_WCQV_DIR );
122
-
123
- /**
124
- * Init.
125
- *
126
- * @since 1.0.0
127
- * @author Francesco Licandro
128
- * @return void
129
- */
130
- function yith_wcqv_init() {
131
-
132
- load_plugin_textdomain( 'yith-woocommerce-quick-view', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
133
- // Load required classes and functions.
134
- require_once 'includes/class.yith-wcqv.php';
135
- // Let's start the game!
136
- YITH_WCQV();
137
- }
138
-
139
- add_action( 'yith_wcqv_init', 'yith_wcqv_init' );
140
-
141
- /**
142
- * Install.
143
- *
144
- * @since 1.0.0
145
- * @author Francesco Licandro
146
- * @return void
147
- */
148
- function yith_wcqv_install() {
149
-
150
- if ( ! function_exists( 'WC' ) ) {
151
- add_action( 'admin_notices', 'yith_wcqv_install_woocommerce_admin_notice' );
152
- } elseif ( defined( 'YITH_WCQV_PREMIUM' ) ) {
153
- add_action( 'admin_notices', 'yith_wcqv_install_free_admin_notice' );
154
- deactivate_plugins( plugin_basename( __FILE__ ) );
155
- } else {
156
- do_action( 'yith_wcqv_init' );
157
- }
158
- }
159
-
160
- add_action( 'plugins_loaded', 'yith_wcqv_install', 11 );
1
+ <?php
2
+ /**
3
+ * Plugin Name: YITH WooCommerce Quick View
4
+ * Plugin URI: https://yithemes.com/themes/plugins/yith-woocommerce-quick-view
5
+ * Description: The <code><strong>YITH WooCommerce Quick View</strong></code> plugin allows your customers to have a quick look about products. <a href="https://yithemes.com/" target="_blank">Get more plugins for your e-commerce shop on <strong>YITH</strong></a>.
6
+ * Version: 1.17.0
7
+ * Author: YITH
8
+ * Author URI: https://yithemes.com/
9
+ * Text Domain: yith-woocommerce-quick-view
10
+ * Domain Path: /languages/
11
+ * WC requires at least: 6.5
12
+ * WC tested up to: 6.7
13
+ *
14
+ * @author YITH
15
+ * @package YITH WooCommerce Quick View
16
+ * @version 1.17.0
17
+ */
18
+
19
+ /** Copyright 2015-2022 Your Inspiration Solutions (email : plugins@yithemes.com)
20
+ *
21
+ * This program is free software; you can redistribute it and/or modify
22
+ * it under the terms of the GNU General Public License, version 2, as
23
+ * published by the Free Software Foundation.
24
+ *
25
+ * This program is distributed in the hope that it will be useful,
26
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
+ * GNU General Public License for more details.
29
+ *
30
+ * You should have received a copy of the GNU General Public License
31
+ * along with this program; if not, write to the Free Software
32
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33
+ */
34
+
35
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
36
+
37
+ if ( ! function_exists( 'is_plugin_active' ) ) {
38
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
39
+ }
40
+
41
+ /**
42
+ * Message if WooCommerce is not installed.
43
+ *
44
+ * @since 1.0.0
45
+ * @author Francesco Licandro
46
+ * @return void
47
+ */
48
+ function yith_wcqv_install_woocommerce_admin_notice() {
49
+ ?>
50
+ <div class="error">
51
+ <p><?php esc_html_e( 'YITH WooCommerce Quick View is enabled but not effective. It requires WooCommerce in order to work.', 'yith-woocommerce-quick-view' ); ?></p>
52
+ </div>
53
+ <?php
54
+ }
55
+
56
+ /**
57
+ * Message if Premium plugin is installed.
58
+ *
59
+ * @since 1.0.0
60
+ * @author Francesco Licandro
61
+ * @return void
62
+ */
63
+ function yith_wcqv_install_free_admin_notice() {
64
+ ?>
65
+ <div class="error">
66
+ <p><?php esc_html_e( 'You can\'t activate the free version of YITH WooCommerce Quick View while you are using the premium one.', 'yith-woocommerce-quick-view' ); ?></p>
67
+ </div>
68
+ <?php
69
+ }
70
+
71
+ if ( ! function_exists( 'yith_plugin_registration_hook' ) ) {
72
+ require_once 'plugin-fw/yit-plugin-registration-hook.php';
73
+ }
74
+ register_activation_hook( __FILE__, 'yith_plugin_registration_hook' );
75
+
76
+
77
+ if ( ! defined( 'YITH_WCQV_VERSION' ) ) {
78
+ define( 'YITH_WCQV_VERSION', '1.17.0' );
79
+ }
80
+
81
+ if ( ! defined( 'YITH_WCQV_FREE_INIT' ) ) {
82
+ define( 'YITH_WCQV_FREE_INIT', plugin_basename( __FILE__ ) );
83
+ }
84
+
85
+ if ( ! defined( 'YITH_WCQV_INIT' ) ) {
86
+ define( 'YITH_WCQV_INIT', plugin_basename( __FILE__ ) );
87
+ }
88
+
89
+ if ( ! defined( 'YITH_WCQV' ) ) {
90
+ define( 'YITH_WCQV', true );
91
+ }
92
+
93
+ if ( ! defined( 'YITH_WCQV_FILE' ) ) {
94
+ define( 'YITH_WCQV_FILE', __FILE__ );
95
+ }
96
+
97
+ if ( ! defined( 'YITH_WCQV_URL' ) ) {
98
+ define( 'YITH_WCQV_URL', plugin_dir_url( __FILE__ ) );
99
+ }
100
+
101
+ if ( ! defined( 'YITH_WCQV_DIR' ) ) {
102
+ define( 'YITH_WCQV_DIR', plugin_dir_path( __FILE__ ) );
103
+ }
104
+
105
+ if ( ! defined( 'YITH_WCQV_TEMPLATE_PATH' ) ) {
106
+ define( 'YITH_WCQV_TEMPLATE_PATH', YITH_WCQV_DIR . 'templates' );
107
+ }
108
+
109
+ if ( ! defined( 'YITH_WCQV_ASSETS_URL' ) ) {
110
+ define( 'YITH_WCQV_ASSETS_URL', YITH_WCQV_URL . 'assets' );
111
+ }
112
+
113
+ if ( ! defined( 'YITH_WCQV_SLUG' ) ) {
114
+ define( 'YITH_WCQV_SLUG', 'yith-woocommerce-quick-view' );
115
+ }
116
+
117
+ /* Plugin Framework Version Check */
118
+ if ( ! function_exists( 'yit_maybe_plugin_fw_loader' ) && file_exists( YITH_WCQV_DIR . 'plugin-fw/init.php' ) ) {
119
+ require_once YITH_WCQV_DIR . 'plugin-fw/init.php';
120
+ }
121
+ yit_maybe_plugin_fw_loader( YITH_WCQV_DIR );
122
+
123
+ /**
124
+ * Init.
125
+ *
126
+ * @since 1.0.0
127
+ * @author Francesco Licandro
128
+ * @return void
129
+ */
130
+ function yith_wcqv_init() {
131
+
132
+ load_plugin_textdomain( 'yith-woocommerce-quick-view', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
133
+ // Load required classes and functions.
134
+ require_once 'includes/class.yith-wcqv.php';
135
+ // Let's start the game!
136
+ YITH_WCQV();
137
+ }
138
+
139
+ add_action( 'yith_wcqv_init', 'yith_wcqv_init' );
140
+
141
+ /**
142
+ * Install.
143
+ *
144
+ * @since 1.0.0
145
+ * @author Francesco Licandro
146
+ * @return void
147
+ */
148
+ function yith_wcqv_install() {
149
+
150
+ if ( ! function_exists( 'WC' ) ) {
151
+ add_action( 'admin_notices', 'yith_wcqv_install_woocommerce_admin_notice' );
152
+ } elseif ( defined( 'YITH_WCQV_PREMIUM' ) ) {
153
+ add_action( 'admin_notices', 'yith_wcqv_install_free_admin_notice' );
154
+ deactivate_plugins( plugin_basename( __FILE__ ) );
155
+ } else {
156
+ do_action( 'yith_wcqv_init' );
157
+ }
158
+ }
159
+
160
+ add_action( 'plugins_loaded', 'yith_wcqv_install', 11 );
languages/yith-woocommerce-quick-view-it_IT.po CHANGED
@@ -1,585 +1,585 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: YITH WooCommerce Quick View\n"
4
- "POT-Creation-Date: 2017-10-11 12:42+0200\n"
5
- "PO-Revision-Date: 2017-10-11 12:42+0200\n"
6
- "Last-Translator: \n"
7
- "Language-Team: YIThemes <plugins@yithemes.com>\n"
8
- "Language: it_IT\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.8.7.1\n"
13
- "X-Poedit-Basepath: .\n"
14
- "Plural-Forms: nplurals=2; plural=n!=1;\n"
15
- "X-Poedit-KeywordsList: __ ;_e;_n:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
16
- "_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
17
- "X-Poedit-SourceCharset: UTF-8\n"
18
- "X-Poedit-SearchPath-0: ..\n"
19
- "X-Poedit-SearchPathExcluded-0: ../plugin-fw\n"
20
-
21
- #: ../includes/class.yith-wcqv-admin.php:129
22
- #: ../includes/class.yith-wcqv-admin.php:151
23
- msgid "Settings"
24
- msgstr "Impostazioni"
25
-
26
- #: ../includes/class.yith-wcqv-admin.php:130
27
- #: ../includes/class.yith-wcqv-admin.php:152
28
- msgid "Premium Version"
29
- msgstr "Versione premium"
30
-
31
- #: ../includes/class.yith-wcqv-admin.php:158
32
- #: ../includes/class.yith-wcqv-admin.php:159
33
- #: ../plugin-options/settings-options.php:57
34
- msgid "Quick View"
35
- msgstr "Quick view"
36
-
37
- #: ../includes/class.yith-wcqv-admin.php:213
38
- msgid "Plugin Documentation"
39
- msgstr "Documentazione plugin"
40
-
41
- #: ../init.php:41
42
- msgid ""
43
- "YITH WooCommerce Quick View is enabled but not effective. It requires "
44
- "WooCommerce in order to work."
45
- msgstr ""
46
- "YITH WooCommerce Quick View è abilitato ma non in funzione. Devi aver "
47
- "installato WooCommerce perché questo possa funzionare correttamente."
48
-
49
- #: ../init.php:50
50
- msgid ""
51
- "You can't activate the free version of YITH WooCommerce Quick View while you "
52
- "are using the premium one."
53
- msgstr ""
54
- "Non è possibile attivare la versione free di YITH WooCommerce Colors and "
55
- "Labels Variations se stai già utilizzando la premium."
56
-
57
- #: ../plugin-options/settings-options.php:8
58
- msgid "Upgrade to the PREMIUM VERSION"
59
- msgstr "Aggiorna alla VERSIONE PREMIUM"
60
-
61
- #: ../plugin-options/settings-options.php:11
62
- #: ../plugin-options/settings-options.php:18
63
- msgid "YITH WooCommerce Quick View"
64
- msgstr "YITH WooCommerce Quick View"
65
-
66
- #: ../plugin-options/settings-options.php:12
67
- msgid "Discover the Advanced Features"
68
- msgstr "Scopri le funzionalità avanzate"
69
-
70
- #: ../plugin-options/settings-options.php:13
71
- msgid ""
72
- "Upgrade to the PREMIUM VERSION of YITH WooCommerce Quick View to benefit "
73
- "from all features!"
74
- msgstr ""
75
- "Aggiorna alla VERSIONE PREMIUM di YITH WooCommerce Quick View per usufruire "
76
- "di tutte le sue funzionalità!"
77
-
78
- #: ../plugin-options/settings-options.php:20
79
- msgid "Get Support and Pro Features"
80
- msgstr "Ottieni supporto e funzionalità aggiuntive"
81
-
82
- #: ../plugin-options/settings-options.php:21
83
- msgid ""
84
- "By purchasing the premium version of the plugin, you will take advantage of "
85
- "the advanced features of the product and you will get one year of free "
86
- "updates and support through our platform available 24h/24."
87
- msgstr ""
88
- "Acquistando la versione premium del plugin, potrai beneficiare delle "
89
- "funzionalità avanzate del prodotto ed otterrai un anno di aggiornamenti "
90
- "gratuiti e supporto per mezzo della nostra piattaforma disponibile 24h/24."
91
-
92
- #: ../plugin-options/settings-options.php:31
93
- msgid "General Options"
94
- msgstr "Opzioni generali"
95
-
96
- #: ../plugin-options/settings-options.php:39
97
- msgid "Enable Quick View"
98
- msgstr "Abilita quick view"
99
-
100
- #: ../plugin-options/settings-options.php:46
101
- msgid "Enable Quick View on mobile"
102
- msgstr "Abilita quick view su dispositivi mobili"
103
-
104
- #: ../plugin-options/settings-options.php:47
105
- msgid "Enable quick view features on mobile device too"
106
- msgstr "Abilita funzionalità quick view anche sui dispositivi mobili"
107
-
108
- #: ../plugin-options/settings-options.php:54
109
- msgid "Quick View Button Label"
110
- msgstr "Testo pulsante quick view"
111
-
112
- #: ../plugin-options/settings-options.php:55
113
- msgid "Label for the quick view button in the WooCommerce loop."
114
- msgstr "Testo per il pulsante Quick view nella pagina shop di WooCommerce"
115
-
116
- #: ../plugin-options/settings-options.php:62
117
- msgid "Enable Lightbox"
118
- msgstr "Abilita lightbox"
119
-
120
- #: ../plugin-options/settings-options.php:63
121
- msgid "Enable lightbox. Product images will open in a lightbox."
122
- msgstr ""
123
- "Abilita la lightbox. Le immagini dei prodotti si apriranno in una lightbox."
124
-
125
- #: ../plugin-options/settings-options.php:74 ../templates/admin/premium.php:323
126
- #: ../templates/admin/premium.php:328
127
- msgid "Style Options"
128
- msgstr "Opzioni di stile"
129
-
130
- #: ../plugin-options/settings-options.php:81
131
- msgid "Modal Window Background Color"
132
- msgstr "Colore finestra modale"
133
-
134
- #: ../plugin-options/settings-options.php:89
135
- msgid "Closing Button Color"
136
- msgstr "Colore pulsante chiusura"
137
-
138
- #: ../plugin-options/settings-options.php:97
139
- msgid "Closing Button Hover Color"
140
- msgstr "Colore pulsante chiusura al passaggio del mouse"
141
-
142
- #: ../templates/admin/premium.php:210 ../templates/admin/premium.php:364
143
- #, php-format
144
- msgid ""
145
- "Upgrade to %1$spremium version%2$s of %1$sYITH WooCommerce Quick View%2$s to "
146
- "benefit from all features!"
147
- msgstr ""
148
- "Aggiorna alla %1$sversione premium%2$s di %1$sYITH WooCommerce Quick View"
149
- "%2$s per usufruire di tutte le sue funzionalità!"
150
-
151
- #: ../templates/admin/premium.php:213 ../templates/admin/premium.php:367
152
- msgid "UPGRADE"
153
- msgstr "AGGIORNA"
154
-
155
- #: ../templates/admin/premium.php:214 ../templates/admin/premium.php:368
156
- msgid "to the premium version"
157
- msgstr "alla versione premium"
158
-
159
- #: ../templates/admin/premium.php:220
160
- msgid "Premium Features"
161
- msgstr "Funzionalità premium"
162
-
163
- #: ../templates/admin/premium.php:223
164
- msgid "Button type"
165
- msgstr "Tipologia pulsante"
166
-
167
- #: ../templates/admin/premium.php:228
168
- msgid "BUTTON TYPE"
169
- msgstr "TIPOLOGIA PULSANTE"
170
-
171
- #: ../templates/admin/premium.php:230
172
- #, php-format
173
- msgid ""
174
- "Choose between the button or a custom icon to access the %1$sQuick View%2$s: "
175
- "you can choose to place it after the \"Add To Cart\" button or inside the "
176
- "thumbnail of the product."
177
- msgstr ""
178
- "Scegli tra il pulsante o un’icona personalizzata per avviare la %1$squick "
179
- "view%2$s: scegli tu se dopo il pulsante “Aggiungi al carrello” o sulla "
180
- "immagine thumbnail del prodotto."
181
-
182
- #: ../templates/admin/premium.php:238 ../templates/admin/premium.php:239
183
- #: ../templates/admin/premium.php:244
184
- msgid "Product Navigation"
185
- msgstr "Navigazione prodotti"
186
-
187
- #: ../templates/admin/premium.php:241
188
- #, php-format
189
- msgid ""
190
- "The navigation in the \"Quick View\" allows browsing among %1$sproducts%2$s "
191
- "displayed in it. The navigation arrows show on mousehover the image of the "
192
- "next/previous product."
193
- msgstr ""
194
- "La navigazione all’interno della visualizzazione rapida permette di scorrere "
195
- "tra i %1$sprodotti%2$s visualizzati. Quando si passa il cursore sulle frecce "
196
- "di navigazione, queste mostrano l’immagine del prodotto immediatamente "
197
- "successivo o precedente."
198
-
199
- #: ../templates/admin/premium.php:255 ../templates/admin/premium.php:256
200
- msgid "Content to display"
201
- msgstr "Contenuto da mostrare"
202
-
203
- #: ../templates/admin/premium.php:258
204
- #, php-format
205
- msgid ""
206
- "The display of the product information in the \"Quick View\" are managed by "
207
- "%1$sadministrators%2$s who can decide whether to show everything or only a "
208
- "part of it."
209
- msgstr ""
210
- "La visualizzazione delle informazioni del prodotto all’interno della “Quick "
211
- "View” sono gestite dall’%1$samministratore%2$s che può decidere se mostrare "
212
- "tutto o solo una parte di esse."
213
-
214
- #: ../templates/admin/premium.php:267
215
- msgid "Quick View Type"
216
- msgstr "Tipologia quick view"
217
-
218
- #: ../templates/admin/premium.php:269
219
- #, php-format
220
- msgid ""
221
- "Quick view has two different displaying modes: the first one opens it as a "
222
- "%1$smodal window%2$s, the other one opens it in the page itself with a "
223
- "%1$scascading effect%2$s above content page."
224
- msgstr ""
225
- "La visualizzazione rapida del prodotto può avvenire in due modi: all’interno "
226
- "di una %1$sfinestra modale%2$s o all’interno della stessa pagina con "
227
- "%1$seffetto a cascata%2$s sul resto del contenuto."
228
-
229
- #: ../templates/admin/premium.php:272
230
- msgid "Quick view type"
231
- msgstr "Tipologia quick view"
232
-
233
- #: ../templates/admin/premium.php:284
234
- msgid "\"View details\" button"
235
- msgstr "Pulsante “Visualizza dettagli”"
236
-
237
- #: ../templates/admin/premium.php:286
238
- msgid ""
239
- "An additional button that allows users to access product detail page "
240
- "directly from quick view window just with a click of the mouse."
241
- msgstr ""
242
- "Un pulsante aggiuntivo per permettere all’utente di accedere alla pagina "
243
- "dettaglio del prodotto direttamente dalla quick view con un semplice clic."
244
-
245
- #: ../templates/admin/premium.php:295
246
- msgid "Type of product images"
247
- msgstr "Tipologia immagini prodotto"
248
-
249
- #: ../templates/admin/premium.php:297
250
- #, php-format
251
- msgid ""
252
- "Each product can have more than one image: choose whether to hide or show "
253
- "them with the %1$sslider%2$s effect or in the classic %1$sWooCommerce%2$s "
254
- "display."
255
- msgstr ""
256
- "Ogni prodotto può avere ulteriori immagini oltre a quella in evidenza: "
257
- "scegli se nasconderle o mostrarle con %1$seffetto scorrimento%2$s o nella "
258
- "classica visualizzazione di %1$sWooCommerce%2$s."
259
-
260
- #: ../templates/admin/premium.php:312
261
- msgid "SHARE"
262
- msgstr "Condivisione"
263
-
264
- #: ../templates/admin/premium.php:314
265
- #, php-format
266
- msgid ""
267
- "%1$sQuick View is also social-friendly!%2$s Activating this option, you will "
268
- "be able to share the Quick View on Facebook, Twitter, Pinterest, Google+, or "
269
- "sending an email."
270
- msgstr ""
271
- "%1$sLa quick view è anche social%2$s! Abilitando l’opzione, potrà essere "
272
- "condivisa su Facebook, Twitter, Pinterest, Google+ e per email."
273
-
274
- #: ../templates/admin/premium.php:325
275
- #, php-format
276
- msgid ""
277
- "A rich option panel to change the colors of the %1$s\"Quick View\"%2$s "
278
- "button and of everything that is within the modal window generated."
279
- msgstr ""
280
- "Un ricco pannello opzioni per modificare i colori del pulsante %1$s“Quick "
281
- "View”%2$s e di tutto ciò che è all’interno della finestra modale generata."
282
-
283
- #: ../templates/admin/premium.php:340
284
- msgid "SHORTCODE"
285
- msgstr ""
286
-
287
- #: ../templates/admin/premium.php:342
288
- msgid ""
289
- "The shortcode of plugin is a $1$srapid$2$s and $1$seasy$2$s solution: you "
290
- "can add a button in any spot of the page to allow your users to see the "
291
- "quick view of a specific product in your store."
292
- msgstr ""
293
-
294
- #: ../templates/admin/premium.php:351
295
- msgid "Compatibility with other YITH's plugins"
296
- msgstr ""
297
-
298
- #: ../templates/admin/premium.php:353
299
- #, php-format
300
- msgid ""
301
- "Thanks to the compatibility with %1$sYITH WooCommerce Zoom Magnifier, YITH "
302
- "WooCommerce Badge Management%2$s and %1$sYITH WooCommerce Wishlist%2$s, you "
303
- "will be free to enrich further the content of your quick view.%3$s Zoom the "
304
- "product image, show a badge, or add the button to open the quick view in all "
305
- "products available in your users' wishlists. With YITH's plugins you make "
306
- "the difference."
307
- msgstr ""
308
-
309
- #~ msgid ""
310
- #~ "In the YIT Plugin tab you can find the YITH WooCommerce Quick View "
311
- #~ "options.\r\n"
312
- #~ "\t\t\t\t\t\t\t\t\t\tWith this menu, you can access to all the settings of "
313
- #~ "our plugins that you have activated.\r\n"
314
- #~ "\t\t\t\t\t\t\t\t\t\tYITH WooCommerce Quick View is available in an "
315
- #~ "outstanding PREMIUM version with many new options,\r\n"
316
- #~ "\t\t\t\t\t\t\t\t\t\t<a href=\""
317
- #~ msgstr ""
318
- #~ "Nella scheda YIT Plugins puoi trovare tutte le opzioni di YITH "
319
- #~ "WooCommerce Quick View.<br>Da questo menu potrai accedere a tutte le "
320
- #~ "impostazioni dei plugin YITH installati."
321
-
322
- #~ msgid ""
323
- #~ "The navigation in the \"Quick View\" allows browsing between the "
324
- #~ "%1$sproducts%2$s within the same %1$scategory%2$s. The navigation arrows "
325
- #~ "show on mousehover the image of the next/previous product."
326
- #~ msgstr ""
327
- #~ "La navigazione all’interno della visualizzazione rapida permette di "
328
- #~ "scorrere tra i %1$sprodotti%2$s visualizzati. Quando si passa il cursore "
329
- #~ "sulle frecce di navigazione, queste mostrano l’immagine del prodotto "
330
- #~ "immediatamente successivo o precedente."
331
-
332
- #~ msgid "General"
333
- #~ msgstr "Generali"
334
-
335
- #~ msgid "Product"
336
- #~ msgstr "Prodotto"
337
-
338
- #~ msgid "Style"
339
- #~ msgstr "Stile"
340
-
341
- #~ msgid "Quick View Navigation"
342
- #~ msgstr "Navigazione quick view"
343
-
344
- #~ msgid ""
345
- #~ "Enable product navigation on quick view. NOTE: only available on modal "
346
- #~ "window style."
347
- #~ msgstr ""
348
- #~ "Abilita scorrimento prodotti all\\’interno della quick view. NOTA: "
349
- #~ "disponibile solo per lo stile finestra modale."
350
-
351
- #~ msgid "Enable navigation in the same product category"
352
- #~ msgstr "Abilita navigazione nella stessa categoria prodotti"
353
-
354
- #~ msgid "Quick View Navigation Style"
355
- #~ msgstr "Stile navigazione quick view"
356
-
357
- #~ msgid "Slide ( thumbnail and product name )"
358
- #~ msgstr "Scorrimento (miniatura e nome prodotto)"
359
-
360
- #~ msgid "Rotate ( thumbnail )"
361
- #~ msgstr "Rotazione (miniatura)"
362
-
363
- #~ msgid "Modal Window"
364
- #~ msgstr "Finestra modale"
365
-
366
- #~ msgid "Cascading"
367
- #~ msgstr "A cascata"
368
-
369
- #~ msgid "Select modal effect"
370
- #~ msgstr "Selezione effetto modale"
371
-
372
- #~ msgid "Slide in"
373
- #~ msgstr "Scorrimento"
374
-
375
- #~ msgid "Fade in"
376
- #~ msgstr "Dissolvenza"
377
-
378
- #~ msgid "Scale up"
379
- #~ msgstr "Ingrandimento"
380
-
381
- #~ msgid "Modal Width"
382
- #~ msgstr "Larghezza finestra"
383
-
384
- #~ msgid "Set width of modal window."
385
- #~ msgstr "Selezione la larghezza della finestra modale"
386
-
387
- #~ msgid "Modal Height"
388
- #~ msgstr "Altezza finestra"
389
-
390
- #~ msgid "Set height of modal window."
391
- #~ msgstr "Seleziona l\\’altezza della finestra modale"
392
-
393
- #~ msgid "Button Options"
394
- #~ msgstr "Opzioni pulsante"
395
-
396
- #~ msgid "Quick View Button Type"
397
- #~ msgstr "Tipo di pulsante quick view"
398
-
399
- #~ msgid "Use button"
400
- #~ msgstr "Usa pulsante"
401
-
402
- #~ msgid "Use icon"
403
- #~ msgstr "Usa icona"
404
-
405
- #~ msgid "Quick View Button Icon"
406
- #~ msgstr "Icona pulsante quick view"
407
-
408
- #~ msgid "Icon for the quick view button in the WooCommerce loop."
409
- #~ msgstr "Icona per il pulsante Quick view nella pagina shop di WooCommerce"
410
-
411
- #~ msgid "Quick View Button Position"
412
- #~ msgstr "Posizione pulsante Quick view"
413
-
414
- #~ msgid "Position of the quick view button."
415
- #~ msgstr "Posizione del pulsante Quick view"
416
-
417
- #~ msgid "After 'add to cart' button"
418
- #~ msgstr "Dopo il pulsante \\‘Aggiungi al carrello\\’"
419
-
420
- #~ msgid "Inside product image"
421
- #~ msgstr "Dentro l\\’immagine prodotto"
422
-
423
- #~ msgid "Content Options"
424
- #~ msgstr "Opzioni contenuto"
425
-
426
- #~ msgid "Select Element to Show"
427
- #~ msgstr "Seleziona elemento da mostrare"
428
-
429
- #~ msgid "Show Product Image"
430
- #~ msgstr "Mostra immagine prodotto"
431
-
432
- #~ msgid "Show Product Name"
433
- #~ msgstr "Mostra nome prodotto"
434
-
435
- #~ msgid "Show Product Rating"
436
- #~ msgstr "Mostra valutazione prodotto"
437
-
438
- #~ msgid "Show Product Price"
439
- #~ msgstr "Mostra prezzo prodotto"
440
-
441
- #~ msgid "Show Product Excerpt"
442
- #~ msgstr "Mostra riepilogo prodotto"
443
-
444
- #~ msgid "Show Product Add To Cart"
445
- #~ msgstr "Mostra \\”Aggiungi al carrello\\” del prodotto"
446
-
447
- #~ msgid "Show Product Meta"
448
- #~ msgstr "Mostra meta prodotto"
449
-
450
- #~ msgid "Product Image Width"
451
- #~ msgstr "Larghezza immagine prodotto"
452
-
453
- #~ msgid "Set width of product image."
454
- #~ msgstr "Imposta la larghezza dell\\’immagine del prodotto."
455
-
456
- #~ msgid "Product Image Height"
457
- #~ msgstr "Altezza immagine prodotto"
458
-
459
- #~ msgid "Set height of product image."
460
- #~ msgstr "Imposta l\\’altezza dell\\’immagine del prodotto."
461
-
462
- #~ msgid "Select Thumbnails Type"
463
- #~ msgstr "Seleziona tipo di miniatura"
464
-
465
- #~ msgid "Don't show"
466
- #~ msgstr "Non mostrare"
467
-
468
- #~ msgid "Slider mode"
469
- #~ msgstr "Modalità scorrimento"
470
-
471
- #~ msgid "Classic mode"
472
- #~ msgstr "Modalità classica"
473
-
474
- #~ msgid "Add 'View Details' Button"
475
- #~ msgstr "Aggiungi pulsante \\’Visualizza dettagli\\’"
476
-
477
- #~ msgid "Check this option to add a button to go to the single product page."
478
- #~ msgstr ""
479
- #~ "Seleziona questa opzione per aggiungere un pulsante che riporti alla "
480
- #~ "pagina singolo prodotto."
481
-
482
- #~ msgid "'View Details' Button Label"
483
- #~ msgstr "Testo pulsante \\’Visualizza dettagli\\’"
484
-
485
- #~ msgid "Set label for 'View Details' button"
486
- #~ msgstr "Scegli il testo del pulsante \\’Visualizza dettagli\\’"
487
-
488
- #~ msgid "View Details"
489
- #~ msgstr "Visualizza dettagli"
490
-
491
- #~ msgid "Enable Ajax Add To Cart"
492
- #~ msgstr "Abilita \\“Aggiungi al carrello\\” in ajax"
493
-
494
- #~ msgid "Check this option to enable add to cart in ajax"
495
- #~ msgstr ""
496
- #~ "Seleziona questa opzione per abilitare il pulsante \\”Aggiungi al carrello"
497
- #~ "\\” in ajax"
498
-
499
- #~ msgid "Share Options"
500
- #~ msgstr "Opzioni di condivisione"
501
-
502
- #~ msgid "Enable Share"
503
- #~ msgstr "Abilita condivisione"
504
-
505
- #~ msgid ""
506
- #~ "Check this option if you want to show the share link for products in "
507
- #~ "quick view"
508
- #~ msgstr ""
509
- #~ "Seleziona questa opzione se vuoi mostrare il link di condivisione per i "
510
- #~ "prodotti nella quick view"
511
-
512
- #~ msgid "Select Socials"
513
- #~ msgstr "Seleziona social"
514
-
515
- #~ msgid "Facebook"
516
- #~ msgstr "Facebook"
517
-
518
- #~ msgid "Twitter"
519
- #~ msgstr "Twitter"
520
-
521
- #~ msgid "Google+"
522
- #~ msgstr "Google+"
523
-
524
- #~ msgid "Pinterest"
525
- #~ msgstr "Pinterest"
526
-
527
- #~ msgid "eMail"
528
- #~ msgstr "email"
529
-
530
- #~ msgid "General Style"
531
- #~ msgstr "Stile generale"
532
-
533
- #~ msgid "'Quick View' Button Color"
534
- #~ msgstr "Colore pulsante 'Quick View'"
535
-
536
- #~ msgid "'Quick View' Button Text Color"
537
- #~ msgstr "Colore testo pulsante 'Quick View'"
538
-
539
- #~ msgid "'Quick View' Button Hover Color "
540
- #~ msgstr "Colore pulsante 'Quick View' al passaggio del mouse"
541
-
542
- #~ msgid "'Quick View' Button Hover Text Color"
543
- #~ msgstr "Colore testo pulsante 'Quick View' al passaggio del mouse"
544
-
545
- #~ msgid "Content Style"
546
- #~ msgstr "Stile contenuto"
547
-
548
- #~ msgid "Main Text Color"
549
- #~ msgstr "Colore principale testo"
550
-
551
- #~ msgid "Star Color"
552
- #~ msgstr "Colore stellina"
553
-
554
- #~ msgid "'Add to Cart' Button Color"
555
- #~ msgstr "Colore pulsante ‘Aggiungi al carrello’"
556
-
557
- #~ msgid "'Add to Cart' Button Text Color"
558
- #~ msgstr "Colore testo pulsante ‘Aggiungi al carrello’"
559
-
560
- #~ msgid "'Add to Cart' Button Hover Color "
561
- #~ msgstr "Colore pulsante ‘Aggiungi al carrello’ al passaggio del mouse"
562
-
563
- #~ msgid "'Add to Cart' Button Hover Text Color"
564
- #~ msgstr "Colore testo pulsante ‘Aggiungi al carrello’ al passaggio del mouse"
565
-
566
- #~ msgid "'View Details' Button Color"
567
- #~ msgstr "Colore pulsante ‘Visualizza dettagli’"
568
-
569
- #~ msgid "'View Details' Button Text Color"
570
- #~ msgstr "Colore testo pulsante ‘Visualizza dettagli’"
571
-
572
- #~ msgid "'View Details' Button Hover Color "
573
- #~ msgstr "Colore pulsante ‘Visualizza dettagli’ al passaggio del mouse "
574
-
575
- #~ msgid "'View Details' Button Hover Text Color"
576
- #~ msgstr "Colore testo pulsante ‘Visualizza dettagli’ al passaggio del mouse "
577
-
578
- #~ msgid "Closing Icon Color"
579
- #~ msgstr "Colore icona chiusura"
580
-
581
- #~ msgid "Closing Icon Hover Color"
582
- #~ msgstr "Colore icona chiusura al passaggio del mouse"
583
-
584
- #~ msgid "May I ask you to see this product, please?"
585
- #~ msgstr "Posso chiederti di guardare questo prodotto, per favore?"
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: YITH WooCommerce Quick View\n"
4
+ "POT-Creation-Date: 2017-10-11 12:42+0200\n"
5
+ "PO-Revision-Date: 2017-10-11 12:42+0200\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: YIThemes <plugins@yithemes.com>\n"
8
+ "Language: it_IT\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.8.7.1\n"
13
+ "X-Poedit-Basepath: .\n"
14
+ "Plural-Forms: nplurals=2; plural=n!=1;\n"
15
+ "X-Poedit-KeywordsList: __ ;_e;_n:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
16
+ "_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
17
+ "X-Poedit-SourceCharset: UTF-8\n"
18
+ "X-Poedit-SearchPath-0: ..\n"
19
+ "X-Poedit-SearchPathExcluded-0: ../plugin-fw\n"
20
+
21
+ #: ../includes/class.yith-wcqv-admin.php:129
22
+ #: ../includes/class.yith-wcqv-admin.php:151
23
+ msgid "Settings"
24
+ msgstr "Impostazioni"
25
+
26
+ #: ../includes/class.yith-wcqv-admin.php:130
27
+ #: ../includes/class.yith-wcqv-admin.php:152
28
+ msgid "Premium Version"
29
+ msgstr "Versione premium"
30
+
31
+ #: ../includes/class.yith-wcqv-admin.php:158
32
+ #: ../includes/class.yith-wcqv-admin.php:159
33
+ #: ../plugin-options/settings-options.php:57
34
+ msgid "Quick View"
35
+ msgstr "Quick view"
36
+
37
+ #: ../includes/class.yith-wcqv-admin.php:213
38
+ msgid "Plugin Documentation"
39
+ msgstr "Documentazione plugin"
40
+
41
+ #: ../init.php:41
42
+ msgid ""
43
+ "YITH WooCommerce Quick View is enabled but not effective. It requires "
44
+ "WooCommerce in order to work."
45
+ msgstr ""
46
+ "YITH WooCommerce Quick View è abilitato ma non in funzione. Devi aver "
47
+ "installato WooCommerce perché questo possa funzionare correttamente."
48
+
49
+ #: ../init.php:50
50
+ msgid ""
51
+ "You can't activate the free version of YITH WooCommerce Quick View while you "
52
+ "are using the premium one."
53
+ msgstr ""
54
+ "Non è possibile attivare la versione free di YITH WooCommerce Colors and "
55
+ "Labels Variations se stai già utilizzando la premium."
56
+
57
+ #: ../plugin-options/settings-options.php:8
58
+ msgid "Upgrade to the PREMIUM VERSION"
59
+ msgstr "Aggiorna alla VERSIONE PREMIUM"
60
+
61
+ #: ../plugin-options/settings-options.php:11
62
+ #: ../plugin-options/settings-options.php:18
63
+ msgid "YITH WooCommerce Quick View"
64
+ msgstr "YITH WooCommerce Quick View"
65
+
66
+ #: ../plugin-options/settings-options.php:12
67
+ msgid "Discover the Advanced Features"
68
+ msgstr "Scopri le funzionalità avanzate"
69
+
70
+ #: ../plugin-options/settings-options.php:13
71
+ msgid ""
72
+ "Upgrade to the PREMIUM VERSION of YITH WooCommerce Quick View to benefit "
73
+ "from all features!"
74
+ msgstr ""
75
+ "Aggiorna alla VERSIONE PREMIUM di YITH WooCommerce Quick View per usufruire "
76
+ "di tutte le sue funzionalità!"
77
+
78
+ #: ../plugin-options/settings-options.php:20
79
+ msgid "Get Support and Pro Features"
80
+ msgstr "Ottieni supporto e funzionalità aggiuntive"
81
+
82
+ #: ../plugin-options/settings-options.php:21
83
+ msgid ""
84
+ "By purchasing the premium version of the plugin, you will take advantage of "
85
+ "the advanced features of the product and you will get one year of free "
86
+ "updates and support through our platform available 24h/24."
87
+ msgstr ""
88
+ "Acquistando la versione premium del plugin, potrai beneficiare delle "
89
+ "funzionalità avanzate del prodotto ed otterrai un anno di aggiornamenti "
90
+ "gratuiti e supporto per mezzo della nostra piattaforma disponibile 24h/24."
91
+
92
+ #: ../plugin-options/settings-options.php:31
93
+ msgid "General Options"
94
+ msgstr "Opzioni generali"
95
+
96
+ #: ../plugin-options/settings-options.php:39
97
+ msgid "Enable Quick View"
98
+ msgstr "Abilita quick view"
99
+
100
+ #: ../plugin-options/settings-options.php:46
101
+ msgid "Enable Quick View on mobile"
102
+ msgstr "Abilita quick view su dispositivi mobili"
103
+
104
+ #: ../plugin-options/settings-options.php:47
105
+ msgid "Enable quick view features on mobile device too"
106
+ msgstr "Abilita funzionalità quick view anche sui dispositivi mobili"
107
+
108
+ #: ../plugin-options/settings-options.php:54
109
+ msgid "Quick View Button Label"
110
+ msgstr "Testo pulsante quick view"
111
+
112
+ #: ../plugin-options/settings-options.php:55
113
+ msgid "Label for the quick view button in the WooCommerce loop."
114
+ msgstr "Testo per il pulsante Quick view nella pagina shop di WooCommerce"
115
+
116
+ #: ../plugin-options/settings-options.php:62
117
+ msgid "Enable Lightbox"
118
+ msgstr "Abilita lightbox"
119
+
120
+ #: ../plugin-options/settings-options.php:63
121
+ msgid "Enable lightbox. Product images will open in a lightbox."
122
+ msgstr ""
123
+ "Abilita la lightbox. Le immagini dei prodotti si apriranno in una lightbox."
124
+
125
+ #: ../plugin-options/settings-options.php:74 ../templates/admin/premium.php:323
126
+ #: ../templates/admin/premium.php:328
127
+ msgid "Style Options"
128
+ msgstr "Opzioni di stile"
129
+
130
+ #: ../plugin-options/settings-options.php:81
131
+ msgid "Modal Window Background Color"
132
+ msgstr "Colore finestra modale"
133
+
134
+ #: ../plugin-options/settings-options.php:89
135
+ msgid "Closing Button Color"
136
+ msgstr "Colore pulsante chiusura"
137
+
138
+ #: ../plugin-options/settings-options.php:97
139
+ msgid "Closing Button Hover Color"
140
+ msgstr "Colore pulsante chiusura al passaggio del mouse"
141
+
142
+ #: ../templates/admin/premium.php:210 ../templates/admin/premium.php:364
143
+ #, php-format
144
+ msgid ""
145
+ "Upgrade to %1$spremium version%2$s of %1$sYITH WooCommerce Quick View%2$s to "
146
+ "benefit from all features!"
147
+ msgstr ""
148
+ "Aggiorna alla %1$sversione premium%2$s di %1$sYITH WooCommerce Quick View"
149
+ "%2$s per usufruire di tutte le sue funzionalità!"
150
+
151
+ #: ../templates/admin/premium.php:213 ../templates/admin/premium.php:367
152
+ msgid "UPGRADE"
153
+ msgstr "AGGIORNA"
154
+
155
+ #: ../templates/admin/premium.php:214 ../templates/admin/premium.php:368
156
+ msgid "to the premium version"
157
+ msgstr "alla versione premium"
158
+
159
+ #: ../templates/admin/premium.php:220
160
+ msgid "Premium Features"
161
+ msgstr "Funzionalità premium"
162
+
163
+ #: ../templates/admin/premium.php:223
164
+ msgid "Button type"
165
+ msgstr "Tipologia pulsante"
166
+
167
+ #: ../templates/admin/premium.php:228
168
+ msgid "BUTTON TYPE"
169
+ msgstr "TIPOLOGIA PULSANTE"
170
+
171
+ #: ../templates/admin/premium.php:230
172
+ #, php-format
173
+ msgid ""
174
+ "Choose between the button or a custom icon to access the %1$sQuick View%2$s: "
175
+ "you can choose to place it after the \"Add To Cart\" button or inside the "
176
+ "thumbnail of the product."
177
+ msgstr ""
178
+ "Scegli tra il pulsante o un’icona personalizzata per avviare la %1$squick "
179
+ "view%2$s: scegli tu se dopo il pulsante “Aggiungi al carrello” o sulla "
180
+ "immagine thumbnail del prodotto."
181
+
182
+ #: ../templates/admin/premium.php:238 ../templates/admin/premium.php:239
183
+ #: ../templates/admin/premium.php:244
184
+ msgid "Product Navigation"
185
+ msgstr "Navigazione prodotti"
186
+
187
+ #: ../templates/admin/premium.php:241
188
+ #, php-format
189
+ msgid ""
190
+ "The navigation in the \"Quick View\" allows browsing among %1$sproducts%2$s "
191
+ "displayed in it. The navigation arrows show on mousehover the image of the "
192
+ "next/previous product."
193
+ msgstr ""
194
+ "La navigazione all’interno della visualizzazione rapida permette di scorrere "
195
+ "tra i %1$sprodotti%2$s visualizzati. Quando si passa il cursore sulle frecce "
196
+ "di navigazione, queste mostrano l’immagine del prodotto immediatamente "
197
+ "successivo o precedente."
198
+
199
+ #: ../templates/admin/premium.php:255 ../templates/admin/premium.php:256
200
+ msgid "Content to display"
201
+ msgstr "Contenuto da mostrare"
202
+
203
+ #: ../templates/admin/premium.php:258
204
+ #, php-format
205
+ msgid ""
206
+ "The display of the product information in the \"Quick View\" are managed by "
207
+ "%1$sadministrators%2$s who can decide whether to show everything or only a "
208
+ "part of it."
209
+ msgstr ""
210
+ "La visualizzazione delle informazioni del prodotto all’interno della “Quick "
211
+ "View” sono gestite dall’%1$samministratore%2$s che può decidere se mostrare "
212
+ "tutto o solo una parte di esse."
213
+
214
+ #: ../templates/admin/premium.php:267
215
+ msgid "Quick View Type"
216
+ msgstr "Tipologia quick view"
217
+
218
+ #: ../templates/admin/premium.php:269
219
+ #, php-format
220
+ msgid ""
221
+ "Quick view has two different displaying modes: the first one opens it as a "
222
+ "%1$smodal window%2$s, the other one opens it in the page itself with a "
223
+ "%1$scascading effect%2$s above content page."
224
+ msgstr ""
225
+ "La visualizzazione rapida del prodotto può avvenire in due modi: all’interno "
226
+ "di una %1$sfinestra modale%2$s o all’interno della stessa pagina con "
227
+ "%1$seffetto a cascata%2$s sul resto del contenuto."
228
+
229
+ #: ../templates/admin/premium.php:272
230
+ msgid "Quick view type"
231
+ msgstr "Tipologia quick view"
232
+
233
+ #: ../templates/admin/premium.php:284
234
+ msgid "\"View details\" button"
235
+ msgstr "Pulsante “Visualizza dettagli”"
236
+
237
+ #: ../templates/admin/premium.php:286
238
+ msgid ""
239
+ "An additional button that allows users to access product detail page "
240
+ "directly from quick view window just with a click of the mouse."
241
+ msgstr ""
242
+ "Un pulsante aggiuntivo per permettere all’utente di accedere alla pagina "
243
+ "dettaglio del prodotto direttamente dalla quick view con un semplice clic."
244
+
245
+ #: ../templates/admin/premium.php:295
246
+ msgid "Type of product images"
247
+ msgstr "Tipologia immagini prodotto"
248
+
249
+ #: ../templates/admin/premium.php:297
250
+ #, php-format
251
+ msgid ""
252
+ "Each product can have more than one image: choose whether to hide or show "
253
+ "them with the %1$sslider%2$s effect or in the classic %1$sWooCommerce%2$s "
254
+ "display."
255
+ msgstr ""
256
+ "Ogni prodotto può avere ulteriori immagini oltre a quella in evidenza: "
257
+ "scegli se nasconderle o mostrarle con %1$seffetto scorrimento%2$s o nella "
258
+ "classica visualizzazione di %1$sWooCommerce%2$s."
259
+
260
+ #: ../templates/admin/premium.php:312
261
+ msgid "SHARE"
262
+ msgstr "Condivisione"
263
+
264
+ #: ../templates/admin/premium.php:314
265
+ #, php-format
266
+ msgid ""
267
+ "%1$sQuick View is also social-friendly!%2$s Activating this option, you will "
268
+ "be able to share the Quick View on Facebook, Twitter, Pinterest, Google+, or "
269
+ "sending an email."
270
+ msgstr ""
271
+ "%1$sLa quick view è anche social%2$s! Abilitando l’opzione, potrà essere "
272
+ "condivisa su Facebook, Twitter, Pinterest, Google+ e per email."
273
+
274
+ #: ../templates/admin/premium.php:325
275
+ #, php-format
276
+ msgid ""
277
+ "A rich option panel to change the colors of the %1$s\"Quick View\"%2$s "
278
+ "button and of everything that is within the modal window generated."
279
+ msgstr ""
280
+ "Un ricco pannello opzioni per modificare i colori del pulsante %1$s“Quick "
281
+ "View”%2$s e di tutto ciò che è all’interno della finestra modale generata."
282
+
283
+ #: ../templates/admin/premium.php:340
284
+ msgid "SHORTCODE"
285
+ msgstr ""
286
+
287
+ #: ../templates/admin/premium.php:342
288
+ msgid ""
289
+ "The shortcode of plugin is a $1$srapid$2$s and $1$seasy$2$s solution: you "
290
+ "can add a button in any spot of the page to allow your users to see the "
291
+ "quick view of a specific product in your store."
292
+ msgstr ""
293
+
294
+ #: ../templates/admin/premium.php:351
295
+ msgid "Compatibility with other YITH's plugins"
296
+ msgstr ""
297
+
298
+ #: ../templates/admin/premium.php:353
299
+ #, php-format
300
+ msgid ""
301
+ "Thanks to the compatibility with %1$sYITH WooCommerce Zoom Magnifier, YITH "
302
+ "WooCommerce Badge Management%2$s and %1$sYITH WooCommerce Wishlist%2$s, you "
303
+ "will be free to enrich further the content of your quick view.%3$s Zoom the "
304
+ "product image, show a badge, or add the button to open the quick view in all "
305
+ "products available in your users' wishlists. With YITH's plugins you make "
306
+ "the difference."
307
+ msgstr ""
308
+
309
+ #~ msgid ""
310
+ #~ "In the YIT Plugin tab you can find the YITH WooCommerce Quick View "
311
+ #~ "options.\r\n"
312
+ #~ "\t\t\t\t\t\t\t\t\t\tWith this menu, you can access to all the settings of "
313
+ #~ "our plugins that you have activated.\r\n"
314
+ #~ "\t\t\t\t\t\t\t\t\t\tYITH WooCommerce Quick View is available in an "
315
+ #~ "outstanding PREMIUM version with many new options,\r\n"
316
+ #~ "\t\t\t\t\t\t\t\t\t\t<a href=\""
317
+ #~ msgstr ""
318
+ #~ "Nella scheda YIT Plugins puoi trovare tutte le opzioni di YITH "
319
+ #~ "WooCommerce Quick View.<br>Da questo menu potrai accedere a tutte le "
320
+ #~ "impostazioni dei plugin YITH installati."
321
+
322
+ #~ msgid ""
323
+ #~ "The navigation in the \"Quick View\" allows browsing between the "
324
+ #~ "%1$sproducts%2$s within the same %1$scategory%2$s. The navigation arrows "
325
+ #~ "show on mousehover the image of the next/previous product."
326
+ #~ msgstr ""
327
+ #~ "La navigazione all’interno della visualizzazione rapida permette di "
328
+ #~ "scorrere tra i %1$sprodotti%2$s visualizzati. Quando si passa il cursore "
329
+ #~ "sulle frecce di navigazione, queste mostrano l’immagine del prodotto "
330
+ #~ "immediatamente successivo o precedente."
331
+
332
+ #~ msgid "General"
333
+ #~ msgstr "Generali"
334
+
335
+ #~ msgid "Product"
336
+ #~ msgstr "Prodotto"
337
+
338
+ #~ msgid "Style"
339
+ #~ msgstr "Stile"
340
+
341
+ #~ msgid "Quick View Navigation"
342
+ #~ msgstr "Navigazione quick view"
343
+
344
+ #~ msgid ""
345
+ #~ "Enable product navigation on quick view. NOTE: only available on modal "
346
+ #~ "window style."
347
+ #~ msgstr ""
348
+ #~ "Abilita scorrimento prodotti all\\’interno della quick view. NOTA: "
349
+ #~ "disponibile solo per lo stile finestra modale."
350
+
351
+ #~ msgid "Enable navigation in the same product category"
352
+ #~ msgstr "Abilita navigazione nella stessa categoria prodotti"
353
+
354
+ #~ msgid "Quick View Navigation Style"
355
+ #~ msgstr "Stile navigazione quick view"
356
+
357
+ #~ msgid "Slide ( thumbnail and product name )"
358
+ #~ msgstr "Scorrimento (miniatura e nome prodotto)"
359
+
360
+ #~ msgid "Rotate ( thumbnail )"
361
+ #~ msgstr "Rotazione (miniatura)"
362
+
363
+ #~ msgid "Modal Window"
364
+ #~ msgstr "Finestra modale"
365
+
366
+ #~ msgid "Cascading"
367
+ #~ msgstr "A cascata"
368
+
369
+ #~ msgid "Select modal effect"
370
+ #~ msgstr "Selezione effetto modale"
371
+
372
+ #~ msgid "Slide in"
373
+ #~ msgstr "Scorrimento"
374
+
375
+ #~ msgid "Fade in"
376
+ #~ msgstr "Dissolvenza"
377
+
378
+ #~ msgid "Scale up"
379
+ #~ msgstr "Ingrandimento"
380
+
381
+ #~ msgid "Modal Width"
382
+ #~ msgstr "Larghezza finestra"
383
+
384
+ #~ msgid "Set width of modal window."
385
+ #~ msgstr "Selezione la larghezza della finestra modale"
386
+
387
+ #~ msgid "Modal Height"
388
+ #~ msgstr "Altezza finestra"
389
+
390
+ #~ msgid "Set height of modal window."
391
+ #~ msgstr "Seleziona l\\’altezza della finestra modale"
392
+
393
+ #~ msgid "Button Options"
394
+ #~ msgstr "Opzioni pulsante"
395
+
396
+ #~ msgid "Quick View Button Type"
397
+ #~ msgstr "Tipo di pulsante quick view"
398
+
399
+ #~ msgid "Use button"
400
+ #~ msgstr "Usa pulsante"
401
+
402
+ #~ msgid "Use icon"
403
+ #~ msgstr "Usa icona"
404
+
405
+ #~ msgid "Quick View Button Icon"
406
+ #~ msgstr "Icona pulsante quick view"
407
+
408
+ #~ msgid "Icon for the quick view button in the WooCommerce loop."
409
+ #~ msgstr "Icona per il pulsante Quick view nella pagina shop di WooCommerce"
410
+
411
+ #~ msgid "Quick View Button Position"
412
+ #~ msgstr "Posizione pulsante Quick view"
413
+
414
+ #~ msgid "Position of the quick view button."
415
+ #~ msgstr "Posizione del pulsante Quick view"
416
+
417
+ #~ msgid "After 'add to cart' button"
418
+ #~ msgstr "Dopo il pulsante \\‘Aggiungi al carrello\\’"
419
+
420
+ #~ msgid "Inside product image"
421
+ #~ msgstr "Dentro l\\’immagine prodotto"
422
+
423
+ #~ msgid "Content Options"
424
+ #~ msgstr "Opzioni contenuto"
425
+
426
+ #~ msgid "Select Element to Show"
427
+ #~ msgstr "Seleziona elemento da mostrare"
428
+
429
+ #~ msgid "Show Product Image"
430
+ #~ msgstr "Mostra immagine prodotto"
431
+
432
+ #~ msgid "Show Product Name"
433
+ #~ msgstr "Mostra nome prodotto"
434
+
435
+ #~ msgid "Show Product Rating"
436
+ #~ msgstr "Mostra valutazione prodotto"
437
+
438
+ #~ msgid "Show Product Price"
439
+ #~ msgstr "Mostra prezzo prodotto"
440
+
441
+ #~ msgid "Show Product Excerpt"
442
+ #~ msgstr "Mostra riepilogo prodotto"
443
+
444
+ #~ msgid "Show Product Add To Cart"
445
+ #~ msgstr "Mostra \\”Aggiungi al carrello\\” del prodotto"
446
+
447
+ #~ msgid "Show Product Meta"
448
+ #~ msgstr "Mostra meta prodotto"
449
+
450
+ #~ msgid "Product Image Width"
451
+ #~ msgstr "Larghezza immagine prodotto"
452
+
453
+ #~ msgid "Set width of product image."
454
+ #~ msgstr "Imposta la larghezza dell\\’immagine del prodotto."
455
+
456
+ #~ msgid "Product Image Height"
457
+ #~ msgstr "Altezza immagine prodotto"
458
+
459
+ #~ msgid "Set height of product image."
460
+ #~ msgstr "Imposta l\\’altezza dell\\’immagine del prodotto."
461
+
462
+ #~ msgid "Select Thumbnails Type"
463
+ #~ msgstr "Seleziona tipo di miniatura"
464
+
465
+ #~ msgid "Don't show"
466
+ #~ msgstr "Non mostrare"
467
+
468
+ #~ msgid "Slider mode"
469
+ #~ msgstr "Modalità scorrimento"
470
+
471
+ #~ msgid "Classic mode"
472
+ #~ msgstr "Modalità classica"
473
+
474
+ #~ msgid "Add 'View Details' Button"
475
+ #~ msgstr "Aggiungi pulsante \\’Visualizza dettagli\\’"
476
+
477
+ #~ msgid "Check this option to add a button to go to the single product page."
478
+ #~ msgstr ""
479
+ #~ "Seleziona questa opzione per aggiungere un pulsante che riporti alla "
480
+ #~ "pagina singolo prodotto."
481
+
482
+ #~ msgid "'View Details' Button Label"
483
+ #~ msgstr "Testo pulsante \\’Visualizza dettagli\\’"
484
+
485
+ #~ msgid "Set label for 'View Details' button"
486
+ #~ msgstr "Scegli il testo del pulsante \\’Visualizza dettagli\\’"
487
+
488
+ #~ msgid "View Details"
489
+ #~ msgstr "Visualizza dettagli"
490
+
491
+ #~ msgid "Enable Ajax Add To Cart"
492
+ #~ msgstr "Abilita \\“Aggiungi al carrello\\” in ajax"
493
+
494
+ #~ msgid "Check this option to enable add to cart in ajax"
495
+ #~ msgstr ""
496
+ #~ "Seleziona questa opzione per abilitare il pulsante \\”Aggiungi al carrello"
497
+ #~ "\\” in ajax"
498
+
499
+ #~ msgid "Share Options"
500
+ #~ msgstr "Opzioni di condivisione"
501
+
502
+ #~ msgid "Enable Share"
503
+ #~ msgstr "Abilita condivisione"
504
+
505
+ #~ msgid ""
506
+ #~ "Check this option if you want to show the share link for products in "
507
+ #~ "quick view"
508
+ #~ msgstr ""
509
+ #~ "Seleziona questa opzione se vuoi mostrare il link di condivisione per i "
510
+ #~ "prodotti nella quick view"
511
+
512
+ #~ msgid "Select Socials"
513
+ #~ msgstr "Seleziona social"
514
+
515
+ #~ msgid "Facebook"
516
+ #~ msgstr "Facebook"
517
+
518
+ #~ msgid "Twitter"
519
+ #~ msgstr "Twitter"
520
+
521
+ #~ msgid "Google+"
522
+ #~ msgstr "Google+"
523
+
524
+ #~ msgid "Pinterest"
525
+ #~ msgstr "Pinterest"
526
+
527
+ #~ msgid "eMail"
528
+ #~ msgstr "email"
529
+
530
+ #~ msgid "General Style"
531
+ #~ msgstr "Stile generale"
532
+
533
+ #~ msgid "'Quick View' Button Color"
534
+ #~ msgstr "Colore pulsante 'Quick View'"
535
+
536
+ #~ msgid "'Quick View' Button Text Color"
537
+ #~ msgstr "Colore testo pulsante 'Quick View'"
538
+
539
+ #~ msgid "'Quick View' Button Hover Color "
540
+ #~ msgstr "Colore pulsante 'Quick View' al passaggio del mouse"
541
+
542
+ #~ msgid "'Quick View' Button Hover Text Color"
543
+ #~ msgstr "Colore testo pulsante 'Quick View' al passaggio del mouse"
544
+
545
+ #~ msgid "Content Style"
546
+ #~ msgstr "Stile contenuto"
547
+
548
+ #~ msgid "Main Text Color"
549
+ #~ msgstr "Colore principale testo"
550
+
551
+ #~ msgid "Star Color"
552
+ #~ msgstr "Colore stellina"
553
+
554
+ #~ msgid "'Add to Cart' Button Color"
555
+ #~ msgstr "Colore pulsante ‘Aggiungi al carrello’"
556
+
557
+ #~ msgid "'Add to Cart' Button Text Color"
558
+ #~ msgstr "Colore testo pulsante ‘Aggiungi al carrello’"
559
+
560
+ #~ msgid "'Add to Cart' Button Hover Color "
561
+ #~ msgstr "Colore pulsante ‘Aggiungi al carrello’ al passaggio del mouse"
562
+
563
+ #~ msgid "'Add to Cart' Button Hover Text Color"
564
+ #~ msgstr "Colore testo pulsante ‘Aggiungi al carrello’ al passaggio del mouse"
565
+
566
+ #~ msgid "'View Details' Button Color"
567
+ #~ msgstr "Colore pulsante ‘Visualizza dettagli’"
568
+
569
+ #~ msgid "'View Details' Button Text Color"
570
+ #~ msgstr "Colore testo pulsante ‘Visualizza dettagli’"
571
+
572
+ #~ msgid "'View Details' Button Hover Color "
573
+ #~ msgstr "Colore pulsante ‘Visualizza dettagli’ al passaggio del mouse "
574
+
575
+ #~ msgid "'View Details' Button Hover Text Color"
576
+ #~ msgstr "Colore testo pulsante ‘Visualizza dettagli’ al passaggio del mouse "
577
+
578
+ #~ msgid "Closing Icon Color"
579
+ #~ msgstr "Colore icona chiusura"
580
+
581
+ #~ msgid "Closing Icon Hover Color"
582
+ #~ msgstr "Colore icona chiusura al passaggio del mouse"
583
+
584
+ #~ msgid "May I ask you to see this product, please?"
585
+ #~ msgstr "Posso chiederti di guardare questo prodotto, per favore?"
languages/yith-woocommerce-quick-view.pot CHANGED
@@ -1,274 +1,274 @@
1
- #, fuzzy
2
- msgid ""
3
- msgstr ""
4
- "Project-Id-Version: YITH WooCommerce Quick View\n"
5
- "POT-Creation-Date: 2017-10-11 12:42+0200\n"
6
- "PO-Revision-Date: 2015-05-18 11:52+0100\n"
7
- "Last-Translator: \n"
8
- "Language-Team: YIThemes <plugins@yithemes.com>\n"
9
- "Language: en\n"
10
- "MIME-Version: 1.0\n"
11
- "Content-Type: text/plain; charset=UTF-8\n"
12
- "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 1.8.7.1\n"
14
- "X-Poedit-Basepath: .\n"
15
- "Plural-Forms: nplurals=2; plural=n!=1;\n"
16
- "X-Poedit-KeywordsList: __ ;_e;_n:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
17
- "_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
18
- "X-Poedit-SourceCharset: UTF-8\n"
19
- "X-Poedit-SearchPath-0: ..\n"
20
- "X-Poedit-SearchPathExcluded-0: ../plugin-fw\n"
21
-
22
- #: ../includes/class.yith-wcqv-admin.php:129
23
- #: ../includes/class.yith-wcqv-admin.php:151
24
- msgid "Settings"
25
- msgstr ""
26
-
27
- #: ../includes/class.yith-wcqv-admin.php:130
28
- #: ../includes/class.yith-wcqv-admin.php:152
29
- msgid "Premium Version"
30
- msgstr ""
31
-
32
- #: ../includes/class.yith-wcqv-admin.php:158
33
- #: ../includes/class.yith-wcqv-admin.php:159
34
- #: ../plugin-options/settings-options.php:57
35
- msgid "Quick View"
36
- msgstr ""
37
-
38
- #: ../includes/class.yith-wcqv-admin.php:213
39
- msgid "Plugin Documentation"
40
- msgstr ""
41
-
42
- #: ../init.php:41
43
- msgid ""
44
- "YITH WooCommerce Quick View is enabled but not effective. It requires "
45
- "WooCommerce in order to work."
46
- msgstr ""
47
-
48
- #: ../init.php:50
49
- msgid ""
50
- "You can't activate the free version of YITH WooCommerce Quick View while you "
51
- "are using the premium one."
52
- msgstr ""
53
-
54
- #: ../plugin-options/settings-options.php:8
55
- msgid "Upgrade to the PREMIUM VERSION"
56
- msgstr ""
57
-
58
- #: ../plugin-options/settings-options.php:11
59
- #: ../plugin-options/settings-options.php:18
60
- msgid "YITH WooCommerce Quick View"
61
- msgstr ""
62
-
63
- #: ../plugin-options/settings-options.php:12
64
- msgid "Discover the Advanced Features"
65
- msgstr ""
66
-
67
- #: ../plugin-options/settings-options.php:13
68
- msgid ""
69
- "Upgrade to the PREMIUM VERSION of YITH WooCommerce Quick View to benefit "
70
- "from all features!"
71
- msgstr ""
72
-
73
- #: ../plugin-options/settings-options.php:20
74
- msgid "Get Support and Pro Features"
75
- msgstr ""
76
-
77
- #: ../plugin-options/settings-options.php:21
78
- msgid ""
79
- "By purchasing the premium version of the plugin, you will take advantage of "
80
- "the advanced features of the product and you will get one year of free "
81
- "updates and support through our platform available 24h/24."
82
- msgstr ""
83
-
84
- #: ../plugin-options/settings-options.php:31
85
- msgid "General Options"
86
- msgstr ""
87
-
88
- #: ../plugin-options/settings-options.php:39
89
- msgid "Enable Quick View"
90
- msgstr ""
91
-
92
- #: ../plugin-options/settings-options.php:46
93
- msgid "Enable Quick View on mobile"
94
- msgstr ""
95
-
96
- #: ../plugin-options/settings-options.php:47
97
- msgid "Enable quick view features on mobile device too"
98
- msgstr ""
99
-
100
- #: ../plugin-options/settings-options.php:54
101
- msgid "Quick View Button Label"
102
- msgstr ""
103
-
104
- #: ../plugin-options/settings-options.php:55
105
- msgid "Label for the quick view button in the WooCommerce loop."
106
- msgstr ""
107
-
108
- #: ../plugin-options/settings-options.php:62
109
- msgid "Enable Lightbox"
110
- msgstr ""
111
-
112
- #: ../plugin-options/settings-options.php:63
113
- msgid "Enable lightbox. Product images will open in a lightbox."
114
- msgstr ""
115
-
116
- #: ../plugin-options/settings-options.php:74 ../templates/admin/premium.php:323
117
- #: ../templates/admin/premium.php:328
118
- msgid "Style Options"
119
- msgstr ""
120
-
121
- #: ../plugin-options/settings-options.php:81
122
- msgid "Modal Window Background Color"
123
- msgstr ""
124
-
125
- #: ../plugin-options/settings-options.php:89
126
- msgid "Closing Button Color"
127
- msgstr ""
128
-
129
- #: ../plugin-options/settings-options.php:97
130
- msgid "Closing Button Hover Color"
131
- msgstr ""
132
-
133
- #: ../templates/admin/premium.php:210 ../templates/admin/premium.php:364
134
- #, php-format
135
- msgid ""
136
- "Upgrade to %1$spremium version%2$s of %1$sYITH WooCommerce Quick View%2$s to "
137
- "benefit from all features!"
138
- msgstr ""
139
-
140
- #: ../templates/admin/premium.php:213 ../templates/admin/premium.php:367
141
- msgid "UPGRADE"
142
- msgstr ""
143
-
144
- #: ../templates/admin/premium.php:214 ../templates/admin/premium.php:368
145
- msgid "to the premium version"
146
- msgstr ""
147
-
148
- #: ../templates/admin/premium.php:220
149
- msgid "Premium Features"
150
- msgstr ""
151
-
152
- #: ../templates/admin/premium.php:223
153
- msgid "Button type"
154
- msgstr ""
155
-
156
- #: ../templates/admin/premium.php:228
157
- msgid "BUTTON TYPE"
158
- msgstr ""
159
-
160
- #: ../templates/admin/premium.php:230
161
- #, php-format
162
- msgid ""
163
- "Choose between the button or a custom icon to access the %1$sQuick View%2$s: "
164
- "you can choose to place it after the \"Add To Cart\" button or inside the "
165
- "thumbnail of the product."
166
- msgstr ""
167
-
168
- #: ../templates/admin/premium.php:238 ../templates/admin/premium.php:239
169
- #: ../templates/admin/premium.php:244
170
- msgid "Product Navigation"
171
- msgstr ""
172
-
173
- #: ../templates/admin/premium.php:241
174
- #, php-format
175
- msgid ""
176
- "The navigation in the \"Quick View\" allows browsing among %1$sproducts%2$s "
177
- "displayed in it. The navigation arrows show on mousehover the image of the "
178
- "next/previous product."
179
- msgstr ""
180
-
181
- #: ../templates/admin/premium.php:255 ../templates/admin/premium.php:256
182
- msgid "Content to display"
183
- msgstr ""
184
-
185
- #: ../templates/admin/premium.php:258
186
- #, php-format
187
- msgid ""
188
- "The display of the product information in the \"Quick View\" are managed by "
189
- "%1$sadministrators%2$s who can decide whether to show everything or only a "
190
- "part of it."
191
- msgstr ""
192
-
193
- #: ../templates/admin/premium.php:267
194
- msgid "Quick View Type"
195
- msgstr ""
196
-
197
- #: ../templates/admin/premium.php:269
198
- #, php-format
199
- msgid ""
200
- "Quick view has two different displaying modes: the first one opens it as a "
201
- "%1$smodal window%2$s, the other one opens it in the page itself with a "
202
- "%1$scascading effect%2$s above content page."
203
- msgstr ""
204
-
205
- #: ../templates/admin/premium.php:272
206
- msgid "Quick view type"
207
- msgstr ""
208
-
209
- #: ../templates/admin/premium.php:284
210
- msgid "\"View details\" button"
211
- msgstr ""
212
-
213
- #: ../templates/admin/premium.php:286
214
- msgid ""
215
- "An additional button that allows users to access product detail page "
216
- "directly from quick view window just with a click of the mouse."
217
- msgstr ""
218
-
219
- #: ../templates/admin/premium.php:295
220
- msgid "Type of product images"
221
- msgstr ""
222
-
223
- #: ../templates/admin/premium.php:297
224
- #, php-format
225
- msgid ""
226
- "Each product can have more than one image: choose whether to hide or show "
227
- "them with the %1$sslider%2$s effect or in the classic %1$sWooCommerce%2$s "
228
- "display."
229
- msgstr ""
230
-
231
- #: ../templates/admin/premium.php:312
232
- msgid "SHARE"
233
- msgstr ""
234
-
235
- #: ../templates/admin/premium.php:314
236
- #, php-format
237
- msgid ""
238
- "%1$sQuick View is also social-friendly!%2$s Activating this option, you will "
239
- "be able to share the Quick View on Facebook, Twitter, Pinterest, Google+, or "
240
- "sending an email."
241
- msgstr ""
242
-
243
- #: ../templates/admin/premium.php:325
244
- #, php-format
245
- msgid ""
246
- "A rich option panel to change the colors of the %1$s\"Quick View\"%2$s "
247
- "button and of everything that is within the modal window generated."
248
- msgstr ""
249
-
250
- #: ../templates/admin/premium.php:340
251
- msgid "SHORTCODE"
252
- msgstr ""
253
-
254
- #: ../templates/admin/premium.php:342
255
- msgid ""
256
- "The shortcode of plugin is a $1$srapid$2$s and $1$seasy$2$s solution: you "
257
- "can add a button in any spot of the page to allow your users to see the "
258
- "quick view of a specific product in your store."
259
- msgstr ""
260
-
261
- #: ../templates/admin/premium.php:351
262
- msgid "Compatibility with other YITH's plugins"
263
- msgstr ""
264
-
265
- #: ../templates/admin/premium.php:353
266
- #, php-format
267
- msgid ""
268
- "Thanks to the compatibility with %1$sYITH WooCommerce Zoom Magnifier, YITH "
269
- "WooCommerce Badge Management%2$s and %1$sYITH WooCommerce Wishlist%2$s, you "
270
- "will be free to enrich further the content of your quick view.%3$s Zoom the "
271
- "product image, show a badge, or add the button to open the quick view in all "
272
- "products available in your users' wishlists. With YITH's plugins you make "
273
- "the difference."
274
- msgstr ""
1
+ #, fuzzy
2
+ msgid ""
3
+ msgstr ""
4
+ "Project-Id-Version: YITH WooCommerce Quick View\n"
5
+ "POT-Creation-Date: 2017-10-11 12:42+0200\n"
6
+ "PO-Revision-Date: 2015-05-18 11:52+0100\n"
7
+ "Last-Translator: \n"
8
+ "Language-Team: YIThemes <plugins@yithemes.com>\n"
9
+ "Language: en\n"
10
+ "MIME-Version: 1.0\n"
11
+ "Content-Type: text/plain; charset=UTF-8\n"
12
+ "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 1.8.7.1\n"
14
+ "X-Poedit-Basepath: .\n"
15
+ "Plural-Forms: nplurals=2; plural=n!=1;\n"
16
+ "X-Poedit-KeywordsList: __ ;_e;_n:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
17
+ "_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
18
+ "X-Poedit-SourceCharset: UTF-8\n"
19
+ "X-Poedit-SearchPath-0: ..\n"
20
+ "X-Poedit-SearchPathExcluded-0: ../plugin-fw\n"
21
+
22
+ #: ../includes/class.yith-wcqv-admin.php:129
23
+ #: ../includes/class.yith-wcqv-admin.php:151
24
+ msgid "Settings"
25
+ msgstr ""
26
+
27
+ #: ../includes/class.yith-wcqv-admin.php:130
28
+ #: ../includes/class.yith-wcqv-admin.php:152
29
+ msgid "Premium Version"
30
+ msgstr ""
31
+
32
+ #: ../includes/class.yith-wcqv-admin.php:158
33
+ #: ../includes/class.yith-wcqv-admin.php:159
34
+ #: ../plugin-options/settings-options.php:57
35
+ msgid "Quick View"
36
+ msgstr ""
37
+
38
+ #: ../includes/class.yith-wcqv-admin.php:213
39
+ msgid "Plugin Documentation"
40
+ msgstr ""
41
+
42
+ #: ../init.php:41
43
+ msgid ""
44
+ "YITH WooCommerce Quick View is enabled but not effective. It requires "
45
+ "WooCommerce in order to work."
46
+ msgstr ""
47
+
48
+ #: ../init.php:50
49
+ msgid ""
50
+ "You can't activate the free version of YITH WooCommerce Quick View while you "
51
+ "are using the premium one."
52
+ msgstr ""
53
+
54
+ #: ../plugin-options/settings-options.php:8
55
+ msgid "Upgrade to the PREMIUM VERSION"
56
+ msgstr ""
57
+
58
+ #: ../plugin-options/settings-options.php:11
59
+ #: ../plugin-options/settings-options.php:18
60
+ msgid "YITH WooCommerce Quick View"
61
+ msgstr ""
62
+
63
+ #: ../plugin-options/settings-options.php:12
64
+ msgid "Discover the Advanced Features"
65
+ msgstr ""
66
+
67
+ #: ../plugin-options/settings-options.php:13
68
+ msgid ""
69
+ "Upgrade to the PREMIUM VERSION of YITH WooCommerce Quick View to benefit "
70
+ "from all features!"
71
+ msgstr ""
72
+
73
+ #: ../plugin-options/settings-options.php:20
74
+ msgid "Get Support and Pro Features"
75
+ msgstr ""
76
+
77
+ #: ../plugin-options/settings-options.php:21
78
+ msgid ""
79
+ "By purchasing the premium version of the plugin, you will take advantage of "
80
+ "the advanced features of the product and you will get one year of free "
81
+ "updates and support through our platform available 24h/24."
82
+ msgstr ""
83
+
84
+ #: ../plugin-options/settings-options.php:31
85
+ msgid "General Options"
86
+ msgstr ""
87
+
88
+ #: ../plugin-options/settings-options.php:39
89
+ msgid "Enable Quick View"
90
+ msgstr ""
91
+
92
+ #: ../plugin-options/settings-options.php:46
93
+ msgid "Enable Quick View on mobile"
94
+ msgstr ""
95
+
96
+ #: ../plugin-options/settings-options.php:47
97
+ msgid "Enable quick view features on mobile device too"
98
+ msgstr ""
99
+
100
+ #: ../plugin-options/settings-options.php:54
101
+ msgid "Quick View Button Label"
102
+ msgstr ""
103
+
104
+ #: ../plugin-options/settings-options.php:55
105
+ msgid "Label for the quick view button in the WooCommerce loop."
106
+ msgstr ""
107
+
108
+ #: ../plugin-options/settings-options.php:62
109
+ msgid "Enable Lightbox"
110
+ msgstr ""
111
+
112
+ #: ../plugin-options/settings-options.php:63
113
+ msgid "Enable lightbox. Product images will open in a lightbox."
114
+ msgstr ""
115
+
116
+ #: ../plugin-options/settings-options.php:74 ../templates/admin/premium.php:323
117
+ #: ../templates/admin/premium.php:328
118
+ msgid "Style Options"
119
+ msgstr ""
120
+
121
+ #: ../plugin-options/settings-options.php:81
122
+ msgid "Modal Window Background Color"
123
+ msgstr ""
124
+
125
+ #: ../plugin-options/settings-options.php:89
126
+ msgid "Closing Button Color"
127
+ msgstr ""
128
+
129
+ #: ../plugin-options/settings-options.php:97
130
+ msgid "Closing Button Hover Color"
131
+ msgstr ""
132
+
133
+ #: ../templates/admin/premium.php:210 ../templates/admin/premium.php:364
134
+ #, php-format
135
+ msgid ""
136
+ "Upgrade to %1$spremium version%2$s of %1$sYITH WooCommerce Quick View%2$s to "
137
+ "benefit from all features!"
138
+ msgstr ""
139
+
140
+ #: ../templates/admin/premium.php:213 ../templates/admin/premium.php:367
141
+ msgid "UPGRADE"
142
+ msgstr ""
143
+
144
+ #: ../templates/admin/premium.php:214 ../templates/admin/premium.php:368
145
+ msgid "to the premium version"
146
+ msgstr ""
147
+
148
+ #: ../templates/admin/premium.php:220
149
+ msgid "Premium Features"
150
+ msgstr ""
151
+
152
+ #: ../templates/admin/premium.php:223
153
+ msgid "Button type"
154
+ msgstr ""
155
+
156
+ #: ../templates/admin/premium.php:228
157
+ msgid "BUTTON TYPE"
158
+ msgstr ""
159
+
160
+ #: ../templates/admin/premium.php:230
161
+ #, php-format
162
+ msgid ""
163
+ "Choose between the button or a custom icon to access the %1$sQuick View%2$s: "
164
+ "you can choose to place it after the \"Add To Cart\" button or inside the "
165
+ "thumbnail of the product."
166
+ msgstr ""
167
+
168
+ #: ../templates/admin/premium.php:238 ../templates/admin/premium.php:239
169
+ #: ../templates/admin/premium.php:244
170
+ msgid "Product Navigation"
171
+ msgstr ""
172
+
173
+ #: ../templates/admin/premium.php:241
174
+ #, php-format
175
+ msgid ""
176
+ "The navigation in the \"Quick View\" allows browsing among %1$sproducts%2$s "
177
+ "displayed in it. The navigation arrows show on mousehover the image of the "
178
+ "next/previous product."
179
+ msgstr ""
180
+
181
+ #: ../templates/admin/premium.php:255 ../templates/admin/premium.php:256
182
+ msgid "Content to display"
183
+ msgstr ""
184
+
185
+ #: ../templates/admin/premium.php:258
186
+ #, php-format
187
+ msgid ""
188
+ "The display of the product information in the \"Quick View\" are managed by "
189
+ "%1$sadministrators%2$s who can decide whether to show everything or only a "
190
+ "part of it."
191
+ msgstr ""
192
+
193
+ #: ../templates/admin/premium.php:267
194
+ msgid "Quick View Type"
195
+ msgstr ""
196
+
197
+ #: ../templates/admin/premium.php:269
198
+ #, php-format
199
+ msgid ""
200
+ "Quick view has two different displaying modes: the first one opens it as a "
201
+ "%1$smodal window%2$s, the other one opens it in the page itself with a "
202
+ "%1$scascading effect%2$s above content page."
203
+ msgstr ""
204
+
205
+ #: ../templates/admin/premium.php:272
206
+ msgid "Quick view type"
207
+ msgstr ""
208
+
209
+ #: ../templates/admin/premium.php:284
210
+ msgid "\"View details\" button"
211
+ msgstr ""
212
+
213
+ #: ../templates/admin/premium.php:286
214
+ msgid ""
215
+ "An additional button that allows users to access product detail page "
216
+ "directly from quick view window just with a click of the mouse."
217
+ msgstr ""
218
+
219
+ #: ../templates/admin/premium.php:295
220
+ msgid "Type of product images"
221
+ msgstr ""
222
+
223
+ #: ../templates/admin/premium.php:297
224
+ #, php-format
225
+ msgid ""
226
+ "Each product can have more than one image: choose whether to hide or show "
227
+ "them with the %1$sslider%2$s effect or in the classic %1$sWooCommerce%2$s "
228
+ "display."
229
+ msgstr ""
230
+
231
+ #: ../templates/admin/premium.php:312
232
+ msgid "SHARE"
233
+ msgstr ""
234
+
235
+ #: ../templates/admin/premium.php:314
236
+ #, php-format
237
+ msgid ""
238
+ "%1$sQuick View is also social-friendly!%2$s Activating this option, you will "
239
+ "be able to share the Quick View on Facebook, Twitter, Pinterest, Google+, or "
240
+ "sending an email."
241
+ msgstr ""
242
+
243
+ #: ../templates/admin/premium.php:325
244
+ #, php-format
245
+ msgid ""
246
+ "A rich option panel to change the colors of the %1$s\"Quick View\"%2$s "
247
+ "button and of everything that is within the modal window generated."
248
+ msgstr ""
249
+
250
+ #: ../templates/admin/premium.php:340
251
+ msgid "SHORTCODE"
252
+ msgstr ""
253
+
254
+ #: ../templates/admin/premium.php:342
255
+ msgid ""
256
+ "The shortcode of plugin is a $1$srapid$2$s and $1$seasy$2$s solution: you "
257
+ "can add a button in any spot of the page to allow your users to see the "
258
+ "quick view of a specific product in your store."
259
+ msgstr ""
260
+
261
+ #: ../templates/admin/premium.php:351
262
+ msgid "Compatibility with other YITH's plugins"
263
+ msgstr ""
264
+
265
+ #: ../templates/admin/premium.php:353
266
+ #, php-format
267
+ msgid ""
268
+ "Thanks to the compatibility with %1$sYITH WooCommerce Zoom Magnifier, YITH "
269
+ "WooCommerce Badge Management%2$s and %1$sYITH WooCommerce Wishlist%2$s, you "
270
+ "will be free to enrich further the content of your quick view.%3$s Zoom the "
271
+ "product image, show a badge, or add the button to open the quick view in all "
272
+ "products available in your users' wishlists. With YITH's plugins you make "
273
+ "the difference."
274
+ msgstr ""
license.txt CHANGED
@@ -1,694 +1,694 @@
1
- Copyright 2015-2021 Your Inspiration Solutions (email : plugins@yithemes.com)
2
-
3
- This program is free software; you can redistribute it and/or modify
4
- it under the terms of the GNU General Public License as published by
5
- the Free Software Foundation; either version 3 of the License, or
6
- (at your option) any later version.
7
-
8
- This program is distributed in the hope that it will be useful,
9
- but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- GNU General Public License for more details.
12
-
13
- You should have received a copy of the GNU General Public License
14
- along with this program; if not, write to the Free Software
15
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16
-
17
- YITH WooCommerce Quick View is released under the GPL
18
-
19
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
-
21
- GNU GENERAL PUBLIC LICENSE
22
- Version 3, 29 June 2007
23
-
24
- Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
25
- Everyone is permitted to copy and distribute verbatim copies
26
- of this license document, but changing it is not allowed.
27
-
28
- Preamble
29
-
30
- The GNU General Public License is a free, copyleft license for
31
- software and other kinds of works.
32
-
33
- The licenses for most software and other practical works are designed
34
- to take away your freedom to share and change the works. By contrast,
35
- the GNU General Public License is intended to guarantee your freedom to
36
- share and change all versions of a program--to make sure it remains free
37
- software for all its users. We, the Free Software Foundation, use the
38
- GNU General Public License for most of our software; it applies also to
39
- any other work released this way by its authors. You can apply it to
40
- your programs, too.
41
-
42
- When we speak of free software, we are referring to freedom, not
43
- price. Our General Public Licenses are designed to make sure that you
44
- have the freedom to distribute copies of free software (and charge for
45
- them if you wish), that you receive source code or can get it if you
46
- want it, that you can change the software or use pieces of it in new
47
- free programs, and that you know you can do these things.
48
-
49
- To protect your rights, we need to prevent others from denying you
50
- these rights or asking you to surrender the rights. Therefore, you have
51
- certain responsibilities if you distribute copies of the software, or if
52
- you modify it: responsibilities to respect the freedom of others.
53
-
54
- For example, if you distribute copies of such a program, whether
55
- gratis or for a fee, you must pass on to the recipients the same
56
- freedoms that you received. You must make sure that they, too, receive
57
- or can get the source code. And you must show them these terms so they
58
- know their rights.
59
-
60
- Developers that use the GNU GPL protect your rights with two steps:
61
- (1) assert copyright on the software, and (2) offer you this License
62
- giving you legal permission to copy, distribute and/or modify it.
63
-
64
- For the developers' and authors' protection, the GPL clearly explains
65
- that there is no warranty for this free software. For both users' and
66
- authors' sake, the GPL requires that modified versions be marked as
67
- changed, so that their problems will not be attributed erroneously to
68
- authors of previous versions.
69
-
70
- Some devices are designed to deny users access to install or run
71
- modified versions of the software inside them, although the manufacturer
72
- can do so. This is fundamentally incompatible with the aim of
73
- protecting users' freedom to change the software. The systematic
74
- pattern of such abuse occurs in the area of products for individuals to
75
- use, which is precisely where it is most unacceptable. Therefore, we
76
- have designed this version of the GPL to prohibit the practice for those
77
- products. If such problems arise substantially in other domains, we
78
- stand ready to extend this provision to those domains in future versions
79
- of the GPL, as needed to protect the freedom of users.
80
-
81
- Finally, every program is threatened constantly by software patents.
82
- States should not allow patents to restrict development and use of
83
- software on general-purpose computers, but in those that do, we wish to
84
- avoid the special danger that patents applied to a free program could
85
- make it effectively proprietary. To prevent this, the GPL assures that
86
- patents cannot be used to render the program non-free.
87
-
88
- The precise terms and conditions for copying, distribution and
89
- modification follow.
90
-
91
- TERMS AND CONDITIONS
92
-
93
- 0. Definitions.
94
-
95
- "This License" refers to version 3 of the GNU General Public License.
96
-
97
- "Copyright" also means copyright-like laws that apply to other kinds of
98
- works, such as semiconductor masks.
99
-
100
- "The Program" refers to any copyrightable work licensed under this
101
- License. Each licensee is addressed as "you". "Licensees" and
102
- "recipients" may be individuals or organizations.
103
-
104
- To "modify" a work means to copy from or adapt all or part of the work
105
- in a fashion requiring copyright permission, other than the making of an
106
- exact copy. The resulting work is called a "modified version" of the
107
- earlier work or a work "based on" the earlier work.
108
-
109
- A "covered work" means either the unmodified Program or a work based
110
- on the Program.
111
-
112
- To "propagate" a work means to do anything with it that, without
113
- permission, would make you directly or secondarily liable for
114
- infringement under applicable copyright law, except executing it on a
115
- computer or modifying a private copy. Propagation includes copying,
116
- distribution (with or without modification), making available to the
117
- public, and in some countries other activities as well.
118
-
119
- To "convey" a work means any kind of propagation that enables other
120
- parties to make or receive copies. Mere interaction with a user through
121
- a computer network, with no transfer of a copy, is not conveying.
122
-
123
- An interactive user interface displays "Appropriate Legal Notices"
124
- to the extent that it includes a convenient and prominently visible
125
- feature that (1) displays an appropriate copyright notice, and (2)
126
- tells the user that there is no warranty for the work (except to the
127
- extent that warranties are provided), that licensees may convey the
128
- work under this License, and how to view a copy of this License. If
129
- the interface presents a list of user commands or options, such as a
130
- menu, a prominent item in the list meets this criterion.
131
-
132
- 1. Source Code.
133
-
134
- The "source code" for a work means the preferred form of the work
135
- for making modifications to it. "Object code" means any non-source
136
- form of a work.
137
-
138
- A "Standard Interface" means an interface that either is an official
139
- standard defined by a recognized standards body, or, in the case of
140
- interfaces specified for a particular programming language, one that
141
- is widely used among developers working in that language.
142
-
143
- The "System Libraries" of an executable work include anything, other
144
- than the work as a whole, that (a) is included in the normal form of
145
- packaging a Major Component, but which is not part of that Major
146
- Component, and (b) serves only to enable use of the work with that
147
- Major Component, or to implement a Standard Interface for which an
148
- implementation is available to the public in source code form. A
149
- "Major Component", in this context, means a major essential component
150
- (kernel, window system, and so on) of the specific operating system
151
- (if any) on which the executable work runs, or a compiler used to
152
- produce the work, or an object code interpreter used to run it.
153
-
154
- The "Corresponding Source" for a work in object code form means all
155
- the source code needed to generate, install, and (for an executable
156
- work) run the object code and to modify the work, including scripts to
157
- control those activities. However, it does not include the work's
158
- System Libraries, or general-purpose tools or generally available free
159
- programs which are used unmodified in performing those activities but
160
- which are not part of the work. For example, Corresponding Source
161
- includes interface definition files associated with source files for
162
- the work, and the source code for shared libraries and dynamically
163
- linked subprograms that the work is specifically designed to require,
164
- such as by intimate data communication or control flow between those
165
- subprograms and other parts of the work.
166
-
167
- The Corresponding Source need not include anything that users
168
- can regenerate automatically from other parts of the Corresponding
169
- Source.
170
-
171
- The Corresponding Source for a work in source code form is that
172
- same work.
173
-
174
- 2. Basic Permissions.
175
-
176
- All rights granted under this License are granted for the term of
177
- copyright on the Program, and are irrevocable provided the stated
178
- conditions are met. This License explicitly affirms your unlimited
179
- permission to run the unmodified Program. The output from running a
180
- covered work is covered by this License only if the output, given its
181
- content, constitutes a covered work. This License acknowledges your
182
- rights of fair use or other equivalent, as provided by copyright law.
183
-
184
- You may make, run and propagate covered works that you do not
185
- convey, without conditions so long as your license otherwise remains
186
- in force. You may convey covered works to others for the sole purpose
187
- of having them make modifications exclusively for you, or provide you
188
- with facilities for running those works, provided that you comply with
189
- the terms of this License in conveying all material for which you do
190
- not control copyright. Those thus making or running the covered works
191
- for you must do so exclusively on your behalf, under your direction
192
- and control, on terms that prohibit them from making any copies of
193
- your copyrighted material outside their relationship with you.
194
-
195
- Conveying under any other circumstances is permitted solely under
196
- the conditions stated below. Sublicensing is not allowed; section 10
197
- makes it unnecessary.
198
-
199
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
200
-
201
- No covered work shall be deemed part of an effective technological
202
- measure under any applicable law fulfilling obligations under article
203
- 11 of the WIPO copyright treaty adopted on 20 December 1996, or
204
- similar laws prohibiting or restricting circumvention of such
205
- measures.
206
-
207
- When you convey a covered work, you waive any legal power to forbid
208
- circumvention of technological measures to the extent such circumvention
209
- is effected by exercising rights under this License with respect to
210
- the covered work, and you disclaim any intention to limit operation or
211
- modification of the work as a means of enforcing, against the work's
212
- users, your or third parties' legal rights to forbid circumvention of
213
- technological measures.
214
-
215
- 4. Conveying Verbatim Copies.
216
-
217
- You may convey verbatim copies of the Program's source code as you
218
- receive it, in any medium, provided that you conspicuously and
219
- appropriately publish on each copy an appropriate copyright notice;
220
- keep intact all notices stating that this License and any
221
- non-permissive terms added in accord with section 7 apply to the code;
222
- keep intact all notices of the absence of any warranty; and give all
223
- recipients a copy of this License along with the Program.
224
-
225
- You may charge any price or no price for each copy that you convey,
226
- and you may offer support or warranty protection for a fee.
227
-
228
- 5. Conveying Modified Source Versions.
229
-
230
- You may convey a work based on the Program, or the modifications to
231
- produce it from the Program, in the form of source code under the
232
- terms of section 4, provided that you also meet all of these conditions:
233
-
234
- a) The work must carry prominent notices stating that you modified
235
- it, and giving a relevant date.
236
-
237
- b) The work must carry prominent notices stating that it is
238
- released under this License and any conditions added under section
239
- 7. This requirement modifies the requirement in section 4 to
240
- "keep intact all notices".
241
-
242
- c) You must license the entire work, as a whole, under this
243
- License to anyone who comes into possession of a copy. This
244
- License will therefore apply, along with any applicable section 7
245
- additional terms, to the whole of the work, and all its parts,
246
- regardless of how they are packaged. This License gives no
247
- permission to license the work in any other way, but it does not
248
- invalidate such permission if you have separately received it.
249
-
250
- d) If the work has interactive user interfaces, each must display
251
- Appropriate Legal Notices; however, if the Program has interactive
252
- interfaces that do not display Appropriate Legal Notices, your
253
- work need not make them do so.
254
-
255
- A compilation of a covered work with other separate and independent
256
- works, which are not by their nature extensions of the covered work,
257
- and which are not combined with it such as to form a larger program,
258
- in or on a volume of a storage or distribution medium, is called an
259
- "aggregate" if the compilation and its resulting copyright are not
260
- used to limit the access or legal rights of the compilation's users
261
- beyond what the individual works permit. Inclusion of a covered work
262
- in an aggregate does not cause this License to apply to the other
263
- parts of the aggregate.
264
-
265
- 6. Conveying Non-Source Forms.
266
-
267
- You may convey a covered work in object code form under the terms
268
- of sections 4 and 5, provided that you also convey the
269
- machine-readable Corresponding Source under the terms of this License,
270
- in one of these ways:
271
-
272
- a) Convey the object code in, or embodied in, a physical product
273
- (including a physical distribution medium), accompanied by the
274
- Corresponding Source fixed on a durable physical medium
275
- customarily used for software interchange.
276
-
277
- b) Convey the object code in, or embodied in, a physical product
278
- (including a physical distribution medium), accompanied by a
279
- written offer, valid for at least three years and valid for as
280
- long as you offer spare parts or customer support for that product
281
- model, to give anyone who possesses the object code either (1) a
282
- copy of the Corresponding Source for all the software in the
283
- product that is covered by this License, on a durable physical
284
- medium customarily used for software interchange, for a price no
285
- more than your reasonable cost of physically performing this
286
- conveying of source, or (2) access to copy the
287
- Corresponding Source from a network server at no charge.
288
-
289
- c) Convey individual copies of the object code with a copy of the
290
- written offer to provide the Corresponding Source. This
291
- alternative is allowed only occasionally and noncommercially, and
292
- only if you received the object code with such an offer, in accord
293
- with subsection 6b.
294
-
295
- d) Convey the object code by offering access from a designated
296
- place (gratis or for a charge), and offer equivalent access to the
297
- Corresponding Source in the same way through the same place at no
298
- further charge. You need not require recipients to copy the
299
- Corresponding Source along with the object code. If the place to
300
- copy the object code is a network server, the Corresponding Source
301
- may be on a different server (operated by you or a third party)
302
- that supports equivalent copying facilities, provided you maintain
303
- clear directions next to the object code saying where to find the
304
- Corresponding Source. Regardless of what server hosts the
305
- Corresponding Source, you remain obligated to ensure that it is
306
- available for as long as needed to satisfy these requirements.
307
-
308
- e) Convey the object code using peer-to-peer transmission, provided
309
- you inform other peers where the object code and Corresponding
310
- Source of the work are being offered to the general public at no
311
- charge under subsection 6d.
312
-
313
- A separable portion of the object code, whose source code is excluded
314
- from the Corresponding Source as a System Library, need not be
315
- included in conveying the object code work.
316
-
317
- A "User Product" is either (1) a "consumer product", which means any
318
- tangible personal property which is normally used for personal, family,
319
- or household purposes, or (2) anything designed or sold for incorporation
320
- into a dwelling. In determining whether a product is a consumer product,
321
- doubtful cases shall be resolved in favor of coverage. For a particular
322
- product received by a particular user, "normally used" refers to a
323
- typical or common use of that class of product, regardless of the status
324
- of the particular user or of the way in which the particular user
325
- actually uses, or expects or is expected to use, the product. A product
326
- is a consumer product regardless of whether the product has substantial
327
- commercial, industrial or non-consumer uses, unless such uses represent
328
- the only significant mode of use of the product.
329
-
330
- "Installation Information" for a User Product means any methods,
331
- procedures, authorization keys, or other information required to install
332
- and execute modified versions of a covered work in that User Product from
333
- a modified version of its Corresponding Source. The information must
334
- suffice to ensure that the continued functioning of the modified object
335
- code is in no case prevented or interfered with solely because
336
- modification has been made.
337
-
338
- If you convey an object code work under this section in, or with, or
339
- specifically for use in, a User Product, and the conveying occurs as
340
- part of a transaction in which the right of possession and use of the
341
- User Product is transferred to the recipient in perpetuity or for a
342
- fixed term (regardless of how the transaction is characterized), the
343
- Corresponding Source conveyed under this section must be accompanied
344
- by the Installation Information. But this requirement does not apply
345
- if neither you nor any third party retains the ability to install
346
- modified object code on the User Product (for example, the work has
347
- been installed in ROM).
348
-
349
- The requirement to provide Installation Information does not include a
350
- requirement to continue to provide support service, warranty, or updates
351
- for a work that has been modified or installed by the recipient, or for
352
- the User Product in which it has been modified or installed. Access to a
353
- network may be denied when the modification itself materially and
354
- adversely affects the operation of the network or violates the rules and
355
- protocols for communication across the network.
356
-
357
- Corresponding Source conveyed, and Installation Information provided,
358
- in accord with this section must be in a format that is publicly
359
- documented (and with an implementation available to the public in
360
- source code form), and must require no special password or key for
361
- unpacking, reading or copying.
362
-
363
- 7. Additional Terms.
364
-
365
- "Additional permissions" are terms that supplement the terms of this
366
- License by making exceptions from one or more of its conditions.
367
- Additional permissions that are applicable to the entire Program shall
368
- be treated as though they were included in this License, to the extent
369
- that they are valid under applicable law. If additional permissions
370
- apply only to part of the Program, that part may be used separately
371
- under those permissions, but the entire Program remains governed by
372
- this License without regard to the additional permissions.
373
-
374
- When you convey a copy of a covered work, you may at your option
375
- remove any additional permissions from that copy, or from any part of
376
- it. (Additional permissions may be written to require their own
377
- removal in certain cases when you modify the work.) You may place
378
- additional permissions on material, added by you to a covered work,
379
- for which you have or can give appropriate copyright permission.
380
-
381
- Notwithstanding any other provision of this License, for material you
382
- add to a covered work, you may (if authorized by the copyright holders of
383
- that material) supplement the terms of this License with terms:
384
-
385
- a) Disclaiming warranty or limiting liability differently from the
386
- terms of sections 15 and 16 of this License; or
387
-
388
- b) Requiring preservation of specified reasonable legal notices or
389
- author attributions in that material or in the Appropriate Legal
390
- Notices displayed by works containing it; or
391
-
392
- c) Prohibiting misrepresentation of the origin of that material, or
393
- requiring that modified versions of such material be marked in
394
- reasonable ways as different from the original version; or
395
-
396
- d) Limiting the use for publicity purposes of names of licensors or
397
- authors of the material; or
398
-
399
- e) Declining to grant rights under trademark law for use of some
400
- trade names, trademarks, or service marks; or
401
-
402
- f) Requiring indemnification of licensors and authors of that
403
- material by anyone who conveys the material (or modified versions of
404
- it) with contractual assumptions of liability to the recipient, for
405
- any liability that these contractual assumptions directly impose on
406
- those licensors and authors.
407
-
408
- All other non-permissive additional terms are considered "further
409
- restrictions" within the meaning of section 10. If the Program as you
410
- received it, or any part of it, contains a notice stating that it is
411
- governed by this License along with a term that is a further
412
- restriction, you may remove that term. If a license document contains
413
- a further restriction but permits relicensing or conveying under this
414
- License, you may add to a covered work material governed by the terms
415
- of that license document, provided that the further restriction does
416
- not survive such relicensing or conveying.
417
-
418
- If you add terms to a covered work in accord with this section, you
419
- must place, in the relevant source files, a statement of the
420
- additional terms that apply to those files, or a notice indicating
421
- where to find the applicable terms.
422
-
423
- Additional terms, permissive or non-permissive, may be stated in the
424
- form of a separately written license, or stated as exceptions;
425
- the above requirements apply either way.
426
-
427
- 8. Termination.
428
-
429
- You may not propagate or modify a covered work except as expressly
430
- provided under this License. Any attempt otherwise to propagate or
431
- modify it is void, and will automatically terminate your rights under
432
- this License (including any patent licenses granted under the third
433
- paragraph of section 11).
434
-
435
- However, if you cease all violation of this License, then your
436
- license from a particular copyright holder is reinstated (a)
437
- provisionally, unless and until the copyright holder explicitly and
438
- finally terminates your license, and (b) permanently, if the copyright
439
- holder fails to notify you of the violation by some reasonable means
440
- prior to 60 days after the cessation.
441
-
442
- Moreover, your license from a particular copyright holder is
443
- reinstated permanently if the copyright holder notifies you of the
444
- violation by some reasonable means, this is the first time you have
445
- received notice of violation of this License (for any work) from that
446
- copyright holder, and you cure the violation prior to 30 days after
447
- your receipt of the notice.
448
-
449
- Termination of your rights under this section does not terminate the
450
- licenses of parties who have received copies or rights from you under
451
- this License. If your rights have been terminated and not permanently
452
- reinstated, you do not qualify to receive new licenses for the same
453
- material under section 10.
454
-
455
- 9. Acceptance Not Required for Having Copies.
456
-
457
- You are not required to accept this License in order to receive or
458
- run a copy of the Program. Ancillary propagation of a covered work
459
- occurring solely as a consequence of using peer-to-peer transmission
460
- to receive a copy likewise does not require acceptance. However,
461
- nothing other than this License grants you permission to propagate or
462
- modify any covered work. These actions infringe copyright if you do
463
- not accept this License. Therefore, by modifying or propagating a
464
- covered work, you indicate your acceptance of this License to do so.
465
-
466
- 10. Automatic Licensing of Downstream Recipients.
467
-
468
- Each time you convey a covered work, the recipient automatically
469
- receives a license from the original licensors, to run, modify and
470
- propagate that work, subject to this License. You are not responsible
471
- for enforcing compliance by third parties with this License.
472
-
473
- An "entity transaction" is a transaction transferring control of an
474
- organization, or substantially all assets of one, or subdividing an
475
- organization, or merging organizations. If propagation of a covered
476
- work results from an entity transaction, each party to that
477
- transaction who receives a copy of the work also receives whatever
478
- licenses to the work the party's predecessor in interest had or could
479
- give under the previous paragraph, plus a right to possession of the
480
- Corresponding Source of the work from the predecessor in interest, if
481
- the predecessor has it or can get it with reasonable efforts.
482
-
483
- You may not impose any further restrictions on the exercise of the
484
- rights granted or affirmed under this License. For example, you may
485
- not impose a license fee, royalty, or other charge for exercise of
486
- rights granted under this License, and you may not initiate litigation
487
- (including a cross-claim or counterclaim in a lawsuit) alleging that
488
- any patent claim is infringed by making, using, selling, offering for
489
- sale, or importing the Program or any portion of it.
490
-
491
- 11. Patents.
492
-
493
- A "contributor" is a copyright holder who authorizes use under this
494
- License of the Program or a work on which the Program is based. The
495
- work thus licensed is called the contributor's "contributor version".
496
-
497
- A contributor's "essential patent claims" are all patent claims
498
- owned or controlled by the contributor, whether already acquired or
499
- hereafter acquired, that would be infringed by some manner, permitted
500
- by this License, of making, using, or selling its contributor version,
501
- but do not include claims that would be infringed only as a
502
- consequence of further modification of the contributor version. For
503
- purposes of this definition, "control" includes the right to grant
504
- patent sublicenses in a manner consistent with the requirements of
505
- this License.
506
-
507
- Each contributor grants you a non-exclusive, worldwide, royalty-free
508
- patent license under the contributor's essential patent claims, to
509
- make, use, sell, offer for sale, import and otherwise run, modify and
510
- propagate the contents of its contributor version.
511
-
512
- In the following three paragraphs, a "patent license" is any express
513
- agreement or commitment, however denominated, not to enforce a patent
514
- (such as an express permission to practice a patent or covenant not to
515
- sue for patent infringement). To "grant" such a patent license to a
516
- party means to make such an agreement or commitment not to enforce a
517
- patent against the party.
518
-
519
- If you convey a covered work, knowingly relying on a patent license,
520
- and the Corresponding Source of the work is not available for anyone
521
- to copy, free of charge and under the terms of this License, through a
522
- publicly available network server or other readily accessible means,
523
- then you must either (1) cause the Corresponding Source to be so
524
- available, or (2) arrange to deprive yourself of the benefit of the
525
- patent license for this particular work, or (3) arrange, in a manner
526
- consistent with the requirements of this License, to extend the patent
527
- license to downstream recipients. "Knowingly relying" means you have
528
- actual knowledge that, but for the patent license, your conveying the
529
- covered work in a country, or your recipient's use of the covered work
530
- in a country, would infringe one or more identifiable patents in that
531
- country that you have reason to believe are valid.
532
-
533
- If, pursuant to or in connection with a single transaction or
534
- arrangement, you convey, or propagate by procuring conveyance of, a
535
- covered work, and grant a patent license to some of the parties
536
- receiving the covered work authorizing them to use, propagate, modify
537
- or convey a specific copy of the covered work, then the patent license
538
- you grant is automatically extended to all recipients of the covered
539
- work and works based on it.
540
-
541
- A patent license is "discriminatory" if it does not include within
542
- the scope of its coverage, prohibits the exercise of, or is
543
- conditioned on the non-exercise of one or more of the rights that are
544
- specifically granted under this License. You may not convey a covered
545
- work if you are a party to an arrangement with a third party that is
546
- in the business of distributing software, under which you make payment
547
- to the third party based on the extent of your activity of conveying
548
- the work, and under which the third party grants, to any of the
549
- parties who would receive the covered work from you, a discriminatory
550
- patent license (a) in connection with copies of the covered work
551
- conveyed by you (or copies made from those copies), or (b) primarily
552
- for and in connection with specific products or compilations that
553
- contain the covered work, unless you entered into that arrangement,
554
- or that patent license was granted, prior to 28 March 2007.
555
-
556
- Nothing in this License shall be construed as excluding or limiting
557
- any implied license or other defenses to infringement that may
558
- otherwise be available to you under applicable patent law.
559
-
560
- 12. No Surrender of Others' Freedom.
561
-
562
- If conditions are imposed on you (whether by court order, agreement or
563
- otherwise) that contradict the conditions of this License, they do not
564
- excuse you from the conditions of this License. If you cannot convey a
565
- covered work so as to satisfy simultaneously your obligations under this
566
- License and any other pertinent obligations, then as a consequence you may
567
- not convey it at all. For example, if you agree to terms that obligate you
568
- to collect a royalty for further conveying from those to whom you convey
569
- the Program, the only way you could satisfy both those terms and this
570
- License would be to refrain entirely from conveying the Program.
571
-
572
- 13. Use with the GNU Affero General Public License.
573
-
574
- Notwithstanding any other provision of this License, you have
575
- permission to link or combine any covered work with a work licensed
576
- under version 3 of the GNU Affero General Public License into a single
577
- combined work, and to convey the resulting work. The terms of this
578
- License will continue to apply to the part which is the covered work,
579
- but the special requirements of the GNU Affero General Public License,
580
- section 13, concerning interaction through a network will apply to the
581
- combination as such.
582
-
583
- 14. Revised Versions of this License.
584
-
585
- The Free Software Foundation may publish revised and/or new versions of
586
- the GNU General Public License from time to time. Such new versions will
587
- be similar in spirit to the present version, but may differ in detail to
588
- address new problems or concerns.
589
-
590
- Each version is given a distinguishing version number. If the
591
- Program specifies that a certain numbered version of the GNU General
592
- Public License "or any later version" applies to it, you have the
593
- option of following the terms and conditions either of that numbered
594
- version or of any later version published by the Free Software
595
- Foundation. If the Program does not specify a version number of the
596
- GNU General Public License, you may choose any version ever published
597
- by the Free Software Foundation.
598
-
599
- If the Program specifies that a proxy can decide which future
600
- versions of the GNU General Public License can be used, that proxy's
601
- public statement of acceptance of a version permanently authorizes you
602
- to choose that version for the Program.
603
-
604
- Later license versions may give you additional or different
605
- permissions. However, no additional obligations are imposed on any
606
- author or copyright holder as a result of your choosing to follow a
607
- later version.
608
-
609
- 15. Disclaimer of Warranty.
610
-
611
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
612
- APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
613
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
614
- OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
615
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
616
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
617
- IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
618
- ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
619
-
620
- 16. Limitation of Liability.
621
-
622
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
623
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
624
- THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
625
- GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
626
- USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
627
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
628
- PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
629
- EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
630
- SUCH DAMAGES.
631
-
632
- 17. Interpretation of Sections 15 and 16.
633
-
634
- If the disclaimer of warranty and limitation of liability provided
635
- above cannot be given local legal effect according to their terms,
636
- reviewing courts shall apply local law that most closely approximates
637
- an absolute waiver of all civil liability in connection with the
638
- Program, unless a warranty or assumption of liability accompanies a
639
- copy of the Program in return for a fee.
640
-
641
- END OF TERMS AND CONDITIONS
642
-
643
- How to Apply These Terms to Your New Programs
644
-
645
- If you develop a new program, and you want it to be of the greatest
646
- possible use to the public, the best way to achieve this is to make it
647
- free software which everyone can redistribute and change under these terms.
648
-
649
- To do so, attach the following notices to the program. It is safest
650
- to attach them to the start of each source file to most effectively
651
- state the exclusion of warranty; and each file should have at least
652
- the "copyright" line and a pointer to where the full notice is found.
653
-
654
- <one line to give the program's name and a brief idea of what it does.>
655
- Copyright © <year> <name of author>
656
-
657
- This program is free software: you can redistribute it and/or modify
658
- it under the terms of the GNU General Public License as published by
659
- the Free Software Foundation, either version 3 of the License, or
660
- (at your option) any later version.
661
-
662
- This program is distributed in the hope that it will be useful,
663
- but WITHOUT ANY WARRANTY; without even the implied warranty of
664
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
665
- GNU General Public License for more details.
666
-
667
- You should have received a copy of the GNU General Public License
668
- along with this program. If not, see <https://www.gnu.org/licenses/>.
669
-
670
- Also add information on how to contact you by electronic and paper mail.
671
-
672
- If the program does terminal interaction, make it output a short
673
- notice like this when it starts in an interactive mode:
674
-
675
- <program> Copyright © <year> <name of author>
676
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
677
- This is free software, and you are welcome to redistribute it
678
- under certain conditions; type `show c' for details.
679
-
680
- The hypothetical commands `show w' and `show c' should show the appropriate
681
- parts of the General Public License. Of course, your program's commands
682
- might be different; for a GUI interface, you would use an "about box".
683
-
684
- You should also get your employer (if you work as a programmer) or school,
685
- if any, to sign a "copyright disclaimer" for the program, if necessary.
686
- For more information on this, and how to apply and follow the GNU GPL, see
687
- <https://www.gnu.org/licenses/>.
688
-
689
- The GNU General Public License does not permit incorporating your program
690
- into proprietary programs. If your program is a subroutine library, you
691
- may consider it more useful to permit linking proprietary applications with
692
- the library. If this is what you want to do, use the GNU Lesser General
693
- Public License instead of this License. But first, please read
694
  <https://www.gnu.org/philosophy/why-not-lgpl.html>.
1
+ Copyright 2015-2021 Your Inspiration Solutions (email : plugins@yithemes.com)
2
+
3
+ This program is free software; you can redistribute it and/or modify
4
+ it under the terms of the GNU General Public License as published by
5
+ the Free Software Foundation; either version 3 of the License, or
6
+ (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License
14
+ along with this program; if not, write to the Free Software
15
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ YITH WooCommerce Quick View is released under the GPL
18
+
19
+ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
+
21
+ GNU GENERAL PUBLIC LICENSE
22
+ Version 3, 29 June 2007
23
+
24
+ Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
25
+ Everyone is permitted to copy and distribute verbatim copies
26
+ of this license document, but changing it is not allowed.
27
+
28
+ Preamble
29
+
30
+ The GNU General Public License is a free, copyleft license for
31
+ software and other kinds of works.
32
+
33
+ The licenses for most software and other practical works are designed
34
+ to take away your freedom to share and change the works. By contrast,
35
+ the GNU General Public License is intended to guarantee your freedom to
36
+ share and change all versions of a program--to make sure it remains free
37
+ software for all its users. We, the Free Software Foundation, use the
38
+ GNU General Public License for most of our software; it applies also to
39
+ any other work released this way by its authors. You can apply it to
40
+ your programs, too.
41
+
42
+ When we speak of free software, we are referring to freedom, not
43
+ price. Our General Public Licenses are designed to make sure that you
44
+ have the freedom to distribute copies of free software (and charge for
45
+ them if you wish), that you receive source code or can get it if you
46
+ want it, that you can change the software or use pieces of it in new
47
+ free programs, and that you know you can do these things.
48
+
49
+ To protect your rights, we need to prevent others from denying you
50
+ these rights or asking you to surrender the rights. Therefore, you have
51
+ certain responsibilities if you distribute copies of the software, or if
52
+ you modify it: responsibilities to respect the freedom of others.
53
+
54
+ For example, if you distribute copies of such a program, whether
55
+ gratis or for a fee, you must pass on to the recipients the same
56
+ freedoms that you received. You must make sure that they, too, receive
57
+ or can get the source code. And you must show them these terms so they
58
+ know their rights.
59
+
60
+ Developers that use the GNU GPL protect your rights with two steps:
61
+ (1) assert copyright on the software, and (2) offer you this License
62
+ giving you legal permission to copy, distribute and/or modify it.
63
+
64
+ For the developers' and authors' protection, the GPL clearly explains
65
+ that there is no warranty for this free software. For both users' and
66
+ authors' sake, the GPL requires that modified versions be marked as
67
+ changed, so that their problems will not be attributed erroneously to
68
+ authors of previous versions.
69
+
70
+ Some devices are designed to deny users access to install or run
71
+ modified versions of the software inside them, although the manufacturer
72
+ can do so. This is fundamentally incompatible with the aim of
73
+ protecting users' freedom to change the software. The systematic
74
+ pattern of such abuse occurs in the area of products for individuals to
75
+ use, which is precisely where it is most unacceptable. Therefore, we
76
+ have designed this version of the GPL to prohibit the practice for those
77
+ products. If such problems arise substantially in other domains, we
78
+ stand ready to extend this provision to those domains in future versions
79
+ of the GPL, as needed to protect the freedom of users.
80
+
81
+ Finally, every program is threatened constantly by software patents.
82
+ States should not allow patents to restrict development and use of
83
+ software on general-purpose computers, but in those that do, we wish to
84
+ avoid the special danger that patents applied to a free program could
85
+ make it effectively proprietary. To prevent this, the GPL assures that
86
+ patents cannot be used to render the program non-free.
87
+
88
+ The precise terms and conditions for copying, distribution and
89
+ modification follow.
90
+
91
+ TERMS AND CONDITIONS
92
+
93
+ 0. Definitions.
94
+
95
+ "This License" refers to version 3 of the GNU General Public License.
96
+
97
+ "Copyright" also means copyright-like laws that apply to other kinds of
98
+ works, such as semiconductor masks.
99
+
100
+ "The Program" refers to any copyrightable work licensed under this
101
+ License. Each licensee is addressed as "you". "Licensees" and
102
+ "recipients" may be individuals or organizations.
103
+
104
+ To "modify" a work means to copy from or adapt all or part of the work
105
+ in a fashion requiring copyright permission, other than the making of an
106
+ exact copy. The resulting work is called a "modified version" of the
107
+ earlier work or a work "based on" the earlier work.
108
+
109
+ A "covered work" means either the unmodified Program or a work based
110
+ on the Program.
111
+
112
+ To "propagate" a work means to do anything with it that, without
113
+ permission, would make you directly or secondarily liable for
114
+ infringement under applicable copyright law, except executing it on a
115
+ computer or modifying a private copy. Propagation includes copying,
116
+ distribution (with or without modification), making available to the
117
+ public, and in some countries other activities as well.
118
+
119
+ To "convey" a work means any kind of propagation that enables other
120
+ parties to make or receive copies. Mere interaction with a user through
121
+ a computer network, with no transfer of a copy, is not conveying.
122
+
123
+ An interactive user interface displays "Appropriate Legal Notices"
124
+ to the extent that it includes a convenient and prominently visible
125
+ feature that (1) displays an appropriate copyright notice, and (2)
126
+ tells the user that there is no warranty for the work (except to the
127
+ extent that warranties are provided), that licensees may convey the
128
+ work under this License, and how to view a copy of this License. If
129
+ the interface presents a list of user commands or options, such as a
130
+ menu, a prominent item in the list meets this criterion.
131
+
132
+ 1. Source Code.
133
+
134
+ The "source code" for a work means the preferred form of the work
135
+ for making modifications to it. "Object code" means any non-source
136
+ form of a work.
137
+
138
+ A "Standard Interface" means an interface that either is an official
139
+ standard defined by a recognized standards body, or, in the case of
140
+ interfaces specified for a particular programming language, one that
141
+ is widely used among developers working in that language.
142
+
143
+ The "System Libraries" of an executable work include anything, other
144
+ than the work as a whole, that (a) is included in the normal form of
145
+ packaging a Major Component, but which is not part of that Major
146
+ Component, and (b) serves only to enable use of the work with that
147
+ Major Component, or to implement a Standard Interface for which an
148
+ implementation is available to the public in source code form. A
149
+ "Major Component", in this context, means a major essential component
150
+ (kernel, window system, and so on) of the specific operating system
151
+ (if any) on which the executable work runs, or a compiler used to
152
+ produce the work, or an object code interpreter used to run it.
153
+
154
+ The "Corresponding Source" for a work in object code form means all
155
+ the source code needed to generate, install, and (for an executable
156
+ work) run the object code and to modify the work, including scripts to
157
+ control those activities. However, it does not include the work's
158
+ System Libraries, or general-purpose tools or generally available free
159
+ programs which are used unmodified in performing those activities but
160
+ which are not part of the work. For example, Corresponding Source
161
+ includes interface definition files associated with source files for
162
+ the work, and the source code for shared libraries and dynamically
163
+ linked subprograms that the work is specifically designed to require,
164
+ such as by intimate data communication or control flow between those
165
+ subprograms and other parts of the work.
166
+
167
+ The Corresponding Source need not include anything that users
168
+ can regenerate automatically from other parts of the Corresponding
169
+ Source.
170
+
171
+ The Corresponding Source for a work in source code form is that
172
+ same work.
173
+
174
+ 2. Basic Permissions.
175
+
176
+ All rights granted under this License are granted for the term of
177
+ copyright on the Program, and are irrevocable provided the stated
178
+ conditions are met. This License explicitly affirms your unlimited
179
+ permission to run the unmodified Program. The output from running a
180
+ covered work is covered by this License only if the output, given its
181
+ content, constitutes a covered work. This License acknowledges your
182
+ rights of fair use or other equivalent, as provided by copyright law.
183
+
184
+ You may make, run and propagate covered works that you do not
185
+ convey, without conditions so long as your license otherwise remains
186
+ in force. You may convey covered works to others for the sole purpose
187
+ of having them make modifications exclusively for you, or provide you
188
+ with facilities for running those works, provided that you comply with
189
+ the terms of this License in conveying all material for which you do
190
+ not control copyright. Those thus making or running the covered works
191
+ for you must do so exclusively on your behalf, under your direction
192
+ and control, on terms that prohibit them from making any copies of
193
+ your copyrighted material outside their relationship with you.
194
+
195
+ Conveying under any other circumstances is permitted solely under
196
+ the conditions stated below. Sublicensing is not allowed; section 10
197
+ makes it unnecessary.
198
+
199
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
200
+
201
+ No covered work shall be deemed part of an effective technological
202
+ measure under any applicable law fulfilling obligations under article
203
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
204
+ similar laws prohibiting or restricting circumvention of such
205
+ measures.
206
+
207
+ When you convey a covered work, you waive any legal power to forbid
208
+ circumvention of technological measures to the extent such circumvention
209
+ is effected by exercising rights under this License with respect to
210
+ the covered work, and you disclaim any intention to limit operation or
211
+ modification of the work as a means of enforcing, against the work's
212
+ users, your or third parties' legal rights to forbid circumvention of
213
+ technological measures.
214
+
215
+ 4. Conveying Verbatim Copies.
216
+
217
+ You may convey verbatim copies of the Program's source code as you
218
+ receive it, in any medium, provided that you conspicuously and
219
+ appropriately publish on each copy an appropriate copyright notice;
220
+ keep intact all notices stating that this License and any
221
+ non-permissive terms added in accord with section 7 apply to the code;
222
+ keep intact all notices of the absence of any warranty; and give all
223
+ recipients a copy of this License along with the Program.
224
+
225
+ You may charge any price or no price for each copy that you convey,
226
+ and you may offer support or warranty protection for a fee.
227
+
228
+ 5. Conveying Modified Source Versions.
229
+
230
+ You may convey a work based on the Program, or the modifications to
231
+ produce it from the Program, in the form of source code under the
232
+ terms of section 4, provided that you also meet all of these conditions:
233
+
234
+ a) The work must carry prominent notices stating that you modified
235
+ it, and giving a relevant date.
236
+
237
+ b) The work must carry prominent notices stating that it is
238
+ released under this License and any conditions added under section
239
+ 7. This requirement modifies the requirement in section 4 to
240
+ "keep intact all notices".
241
+
242
+ c) You must license the entire work, as a whole, under this
243
+ License to anyone who comes into possession of a copy. This
244
+ License will therefore apply, along with any applicable section 7
245
+ additional terms, to the whole of the work, and all its parts,
246
+ regardless of how they are packaged. This License gives no
247
+ permission to license the work in any other way, but it does not
248
+ invalidate such permission if you have separately received it.
249
+
250
+ d) If the work has interactive user interfaces, each must display
251
+ Appropriate Legal Notices; however, if the Program has interactive
252
+ interfaces that do not display Appropriate Legal Notices, your
253
+ work need not make them do so.
254
+
255
+ A compilation of a covered work with other separate and independent
256
+ works, which are not by their nature extensions of the covered work,
257
+ and which are not combined with it such as to form a larger program,
258
+ in or on a volume of a storage or distribution medium, is called an
259
+ "aggregate" if the compilation and its resulting copyright are not
260
+ used to limit the access or legal rights of the compilation's users
261
+ beyond what the individual works permit. Inclusion of a covered work
262
+ in an aggregate does not cause this License to apply to the other
263
+ parts of the aggregate.
264
+
265
+ 6. Conveying Non-Source Forms.
266
+
267
+ You may convey a covered work in object code form under the terms
268
+ of sections 4 and 5, provided that you also convey the
269
+ machine-readable Corresponding Source under the terms of this License,
270
+ in one of these ways:
271
+
272
+ a) Convey the object code in, or embodied in, a physical product
273
+ (including a physical distribution medium), accompanied by the
274
+ Corresponding Source fixed on a durable physical medium
275
+ customarily used for software interchange.
276
+
277
+ b) Convey the object code in, or embodied in, a physical product
278
+ (including a physical distribution medium), accompanied by a
279
+ written offer, valid for at least three years and valid for as
280
+ long as you offer spare parts or customer support for that product
281
+ model, to give anyone who possesses the object code either (1) a
282
+ copy of the Corresponding Source for all the software in the
283
+ product that is covered by this License, on a durable physical
284
+ medium customarily used for software interchange, for a price no
285
+ more than your reasonable cost of physically performing this
286
+ conveying of source, or (2) access to copy the
287
+ Corresponding Source from a network server at no charge.
288
+
289
+ c) Convey individual copies of the object code with a copy of the
290
+ written offer to provide the Corresponding Source. This
291
+ alternative is allowed only occasionally and noncommercially, and
292
+ only if you received the object code with such an offer, in accord
293
+ with subsection 6b.
294
+
295
+ d) Convey the object code by offering access from a designated
296
+ place (gratis or for a charge), and offer equivalent access to the
297
+ Corresponding Source in the same way through the same place at no
298
+ further charge. You need not require recipients to copy the
299
+ Corresponding Source along with the object code. If the place to
300
+ copy the object code is a network server, the Corresponding Source
301
+ may be on a different server (operated by you or a third party)
302
+ that supports equivalent copying facilities, provided you maintain
303
+ clear directions next to the object code saying where to find the
304
+ Corresponding Source. Regardless of what server hosts the
305
+ Corresponding Source, you remain obligated to ensure that it is
306
+ available for as long as needed to satisfy these requirements.
307
+
308
+ e) Convey the object code using peer-to-peer transmission, provided
309
+ you inform other peers where the object code and Corresponding
310
+ Source of the work are being offered to the general public at no
311
+ charge under subsection 6d.
312
+
313
+ A separable portion of the object code, whose source code is excluded
314
+ from the Corresponding Source as a System Library, need not be
315
+ included in conveying the object code work.
316
+
317
+ A "User Product" is either (1) a "consumer product", which means any
318
+ tangible personal property which is normally used for personal, family,
319
+ or household purposes, or (2) anything designed or sold for incorporation
320
+ into a dwelling. In determining whether a product is a consumer product,
321
+ doubtful cases shall be resolved in favor of coverage. For a particular
322
+ product received by a particular user, "normally used" refers to a
323
+ typical or common use of that class of product, regardless of the status
324
+ of the particular user or of the way in which the particular user
325
+ actually uses, or expects or is expected to use, the product. A product
326
+ is a consumer product regardless of whether the product has substantial
327
+ commercial, industrial or non-consumer uses, unless such uses represent
328
+ the only significant mode of use of the product.
329
+
330
+ "Installation Information" for a User Product means any methods,
331
+ procedures, authorization keys, or other information required to install
332
+ and execute modified versions of a covered work in that User Product from
333
+ a modified version of its Corresponding Source. The information must
334
+ suffice to ensure that the continued functioning of the modified object
335
+ code is in no case prevented or interfered with solely because
336
+ modification has been made.
337
+
338
+ If you convey an object code work under this section in, or with, or
339
+ specifically for use in, a User Product, and the conveying occurs as
340
+ part of a transaction in which the right of possession and use of the
341
+ User Product is transferred to the recipient in perpetuity or for a
342
+ fixed term (regardless of how the transaction is characterized), the
343
+ Corresponding Source conveyed under this section must be accompanied
344
+ by the Installation Information. But this requirement does not apply
345
+ if neither you nor any third party retains the ability to install
346
+ modified object code on the User Product (for example, the work has
347
+ been installed in ROM).
348
+
349
+ The requirement to provide Installation Information does not include a
350
+ requirement to continue to provide support service, warranty, or updates
351
+ for a work that has been modified or installed by the recipient, or for
352
+ the User Product in which it has been modified or installed. Access to a
353
+ network may be denied when the modification itself materially and
354
+ adversely affects the operation of the network or violates the rules and
355
+ protocols for communication across the network.
356
+
357
+ Corresponding Source conveyed, and Installation Information provided,
358
+ in accord with this section must be in a format that is publicly
359
+ documented (and with an implementation available to the public in
360
+ source code form), and must require no special password or key for
361
+ unpacking, reading or copying.
362
+
363
+ 7. Additional Terms.
364
+
365
+ "Additional permissions" are terms that supplement the terms of this
366
+ License by making exceptions from one or more of its conditions.
367
+ Additional permissions that are applicable to the entire Program shall
368
+ be treated as though they were included in this License, to the extent
369
+ that they are valid under applicable law. If additional permissions
370
+ apply only to part of the Program, that part may be used separately
371
+ under those permissions, but the entire Program remains governed by
372
+ this License without regard to the additional permissions.
373
+
374
+ When you convey a copy of a covered work, you may at your option
375
+ remove any additional permissions from that copy, or from any part of
376
+ it. (Additional permissions may be written to require their own
377
+ removal in certain cases when you modify the work.) You may place
378
+ additional permissions on material, added by you to a covered work,
379
+ for which you have or can give appropriate copyright permission.
380
+
381
+ Notwithstanding any other provision of this License, for material you
382
+ add to a covered work, you may (if authorized by the copyright holders of
383
+ that material) supplement the terms of this License with terms:
384
+
385
+ a) Disclaiming warranty or limiting liability differently from the
386
+ terms of sections 15 and 16 of this License; or
387
+
388
+ b) Requiring preservation of specified reasonable legal notices or
389
+ author attributions in that material or in the Appropriate Legal
390
+ Notices displayed by works containing it; or
391
+
392
+ c) Prohibiting misrepresentation of the origin of that material, or
393
+ requiring that modified versions of such material be marked in
394
+ reasonable ways as different from the original version; or
395
+
396
+ d) Limiting the use for publicity purposes of names of licensors or
397
+ authors of the material; or
398
+
399
+ e) Declining to grant rights under trademark law for use of some
400
+ trade names, trademarks, or service marks; or
401
+
402
+ f) Requiring indemnification of licensors and authors of that
403
+ material by anyone who conveys the material (or modified versions of
404
+ it) with contractual assumptions of liability to the recipient, for
405
+ any liability that these contractual assumptions directly impose on
406
+ those licensors and authors.
407
+
408
+ All other non-permissive additional terms are considered "further
409
+ restrictions" within the meaning of section 10. If the Program as you
410
+ received it, or any part of it, contains a notice stating that it is
411
+ governed by this License along with a term that is a further
412
+ restriction, you may remove that term. If a license document contains
413
+ a further restriction but permits relicensing or conveying under this
414
+ License, you may add to a covered work material governed by the terms
415
+ of that license document, provided that the further restriction does
416
+ not survive such relicensing or conveying.
417
+
418
+ If you add terms to a covered work in accord with this section, you
419
+ must place, in the relevant source files, a statement of the
420
+ additional terms that apply to those files, or a notice indicating
421
+ where to find the applicable terms.
422
+
423
+ Additional terms, permissive or non-permissive, may be stated in the
424
+ form of a separately written license, or stated as exceptions;
425
+ the above requirements apply either way.
426
+
427
+ 8. Termination.
428
+
429
+ You may not propagate or modify a covered work except as expressly
430
+ provided under this License. Any attempt otherwise to propagate or
431
+ modify it is void, and will automatically terminate your rights under
432
+ this License (including any patent licenses granted under the third
433
+ paragraph of section 11).
434
+
435
+ However, if you cease all violation of this License, then your
436
+ license from a particular copyright holder is reinstated (a)
437
+ provisionally, unless and until the copyright holder explicitly and
438
+ finally terminates your license, and (b) permanently, if the copyright
439
+ holder fails to notify you of the violation by some reasonable means
440
+ prior to 60 days after the cessation.
441
+
442
+ Moreover, your license from a particular copyright holder is
443
+ reinstated permanently if the copyright holder notifies you of the
444
+ violation by some reasonable means, this is the first time you have
445
+ received notice of violation of this License (for any work) from that
446
+ copyright holder, and you cure the violation prior to 30 days after
447
+ your receipt of the notice.
448
+
449
+ Termination of your rights under this section does not terminate the
450
+ licenses of parties who have received copies or rights from you under
451
+ this License. If your rights have been terminated and not permanently
452
+ reinstated, you do not qualify to receive new licenses for the same
453
+ material under section 10.
454
+
455
+ 9. Acceptance Not Required for Having Copies.
456
+
457
+ You are not required to accept this License in order to receive or
458
+ run a copy of the Program. Ancillary propagation of a covered work
459
+ occurring solely as a consequence of using peer-to-peer transmission
460
+ to receive a copy likewise does not require acceptance. However,
461
+ nothing other than this License grants you permission to propagate or
462
+ modify any covered work. These actions infringe copyright if you do
463
+ not accept this License. Therefore, by modifying or propagating a
464
+ covered work, you indicate your acceptance of this License to do so.
465
+
466
+ 10. Automatic Licensing of Downstream Recipients.
467
+
468
+ Each time you convey a covered work, the recipient automatically
469
+ receives a license from the original licensors, to run, modify and
470
+ propagate that work, subject to this License. You are not responsible
471
+ for enforcing compliance by third parties with this License.
472
+
473
+ An "entity transaction" is a transaction transferring control of an
474
+ organization, or substantially all assets of one, or subdividing an
475
+ organization, or merging organizations. If propagation of a covered
476
+ work results from an entity transaction, each party to that
477
+ transaction who receives a copy of the work also receives whatever
478
+ licenses to the work the party's predecessor in interest had or could
479
+ give under the previous paragraph, plus a right to possession of the
480
+ Corresponding Source of the work from the predecessor in interest, if
481
+ the predecessor has it or can get it with reasonable efforts.
482
+
483
+ You may not impose any further restrictions on the exercise of the
484
+ rights granted or affirmed under this License. For example, you may
485
+ not impose a license fee, royalty, or other charge for exercise of
486
+ rights granted under this License, and you may not initiate litigation
487
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
488
+ any patent claim is infringed by making, using, selling, offering for
489
+ sale, or importing the Program or any portion of it.
490
+
491
+ 11. Patents.
492
+
493
+ A "contributor" is a copyright holder who authorizes use under this
494
+ License of the Program or a work on which the Program is based. The
495
+ work thus licensed is called the contributor's "contributor version".
496
+
497
+ A contributor's "essential patent claims" are all patent claims
498
+ owned or controlled by the contributor, whether already acquired or
499
+ hereafter acquired, that would be infringed by some manner, permitted
500
+ by this License, of making, using, or selling its contributor version,
501
+ but do not include claims that would be infringed only as a
502
+ consequence of further modification of the contributor version. For
503
+ purposes of this definition, "control" includes the right to grant
504
+ patent sublicenses in a manner consistent with the requirements of
505
+ this License.
506
+
507
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
508
+ patent license under the contributor's essential patent claims, to
509
+ make, use, sell, offer for sale, import and otherwise run, modify and
510
+ propagate the contents of its contributor version.
511
+
512
+ In the following three paragraphs, a "patent license" is any express
513
+ agreement or commitment, however denominated, not to enforce a patent
514
+ (such as an express permission to practice a patent or covenant not to
515
+ sue for patent infringement). To "grant" such a patent license to a
516
+ party means to make such an agreement or commitment not to enforce a
517
+ patent against the party.
518
+
519
+ If you convey a covered work, knowingly relying on a patent license,
520
+ and the Corresponding Source of the work is not available for anyone
521
+ to copy, free of charge and under the terms of this License, through a
522
+ publicly available network server or other readily accessible means,
523
+ then you must either (1) cause the Corresponding Source to be so
524
+ available, or (2) arrange to deprive yourself of the benefit of the
525
+ patent license for this particular work, or (3) arrange, in a manner
526
+ consistent with the requirements of this License, to extend the patent
527
+ license to downstream recipients. "Knowingly relying" means you have
528
+ actual knowledge that, but for the patent license, your conveying the
529
+ covered work in a country, or your recipient's use of the covered work
530
+ in a country, would infringe one or more identifiable patents in that
531
+ country that you have reason to believe are valid.
532
+
533
+ If, pursuant to or in connection with a single transaction or
534
+ arrangement, you convey, or propagate by procuring conveyance of, a
535
+ covered work, and grant a patent license to some of the parties
536
+ receiving the covered work authorizing them to use, propagate, modify
537
+ or convey a specific copy of the covered work, then the patent license
538
+ you grant is automatically extended to all recipients of the covered
539
+ work and works based on it.
540
+
541
+ A patent license is "discriminatory" if it does not include within
542
+ the scope of its coverage, prohibits the exercise of, or is
543
+ conditioned on the non-exercise of one or more of the rights that are
544
+ specifically granted under this License. You may not convey a covered
545
+ work if you are a party to an arrangement with a third party that is
546
+ in the business of distributing software, under which you make payment
547
+ to the third party based on the extent of your activity of conveying
548
+ the work, and under which the third party grants, to any of the
549
+ parties who would receive the covered work from you, a discriminatory
550
+ patent license (a) in connection with copies of the covered work
551
+ conveyed by you (or copies made from those copies), or (b) primarily
552
+ for and in connection with specific products or compilations that
553
+ contain the covered work, unless you entered into that arrangement,
554
+ or that patent license was granted, prior to 28 March 2007.
555
+
556
+ Nothing in this License shall be construed as excluding or limiting
557
+ any implied license or other defenses to infringement that may
558
+ otherwise be available to you under applicable patent law.
559
+
560
+ 12. No Surrender of Others' Freedom.
561
+
562
+ If conditions are imposed on you (whether by court order, agreement or
563
+ otherwise) that contradict the conditions of this License, they do not
564
+ excuse you from the conditions of this License. If you cannot convey a
565
+ covered work so as to satisfy simultaneously your obligations under this
566
+ License and any other pertinent obligations, then as a consequence you may
567
+ not convey it at all. For example, if you agree to terms that obligate you
568
+ to collect a royalty for further conveying from those to whom you convey
569
+ the Program, the only way you could satisfy both those terms and this
570
+ License would be to refrain entirely from conveying the Program.
571
+
572
+ 13. Use with the GNU Affero General Public License.
573
+
574
+ Notwithstanding any other provision of this License, you have
575
+ permission to link or combine any covered work with a work licensed
576
+ under version 3 of the GNU Affero General Public License into a single
577
+ combined work, and to convey the resulting work. The terms of this
578
+ License will continue to apply to the part which is the covered work,
579
+ but the special requirements of the GNU Affero General Public License,
580
+ section 13, concerning interaction through a network will apply to the
581
+ combination as such.
582
+
583
+ 14. Revised Versions of this License.
584
+
585
+ The Free Software Foundation may publish revised and/or new versions of
586
+ the GNU General Public License from time to time. Such new versions will
587
+ be similar in spirit to the present version, but may differ in detail to
588
+ address new problems or concerns.
589
+
590
+ Each version is given a distinguishing version number. If the
591
+ Program specifies that a certain numbered version of the GNU General
592
+ Public License "or any later version" applies to it, you have the
593
+ option of following the terms and conditions either of that numbered
594
+ version or of any later version published by the Free Software
595
+ Foundation. If the Program does not specify a version number of the
596
+ GNU General Public License, you may choose any version ever published
597
+ by the Free Software Foundation.
598
+
599
+ If the Program specifies that a proxy can decide which future
600
+ versions of the GNU General Public License can be used, that proxy's
601
+ public statement of acceptance of a version permanently authorizes you
602
+ to choose that version for the Program.
603
+
604
+ Later license versions may give you additional or different
605
+ permissions. However, no additional obligations are imposed on any
606
+ author or copyright holder as a result of your choosing to follow a
607
+ later version.
608
+
609
+ 15. Disclaimer of Warranty.
610
+
611
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
612
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
613
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
614
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
615
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
616
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
617
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
618
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
619
+
620
+ 16. Limitation of Liability.
621
+
622
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
623
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
624
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
625
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
626
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
627
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
628
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
629
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
630
+ SUCH DAMAGES.
631
+
632
+ 17. Interpretation of Sections 15 and 16.
633
+
634
+ If the disclaimer of warranty and limitation of liability provided
635
+ above cannot be given local legal effect according to their terms,
636
+ reviewing courts shall apply local law that most closely approximates
637
+ an absolute waiver of all civil liability in connection with the
638
+ Program, unless a warranty or assumption of liability accompanies a
639
+ copy of the Program in return for a fee.
640
+
641
+ END OF TERMS AND CONDITIONS
642
+
643
+ How to Apply These Terms to Your New Programs
644
+
645
+ If you develop a new program, and you want it to be of the greatest
646
+ possible use to the public, the best way to achieve this is to make it
647
+ free software which everyone can redistribute and change under these terms.
648
+
649
+ To do so, attach the following notices to the program. It is safest
650
+ to attach them to the start of each source file to most effectively
651
+ state the exclusion of warranty; and each file should have at least
652
+ the "copyright" line and a pointer to where the full notice is found.
653
+
654
+ <one line to give the program's name and a brief idea of what it does.>
655
+ Copyright © <year> <name of author>
656
+
657
+ This program is free software: you can redistribute it and/or modify
658
+ it under the terms of the GNU General Public License as published by
659
+ the Free Software Foundation, either version 3 of the License, or
660
+ (at your option) any later version.
661
+
662
+ This program is distributed in the hope that it will be useful,
663
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
664
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
665
+ GNU General Public License for more details.
666
+
667
+ You should have received a copy of the GNU General Public License
668
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
669
+
670
+ Also add information on how to contact you by electronic and paper mail.
671
+
672
+ If the program does terminal interaction, make it output a short
673
+ notice like this when it starts in an interactive mode:
674
+
675
+ <program> Copyright © <year> <name of author>
676
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
677
+ This is free software, and you are welcome to redistribute it
678
+ under certain conditions; type `show c' for details.
679
+
680
+ The hypothetical commands `show w' and `show c' should show the appropriate
681
+ parts of the General Public License. Of course, your program's commands
682
+ might be different; for a GUI interface, you would use an "about box".
683
+
684
+ You should also get your employer (if you work as a programmer) or school,
685
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
686
+ For more information on this, and how to apply and follow the GNU GPL, see
687
+ <https://www.gnu.org/licenses/>.
688
+
689
+ The GNU General Public License does not permit incorporating your program
690
+ into proprietary programs. If your program is a subroutine library, you
691
+ may consider it more useful to permit linking proprietary applications with
692
+ the library. If this is what you want to do, use the GNU Lesser General
693
+ Public License instead of this License. But first, please read
694
  <https://www.gnu.org/philosophy/why-not-lgpl.html>.
plugin-fw/LICENSE.txt CHANGED
@@ -1,740 +1,740 @@
1
- YITH Plugin Framework
2
-
3
- Copyright 2015-2021 Your Inspiration Solutions (email : plugins@yithemes.com)
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program; if not, write to the Free Software
17
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
-
19
- YITH Plugin Framework is released under the GPL
20
-
21
- This program incorporates work covered by the following copyright and
22
- permission notices:
23
-
24
- node-md5 is Copyright (c) 2011-2015, Paul Vorbach - (c) 2009, Jeff Mott.
25
- https://github.com/pvorb/node-md5
26
- This package is licensed under the BSD 3-Clause "New" or "Revised" License (the complete text of this license is shown below):
27
- https://github.com/pvorb/node-md5/blob/master/LICENSE
28
-
29
- Wherever third party code has been used, credit has been given in the code's
30
- comments.
31
-
32
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
33
-
34
- GNU GENERAL PUBLIC LICENSE
35
- Version 3, 29 June 2007
36
-
37
- Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
38
- Everyone is permitted to copy and distribute verbatim copies
39
- of this license document, but changing it is not allowed.
40
-
41
- Preamble
42
-
43
- The GNU General Public License is a free, copyleft license for
44
- software and other kinds of works.
45
-
46
- The licenses for most software and other practical works are designed
47
- to take away your freedom to share and change the works. By contrast,
48
- the GNU General Public License is intended to guarantee your freedom to
49
- share and change all versions of a program--to make sure it remains free
50
- software for all its users. We, the Free Software Foundation, use the
51
- GNU General Public License for most of our software; it applies also to
52
- any other work released this way by its authors. You can apply it to
53
- your programs, too.
54
-
55
- When we speak of free software, we are referring to freedom, not
56
- price. Our General Public Licenses are designed to make sure that you
57
- have the freedom to distribute copies of free software (and charge for
58
- them if you wish), that you receive source code or can get it if you
59
- want it, that you can change the software or use pieces of it in new
60
- free programs, and that you know you can do these things.
61
-
62
- To protect your rights, we need to prevent others from denying you
63
- these rights or asking you to surrender the rights. Therefore, you have
64
- certain responsibilities if you distribute copies of the software, or if
65
- you modify it: responsibilities to respect the freedom of others.
66
-
67
- For example, if you distribute copies of such a program, whether
68
- gratis or for a fee, you must pass on to the recipients the same
69
- freedoms that you received. You must make sure that they, too, receive
70
- or can get the source code. And you must show them these terms so they
71
- know their rights.
72
-
73
- Developers that use the GNU GPL protect your rights with two steps:
74
- (1) assert copyright on the software, and (2) offer you this License
75
- giving you legal permission to copy, distribute and/or modify it.
76
-
77
- For the developers' and authors' protection, the GPL clearly explains
78
- that there is no warranty for this free software. For both users' and
79
- authors' sake, the GPL requires that modified versions be marked as
80
- changed, so that their problems will not be attributed erroneously to
81
- authors of previous versions.
82
-
83
- Some devices are designed to deny users access to install or run
84
- modified versions of the software inside them, although the manufacturer
85
- can do so. This is fundamentally incompatible with the aim of
86
- protecting users' freedom to change the software. The systematic
87
- pattern of such abuse occurs in the area of products for individuals to
88
- use, which is precisely where it is most unacceptable. Therefore, we
89
- have designed this version of the GPL to prohibit the practice for those
90
- products. If such problems arise substantially in other domains, we
91
- stand ready to extend this provision to those domains in future versions
92
- of the GPL, as needed to protect the freedom of users.
93
-
94
- Finally, every program is threatened constantly by software patents.
95
- States should not allow patents to restrict development and use of
96
- software on general-purpose computers, but in those that do, we wish to
97
- avoid the special danger that patents applied to a free program could
98
- make it effectively proprietary. To prevent this, the GPL assures that
99
- patents cannot be used to render the program non-free.
100
-
101
- The precise terms and conditions for copying, distribution and
102
- modification follow.
103
-
104
- TERMS AND CONDITIONS
105
-
106
- 0. Definitions.
107
-
108
- "This License" refers to version 3 of the GNU General Public License.
109
-
110
- "Copyright" also means copyright-like laws that apply to other kinds of
111
- works, such as semiconductor masks.
112
-
113
- "The Program" refers to any copyrightable work licensed under this
114
- License. Each licensee is addressed as "you". "Licensees" and
115
- "recipients" may be individuals or organizations.
116
-
117
- To "modify" a work means to copy from or adapt all or part of the work
118
- in a fashion requiring copyright permission, other than the making of an
119
- exact copy. The resulting work is called a "modified version" of the
120
- earlier work or a work "based on" the earlier work.
121
-
122
- A "covered work" means either the unmodified Program or a work based
123
- on the Program.
124
-
125
- To "propagate" a work means to do anything with it that, without
126
- permission, would make you directly or secondarily liable for
127
- infringement under applicable copyright law, except executing it on a
128
- computer or modifying a private copy. Propagation includes copying,
129
- distribution (with or without modification), making available to the
130
- public, and in some countries other activities as well.
131
-
132
- To "convey" a work means any kind of propagation that enables other
133
- parties to make or receive copies. Mere interaction with a user through
134
- a computer network, with no transfer of a copy, is not conveying.
135
-
136
- An interactive user interface displays "Appropriate Legal Notices"
137
- to the extent that it includes a convenient and prominently visible
138
- feature that (1) displays an appropriate copyright notice, and (2)
139
- tells the user that there is no warranty for the work (except to the
140
- extent that warranties are provided), that licensees may convey the
141
- work under this License, and how to view a copy of this License. If
142
- the interface presents a list of user commands or options, such as a
143
- menu, a prominent item in the list meets this criterion.
144
-
145
- 1. Source Code.
146
-
147
- The "source code" for a work means the preferred form of the work
148
- for making modifications to it. "Object code" means any non-source
149
- form of a work.
150
-
151
- A "Standard Interface" means an interface that either is an official
152
- standard defined by a recognized standards body, or, in the case of
153
- interfaces specified for a particular programming language, one that
154
- is widely used among developers working in that language.
155
-
156
- The "System Libraries" of an executable work include anything, other
157
- than the work as a whole, that (a) is included in the normal form of
158
- packaging a Major Component, but which is not part of that Major
159
- Component, and (b) serves only to enable use of the work with that
160
- Major Component, or to implement a Standard Interface for which an
161
- implementation is available to the public in source code form. A
162
- "Major Component", in this context, means a major essential component
163
- (kernel, window system, and so on) of the specific operating system
164
- (if any) on which the executable work runs, or a compiler used to
165
- produce the work, or an object code interpreter used to run it.
166
-
167
- The "Corresponding Source" for a work in object code form means all
168
- the source code needed to generate, install, and (for an executable
169
- work) run the object code and to modify the work, including scripts to
170
- control those activities. However, it does not include the work's
171
- System Libraries, or general-purpose tools or generally available free
172
- programs which are used unmodified in performing those activities but
173
- which are not part of the work. For example, Corresponding Source
174
- includes interface definition files associated with source files for
175
- the work, and the source code for shared libraries and dynamically
176
- linked subprograms that the work is specifically designed to require,
177
- such as by intimate data communication or control flow between those
178
- subprograms and other parts of the work.
179
-
180
- The Corresponding Source need not include anything that users
181
- can regenerate automatically from other parts of the Corresponding
182
- Source.
183
-
184
- The Corresponding Source for a work in source code form is that
185
- same work.
186
-
187
- 2. Basic Permissions.
188
-
189
- All rights granted under this License are granted for the term of
190
- copyright on the Program, and are irrevocable provided the stated
191
- conditions are met. This License explicitly affirms your unlimited
192
- permission to run the unmodified Program. The output from running a
193
- covered work is covered by this License only if the output, given its
194
- content, constitutes a covered work. This License acknowledges your
195
- rights of fair use or other equivalent, as provided by copyright law.
196
-
197
- You may make, run and propagate covered works that you do not
198
- convey, without conditions so long as your license otherwise remains
199
- in force. You may convey covered works to others for the sole purpose
200
- of having them make modifications exclusively for you, or provide you
201
- with facilities for running those works, provided that you comply with
202
- the terms of this License in conveying all material for which you do
203
- not control copyright. Those thus making or running the covered works
204
- for you must do so exclusively on your behalf, under your direction
205
- and control, on terms that prohibit them from making any copies of
206
- your copyrighted material outside their relationship with you.
207
-
208
- Conveying under any other circumstances is permitted solely under
209
- the conditions stated below. Sublicensing is not allowed; section 10
210
- makes it unnecessary.
211
-
212
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
213
-
214
- No covered work shall be deemed part of an effective technological
215
- measure under any applicable law fulfilling obligations under article
216
- 11 of the WIPO copyright treaty adopted on 20 December 1996, or
217
- similar laws prohibiting or restricting circumvention of such
218
- measures.
219
-
220
- When you convey a covered work, you waive any legal power to forbid
221
- circumvention of technological measures to the extent such circumvention
222
- is effected by exercising rights under this License with respect to
223
- the covered work, and you disclaim any intention to limit operation or
224
- modification of the work as a means of enforcing, against the work's
225
- users, your or third parties' legal rights to forbid circumvention of
226
- technological measures.
227
-
228
- 4. Conveying Verbatim Copies.
229
-
230
- You may convey verbatim copies of the Program's source code as you
231
- receive it, in any medium, provided that you conspicuously and
232
- appropriately publish on each copy an appropriate copyright notice;
233
- keep intact all notices stating that this License and any
234
- non-permissive terms added in accord with section 7 apply to the code;
235
- keep intact all notices of the absence of any warranty; and give all
236
- recipients a copy of this License along with the Program.
237
-
238
- You may charge any price or no price for each copy that you convey,
239
- and you may offer support or warranty protection for a fee.
240
-
241
- 5. Conveying Modified Source Versions.
242
-
243
- You may convey a work based on the Program, or the modifications to
244
- produce it from the Program, in the form of source code under the
245
- terms of section 4, provided that you also meet all of these conditions:
246
-
247
- a) The work must carry prominent notices stating that you modified
248
- it, and giving a relevant date.
249
-
250
- b) The work must carry prominent notices stating that it is
251
- released under this License and any conditions added under section
252
- 7. This requirement modifies the requirement in section 4 to
253
- "keep intact all notices".
254
-
255
- c) You must license the entire work, as a whole, under this
256
- License to anyone who comes into possession of a copy. This
257
- License will therefore apply, along with any applicable section 7
258
- additional terms, to the whole of the work, and all its parts,
259
- regardless of how they are packaged. This License gives no
260
- permission to license the work in any other way, but it does not
261
- invalidate such permission if you have separately received it.
262
-
263
- d) If the work has interactive user interfaces, each must display
264
- Appropriate Legal Notices; however, if the Program has interactive
265
- interfaces that do not display Appropriate Legal Notices, your
266
- work need not make them do so.
267
-
268
- A compilation of a covered work with other separate and independent
269
- works, which are not by their nature extensions of the covered work,
270
- and which are not combined with it such as to form a larger program,
271
- in or on a volume of a storage or distribution medium, is called an
272
- "aggregate" if the compilation and its resulting copyright are not
273
- used to limit the access or legal rights of the compilation's users
274
- beyond what the individual works permit. Inclusion of a covered work
275
- in an aggregate does not cause this License to apply to the other
276
- parts of the aggregate.
277
-
278
- 6. Conveying Non-Source Forms.
279
-
280
- You may convey a covered work in object code form under the terms
281
- of sections 4 and 5, provided that you also convey the
282
- machine-readable Corresponding Source under the terms of this License,
283
- in one of these ways:
284
-
285
- a) Convey the object code in, or embodied in, a physical product
286
- (including a physical distribution medium), accompanied by the
287
- Corresponding Source fixed on a durable physical medium
288
- customarily used for software interchange.
289
-
290
- b) Convey the object code in, or embodied in, a physical product
291
- (including a physical distribution medium), accompanied by a
292
- written offer, valid for at least three years and valid for as
293
- long as you offer spare parts or customer support for that product
294
- model, to give anyone who possesses the object code either (1) a
295
- copy of the Corresponding Source for all the software in the
296
- product that is covered by this License, on a durable physical
297
- medium customarily used for software interchange, for a price no
298
- more than your reasonable cost of physically performing this
299
- conveying of source, or (2) access to copy the
300
- Corresponding Source from a network server at no charge.
301
-
302
- c) Convey individual copies of the object code with a copy of the
303
- written offer to provide the Corresponding Source. This
304
- alternative is allowed only occasionally and noncommercially, and
305
- only if you received the object code with such an offer, in accord
306
- with subsection 6b.
307
-
308
- d) Convey the object code by offering access from a designated
309
- place (gratis or for a charge), and offer equivalent access to the
310
- Corresponding Source in the same way through the same place at no
311
- further charge. You need not require recipients to copy the
312
- Corresponding Source along with the object code. If the place to
313
- copy the object code is a network server, the Corresponding Source
314
- may be on a different server (operated by you or a third party)
315
- that supports equivalent copying facilities, provided you maintain
316
- clear directions next to the object code saying where to find the
317
- Corresponding Source. Regardless of what server hosts the
318
- Corresponding Source, you remain obligated to ensure that it is
319
- available for as long as needed to satisfy these requirements.
320
-
321
- e) Convey the object code using peer-to-peer transmission, provided
322
- you inform other peers where the object code and Corresponding
323
- Source of the work are being offered to the general public at no
324
- charge under subsection 6d.
325
-
326
- A separable portion of the object code, whose source code is excluded
327
- from the Corresponding Source as a System Library, need not be
328
- included in conveying the object code work.
329
-
330
- A "User Product" is either (1) a "consumer product", which means any
331
- tangible personal property which is normally used for personal, family,
332
- or household purposes, or (2) anything designed or sold for incorporation
333
- into a dwelling. In determining whether a product is a consumer product,
334
- doubtful cases shall be resolved in favor of coverage. For a particular
335
- product received by a particular user, "normally used" refers to a
336
- typical or common use of that class of product, regardless of the status
337
- of the particular user or of the way in which the particular user
338
- actually uses, or expects or is expected to use, the product. A product
339
- is a consumer product regardless of whether the product has substantial
340
- commercial, industrial or non-consumer uses, unless such uses represent
341
- the only significant mode of use of the product.
342
-
343
- "Installation Information" for a User Product means any methods,
344
- procedures, authorization keys, or other information required to install
345
- and execute modified versions of a covered work in that User Product from
346
- a modified version of its Corresponding Source. The information must
347
- suffice to ensure that the continued functioning of the modified object
348
- code is in no case prevented or interfered with solely because
349
- modification has been made.
350
-
351
- If you convey an object code work under this section in, or with, or
352
- specifically for use in, a User Product, and the conveying occurs as
353
- part of a transaction in which the right of possession and use of the
354
- User Product is transferred to the recipient in perpetuity or for a
355
- fixed term (regardless of how the transaction is characterized), the
356
- Corresponding Source conveyed under this section must be accompanied
357
- by the Installation Information. But this requirement does not apply
358
- if neither you nor any third party retains the ability to install
359
- modified object code on the User Product (for example, the work has
360
- been installed in ROM).
361
-
362
- The requirement to provide Installation Information does not include a
363
- requirement to continue to provide support service, warranty, or updates
364
- for a work that has been modified or installed by the recipient, or for
365
- the User Product in which it has been modified or installed. Access to a
366
- network may be denied when the modification itself materially and
367
- adversely affects the operation of the network or violates the rules and
368
- protocols for communication across the network.
369
-
370
- Corresponding Source conveyed, and Installation Information provided,
371
- in accord with this section must be in a format that is publicly
372
- documented (and with an implementation available to the public in
373
- source code form), and must require no special password or key for
374
- unpacking, reading or copying.
375
-
376
- 7. Additional Terms.
377
-
378
- "Additional permissions" are terms that supplement the terms of this
379
- License by making exceptions from one or more of its conditions.
380
- Additional permissions that are applicable to the entire Program shall
381
- be treated as though they were included in this License, to the extent
382
- that they are valid under applicable law. If additional permissions
383
- apply only to part of the Program, that part may be used separately
384
- under those permissions, but the entire Program remains governed by
385
- this License without regard to the additional permissions.
386
-
387
- When you convey a copy of a covered work, you may at your option
388
- remove any additional permissions from that copy, or from any part of
389
- it. (Additional permissions may be written to require their own
390
- removal in certain cases when you modify the work.) You may place
391
- additional permissions on material, added by you to a covered work,
392
- for which you have or can give appropriate copyright permission.
393
-
394
- Notwithstanding any other provision of this License, for material you
395
- add to a covered work, you may (if authorized by the copyright holders of
396
- that material) supplement the terms of this License with terms:
397
-
398
- a) Disclaiming warranty or limiting liability differently from the
399
- terms of sections 15 and 16 of this License; or
400
-
401
- b) Requiring preservation of specified reasonable legal notices or
402
- author attributions in that material or in the Appropriate Legal
403
- Notices displayed by works containing it; or
404
-
405
- c) Prohibiting misrepresentation of the origin of that material, or
406
- requiring that modified versions of such material be marked in
407
- reasonable ways as different from the original version; or
408
-
409
- d) Limiting the use for publicity purposes of names of licensors or
410
- authors of the material; or
411
-
412
- e) Declining to grant rights under trademark law for use of some
413
- trade names, trademarks, or service marks; or
414
-
415
- f) Requiring indemnification of licensors and authors of that
416
- material by anyone who conveys the material (or modified versions of
417
- it) with contractual assumptions of liability to the recipient, for
418
- any liability that these contractual assumptions directly impose on
419
- those licensors and authors.
420
-
421
- All other non-permissive additional terms are considered "further
422
- restrictions" within the meaning of section 10. If the Program as you
423
- received it, or any part of it, contains a notice stating that it is
424
- governed by this License along with a term that is a further
425
- restriction, you may remove that term. If a license document contains
426
- a further restriction but permits relicensing or conveying under this
427
- License, you may add to a covered work material governed by the terms
428
- of that license document, provided that the further restriction does
429
- not survive such relicensing or conveying.
430
-
431
- If you add terms to a covered work in accord with this section, you
432
- must place, in the relevant source files, a statement of the
433
- additional terms that apply to those files, or a notice indicating
434
- where to find the applicable terms.
435
-
436
- Additional terms, permissive or non-permissive, may be stated in the
437
- form of a separately written license, or stated as exceptions;
438
- the above requirements apply either way.
439
-
440
- 8. Termination.
441
-
442
- You may not propagate or modify a covered work except as expressly
443
- provided under this License. Any attempt otherwise to propagate or
444
- modify it is void, and will automatically terminate your rights under
445
- this License (including any patent licenses granted under the third
446
- paragraph of section 11).
447
-
448
- However, if you cease all violation of this License, then your
449
- license from a particular copyright holder is reinstated (a)
450
- provisionally, unless and until the copyright holder explicitly and
451
- finally terminates your license, and (b) permanently, if the copyright
452
- holder fails to notify you of the violation by some reasonable means
453
- prior to 60 days after the cessation.
454
-
455
- Moreover, your license from a particular copyright holder is
456
- reinstated permanently if the copyright holder notifies you of the
457
- violation by some reasonable means, this is the first time you have
458
- received notice of violation of this License (for any work) from that
459
- copyright holder, and you cure the violation prior to 30 days after
460
- your receipt of the notice.
461
-
462
- Termination of your rights under this section does not terminate the
463
- licenses of parties who have received copies or rights from you under
464
- this License. If your rights have been terminated and not permanently
465
- reinstated, you do not qualify to receive new licenses for the same
466
- material under section 10.
467
-
468
- 9. Acceptance Not Required for Having Copies.
469
-
470
- You are not required to accept this License in order to receive or
471
- run a copy of the Program. Ancillary propagation of a covered work
472
- occurring solely as a consequence of using peer-to-peer transmission
473
- to receive a copy likewise does not require acceptance. However,
474
- nothing other than this License grants you permission to propagate or
475
- modify any covered work. These actions infringe copyright if you do
476
- not accept this License. Therefore, by modifying or propagating a
477
- covered work, you indicate your acceptance of this License to do so.
478
-
479
- 10. Automatic Licensing of Downstream Recipients.
480
-
481
- Each time you convey a covered work, the recipient automatically
482
- receives a license from the original licensors, to run, modify and
483
- propagate that work, subject to this License. You are not responsible
484
- for enforcing compliance by third parties with this License.
485
-
486
- An "entity transaction" is a transaction transferring control of an
487
- organization, or substantially all assets of one, or subdividing an
488
- organization, or merging organizations. If propagation of a covered
489
- work results from an entity transaction, each party to that
490
- transaction who receives a copy of the work also receives whatever
491
- licenses to the work the party's predecessor in interest had or could
492
- give under the previous paragraph, plus a right to possession of the
493
- Corresponding Source of the work from the predecessor in interest, if
494
- the predecessor has it or can get it with reasonable efforts.
495
-
496
- You may not impose any further restrictions on the exercise of the
497
- rights granted or affirmed under this License. For example, you may
498
- not impose a license fee, royalty, or other charge for exercise of
499
- rights granted under this License, and you may not initiate litigation
500
- (including a cross-claim or counterclaim in a lawsuit) alleging that
501
- any patent claim is infringed by making, using, selling, offering for
502
- sale, or importing the Program or any portion of it.
503
-
504
- 11. Patents.
505
-
506
- A "contributor" is a copyright holder who authorizes use under this
507
- License of the Program or a work on which the Program is based. The
508
- work thus licensed is called the contributor's "contributor version".
509
-
510
- A contributor's "essential patent claims" are all patent claims
511
- owned or controlled by the contributor, whether already acquired or
512
- hereafter acquired, that would be infringed by some manner, permitted
513
- by this License, of making, using, or selling its contributor version,
514
- but do not include claims that would be infringed only as a
515
- consequence of further modification of the contributor version. For
516
- purposes of this definition, "control" includes the right to grant
517
- patent sublicenses in a manner consistent with the requirements of
518
- this License.
519
-
520
- Each contributor grants you a non-exclusive, worldwide, royalty-free
521
- patent license under the contributor's essential patent claims, to
522
- make, use, sell, offer for sale, import and otherwise run, modify and
523
- propagate the contents of its contributor version.
524
-
525
- In the following three paragraphs, a "patent license" is any express
526
- agreement or commitment, however denominated, not to enforce a patent
527
- (such as an express permission to practice a patent or covenant not to
528
- sue for patent infringement). To "grant" such a patent license to a
529
- party means to make such an agreement or commitment not to enforce a
530
- patent against the party.
531
-
532
- If you convey a covered work, knowingly relying on a patent license,
533
- and the Corresponding Source of the work is not available for anyone
534
- to copy, free of charge and under the terms of this License, through a
535
- publicly available network server or other readily accessible means,
536
- then you must either (1) cause the Corresponding Source to be so
537
- available, or (2) arrange to deprive yourself of the benefit of the
538
- patent license for this particular work, or (3) arrange, in a manner
539
- consistent with the requirements of this License, to extend the patent
540
- license to downstream recipients. "Knowingly relying" means you have
541
- actual knowledge that, but for the patent license, your conveying the
542
- covered work in a country, or your recipient's use of the covered work
543
- in a country, would infringe one or more identifiable patents in that
544
- country that you have reason to believe are valid.
545
-
546
- If, pursuant to or in connection with a single transaction or
547
- arrangement, you convey, or propagate by procuring conveyance of, a
548
- covered work, and grant a patent license to some of the parties
549
- receiving the covered work authorizing them to use, propagate, modify
550
- or convey a specific copy of the covered work, then the patent license
551
- you grant is automatically extended to all recipients of the covered
552
- work and works based on it.
553
-
554
- A patent license is "discriminatory" if it does not include within
555
- the scope of its coverage, prohibits the exercise of, or is
556
- conditioned on the non-exercise of one or more of the rights that are
557
- specifically granted under this License. You may not convey a covered
558
- work if you are a party to an arrangement with a third party that is
559
- in the business of distributing software, under which you make payment
560
- to the third party based on the extent of your activity of conveying
561
- the work, and under which the third party grants, to any of the
562
- parties who would receive the covered work from you, a discriminatory
563
- patent license (a) in connection with copies of the covered work
564
- conveyed by you (or copies made from those copies), or (b) primarily
565
- for and in connection with specific products or compilations that
566
- contain the covered work, unless you entered into that arrangement,
567
- or that patent license was granted, prior to 28 March 2007.
568
-
569
- Nothing in this License shall be construed as excluding or limiting
570
- any implied license or other defenses to infringement that may
571
- otherwise be available to you under applicable patent law.
572
-
573
- 12. No Surrender of Others' Freedom.
574
-
575
- If conditions are imposed on you (whether by court order, agreement or
576
- otherwise) that contradict the conditions of this License, they do not
577
- excuse you from the conditions of this License. If you cannot convey a
578
- covered work so as to satisfy simultaneously your obligations under this
579
- License and any other pertinent obligations, then as a consequence you may
580
- not convey it at all. For example, if you agree to terms that obligate you
581
- to collect a royalty for further conveying from those to whom you convey
582
- the Program, the only way you could satisfy both those terms and this
583
- License would be to refrain entirely from conveying the Program.
584
-
585
- 13. Use with the GNU Affero General Public License.
586
-
587
- Notwithstanding any other provision of this License, you have
588
- permission to link or combine any covered work with a work licensed
589
- under version 3 of the GNU Affero General Public License into a single
590
- combined work, and to convey the resulting work. The terms of this
591
- License will continue to apply to the part which is the covered work,
592
- but the special requirements of the GNU Affero General Public License,
593
- section 13, concerning interaction through a network will apply to the
594
- combination as such.
595
-
596
- 14. Revised Versions of this License.
597
-
598
- The Free Software Foundation may publish revised and/or new versions of
599
- the GNU General Public License from time to time. Such new versions will
600
- be similar in spirit to the present version, but may differ in detail to
601
- address new problems or concerns.
602
-
603
- Each version is given a distinguishing version number. If the
604
- Program specifies that a certain numbered version of the GNU General
605
- Public License "or any later version" applies to it, you have the
606
- option of following the terms and conditions either of that numbered
607
- version or of any later version published by the Free Software
608
- Foundation. If the Program does not specify a version number of the
609
- GNU General Public License, you may choose any version ever published
610
- by the Free Software Foundation.
611
-
612
- If the Program specifies that a proxy can decide which future
613
- versions of the GNU General Public License can be used, that proxy's
614
- public statement of acceptance of a version permanently authorizes you
615
- to choose that version for the Program.
616
-
617
- Later license versions may give you additional or different
618
- permissions. However, no additional obligations are imposed on any
619
- author or copyright holder as a result of your choosing to follow a
620
- later version.
621
-
622
- 15. Disclaimer of Warranty.
623
-
624
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
625
- APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
626
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
627
- OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
628
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
629
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
630
- IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
631
- ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
632
-
633
- 16. Limitation of Liability.
634
-
635
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
636
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
637
- THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
638
- GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
639
- USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
640
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
641
- PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
642
- EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
643
- SUCH DAMAGES.
644
-
645
- 17. Interpretation of Sections 15 and 16.
646
-
647
- If the disclaimer of warranty and limitation of liability provided
648
- above cannot be given local legal effect according to their terms,
649
- reviewing courts shall apply local law that most closely approximates
650
- an absolute waiver of all civil liability in connection with the
651
- Program, unless a warranty or assumption of liability accompanies a
652
- copy of the Program in return for a fee.
653
-
654
- END OF TERMS AND CONDITIONS
655
-
656
- How to Apply These Terms to Your New Programs
657
-
658
- If you develop a new program, and you want it to be of the greatest
659
- possible use to the public, the best way to achieve this is to make it
660
- free software which everyone can redistribute and change under these terms.
661
-
662
- To do so, attach the following notices to the program. It is safest
663
- to attach them to the start of each source file to most effectively
664
- state the exclusion of warranty; and each file should have at least
665
- the "copyright" line and a pointer to where the full notice is found.
666
-
667
- <one line to give the program's name and a brief idea of what it does.>
668
- Copyright © <year> <name of author>
669
-
670
- This program is free software: you can redistribute it and/or modify
671
- it under the terms of the GNU General Public License as published by
672
- the Free Software Foundation, either version 3 of the License, or
673
- (at your option) any later version.
674
-
675
- This program is distributed in the hope that it will be useful,
676
- but WITHOUT ANY WARRANTY; without even the implied warranty of
677
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
678
- GNU General Public License for more details.
679
-
680
- You should have received a copy of the GNU General Public License
681
- along with this program. If not, see <https://www.gnu.org/licenses/>.
682
-
683
- Also add information on how to contact you by electronic and paper mail.
684
-
685
- If the program does terminal interaction, make it output a short
686
- notice like this when it starts in an interactive mode:
687
-
688
- <program> Copyright © <year> <name of author>
689
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
690
- This is free software, and you are welcome to redistribute it
691
- under certain conditions; type `show c' for details.
692
-
693
- The hypothetical commands `show w' and `show c' should show the appropriate
694
- parts of the General Public License. Of course, your program's commands
695
- might be different; for a GUI interface, you would use an "about box".
696
-
697
- You should also get your employer (if you work as a programmer) or school,
698
- if any, to sign a "copyright disclaimer" for the program, if necessary.
699
- For more information on this, and how to apply and follow the GNU GPL, see
700
- <https://www.gnu.org/licenses/>.
701
-
702
- The GNU General Public License does not permit incorporating your program
703
- into proprietary programs. If your program is a subroutine library, you
704
- may consider it more useful to permit linking proprietary applications with
705
- the library. If this is what you want to do, use the GNU Lesser General
706
- Public License instead of this License. But first, please read
707
- <https://www.gnu.org/philosophy/why-not-lgpl.html>.
708
-
709
-
710
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
711
-
712
- node-md5: BSD 3-Clause "New" or "Revised" License
713
-
714
- Copyright © 2011-2015, Paul Vorbach.
715
- Copyright © 2009, Jeff Mott.
716
-
717
- All rights reserved.
718
-
719
- Redistribution and use in source and binary forms, with or without modification,
720
- are permitted provided that the following conditions are met:
721
-
722
- * Redistributions of source code must retain the above copyright notice, this
723
- list of conditions and the following disclaimer.
724
- * Redistributions in binary form must reproduce the above copyright notice, this
725
- list of conditions and the following disclaimer in the documentation and/or
726
- other materials provided with the distribution.
727
- * Neither the name Crypto-JS nor the names of its contributors may be used to
728
- endorse or promote products derived from this software without specific prior
729
- written permission.
730
-
731
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
732
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
733
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
734
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
735
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
736
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
737
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
738
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
739
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
740
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1
+ YITH Plugin Framework
2
+
3
+ Copyright 2015-2021 Your Inspiration Solutions (email : plugins@yithemes.com)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ YITH Plugin Framework is released under the GPL
20
+
21
+ This program incorporates work covered by the following copyright and
22
+ permission notices:
23
+
24
+ node-md5 is Copyright (c) 2011-2015, Paul Vorbach - (c) 2009, Jeff Mott.
25
+ https://github.com/pvorb/node-md5
26
+ This package is licensed under the BSD 3-Clause "New" or "Revised" License (the complete text of this license is shown below):
27
+ https://github.com/pvorb/node-md5/blob/master/LICENSE
28
+
29
+ Wherever third party code has been used, credit has been given in the code's
30
+ comments.
31
+
32
+ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
33
+
34
+ GNU GENERAL PUBLIC LICENSE
35
+ Version 3, 29 June 2007
36
+
37
+ Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
38
+ Everyone is permitted to copy and distribute verbatim copies
39
+ of this license document, but changing it is not allowed.
40
+
41
+ Preamble
42
+
43
+ The GNU General Public License is a free, copyleft license for
44
+ software and other kinds of works.
45
+
46
+ The licenses for most software and other practical works are designed
47
+ to take away your freedom to share and change the works. By contrast,
48
+ the GNU General Public License is intended to guarantee your freedom to
49
+ share and change all versions of a program--to make sure it remains free
50
+ software for all its users. We, the Free Software Foundation, use the
51
+ GNU General Public License for most of our software; it applies also to
52
+ any other work released this way by its authors. You can apply it to
53
+ your programs, too.
54
+
55
+ When we speak of free software, we are referring to freedom, not
56
+ price. Our General Public Licenses are designed to make sure that you
57
+ have the freedom to distribute copies of free software (and charge for
58
+ them if you wish), that you receive source code or can get it if you
59
+ want it, that you can change the software or use pieces of it in new
60
+ free programs, and that you know you can do these things.
61
+
62
+ To protect your rights, we need to prevent others from denying you
63
+ these rights or asking you to surrender the rights. Therefore, you have
64
+ certain responsibilities if you distribute copies of the software, or if
65
+ you modify it: responsibilities to respect the freedom of others.
66
+
67
+ For example, if you distribute copies of such a program, whether
68
+ gratis or for a fee, you must pass on to the recipients the same
69
+ freedoms that you received. You must make sure that they, too, receive
70
+ or can get the source code. And you must show them these terms so they
71
+ know their rights.
72
+
73
+ Developers that use the GNU GPL protect your rights with two steps:
74
+ (1) assert copyright on the software, and (2) offer you this License
75
+ giving you legal permission to copy, distribute and/or modify it.
76
+
77
+ For the developers' and authors' protection, the GPL clearly explains
78
+ that there is no warranty for this free software. For both users' and
79
+ authors' sake, the GPL requires that modified versions be marked as
80
+ changed, so that their problems will not be attributed erroneously to
81
+ authors of previous versions.
82
+
83
+ Some devices are designed to deny users access to install or run
84
+ modified versions of the software inside them, although the manufacturer
85
+ can do so. This is fundamentally incompatible with the aim of
86
+ protecting users' freedom to change the software. The systematic
87
+ pattern of such abuse occurs in the area of products for individuals to
88
+ use, which is precisely where it is most unacceptable. Therefore, we
89
+ have designed this version of the GPL to prohibit the practice for those
90
+ products. If such problems arise substantially in other domains, we
91
+ stand ready to extend this provision to those domains in future versions
92
+ of the GPL, as needed to protect the freedom of users.
93
+
94
+ Finally, every program is threatened constantly by software patents.
95
+ States should not allow patents to restrict development and use of
96
+ software on general-purpose computers, but in those that do, we wish to
97
+ avoid the special danger that patents applied to a free program could
98
+ make it effectively proprietary. To prevent this, the GPL assures that
99
+ patents cannot be used to render the program non-free.
100
+
101
+ The precise terms and conditions for copying, distribution and
102
+ modification follow.
103
+
104
+ TERMS AND CONDITIONS
105
+
106
+ 0. Definitions.
107
+
108
+ "This License" refers to version 3 of the GNU General Public License.
109
+
110
+ "Copyright" also means copyright-like laws that apply to other kinds of
111
+ works, such as semiconductor masks.
112
+
113
+ "The Program" refers to any copyrightable work licensed under this
114
+ License. Each licensee is addressed as "you". "Licensees" and
115
+ "recipients" may be individuals or organizations.
116
+
117
+ To "modify" a work means to copy from or adapt all or part of the work
118
+ in a fashion requiring copyright permission, other than the making of an
119
+ exact copy. The resulting work is called a "modified version" of the
120
+ earlier work or a work "based on" the earlier work.
121
+
122
+ A "covered work" means either the unmodified Program or a work based
123
+ on the Program.
124
+
125
+ To "propagate" a work means to do anything with it that, without
126
+ permission, would make you directly or secondarily liable for
127
+ infringement under applicable copyright law, except executing it on a
128
+ computer or modifying a private copy. Propagation includes copying,
129
+ distribution (with or without modification), making available to the
130
+ public, and in some countries other activities as well.
131
+
132
+ To "convey" a work means any kind of propagation that enables other
133
+ parties to make or receive copies. Mere interaction with a user through
134
+ a computer network, with no transfer of a copy, is not conveying.
135
+
136
+ An interactive user interface displays "Appropriate Legal Notices"
137
+ to the extent that it includes a convenient and prominently visible
138
+ feature that (1) displays an appropriate copyright notice, and (2)
139
+ tells the user that there is no warranty for the work (except to the
140
+ extent that warranties are provided), that licensees may convey the
141
+ work under this License, and how to view a copy of this License. If
142
+ the interface presents a list of user commands or options, such as a
143
+ menu, a prominent item in the list meets this criterion.
144
+
145
+ 1. Source Code.
146
+
147
+ The "source code" for a work means the preferred form of the work
148
+ for making modifications to it. "Object code" means any non-source
149
+ form of a work.
150
+
151
+ A "Standard Interface" means an interface that either is an official
152
+ standard defined by a recognized standards body, or, in the case of
153
+ interfaces specified for a particular programming language, one that
154
+ is widely used among developers working in that language.
155
+
156
+ The "System Libraries" of an executable work include anything, other
157
+ than the work as a whole, that (a) is included in the normal form of
158
+ packaging a Major Component, but which is not part of that Major
159
+ Component, and (b) serves only to enable use of the work with that
160
+ Major Component, or to implement a Standard Interface for which an
161
+ implementation is available to the public in source code form. A
162
+ "Major Component", in this context, means a major essential component
163
+ (kernel, window system, and so on) of the specific operating system
164
+ (if any) on which the executable work runs, or a compiler used to
165
+ produce the work, or an object code interpreter used to run it.
166
+
167
+ The "Corresponding Source" for a work in object code form means all
168
+ the source code needed to generate, install, and (for an executable
169
+ work) run the object code and to modify the work, including scripts to
170
+ control those activities. However, it does not include the work's
171
+ System Libraries, or general-purpose tools or generally available free
172
+ programs which are used unmodified in performing those activities but
173
+ which are not part of the work. For example, Corresponding Source
174
+ includes interface definition files associated with source files for
175
+ the work, and the source code for shared libraries and dynamically
176
+ linked subprograms that the work is specifically designed to require,
177
+ such as by intimate data communication or control flow between those
178
+ subprograms and other parts of the work.
179
+
180
+ The Corresponding Source need not include anything that users
181
+ can regenerate automatically from other parts of the Corresponding
182
+ Source.
183
+
184
+ The Corresponding Source for a work in source code form is that
185
+ same work.
186
+
187
+ 2. Basic Permissions.
188
+
189
+ All rights granted under this License are granted for the term of
190
+ copyright on the Program, and are irrevocable provided the stated
191
+ conditions are met. This License explicitly affirms your unlimited
192
+ permission to run the unmodified Program. The output from running a
193
+ covered work is covered by this License only if the output, given its
194
+ content, constitutes a covered work. This License acknowledges your
195
+ rights of fair use or other equivalent, as provided by copyright law.
196
+
197
+ You may make, run and propagate covered works that you do not
198
+ convey, without conditions so long as your license otherwise remains
199
+ in force. You may convey covered works to others for the sole purpose
200
+ of having them make modifications exclusively for you, or provide you
201
+ with facilities for running those works, provided that you comply with
202
+ the terms of this License in conveying all material for which you do
203
+ not control copyright. Those thus making or running the covered works
204
+ for you must do so exclusively on your behalf, under your direction
205
+ and control, on terms that prohibit them from making any copies of
206
+ your copyrighted material outside their relationship with you.
207
+
208
+ Conveying under any other circumstances is permitted solely under
209
+ the conditions stated below. Sublicensing is not allowed; section 10
210
+ makes it unnecessary.
211
+
212
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
213
+
214
+ No covered work shall be deemed part of an effective technological
215
+ measure under any applicable law fulfilling obligations under article
216
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
217
+ similar laws prohibiting or restricting circumvention of such
218
+ measures.
219
+
220
+ When you convey a covered work, you waive any legal power to forbid
221
+ circumvention of technological measures to the extent such circumvention
222
+ is effected by exercising rights under this License with respect to
223
+ the covered work, and you disclaim any intention to limit operation or
224
+ modification of the work as a means of enforcing, against the work's
225
+ users, your or third parties' legal rights to forbid circumvention of
226
+ technological measures.
227
+
228
+ 4. Conveying Verbatim Copies.
229
+
230
+ You may convey verbatim copies of the Program's source code as you
231
+ receive it, in any medium, provided that you conspicuously and
232
+ appropriately publish on each copy an appropriate copyright notice;
233
+ keep intact all notices stating that this License and any
234
+ non-permissive terms added in accord with section 7 apply to the code;
235
+ keep intact all notices of the absence of any warranty; and give all
236
+ recipients a copy of this License along with the Program.
237
+
238
+ You may charge any price or no price for each copy that you convey,
239
+ and you may offer support or warranty protection for a fee.
240
+
241
+ 5. Conveying Modified Source Versions.
242
+
243
+ You may convey a work based on the Program, or the modifications to
244
+ produce it from the Program, in the form of source code under the
245
+ terms of section 4, provided that you also meet all of these conditions:
246
+
247
+ a) The work must carry prominent notices stating that you modified
248
+ it, and giving a relevant date.
249
+
250
+ b) The work must carry prominent notices stating that it is
251
+ released under this License and any conditions added under section
252
+ 7. This requirement modifies the requirement in section 4 to
253
+ "keep intact all notices".
254
+
255
+ c) You must license the entire work, as a whole, under this
256
+ License to anyone who comes into possession of a copy. This
257
+ License will therefore apply, along with any applicable section 7
258
+ additional terms, to the whole of the work, and all its parts,
259
+ regardless of how they are packaged. This License gives no
260
+ permission to license the work in any other way, but it does not
261
+ invalidate such permission if you have separately received it.
262
+
263
+ d) If the work has interactive user interfaces, each must display
264
+ Appropriate Legal Notices; however, if the Program has interactive
265
+ interfaces that do not display Appropriate Legal Notices, your
266
+ work need not make them do so.
267
+
268
+ A compilation of a covered work with other separate and independent
269
+ works, which are not by their nature extensions of the covered work,
270
+ and which are not combined with it such as to form a larger program,
271
+ in or on a volume of a storage or distribution medium, is called an
272
+ "aggregate" if the compilation and its resulting copyright are not
273
+ used to limit the access or legal rights of the compilation's users
274
+ beyond what the individual works permit. Inclusion of a covered work
275
+ in an aggregate does not cause this License to apply to the other
276
+ parts of the aggregate.
277
+
278
+ 6. Conveying Non-Source Forms.
279
+
280
+ You may convey a covered work in object code form under the terms
281
+ of sections 4 and 5, provided that you also convey the
282
+ machine-readable Corresponding Source under the terms of this License,
283
+ in one of these ways:
284
+
285
+ a) Convey the object code in, or embodied in, a physical product
286
+ (including a physical distribution medium), accompanied by the
287
+ Corresponding Source fixed on a durable physical medium
288
+ customarily used for software interchange.
289
+
290
+ b) Convey the object code in, or embodied in, a physical product
291
+ (including a physical distribution medium), accompanied by a
292
+ written offer, valid for at least three years and valid for as
293
+ long as you offer spare parts or customer support for that product
294
+ model, to give anyone who possesses the object code either (1) a
295
+ copy of the Corresponding Source for all the software in the
296
+ product that is covered by this License, on a durable physical
297
+ medium customarily used for software interchange, for a price no
298
+ more than your reasonable cost of physically performing this
299
+ conveying of source, or (2) access to copy the
300
+ Corresponding Source from a network server at no charge.
301
+
302
+ c) Convey individual copies of the object code with a copy of the
303
+ written offer to provide the Corresponding Source. This
304
+ alternative is allowed only occasionally and noncommercially, and
305
+ only if you received the object code with such an offer, in accord
306
+ with subsection 6b.
307
+
308
+ d) Convey the object code by offering access from a designated
309
+ place (gratis or for a charge), and offer equivalent access to the
310
+ Corresponding Source in the same way through the same place at no
311
+ further charge. You need not require recipients to copy the
312
+ Corresponding Source along with the object code. If the place to
313
+ copy the object code is a network server, the Corresponding Source
314
+ may be on a different server (operated by you or a third party)
315
+ that supports equivalent copying facilities, provided you maintain
316
+ clear directions next to the object code saying where to find the
317
+ Corresponding Source. Regardless of what server hosts the
318
+ Corresponding Source, you remain obligated to ensure that it is
319
+ available for as long as needed to satisfy these requirements.
320
+
321
+ e) Convey the object code using peer-to-peer transmission, provided
322
+ you inform other peers where the object code and Corresponding
323
+ Source of the work are being offered to the general public at no
324
+ charge under subsection 6d.
325
+
326
+ A separable portion of the object code, whose source code is excluded
327
+ from the Corresponding Source as a System Library, need not be
328
+ included in conveying the object code work.
329
+
330
+ A "User Product" is either (1) a "consumer product", which means any
331
+ tangible personal property which is normally used for personal, family,
332
+ or household purposes, or (2) anything designed or sold for incorporation
333
+ into a dwelling. In determining whether a product is a consumer product,
334
+ doubtful cases shall be resolved in favor of coverage. For a particular
335
+ product received by a particular user, "normally used" refers to a
336
+ typical or common use of that class of product, regardless of the status
337
+ of the particular user or of the way in which the particular user
338
+ actually uses, or expects or is expected to use, the product. A product
339
+ is a consumer product regardless of whether the product has substantial
340
+ commercial, industrial or non-consumer uses, unless such uses represent
341
+ the only significant mode of use of the product.
342
+
343
+ "Installation Information" for a User Product means any methods,
344
+ procedures, authorization keys, or other information required to install
345
+ and execute modified versions of a covered work in that User Product from
346
+ a modified version of its Corresponding Source. The information must
347
+ suffice to ensure that the continued functioning of the modified object
348
+ code is in no case prevented or interfered with solely because
349
+ modification has been made.
350
+
351
+ If you convey an object code work under this section in, or with, or
352
+ specifically for use in, a User Product, and the conveying occurs as
353
+ part of a transaction in which the right of possession and use of the
354
+ User Product is transferred to the recipient in perpetuity or for a
355
+ fixed term (regardless of how the transaction is characterized), the
356
+ Corresponding Source conveyed under this section must be accompanied
357
+ by the Installation Information. But this requirement does not apply
358
+ if neither you nor any third party retains the ability to install
359
+ modified object code on the User Product (for example, the work has
360
+ been installed in ROM).
361
+
362
+ The requirement to provide Installation Information does not include a
363
+ requirement to continue to provide support service, warranty, or updates
364
+ for a work that has been modified or installed by the recipient, or for
365
+ the User Product in which it has been modified or installed. Access to a
366
+ network may be denied when the modification itself materially and
367
+ adversely affects the operation of the network or violates the rules and
368
+ protocols for communication across the network.
369
+
370
+ Corresponding Source conveyed, and Installation Information provided,
371
+ in accord with this section must be in a format that is publicly
372
+ documented (and with an implementation available to the public in
373
+ source code form), and must require no special password or key for
374
+ unpacking, reading or copying.
375
+
376
+ 7. Additional Terms.
377
+
378
+ "Additional permissions" are terms that supplement the terms of this
379
+ License by making exceptions from one or more of its conditions.
380
+ Additional permissions that are applicable to the entire Program shall
381
+ be treated as though they were included in this License, to the extent
382
+ that they are valid under applicable law. If additional permissions
383
+ apply only to part of the Program, that part may be used separately
384
+ under those permissions, but the entire Program remains governed by
385
+ this License without regard to the additional permissions.
386
+
387
+ When you convey a copy of a covered work, you may at your option
388
+ remove any additional permissions from that copy, or from any part of
389
+ it. (Additional permissions may be written to require their own
390
+ removal in certain cases when you modify the work.) You may place
391
+ additional permissions on material, added by you to a covered work,
392
+ for which you have or can give appropriate copyright permission.
393
+
394
+ Notwithstanding any other provision of this License, for material you
395
+ add to a covered work, you may (if authorized by the copyright holders of
396
+ that material) supplement the terms of this License with terms:
397
+
398
+ a) Disclaiming warranty or limiting liability differently from the
399
+ terms of sections 15 and 16 of this License; or
400
+
401
+ b) Requiring preservation of specified reasonable legal notices or
402
+ author attributions in that material or in the Appropriate Legal
403
+ Notices displayed by works containing it; or
404
+
405
+ c) Prohibiting misrepresentation of the origin of that material, or
406
+ requiring that modified versions of such material be marked in
407
+ reasonable ways as different from the original version; or
408
+
409
+ d) Limiting the use for publicity purposes of names of licensors or
410
+ authors of the material; or
411
+
412
+ e) Declining to grant rights under trademark law for use of some
413
+ trade names, trademarks, or service marks; or
414
+
415
+ f) Requiring indemnification of licensors and authors of that
416
+ material by anyone who conveys the material (or modified versions of
417
+ it) with contractual assumptions of liability to the recipient, for
418
+ any liability that these contractual assumptions directly impose on
419
+ those licensors and authors.
420
+
421
+ All other non-permissive additional terms are considered "further
422
+ restrictions" within the meaning of section 10. If the Program as you
423
+ received it, or any part of it, contains a notice stating that it is
424
+ governed by this License along with a term that is a further
425
+ restriction, you may remove that term. If a license document contains
426
+ a further restriction but permits relicensing or conveying under this
427
+ License, you may add to a covered work material governed by the terms
428
+ of that license document, provided that the further restriction does
429
+ not survive such relicensing or conveying.
430
+
431
+ If you add terms to a covered work in accord with this section, you
432
+ must place, in the relevant source files, a statement of the
433
+ additional terms that apply to those files, or a notice indicating
434
+ where to find the applicable terms.
435
+
436
+ Additional terms, permissive or non-permissive, may be stated in the
437
+ form of a separately written license, or stated as exceptions;
438
+ the above requirements apply either way.
439
+
440
+ 8. Termination.
441
+
442
+ You may not propagate or modify a covered work except as expressly
443
+ provided under this License. Any attempt otherwise to propagate or
444
+ modify it is void, and will automatically terminate your rights under
445
+ this License (including any patent licenses granted under the third
446
+ paragraph of section 11).
447
+
448
+ However, if you cease all violation of this License, then your
449
+ license from a particular copyright holder is reinstated (a)
450
+ provisionally, unless and until the copyright holder explicitly and
451
+ finally terminates your license, and (b) permanently, if the copyright
452
+ holder fails to notify you of the violation by some reasonable means
453
+ prior to 60 days after the cessation.
454
+
455
+ Moreover, your license from a particular copyright holder is
456
+ reinstated permanently if the copyright holder notifies you of the
457
+ violation by some reasonable means, this is the first time you have
458
+ received notice of violation of this License (for any work) from that
459
+ copyright holder, and you cure the violation prior to 30 days after
460
+ your receipt of the notice.
461
+
462
+ Termination of your rights under this section does not terminate the
463
+ licenses of parties who have received copies or rights from you under
464
+ this License. If your rights have been terminated and not permanently
465
+ reinstated, you do not qualify to receive new licenses for the same
466
+ material under section 10.
467
+
468
+ 9. Acceptance Not Required for Having Copies.
469
+
470
+ You are not required to accept this License in order to receive or
471
+ run a copy of the Program. Ancillary propagation of a covered work
472
+ occurring solely as a consequence of using peer-to-peer transmission
473
+ to receive a copy likewise does not require acceptance. However,
474
+ nothing other than this License grants you permission to propagate or
475
+ modify any covered work. These actions infringe copyright if you do
476
+ not accept this License. Therefore, by modifying or propagating a
477
+ covered work, you indicate your acceptance of this License to do so.
478
+
479
+ 10. Automatic Licensing of Downstream Recipients.
480
+
481
+ Each time you convey a covered work, the recipient automatically
482
+ receives a license from the original licensors, to run, modify and
483
+ propagate that work, subject to this License. You are not responsible
484
+ for enforcing compliance by third parties with this License.
485
+
486
+ An "entity transaction" is a transaction transferring control of an
487
+ organization, or substantially all assets of one, or subdividing an
488
+ organization, or merging organizations. If propagation of a covered
489
+ work results from an entity transaction, each party to that
490
+ transaction who receives a copy of the work also receives whatever
491
+ licenses to the work the party's predecessor in interest had or could
492
+ give under the previous paragraph, plus a right to possession of the
493
+ Corresponding Source of the work from the predecessor in interest, if
494
+ the predecessor has it or can get it with reasonable efforts.
495
+
496
+ You may not impose any further restrictions on the exercise of the
497
+ rights granted or affirmed under this License. For example, you may
498
+ not impose a license fee, royalty, or other charge for exercise of
499
+ rights granted under this License, and you may not initiate litigation
500
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
501
+ any patent claim is infringed by making, using, selling, offering for
502
+ sale, or importing the Program or any portion of it.
503
+
504
+ 11. Patents.
505
+
506
+ A "contributor" is a copyright holder who authorizes use under this
507
+ License of the Program or a work on which the Program is based. The
508
+ work thus licensed is called the contributor's "contributor version".
509
+
510
+ A contributor's "essential patent claims" are all patent claims
511
+ owned or controlled by the contributor, whether already acquired or
512
+ hereafter acquired, that would be infringed by some manner, permitted
513
+ by this License, of making, using, or selling its contributor version,
514
+ but do not include claims that would be infringed only as a
515
+ consequence of further modification of the contributor version. For
516
+ purposes of this definition, "control" includes the right to grant
517
+ patent sublicenses in a manner consistent with the requirements of
518
+ this License.
519
+
520
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
521
+ patent license under the contributor's essential patent claims, to
522
+ make, use, sell, offer for sale, import and otherwise run, modify and
523
+ propagate the contents of its contributor version.
524
+
525
+ In the following three paragraphs, a "patent license" is any express
526
+ agreement or commitment, however denominated, not to enforce a patent
527
+ (such as an express permission to practice a patent or covenant not to
528
+ sue for patent infringement). To "grant" such a patent license to a
529
+ party means to make such an agreement or commitment not to enforce a
530
+ patent against the party.
531
+
532
+ If you convey a covered work, knowingly relying on a patent license,
533
+ and the Corresponding Source of the work is not available for anyone
534
+ to copy, free of charge and under the terms of this License, through a
535
+ publicly available network server or other readily accessible means,
536
+ then you must either (1) cause the Corresponding Source to be so
537
+ available, or (2) arrange to deprive yourself of the benefit of the
538
+ patent license for this particular work, or (3) arrange, in a manner
539
+ consistent with the requirements of this License, to extend the patent
540
+ license to downstream recipients. "Knowingly relying" means you have
541
+ actual knowledge that, but for the patent license, your conveying the
542
+ covered work in a country, or your recipient's use of the covered work
543
+ in a country, would infringe one or more identifiable patents in that
544
+ country that you have reason to believe are valid.
545
+
546
+ If, pursuant to or in connection with a single transaction or
547
+ arrangement, you convey, or propagate by procuring conveyance of, a
548
+ covered work, and grant a patent license to some of the parties
549
+ receiving the covered work authorizing them to use, propagate, modify
550
+ or convey a specific copy of the covered work, then the patent license
551
+ you grant is automatically extended to all recipients of the covered
552
+ work and works based on it.
553
+
554
+ A patent license is "discriminatory" if it does not include within
555
+ the scope of its coverage, prohibits the exercise of, or is
556
+ conditioned on the non-exercise of one or more of the rights that are
557
+ specifically granted under this License. You may not convey a covered
558
+ work if you are a party to an arrangement with a third party that is
559
+ in the business of distributing software, under which you make payment
560
+ to the third party based on the extent of your activity of conveying
561
+ the work, and under which the third party grants, to any of the
562
+ parties who would receive the covered work from you, a discriminatory
563
+ patent license (a) in connection with copies of the covered work
564
+ conveyed by you (or copies made from those copies), or (b) primarily
565
+ for and in connection with specific products or compilations that
566
+ contain the covered work, unless you entered into that arrangement,
567
+ or that patent license was granted, prior to 28 March 2007.
568
+
569
+ Nothing in this License shall be construed as excluding or limiting
570
+ any implied license or other defenses to infringement that may
571
+ otherwise be available to you under applicable patent law.
572
+
573
+ 12. No Surrender of Others' Freedom.
574
+
575
+ If conditions are imposed on you (whether by court order, agreement or
576
+ otherwise) that contradict the conditions of this License, they do not
577
+ excuse you from the conditions of this License. If you cannot convey a
578
+ covered work so as to satisfy simultaneously your obligations under this
579
+ License and any other pertinent obligations, then as a consequence you may
580
+ not convey it at all. For example, if you agree to terms that obligate you
581
+ to collect a royalty for further conveying from those to whom you convey
582
+ the Program, the only way you could satisfy both those terms and this
583
+ License would be to refrain entirely from conveying the Program.
584
+
585
+ 13. Use with the GNU Affero General Public License.
586
+
587
+ Notwithstanding any other provision of this License, you have
588
+ permission to link or combine any covered work with a work licensed
589
+ under version 3 of the GNU Affero General Public License into a single
590
+ combined work, and to convey the resulting work. The terms of this
591
+ License will continue to apply to the part which is the covered work,
592
+ but the special requirements of the GNU Affero General Public License,
593
+ section 13, concerning interaction through a network will apply to the
594
+ combination as such.
595
+
596
+ 14. Revised Versions of this License.
597
+
598
+ The Free Software Foundation may publish revised and/or new versions of
599
+ the GNU General Public License from time to time. Such new versions will
600
+ be similar in spirit to the present version, but may differ in detail to
601
+ address new problems or concerns.
602
+
603
+ Each version is given a distinguishing version number. If the
604
+ Program specifies that a certain numbered version of the GNU General
605
+ Public License "or any later version" applies to it, you have the
606
+ option of following the terms and conditions either of that numbered
607
+ version or of any later version published by the Free Software
608
+ Foundation. If the Program does not specify a version number of the
609
+ GNU General Public License, you may choose any version ever published
610
+ by the Free Software Foundation.
611
+
612
+ If the Program specifies that a proxy can decide which future
613
+ versions of the GNU General Public License can be used, that proxy's
614
+ public statement of acceptance of a version permanently authorizes you
615
+ to choose that version for the Program.
616
+
617
+ Later license versions may give you additional or different
618
+ permissions. However, no additional obligations are imposed on any
619
+ author or copyright holder as a result of your choosing to follow a
620
+ later version.
621
+
622
+ 15. Disclaimer of Warranty.
623
+
624
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
625
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
626
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
627
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
628
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
629
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
630
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
631
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
632
+
633
+ 16. Limitation of Liability.
634
+
635
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
636
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
637
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
638
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
639
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
640
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
641
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
642
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
643
+ SUCH DAMAGES.
644
+
645
+ 17. Interpretation of Sections 15 and 16.
646
+
647
+ If the disclaimer of warranty and limitation of liability provided
648
+ above cannot be given local legal effect according to their terms,
649
+ reviewing courts shall apply local law that most closely approximates
650
+ an absolute waiver of all civil liability in connection with the
651
+ Program, unless a warranty or assumption of liability accompanies a
652
+ copy of the Program in return for a fee.
653
+
654
+ END OF TERMS AND CONDITIONS
655
+
656
+ How to Apply These Terms to Your New Programs
657
+
658
+ If you develop a new program, and you want it to be of the greatest
659
+ possible use to the public, the best way to achieve this is to make it
660
+ free software which everyone can redistribute and change under these terms.
661
+
662
+ To do so, attach the following notices to the program. It is safest
663
+ to attach them to the start of each source file to most effectively
664
+ state the exclusion of warranty; and each file should have at least
665
+ the "copyright" line and a pointer to where the full notice is found.
666
+
667
+ <one line to give the program's name and a brief idea of what it does.>
668
+ Copyright © <year> <name of author>
669
+
670
+ This program is free software: you can redistribute it and/or modify
671
+ it under the terms of the GNU General Public License as published by
672
+ the Free Software Foundation, either version 3 of the License, or
673
+ (at your option) any later version.
674
+
675
+ This program is distributed in the hope that it will be useful,
676
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
677
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
678
+ GNU General Public License for more details.
679
+
680
+ You should have received a copy of the GNU General Public License
681
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
682
+
683
+ Also add information on how to contact you by electronic and paper mail.
684
+
685
+ If the program does terminal interaction, make it output a short
686
+ notice like this when it starts in an interactive mode:
687
+
688
+ <program> Copyright © <year> <name of author>
689
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
690
+ This is free software, and you are welcome to redistribute it
691
+ under certain conditions; type `show c' for details.
692
+
693
+ The hypothetical commands `show w' and `show c' should show the appropriate
694
+ parts of the General Public License. Of course, your program's commands
695
+ might be different; for a GUI interface, you would use an "about box".
696
+
697
+ You should also get your employer (if you work as a programmer) or school,
698
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
699
+ For more information on this, and how to apply and follow the GNU GPL, see
700
+ <https://www.gnu.org/licenses/>.
701
+
702
+ The GNU General Public License does not permit incorporating your program
703
+ into proprietary programs. If your program is a subroutine library, you
704
+ may consider it more useful to permit linking proprietary applications with
705
+ the library. If this is what you want to do, use the GNU Lesser General
706
+ Public License instead of this License. But first, please read
707
+ <https://www.gnu.org/philosophy/why-not-lgpl.html>.
708
+
709
+
710
+ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
711
+
712
+ node-md5: BSD 3-Clause "New" or "Revised" License
713
+
714
+ Copyright © 2011-2015, Paul Vorbach.
715
+ Copyright © 2009, Jeff Mott.
716
+
717
+ All rights reserved.
718
+
719
+ Redistribution and use in source and binary forms, with or without modification,
720
+ are permitted provided that the following conditions are met:
721
+
722
+ * Redistributions of source code must retain the above copyright notice, this
723
+ list of conditions and the following disclaimer.
724
+ * Redistributions in binary form must reproduce the above copyright notice, this
725
+ list of conditions and the following disclaimer in the documentation and/or
726
+ other materials provided with the distribution.
727
+ * Neither the name Crypto-JS nor the names of its contributors may be used to
728
+ endorse or promote products derived from this software without specific prior
729
+ written permission.
730
+
731
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
732
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
733
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
734
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
735
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
736
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
737
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
738
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
739
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
740
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
plugin-fw/assets/css/codemirror/codemirror.css CHANGED
@@ -1,260 +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
- }
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/colorbox.css CHANGED
@@ -1,66 +1,66 @@
1
- /*
2
- Colorbox Core Style:
3
- The following CSS is consistent between example themes and should not be altered.
4
- */
5
- #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden; -webkit-transform: translate3d(0,0,0);}
6
- #cboxWrapper {max-width:none;}
7
- #cboxOverlay{position:fixed; width:100%; height:100%;}
8
- #cboxMiddleLeft, #cboxBottomLeft{clear:left;}
9
- #cboxContent{position:relative;}
10
- #cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;}
11
- #cboxTitle{margin:0;}
12
- #cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;}
13
- #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
14
- .cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;}
15
- .cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;}
16
- #colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;}
17
-
18
- /*
19
- User Style:
20
- Change the following styles to modify the appearance of Colorbox. They are
21
- ordered & tabbed in a way that represents the nesting of the generated HTML.
22
- */
23
- #cboxOverlay{background:#fff; opacity: 0.9; filter: alpha(opacity = 90);}
24
- #colorbox{outline:0;}
25
- #cboxTopLeft{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat 0 0;}
26
- #cboxTopCenter{height:25px; background:url(../images/colorbox/border1.png) repeat-x 0 -50px;}
27
- #cboxTopRight{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat -25px 0;}
28
- #cboxBottomLeft{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat 0 -25px;}
29
- #cboxBottomCenter{height:25px; background:url(../images/colorbox/border1.png) repeat-x 0 -75px;}
30
- #cboxBottomRight{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat -25px -25px;}
31
- #cboxMiddleLeft{width:25px; background:url(../images/colorbox/border2.png) repeat-y 0 0;}
32
- #cboxMiddleRight{width:25px; background:url(../images/colorbox/border2.png) repeat-y -25px 0;}
33
- #cboxContent{background:#fff; overflow:hidden;}
34
- .cboxIframe{background:#fff;}
35
- #cboxError{padding:50px; border:1px solid #ccc;}
36
- #cboxLoadedContent{margin-bottom:20px;}
37
- #cboxTitle{position:absolute; bottom:0px; left:0; text-align:center; width:100%; color:#999;}
38
- #cboxCurrent{position:absolute; bottom:0px; left:100px; color:#999;}
39
- #cboxLoadingOverlay{background:#fff url(../images/colorbox/loading.gif) no-repeat 5px 5px;}
40
-
41
- /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */
42
- #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; width:auto; background:none; }
43
-
44
- /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */
45
- #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;}
46
-
47
- #cboxSlideshow{position:absolute; bottom:0px; right:42px; color:#444;}
48
- #cboxPrevious{position:absolute; bottom:0px; left:0; color:#444;}
49
- #cboxNext{position:absolute; bottom:0px; left:63px; color:#444;}
50
- #cboxClose{position:absolute; bottom:0; right:0; display:block; color:#444;}
51
-
52
- /*
53
- The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill
54
- when an alpha filter (opacity change) is set on the element or ancestor element. This style is not applied to or needed in IE9.
55
- See: http://jacklmoore.com/notes/ie-transparency-problems/
56
- */
57
- .cboxIE #cboxTopLeft,
58
- .cboxIE #cboxTopCenter,
59
- .cboxIE #cboxTopRight,
60
- .cboxIE #cboxBottomLeft,
61
- .cboxIE #cboxBottomCenter,
62
- .cboxIE #cboxBottomRight,
63
- .cboxIE #cboxMiddleLeft,
64
- .cboxIE #cboxMiddleRight {
65
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF);
66
  }
1
+ /*
2
+ Colorbox Core Style:
3
+ The following CSS is consistent between example themes and should not be altered.
4
+ */
5
+ #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden; -webkit-transform: translate3d(0,0,0);}
6
+ #cboxWrapper {max-width:none;}
7
+ #cboxOverlay{position:fixed; width:100%; height:100%;}
8
+ #cboxMiddleLeft, #cboxBottomLeft{clear:left;}
9
+ #cboxContent{position:relative;}
10
+ #cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;}
11
+ #cboxTitle{margin:0;}
12
+ #cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;}
13
+ #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
14
+ .cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;}
15
+ .cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;}
16
+ #colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;}
17
+
18
+ /*
19
+ User Style:
20
+ Change the following styles to modify the appearance of Colorbox. They are
21
+ ordered & tabbed in a way that represents the nesting of the generated HTML.
22
+ */
23
+ #cboxOverlay{background:#fff; opacity: 0.9; filter: alpha(opacity = 90);}
24
+ #colorbox{outline:0;}
25
+ #cboxTopLeft{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat 0 0;}
26
+ #cboxTopCenter{height:25px; background:url(../images/colorbox/border1.png) repeat-x 0 -50px;}
27
+ #cboxTopRight{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat -25px 0;}
28
+ #cboxBottomLeft{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat 0 -25px;}
29
+ #cboxBottomCenter{height:25px; background:url(../images/colorbox/border1.png) repeat-x 0 -75px;}
30
+ #cboxBottomRight{width:25px; height:25px; background:url(../images/colorbox/border1.png) no-repeat -25px -25px;}
31
+ #cboxMiddleLeft{width:25px; background:url(../images/colorbox/border2.png) repeat-y 0 0;}
32
+ #cboxMiddleRight{width:25px; background:url(../images/colorbox/border2.png) repeat-y -25px 0;}
33
+ #cboxContent{background:#fff; overflow:hidden;}
34
+ .cboxIframe{background:#fff;}
35
+ #cboxError{padding:50px; border:1px solid #ccc;}
36
+ #cboxLoadedContent{margin-bottom:20px;}
37
+ #cboxTitle{position:absolute; bottom:0px; left:0; text-align:center; width:100%; color:#999;}
38
+ #cboxCurrent{position:absolute; bottom:0px; left:100px; color:#999;}
39
+ #cboxLoadingOverlay{background:#fff url(../images/colorbox/loading.gif) no-repeat 5px 5px;}
40
+
41
+ /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */
42
+ #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; width:auto; background:none; }
43
+
44
+ /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */
45
+ #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;}
46
+
47
+ #cboxSlideshow{position:absolute; bottom:0px; right:42px; color:#444;}
48
+ #cboxPrevious{position:absolute; bottom:0px; left:0; color:#444;}
49
+ #cboxNext{position:absolute; bottom:0px; left:63px; color:#444;}
50
+ #cboxClose{position:absolute; bottom:0; right:0; display:block; color:#444;}
51
+
52
+ /*
53
+ The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill
54
+ when an alpha filter (opacity change) is set on the element or ancestor element. This style is not applied to or needed in IE9.
55
+ See: http://jacklmoore.com/notes/ie-transparency-problems/
56
+ */
57
+ .cboxIE #cboxTopLeft,
58
+ .cboxIE #cboxTopCenter,
59
+ .cboxIE #cboxTopRight,
60
+ .cboxIE #cboxBottomLeft,
61
+ .cboxIE #cboxBottomCenter,
62
+ .cboxIE #cboxBottomRight,
63
+ .cboxIE #cboxMiddleLeft,
64
+ .cboxIE #cboxMiddleRight {
65
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF);
66
  }
plugin-fw/assets/css/elementor.css CHANGED
@@ -1,36 +1,36 @@
1
- /**
2
- * Style for Elementor Editor customization
3
- */
4
-
5
- .yith-plugin-fw-elementor-widget-description {
6
- margin-bottom : 10px;
7
- font-style : italic;
8
- }
9
-
10
- .yith-plugin-fw-elementor-shortcode-widget--shortcode,
11
- .yith-plugin-fw-elementor-shortcode-widget--empty-html {
12
- font-family : -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
13
- padding : 1em 1em 1.2em;
14
- border : 1px solid #1e1e1e;
15
- border-radius : 4px;
16
- }
17
-
18
- .yith-plugin-fw-elementor-shortcode-widget__title {
19
- font-size : 15px;
20
- font-weight : 700;
21
- margin-bottom : 10px;
22
- }
23
-
24
- .yith-plugin-fw-elementor-shortcode-widget__message {
25
- font-style : italic;
26
- font-size : 13px;
27
- }
28
-
29
- .yith-plugin-fw-elementor-shortcode-widget--shortcode .yith-plugin-fw-elementor-shortcode-widget__content {
30
- font-family : Menlo, Consolas, monaco, monospace;
31
- color : #1e1e1e;
32
- font-size : 13px;
33
- padding : 0.8em 1em;
34
- border : 1px solid #ddd;
35
- border-radius : 4px;
36
  }
1
+ /**
2
+ * Style for Elementor Editor customization
3
+ */
4
+
5
+ .yith-plugin-fw-elementor-widget-description {
6
+ margin-bottom : 10px;
7
+ font-style : italic;
8
+ }
9
+
10
+ .yith-plugin-fw-elementor-shortcode-widget--shortcode,
11
+ .yith-plugin-fw-elementor-shortcode-widget--empty-html {
12
+ font-family : -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
13
+ padding : 1em 1em 1.2em;
14
+ border : 1px solid #1e1e1e;
15
+ border-radius : 4px;
16
+ }
17
+
18
+ .yith-plugin-fw-elementor-shortcode-widget__title {
19
+ font-size : 15px;
20
+ font-weight : 700;
21
+ margin-bottom : 10px;
22
+ }
23
+
24
+ .yith-plugin-fw-elementor-shortcode-widget__message {
25
+ font-style : italic;
26
+ font-size : 13px;
27
+ }
28
+
29
+ .yith-plugin-fw-elementor-shortcode-widget--shortcode .yith-plugin-fw-elementor-shortcode-widget__content {
30
+ font-family : Menlo, Consolas, monaco, monospace;
31
+ color : #1e1e1e;
32
+ font-size : 13px;
33
+ padding : 0.8em 1em;
34
+ border : 1px solid #ddd;
35
+ border-radius : 4px;
36
  }
plugin-fw/assets/css/scss/yith-plugin-ui.scss CHANGED
@@ -1,8 +1,8 @@
1
- @import "yith-plugin-ui/head_comment";
2
-
3
- @import "yith-plugin-ui/variables";
4
- @import "yith-plugin-ui/wp-pages";
5
- @import "yith-plugin-ui/taxonomy";
6
- @import "yith-plugin-ui/components";
7
- @import "yith-plugin-ui/tables";
8
- @import "yith-plugin-ui/animations";
1
+ @import "yith-plugin-ui/head_comment";
2
+
3
+ @import "yith-plugin-ui/variables";
4
+ @import "yith-plugin-ui/wp-pages";
5
+ @import "yith-plugin-ui/taxonomy";
6
+ @import "yith-plugin-ui/components";
7
+ @import "yith-plugin-ui/tables";
8
+ @import "yith-plugin-ui/animations";
plugin-fw/assets/css/scss/yith-plugin-ui/_tables.scss CHANGED
@@ -1,56 +1,56 @@
1
- /**
2
- * YITH Plugin UI - Post Type Style
3
- */
4
-
5
- @import "mixins/tables";
6
-
7
- table.yith-plugin-fw__classic-table {
8
- @include classic-table;
9
-
10
- &.wp-list-table{
11
- @include wp-table-commons;
12
- }
13
- }
14
-
15
- table.yith-plugin-fw__boxed-table {
16
- @include boxed-table;
17
-
18
- &.wp-list-table{
19
- @include wp-table-commons;
20
- }
21
- }
22
-
23
- // WP List Tables
24
- .yith-plugin-ui--classic-wp-list-style, .yith-plugin-ui #plugin-fw-wc .yith-plugin-ui--classic-wp-list-style {
25
-
26
- table.wp-list-table {
27
- @include classic-table;
28
-
29
- @include wp-table-commons;
30
- }
31
-
32
- .tablenav.bottom {
33
- display: none;
34
-
35
- .yith-plugin-fw__list-table-blank-state {
36
- display: flex;
37
- }
38
- }
39
- }
40
-
41
- .yith-plugin-ui--boxed-wp-list-style, .yith-plugin-ui #plugin-fw-wc .yith-plugin-ui--boxed-wp-list-style {
42
-
43
- table.wp-list-table {
44
- @include boxed-table;
45
-
46
- @include wp-table-commons;
47
- }
48
-
49
- .tablenav.bottom {
50
- display: none;
51
-
52
- .yith-plugin-fw__list-table-blank-state {
53
- display: flex;
54
- }
55
- }
56
- }
1
+ /**
2
+ * YITH Plugin UI - Post Type Style
3
+ */
4
+
5
+ @import "mixins/tables";
6
+
7
+ table.yith-plugin-fw__classic-table {
8
+ @include classic-table;
9
+
10
+ &.wp-list-table{
11
+ @include wp-table-commons;
12
+ }
13
+ }
14
+
15
+ table.yith-plugin-fw__boxed-table {
16
+ @include boxed-table;
17
+
18
+ &.wp-list-table{
19
+ @include wp-table-commons;
20
+ }
21
+ }
22
+
23
+ // WP List Tables
24
+ .yith-plugin-ui--classic-wp-list-style, .yith-plugin-ui #plugin-fw-wc .yith-plugin-ui--classic-wp-list-style {
25
+
26
+ table.wp-list-table {
27
+ @include classic-table;
28
+
29
+ @include wp-table-commons;
30
+ }
31
+
32
+ .tablenav.bottom {
33
+ display: none;
34
+
35
+ .yith-plugin-fw__list-table-blank-state {
36
+ display: flex;
37
+ }
38
+ }
39
+ }
40
+
41
+ .yith-plugin-ui--boxed-wp-list-style, .yith-plugin-ui #plugin-fw-wc .yith-plugin-ui--boxed-wp-list-style {
42
+
43
+ table.wp-list-table {
44
+ @include boxed-table;
45
+
46
+ @include wp-table-commons;
47
+ }
48
+
49
+ .tablenav.bottom {
50
+ display: none;
51
+
52
+ .yith-plugin-fw__list-table-blank-state {
53
+ display: flex;
54
+ }
55
+ }
56
+ }
plugin-fw/assets/css/scss/yith-plugin-ui/_taxonomy.scss CHANGED
@@ -1,52 +1,52 @@
1
- /**
2
- * YITH Plugin UI - Taxonomy Style
3
- */
4
-
5
- .yith-plugin-ui.yith-plugin-ui--taxonomy-type, .yith-plugin-ui--taxonomy-type {
6
-
7
- // List
8
-
9
- #col-container {
10
- display: flex;
11
- }
12
-
13
- #col-left {
14
- padding: 20px;
15
- background: #f1f1f1;
16
- border-radius: 8px;
17
- box-sizing: border-box;
18
- margin-right: 15px;
19
- }
20
-
21
- #col-right {
22
- flex: 1;
23
- }
24
-
25
- h2 {
26
- border: none;
27
- padding: 0;
28
- font-size: 14px;
29
- background: transparent;
30
- }
31
-
32
- // Edit Tax
33
- .wrap h1 {
34
- color: #2a8db0;
35
- font-size: 16px;
36
- font-weight: 600;
37
- }
38
- }
39
-
40
- @media screen and (max-width: 782px) {
41
- .yith-plugin-ui.yith-plugin-ui--taxonomy-type {
42
- #col-container {
43
- display: block;
44
- }
45
-
46
- #col-left, #col-right {
47
- float: none;
48
- width: 100%;
49
- }
50
- }
51
- }
52
-
1
+ /**
2
+ * YITH Plugin UI - Taxonomy Style
3
+ */
4
+
5
+ .yith-plugin-ui.yith-plugin-ui--taxonomy-type, .yith-plugin-ui--taxonomy-type {
6
+
7
+ // List
8
+
9
+ #col-container {
10
+ display: flex;
11
+ }
12
+
13
+ #col-left {
14
+ padding: 20px;
15
+ background: #f1f1f1;
16
+ border-radius: 8px;
17
+ box-sizing: border-box;
18
+ margin-right: 15px;
19
+ }
20
+
21
+ #col-right {
22
+ flex: 1;
23
+ }
24
+
25
+ h2 {
26
+ border: none;
27
+ padding: 0;
28
+ font-size: 14px;
29
+ background: transparent;
30
+ }
31
+
32
+ // Edit Tax
33
+ .wrap h1 {
34
+ color: #2a8db0;
35
+ font-size: 16px;
36
+ font-weight: 600;
37
+ }
38
+ }
39
+
40
+ @media screen and (max-width: 782px) {
41
+ .yith-plugin-ui.yith-plugin-ui--taxonomy-type {
42
+ #col-container {
43
+ display: block;
44
+ }
45
+
46
+ #col-left, #col-right {
47
+ float: none;
48
+ width: 100%;
49
+ }
50
+ }
51
+ }
52
+
plugin-fw/assets/css/scss/yith-plugin-ui/_wp-pages.scss CHANGED
@@ -1,88 +1,88 @@
1
- /**
2
- * YITH Plugin UI - WP Pages
3
- */
4
-
5
- .yith-plugin-fw-wp-page-wrapper {
6
-
7
- .yith-plugin-fw__back-to-wp-list__wrapper {
8
- margin: -5px 0 15px;
9
-
10
- .yith-plugin-fw__back-to-wp-list {
11
- text-decoration: none;
12
- font-weight: 600;
13
- text-transform: uppercase;
14
- color: var(--yith-link);
15
- vertical-align: middle;
16
-
17
- &:before {
18
- content: "\e901";
19
- font-family: yith-icon;
20
- margin-right: 5px;
21
- font-size: .8em;
22
- vertical-align: middle;
23
- }
24
- }
25
- }
26
-
27
- .wrap div#message.updated {
28
- display: none;
29
- padding: 15px 40px 15px 45px;
30
- margin: 15px 0 20px;
31
- border-radius: 5px;
32
- background: var(--yith-success-lightest);
33
- border: 1px solid var(--yith-success-light);
34
- font-weight: 600;
35
- font-size: 14px;
36
- text-align: left;
37
- color: var(--yith-content-text);
38
- box-shadow: 1px 1px 2px var(--yith-success-lighter);
39
-
40
-
41
- &:before {
42
- font-family: yith-icon;
43
- content: "\e921";
44
- position: absolute;
45
- top: 50%;
46
- left: 13px;
47
- font-size: 21px;
48
- font-weight: 400;
49
- transform: translateY(-50%);
50
- color: var(--yith-success);
51
- }
52
-
53
- p {
54
- padding: 0;
55
- margin: 0;
56
- }
57
-
58
- .notice-dismiss {
59
- position: absolute;
60
- top: 50%;
61
- right: 10px;
62
- transform: translateY(-50%);
63
- border-radius: 50%;
64
- color: var(--yith-success);
65
- padding: 7px;
66
- background: transparent;
67
- box-shadow: 0 0 0 5px rgba(0, 0, 0, 0);
68
- transition: all .3s ease-in-out;
69
-
70
- &:before {
71
- font-family: yith-icon;
72
- content: "\e906";
73
- font-weight: 600;
74
- font-size: 12px;
75
- color: inherit;
76
- }
77
-
78
- &:hover {
79
- box-shadow: 0 0 0 0 var(--yith-success-lighter);
80
- background: var(--yith-success-lighter);
81
- }
82
-
83
- &:hover:before, &:active:before, &:focus:before {
84
- color: inherit;
85
- }
86
- }
87
- }
88
  }
1
+ /**
2
+ * YITH Plugin UI - WP Pages
3
+ */
4
+
5
+ .yith-plugin-fw-wp-page-wrapper {
6
+
7
+ .yith-plugin-fw__back-to-wp-list__wrapper {
8
+ margin: -5px 0 15px;
9
+
10
+ .yith-plugin-fw__back-to-wp-list {
11
+ text-decoration: none;
12
+ font-weight: 600;
13
+ text-transform: uppercase;
14
+ color: var(--yith-link);
15
+ vertical-align: middle;
16
+
17
+ &:before {
18
+ content: "\e901";
19
+ font-family: yith-icon;
20
+ margin-right: 5px;
21
+ font-size: .8em;
22
+ vertical-align: middle;
23
+ }
24
+ }
25
+ }
26
+
27
+ .wrap div#message.updated {
28
+ display: none;
29
+ padding: 15px 40px 15px 45px;
30
+ margin: 15px 0 20px;
31
+ border-radius: 5px;
32
+ background: var(--yith-success-lightest);
33
+ border: 1px solid var(--yith-success-light);
34
+ font-weight: 600;
35
+ font-size: 14px;
36
+ text-align: left;
37
+ color: var(--yith-content-text);
38
+ box-shadow: 1px 1px 2px var(--yith-success-lighter);
39
+
40
+
41
+ &:before {
42
+ font-family: yith-icon;
43
+ content: "\e921";
44
+ position: absolute;
45
+ top: 50%;
46
+ left: 13px;
47
+ font-size: 21px;
48
+ font-weight: 400;
49
+ transform: translateY(-50%);
50
+ color: var(--yith-success);
51
+ }
52
+
53
+ p {
54
+ padding: 0;
55
+ margin: 0;
56
+ }
57
+
58
+ .notice-dismiss {
59
+ position: absolute;
60
+ top: 50%;
61
+ right: 10px;
62
+ transform: translateY(-50%);
63
+ border-radius: 50%;
64
+ color: var(--yith-success);
65
+ padding: 7px;
66
+ background: transparent;
67
+ box-shadow: 0 0 0 5px rgba(0, 0, 0, 0);
68
+ transition: all .3s ease-in-out;
69
+
70
+ &:before {
71
+ font-family: yith-icon;
72
+ content: "\e906";
73
+ font-weight: 600;
74
+ font-size: 12px;
75
+ color: inherit;
76
+ }
77
+
78
+ &:hover {
79
+ box-shadow: 0 0 0 0 var(--yith-success-lighter);
80
+ background: var(--yith-success-lighter);
81
+ }
82
+
83
+ &:hover:before, &:active:before, &:focus:before {
84
+ color: inherit;
85
+ }
86
+ }
87
+ }
88
  }
plugin-fw/assets/css/scss/yith-plugin-ui/components/_action-button.scss CHANGED
@@ -1,80 +1,80 @@
1
- .yith-plugin-ui .yith-plugin-fw__action-button, .yith-plugin-fw__action-button {
2
- height: 35px;
3
- width: 35px;
4
- background-color: var(--yith-content-bg);
5
- display: inline-block;
6
- border: 0;
7
- border-radius: 50%;
8
- transition: .3s;
9
- cursor: pointer;
10
- box-shadow: 0 2px 7px rgba(170, 198, 222, .5);
11
- outline: none;
12
- position: relative;
13
- margin: 0 5px 5px 0;
14
- vertical-align: middle;
15
-
16
- .yith-plugin-fw__action-button__link {
17
- height: 100%;
18
- width: 100%;
19
- display: inline-block;
20
- }
21
-
22
- .yith-plugin-fw__action-button__icon {
23
- position: absolute;
24
- color: var(--yith-link);
25
- font-size: 17px;
26
- top: 50%;
27
- left: 50%;
28
- transform: translateX(-50%) translateY(-50%);
29
- }
30
-
31
- &.yith-plugin-fw__action-button--trash-action .yith-plugin-fw__action-button__icon,
32
- &.yith-plugin-fw__action-button--delete-action .yith-plugin-fw__action-button__icon {
33
- color: #a10000;
34
- }
35
-
36
- .yith-plugin-fw__action-button__menu {
37
- position: absolute;
38
- display: none;
39
- flex-direction: column;
40
- width: max-content;
41
- right: 0;
42
- margin: 5px 0 0 0;
43
- padding: 8px 0;
44
- background: var(--yith-content-bg);
45
- border-radius: 5px;
46
- box-shadow: 0 2px 7px rgba(170, 198, 222, .5);
47
- z-index: 10;
48
- animation: yith-plugin-fw-appear-from-top .3s forwards;
49
- }
50
-
51
- .yith-plugin-fw__action-button__menu__item {
52
- margin: 0;
53
- display: block;
54
- padding: 7px 25px;
55
- color: var(--yith-content-text);
56
- cursor: pointer;
57
- text-decoration: none;
58
- text-align: right;
59
-
60
- &:hover {
61
- color: var(--yith-link);
62
- }
63
- }
64
-
65
- &.yith-plugin-fw__action-button--has-menu {
66
- .yith-plugin-fw__action-button__icon {
67
- color: var(--yith-content-text);
68
- }
69
-
70
- &.yith-plugin-fw__action-button--opened {
71
- .yith-plugin-fw__action-button__icon {
72
- color: var(--yith-link);
73
- }
74
-
75
- .yith-plugin-fw__action-button__menu {
76
- display: flex;
77
- }
78
- }
79
- }
80
  }
1
+ .yith-plugin-ui .yith-plugin-fw__action-button, .yith-plugin-fw__action-button {
2
+ height: 35px;
3
+ width: 35px;
4
+ background-color: var(--yith-content-bg);
5
+ display: inline-block;
6
+ border: 0;
7
+ border-radius: 50%;
8
+ transition: .3s;
9
+ cursor: pointer;
10
+ box-shadow: 0 2px 7px rgba(170, 198, 222, .5);
11
+ outline: none;
12
+ position: relative;
13
+ margin: 0 5px 5px 0;
14
+ vertical-align: middle;
15
+
16
+ .yith-plugin-fw__action-button__link {
17
+ height: 100%;
18
+ width: 100%;
19
+ display: inline-block;
20
+ }
21
+
22
+ .yith-plugin-fw__action-button__icon {
23
+ position: absolute;
24
+ color: var(--yith-link);
25
+ font-size: 17px;
26
+ top: 50%;
27
+ left: 50%;
28
+ transform: translateX(-50%) translateY(-50%);
29
+ }
30
+
31
+ &.yith-plugin-fw__action-button--trash-action .yith-plugin-fw__action-button__icon,
32
+ &.yith-plugin-fw__action-button--delete-action .yith-plugin-fw__action-button__icon {
33
+ color: #a10000;
34
+ }
35
+
36
+ .yith-plugin-fw__action-button__menu {
37
+ position: absolute;
38
+ display: none;
39
+ flex-direction: column;
40
+ width: max-content;
41
+ right: 0;
42
+ margin: 5px 0 0 0;
43
+ padding: 8px 0;
44
+ background: var(--yith-content-bg);
45
+ border-radius: 5px;
46
+ box-shadow: 0 2px 7px rgba(170, 198, 222, .5);
47
+ z-index: 10;
48
+ animation: yith-plugin-fw-appear-from-top .3s forwards;
49
+ }
50
+
51
+ .yith-plugin-fw__action-button__menu__item {
52
+ margin: 0;
53
+ display: block;
54
+ padding: 7px 25px;
55
+ color: var(--yith-content-text);
56
+ cursor: pointer;
57
+ text-decoration: none;
58
+ text-align: right;
59
+
60
+ &:hover {
61
+ color: var(--yith-link);
62
+ }
63
+ }
64
+
65
+ &.yith-plugin-fw__action-button--has-menu {
66
+ .yith-plugin-fw__action-button__icon {
67
+ color: var(--yith-content-text);
68
+ }
69
+
70
+ &.yith-plugin-fw__action-button--opened {
71
+ .yith-plugin-fw__action-button__icon {
72
+ color: var(--yith-link);
73
+ }
74
+
75
+ .yith-plugin-fw__action-button__menu {
76
+ display: flex;
77
+ }
78
+ }
79
+ }
80
  }
plugin-fw/assets/css/scss/yith-plugin-ui/components/_boxed-row.scss CHANGED
@@ -1,14 +1,14 @@
1
-
2
- .yith-plugin-fw__boxed-row, .yith-plugin-fw__boxed-row--hover-highlight {
3
- background: var(--yith-content-bg);
4
- border-radius: 5px;
5
- box-shadow: 0 0 0 1px var(--yith-light-border-color), 0 3px 11px 6px var(--yith-light-shadow);
6
- transition: background-color .2s ease-in-out;
7
- padding: 25px;
8
- margin-bottom: 25px;
9
- margin-top: 25px;
10
- }
11
-
12
- .yith-plugin-fw__boxed-row--hover-highlight:hover {
13
- background: var(--yith-table-row-highlight);
14
- }
1
+
2
+ .yith-plugin-fw__boxed-row, .yith-plugin-fw__boxed-row--hover-highlight {
3
+ background: var(--yith-content-bg);
4
+ border-radius: 5px;
5
+ box-shadow: 0 0 0 1px var(--yith-light-border-color), 0 3px 11px 6px var(--yith-light-shadow);
6
+ transition: background-color .2s ease-in-out;
7
+ padding: 25px;
8
+ margin-bottom: 25px;
9
+ margin-top: 25px;
10
+ }
11
+
12
+ .yith-plugin-fw__boxed-row--hover-highlight:hover {
13
+ background: var(--yith-table-row-highlight);
14
+ }
plugin-fw/assets/css/scss/yith-plugin-ui/components/_buttons.scss CHANGED
@@ -1,224 +1,224 @@
1
- @import "../mixins/buttons";
2
-
3
- .yith-plugin-ui, .wp-core-ui .yith-plugin-ui {
4
-
5
- // WordPress Buttons.
6
- .button-primary, .button-secondary {
7
- border-radius : 3px;
8
- text-transform : none;
9
- box-shadow : none;
10
- border : 1px solid;
11
- font-weight : 600;
12
- padding : 0 12px;
13
- outline : none;
14
- height : auto;
15
- transition : all ease 0.3s;
16
- text-shadow : none;
17
- display : inline-block;
18
- text-decoration : none;
19
- cursor : pointer;
20
- white-space : nowrap;
21
-
22
- &:focus {
23
- outline : none;
24
- box-shadow : none;
25
- }
26
-
27
- &.button-small {
28
- padding : 0 8px;
29
- }
30
- }
31
-
32
- .button-secondary {
33
- @include button-secondary;
34
- }
35
-
36
- .button-primary {
37
- @include button-primary;
38
- }
39
-
40
- .button.action,
41
- #doaction,
42
- #doaction2,
43
- #post-query-submit,
44
- #posts-filter #delete_all,
45
- #search-submit,
46
- .button.filter-button {
47
- @include button;
48
- @include button-secondary;
49
- height : auto;
50
- line-height : 33px;
51
- border-radius : 8px;
52
- padding : 0 15px;
53
- font-weight : 600;
54
- }
55
-
56
- #posts-filter #delete_all {
57
- @include button-delete-outline;
58
- }
59
-
60
- .tablenav .tablenav-pages .button,
61
- .tablenav .tablenav-pages .tablenav-pages-navspan {
62
- @include button-secondary;
63
- }
64
-
65
- @media screen and (max-width : 782px) {
66
- .tablenav .tablenav-pages .button, .tablenav .tablenav-pages .tablenav-pages-navspan {
67
- min-width : 44px;
68
- padding : 12px 8px;
69
- font-size : 18px;
70
- line-height : 1;
71
- }
72
- }
73
-
74
- // YITH Buttons.
75
- .yith-plugin-fw__button, [class^="yith-plugin-fw__button--"], [class*=" yith-plugin-fw__button--"],
76
- .yith-add-button, .yith-edit-button, .yith-update-button, .yith-remove-button, .yith-plugin-fw-upload-button, .yith-save-button, .yith-plugin-fw-select-all, .yith-plugin-fw-deselect-all, .yith-plugin-fw-upload-button-reset // Old buttons.
77
- {
78
- @include button;
79
- }
80
-
81
- .yith-plugin-fw__button--primary {
82
- @include button-primary;
83
- }
84
-
85
- .yith-plugin-fw__button--secondary {
86
- @include button-secondary;
87
- }
88
-
89
- .yith-plugin-fw__button--delete {
90
- @include button-delete;
91
- }
92
-
93
- .yith-plugin-fw__button--add, .yith-add-button {
94
- @include button-primary;
95
-
96
- @include button-with-icon("\f115");
97
-
98
- &:before {
99
- display : inline-block;
100
- margin : 0 10px 0 -5px;
101
- font-size : .95em;
102
- transition : transform .2s, margin .2s, font-size .2s;
103
- transition-timing-function : ease-in-out;
104
- }
105
-
106
- &.closed {
107
- @include button-secondary;
108
-
109
- &:before {
110
- font-size : 1.15em;
111
- margin : 0 8px 0 -5px;
112
- transform : rotate(-45deg);
113
- }
114
- }
115
- }
116
-
117
- .yith-plugin-fw__button--close {
118
- @include button-secondary;
119
-
120
- @include button-with-icon("\f117");
121
- }
122
-
123
- .yith-plugin-fw__button--edit, .yith-edit-button {
124
- @include button-secondary;
125
-
126
- @include button-with-icon("\e907");
127
- }
128
-
129
- .yith-plugin-fw__button--update, .yith-update-button {
130
- @include button-update;
131
-
132
- @include button-with-icon("\e90b");
133
- }
134
-
135
- .yith-plugin-fw__button--trash, .yith-remove-button {
136
- @include button-delete;
137
-
138
- @include button-with-icon("\e90d");
139
- }
140
-
141
- .yith-plugin-fw__button--upload, .yith-plugin-fw-upload-button {
142
- @include button-primary;
143
-
144
- @include button-with-icon("\e90c");
145
- }
146
-
147
- // Old buttons.
148
- .yith-save-button {
149
- @include button-primary;
150
- }
151
-
152
- .yith-plugin-fw-select-all,
153
- .yith-plugin-fw-deselect-all,
154
- .yith-plugin-fw-upload-button-reset {
155
- @include button-secondary;
156
- }
157
-
158
- // with icons.
159
- .button-secondary span.yith-icon {
160
- margin-left : 0;
161
- margin-right : 10px;
162
- line-height : normal;
163
-
164
- &:before {
165
- color : inherit;
166
- font-size : 15px;
167
- font-weight : 400;
168
- }
169
- }
170
-
171
- // With icon
172
- .yith-plugin-fw__button--with-icon {
173
- position : relative;
174
- padding-left : 30px;
175
-
176
- i {
177
- position : absolute;
178
- top : 50%;
179
- left : 10px;
180
- transform : translateY(-50%);
181
- font-size : 1em;
182
- font-weight : 400;
183
- }
184
- }
185
-
186
-
187
- // Button Sizes
188
- .yith-plugin-fw__button--xl, .button-xl {
189
- padding : 0 20px;
190
- font-size : 14px;
191
- line-height : 38px;
192
-
193
- &::before {
194
- margin : 0 10px 0 -5px;
195
- }
196
-
197
- &.yith-plugin-fw__button--with-icon {
198
- padding-left : 40px;
199
-
200
- i {
201
- left : 14px;
202
- }
203
- }
204
- }
205
-
206
- .yith-plugin-fw__button--xxl {
207
- padding : 0 28px;
208
- font-size : 16px;
209
- line-height : 45px;
210
-
211
- &::before {
212
- margin : 0 15px 0 -10px;
213
- }
214
-
215
- &.yith-plugin-fw__button--with-icon {
216
- padding-left : 45px;
217
-
218
- i {
219
- left : 15px;
220
- }
221
- }
222
- }
223
- }
224
-
1
+ @import "../mixins/buttons";
2
+
3
+ .yith-plugin-ui, .wp-core-ui .yith-plugin-ui {
4
+
5
+ // WordPress Buttons.
6
+ .button-primary, .button-secondary {
7
+ border-radius : 3px;
8
+ text-transform : none;
9
+ box-shadow : none;
10
+ border : 1px solid;
11
+ font-weight : 600;
12
+ padding : 0 12px;
13
+ outline : none;
14
+ height : auto;
15
+ transition : all ease 0.3s;
16
+ text-shadow : none;
17
+ display : inline-block;
18
+ text-decoration : none;
19
+ cursor : pointer;
20
+ white-space : nowrap;
21
+
22
+ &:focus {
23
+ outline : none;
24
+ box-shadow : none;
25
+ }
26
+
27
+ &.button-small {
28
+ padding : 0 8px;
29
+ }
30
+ }
31
+
32
+ .button-secondary {
33
+ @include button-secondary;
34
+ }
35
+
36
+ .button-primary {
37
+ @include button-primary;
38
+ }
39
+
40
+ .button.action,
41
+ #doaction,
42
+ #doaction2,
43
+ #post-query-submit,
44
+ #posts-filter #delete_all,
45
+ #search-submit,
46
+ .button.filter-button {
47
+ @include button;
48
+ @include button-secondary;
49
+ height : auto;
50
+ line-height : 33px;
51
+ border-radius : 8px;
52
+ padding : 0 15px;
53
+ font-weight : 600;
54
+ }
55
+
56
+ #posts-filter #delete_all {
57
+ @include button-delete-outline;
58
+ }
59
+
60
+ .tablenav .tablenav-pages .button,
61
+ .tablenav .tablenav-pages .tablenav-pages-navspan {
62
+ @include button-secondary;
63
+ }
64
+
65
+ @media screen and (max-width : 782px) {
66
+ .tablenav .tablenav-pages .button, .tablenav .tablenav-pages .tablenav-pages-navspan {
67
+ min-width : 44px;
68
+ padding : 12px 8px;
69
+ font-size : 18px;
70
+ line-height : 1;
71
+ }
72
+ }
73
+
74
+ // YITH Buttons.
75
+ .yith-plugin-fw__button, [class^="yith-plugin-fw__button--"], [class*=" yith-plugin-fw__button--"],
76
+ .yith-add-button, .yith-edit-button, .yith-update-button, .yith-remove-button, .yith-plugin-fw-upload-button, .yith-save-button, .yith-plugin-fw-select-all, .yith-plugin-fw-deselect-all, .yith-plugin-fw-upload-button-reset // Old buttons.
77
+ {
78
+ @include button;
79
+ }
80
+
81
+ .yith-plugin-fw__button--primary {
82
+ @include button-primary;
83
+ }
84
+
85
+ .yith-plugin-fw__button--secondary {
86
+ @include button-secondary;
87
+ }
88
+
89
+ .yith-plugin-fw__button--delete {
90
+ @include button-delete;
91
+ }
92
+
93
+ .yith-plugin-fw__button--add, .yith-add-button {
94
+ @include button-primary;
95
+
96
+ @include button-with-icon("\f115");
97
+
98
+ &:before {
99
+ display : inline-block;
100
+ margin : 0 10px 0 -5px;
101
+ font-size : .95em;
102
+ transition : transform .2s, margin .2s, font-size .2s;
103
+ transition-timing-function : ease-in-out;
104
+ }
105
+
106
+ &.closed {
107
+ @include button-secondary;
108
+
109
+ &:before {
110
+ font-size : 1.15em;
111
+ margin : 0 8px 0 -5px;
112
+ transform : rotate(-45deg);
113
+ }
114
+ }
115
+ }
116
+
117
+ .yith-plugin-fw__button--close {
118
+ @include button-secondary;
119
+
120
+ @include button-with-icon("\f117");
121
+ }
122
+
123
+ .yith-plugin-fw__button--edit, .yith-edit-button {
124
+ @include button-secondary;
125
+
126
+ @include button-with-icon("\e907");
127
+ }
128
+
129
+ .yith-plugin-fw__button--update, .yith-update-button {
130
+ @include button-update;
131
+
132
+ @include button-with-icon("\e90b");
133
+ }
134
+
135
+ .yith-plugin-fw__button--trash, .yith-remove-button {
136
+ @include button-delete;
137
+
138
+ @include button-with-icon("\e90d");
139
+ }
140
+
141
+ .yith-plugin-fw__button--upload, .yith-plugin-fw-upload-button {
142
+ @include button-primary;
143
+
144
+ @include button-with-icon("\e90c");
145
+ }
146
+
147
+ // Old buttons.
148
+ .yith-save-button {
149
+ @include button-primary;
150
+ }
151
+
152
+ .yith-plugin-fw-select-all,
153
+ .yith-plugin-fw-deselect-all,
154
+ .yith-plugin-fw-upload-button-reset {
155
+ @include button-secondary;
156
+ }
157
+
158
+ // with icons.
159
+ .button-secondary span.yith-icon {
160
+ margin-left : 0;
161
+ margin-right : 10px;
162
+ line-height : normal;
163
+
164
+ &:before {
165
+ color : inherit;
166
+ font-size : 15px;
167
+ font-weight : 400;
168
+ }
169
+ }
170
+
171
+ // With icon
172
+ .yith-plugin-fw__button--with-icon {
173
+ position : relative;
174
+ padding-left : 30px;
175
+
176
+ i {
177
+ position : absolute;
178
+ top : 50%;
179
+ left : 10px;
180
+ transform : translateY(-50%);
181
+ font-size : 1em;
182
+ font-weight : 400;
183
+ }
184
+ }
185
+
186
+
187
+ // Button Sizes
188
+ .yith-plugin-fw__button--xl, .button-xl {
189
+ padding : 0 20px;
190
+ font-size : 14px;
191
+ line-height : 38px;
192
+
193
+ &::before {
194
+ margin : 0 10px 0 -5px;
195
+ }
196
+
197
+ &.yith-plugin-fw__button--with-icon {
198
+ padding-left : 40px;
199
+
200
+ i {
201
+ left : 14px;
202
+ }
203
+ }
204
+ }
205
+
206
+ .yith-plugin-fw__button--xxl {
207
+ padding : 0 28px;
208
+ font-size : 16px;
209
+ line-height : 45px;
210
+
211
+ &::before {
212
+ margin : 0 15px 0 -10px;
213
+ }
214
+
215
+ &.yith-plugin-fw__button--with-icon {
216
+ padding-left : 45px;
217
+
218
+ i {
219
+ left : 15px;
220
+ }
221
+ }
222
+ }
223
+ }
224
+
plugin-fw/assets/css/scss/yith-plugin-ui/components/_confirm.scss CHANGED
@@ -1,41 +1,41 @@
1
- @import "../mixins/buttons";
2
-
3
- .yith-plugin-fw__confirm__wrap {
4
-
5
- .yith-plugin-fw__confirm__message {
6
- margin-bottom: 20px;
7
- }
8
-
9
- .yith-plugin-fw__confirm__footer {
10
- text-align: right;
11
- }
12
-
13
-
14
- .yith-plugin-fw__confirm__button {
15
- height: auto;
16
- line-height: 33px;
17
- border-radius: 4px;
18
- padding: 0 20px;
19
- font-weight: 600;
20
- cursor: pointer;
21
- display: inline-block;
22
- margin-right: 10px;
23
- white-space: nowrap;
24
-
25
- &:last-child {
26
- margin-right: 0;
27
- }
28
-
29
- &.yith-plugin-fw__confirm__button--cancel {
30
- @include button-secondary;
31
- }
32
-
33
- &.yith-plugin-fw__confirm__button--confirm {
34
- @include button-primary;
35
- }
36
-
37
- &.yith-plugin-fw__confirm__button--delete {
38
- @include button-delete;
39
- }
40
- }
41
  }
1
+ @import "../mixins/buttons";
2
+
3
+ .yith-plugin-fw__confirm__wrap {
4
+
5
+ .yith-plugin-fw__confirm__message {
6
+ margin-bottom: 20px;
7
+ }
8
+
9
+ .yith-plugin-fw__confirm__footer {
10
+ text-align: right;
11
+ }
12
+
13
+
14
+ .yith-plugin-fw__confirm__button {
15
+ height: auto;
16
+ line-height: 33px;
17
+ border-radius: 4px;
18
+ padding: 0 20px;
19
+ font-weight: 600;
20
+ cursor: pointer;
21
+ display: inline-block;
22
+ margin-right: 10px;
23
+ white-space: nowrap;
24
+
25
+ &:last-child {
26
+ margin-right: 0;
27
+ }
28
+
29
+ &.yith-plugin-fw__confirm__button--cancel {
30
+ @include button-secondary;
31
+ }
32
+
33
+ &.yith-plugin-fw__confirm__button--confirm {
34
+ @include button-primary;
35
+ }
36
+
37
+ &.yith-plugin-fw__confirm__button--delete {
38
+ @include button-delete;
39
+ }
40
+ }
41
  }
plugin-fw/assets/css/scss/yith-plugin-ui/components/_list-table-blank-state.scss CHANGED
@@ -1,25 +1,25 @@
1
- .yith-plugin-fw__list-table-blank-state {
2
- padding: 30px 30px 0;
3
- text-align: center;
4
- display: flex;
5
- flex-direction: column;
6
-
7
- & > * {
8
- margin-bottom: 30px;
9
- }
10
-
11
- img.yith-plugin-fw__list-table-blank-state__icon {
12
- width: 100px;
13
- margin: 0 auto 30px;
14
- }
15
-
16
- i.yith-plugin-fw__list-table-blank-state__icon {
17
- font-size: 65px;
18
- margin: 0 auto 30px;
19
- }
20
-
21
- .yith-plugin-fw__list-table-blank-state__message {
22
- font-size: 1.4em;
23
- line-height: 1.5;
24
- }
25
  }
1
+ .yith-plugin-fw__list-table-blank-state {
2
+ padding: 30px 30px 0;
3
+ text-align: center;
4
+ display: flex;
5
+ flex-direction: column;
6
+
7
+ & > * {
8
+ margin-bottom: 30px;
9
+ }
10
+
11
+ img.yith-plugin-fw__list-table-blank-state__icon {
12
+ width: 100px;
13
+ margin: 0 auto 30px;
14
+ }
15
+
16
+ i.yith-plugin-fw__list-table-blank-state__icon {
17
+ font-size: 65px;
18
+ margin: 0 auto 30px;
19
+ }
20
+
21
+ .yith-plugin-fw__list-table-blank-state__message {
22
+ font-size: 1.4em;
23
+ line-height: 1.5;
24
+ }
25
  }
plugin-fw/assets/css/scss/yith-plugin-ui/components/_modal.scss CHANGED
@@ -1,128 +1,128 @@
1
- .yith-plugin-fw__modal__wrap {
2
- display: flex;
3
- align-items: center;
4
- justify-content: center;
5
- position: fixed;
6
- top: 0;
7
- left: 0;
8
- width: 100%;
9
- height: 100%;
10
- z-index: 999999;
11
- background: rgba(34, 59, 80, 0.7);
12
- animation: yith-plugin-fw-fade-in .3s forwards;
13
- box-sizing: border-box;
14
-
15
- .yith-plugin-fw__modal__main {
16
- position: relative;
17
- background: #fff;
18
- border-radius: 10px;
19
- box-shadow: 1px 3px 16px rgba(0, 22, 59, .4);
20
- animation: yith-plugin-fw-appear-from-top .3s forwards;
21
- overflow: hidden;
22
- max-width: calc(100% - 20px);
23
- max-height: calc(100% - 20px);
24
- display: flex;
25
- flex-direction: column;
26
- }
27
-
28
- .yith-plugin-fw__modal__close {
29
- position: absolute;
30
- top: 0;
31
- right: 0;
32
- padding: 8px;
33
- font-size: 14px;
34
- font-weight: 600;
35
- color: #aaa;
36
- cursor: pointer;
37
-
38
- &:hover {
39
- color: #444;
40
- }
41
- }
42
-
43
- .yith-plugin-fw__modal__title {
44
- padding: 20px 25px;
45
- font-size: 1.5em;
46
- font-weight: 600;
47
- line-height: 1.5em;
48
- color: var(--yith-primary);
49
- }
50
-
51
- .yith-plugin-fw__modal__content {
52
- padding: 0 25px 25px;
53
- }
54
-
55
- .yith-plugin-fw__modal__footer {
56
- padding: 25px;
57
- background: #f7f7f7;
58
- }
59
-
60
- &.yith-plugin-fw__modal__wrap--scroll-content {
61
- .yith-plugin-fw__modal__content {
62
- overflow-y: auto;
63
- }
64
- }
65
- }
66
-
67
- .yith-plugin-fw__modal--opened {
68
- overflow: hidden;
69
- }
70
-
71
- // Allow seeing WP Menu.
72
-
73
- .yith-plugin-fw__modal--allow-wp-menu {
74
- .yith-plugin-fw__modal__wrap {
75
- z-index: 99;
76
- padding-left: $wp_menu_size;
77
- padding-top: $wp_top_bar_size;
78
- }
79
-
80
- #adminmenuback {
81
- z-index: 100;
82
- }
83
- }
84
-
85
- @media only screen and (max-width: 960px) {
86
- .folded {
87
- .yith-plugin-fw__modal__wrap {
88
- padding-left: $wp_menu_folded_size;
89
- }
90
- }
91
-
92
- .auto-fold {
93
- .yith-plugin-fw__modal--allow-wp-menu {
94
- .yith-plugin-fw__modal__wrap {
95
- padding-left: $wp_menu_folded_size;
96
- }
97
- }
98
- }
99
- }
100
-
101
- @media screen and (max-width: 782px) {
102
- .auto-fold {
103
- .yith-plugin-fw__modal--allow-wp-menu {
104
- .yith-plugin-fw__modal__wrap {
105
- z-index: 999999;
106
- width: 100%;
107
- height: 100%;
108
- padding-left: 0;
109
- padding-top: 0;
110
- }
111
- }
112
-
113
- .yith-plugin-fw__modal--allow-wp-menu-in-mobile {
114
- .yith-plugin-fw__modal__wrap {
115
- z-index: 99;
116
- padding-top: $wp_top_bar_mobile_size;
117
- }
118
-
119
- &.wp-responsive-open {
120
- .yith-plugin-fw__modal__wrap {
121
- padding-left: $wp_menu_mobile_size;
122
- }
123
- }
124
- }
125
-
126
-
127
- }
128
  }
1
+ .yith-plugin-fw__modal__wrap {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ position: fixed;
6
+ top: 0;
7
+ left: 0;
8
+ width: 100%;
9
+ height: 100%;
10
+ z-index: 999999;
11
+ background: rgba(34, 59, 80, 0.7);
12
+ animation: yith-plugin-fw-fade-in .3s forwards;
13
+ box-sizing: border-box;
14
+
15
+ .yith-plugin-fw__modal__main {
16
+ position: relative;
17
+ background: #fff;
18
+ border-radius: 10px;
19
+ box-shadow: 1px 3px 16px rgba(0, 22, 59, .4);
20
+ animation: yith-plugin-fw-appear-from-top .3s forwards;
21
+ overflow: hidden;
22
+ max-width: calc(100% - 20px);
23
+ max-height: calc(100% - 20px);
24
+ display: flex;
25
+ flex-direction: column;
26
+ }
27
+
28
+ .yith-plugin-fw__modal__close {
29
+ position: absolute;
30
+ top: 0;
31
+ right: 0;
32
+ padding: 8px;
33
+ font-size: 14px;
34
+ font-weight: 600;
35
+ color: #aaa;
36
+ cursor: pointer;
37
+
38
+ &:hover {
39
+ color: #444;
40
+ }
41
+ }
42
+
43
+ .yith-plugin-fw__modal__title {
44
+ padding: 20px 25px;
45
+ font-size: 1.5em;
46
+ font-weight: 600;
47
+ line-height: 1.5em;
48
+ color: var(--yith-primary);
49
+ }
50
+
51
+ .yith-plugin-fw__modal__content {
52
+ padding: 0 25px 25px;
53
+ }
54
+
55
+ .yith-plugin-fw__modal__footer {
56
+ padding: 25px;
57
+ background: #f7f7f7;
58
+ }
59
+
60
+ &.yith-plugin-fw__modal__wrap--scroll-content {
61
+ .yith-plugin-fw__modal__content {
62
+ overflow-y: auto;
63
+ }
64
+ }
65
+ }
66
+
67
+ .yith-plugin-fw__modal--opened {
68
+ overflow: hidden;
69
+ }
70
+
71
+ // Allow seeing WP Menu.
72
+
73
+ .yith-plugin-fw__modal--allow-wp-menu {
74
+ .yith-plugin-fw__modal__wrap {
75
+ z-index: 99;
76
+ padding-left: $wp_menu_size;
77
+ padding-top: $wp_top_bar_size;
78
+ }
79
+
80
+ #adminmenuback {
81
+ z-index: 100;
82
+ }
83
+ }
84
+
85
+ @media only screen and (max-width: 960px) {
86
+ .folded {
87
+ .yith-plugin-fw__modal__wrap {
88
+ padding-left: $wp_menu_folded_size;
89
+ }
90
+ }
91
+
92
+ .auto-fold {
93
+ .yith-plugin-fw__modal--allow-wp-menu {
94
+ .yith-plugin-fw__modal__wrap {
95
+ padding-left: $wp_menu_folded_size;
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ @media screen and (max-width: 782px) {
102
+ .auto-fold {
103
+ .yith-plugin-fw__modal--allow-wp-menu {
104
+ .yith-plugin-fw__modal__wrap {
105
+ z-index: 999999;
106
+ width: 100%;
107
+ height: 100%;
108
+ padding-left: 0;
109
+ padding-top: 0;
110
+ }
111
+ }
112
+
113
+ .yith-plugin-fw__modal--allow-wp-menu-in-mobile {
114
+ .yith-plugin-fw__modal__wrap {
115
+ z-index: 99;
116
+ padding-top: $wp_top_bar_mobile_size;
117
+ }
118
+
119
+ &.wp-responsive-open {
120
+ .yith-plugin-fw__modal__wrap {
121
+ padding-left: $wp_menu_mobile_size;
122
+ }
123
+ }
124
+ }
125
+
126
+
127
+ }
128
  }
plugin-fw/assets/css/scss/yith-plugin-ui/mixins/_buttons.scss CHANGED
@@ -1,124 +1,124 @@
1
- @mixin button {
2
- display: inline-block;
3
- height: auto;
4
- line-height: 30px;
5
- border-radius: 4px;
6
- padding: 0 17px;
7
- font-weight: 600;
8
- cursor: pointer;
9
- transition: all .3s ease-in-out;
10
- text-decoration: none;
11
- white-space: nowrap;
12
-
13
- &:focus {
14
- outline: none;
15
- box-shadow: none;
16
- }
17
- }
18
-
19
- @mixin button-primary {
20
- background: var(--yith-primary);
21
- color: var(--yith-primary-text);
22
- border: 1px solid var(--yith-primary);
23
-
24
- &:focus {
25
- background: var(--yith-primary);
26
- color: var(--yith-primary-text);
27
- border: 1px solid var(--yith-primary);
28
- box-shadow: 0 0 0 3px var(--yith-primary-focus);
29
- }
30
-
31
- &:hover, &:active {
32
- background: var(--yith-primary-hover);
33
- color: var(--yith-primary-text);
34
- border: 1px solid var(--yith-primary-hover);
35
- }
36
- }
37
-
38
- @mixin button-secondary {
39
- background: var(--yith-outline-bg);
40
- border: 1px solid var(--yith-outline-border);
41
- color: var(--yith-outline-text);
42
-
43
- &:focus {
44
- background: var(--yith-outline-bg);
45
- border: 1px solid var(--yith-outline-border);
46
- color: var(--yith-outline-text);
47
- box-shadow: 0 0 0 3px var(--yith-outline-focus);
48
- }
49
-
50
- &:hover, &:active {
51
- background: var(--yith-outline-bg-hover);
52
- border-color: var(--yith-outline-border-hover);
53
- color: var(--yith-outline-text);
54
- }
55
- }
56
-
57
- @mixin button-update {
58
- background: var(--yith-update);
59
- color: var(--yith-update-text);
60
- border: 1px solid var(--yith-update);
61
-
62
- &:focus {
63
- background: var(--yith-update);
64
- color: var(--yith-update-text);
65
- border: 1px solid var(--yith-update);
66
- box-shadow: 0 0 0 3px var(--yith-update-focus);
67
- }
68
-
69
- &:hover, &:active {
70
- background: var(--yith-update-hover);
71
- color: var(--yith-update-text);
72
- border: 1px solid var(--yith-update-hover);
73
- }
74
- }
75
-
76
- @mixin button-delete {
77
- background: var(--yith-delete);
78
- color: var(--yith-delete-text);
79
- border: 1px solid var(--yith-delete);
80
-
81
- &:focus {
82
- background: var(--yith-delete);
83
- color: var(--yith-delete-text);
84
- border: 1px solid var(--yith-delete);
85
- box-shadow: 0 0 0 3px var(--yith-delete-focus);
86
- }
87
-
88
- &:hover, &:active {
89
- background: var(--yith-delete-hover);
90
- color: var(--yith-delete-text);
91
- border: 1px solid var(--yith-delete-hover);
92
- }
93
- }
94
-
95
- @mixin button-delete-outline {
96
- background: var(--yith-delete-outline-bg);
97
- border: 1px solid var(--yith-delete-outline-border);
98
- color: var(--yith-delete-outline-text);
99
-
100
- &:focus {
101
- background: var(--yith-delete-outline-bg);
102
- border: 1px solid var(--yith-delete-outline-border);
103
- color: var(--yith-delete-outline-text);
104
- box-shadow: 0 0 0 3px var(--yith-delete-outline-focus);
105
- }
106
-
107
- &:hover, &:active {
108
- background: var(--yith-delete-outline-bg-hover);
109
- border-color: var(--yith-delete-outline-border-hover);
110
- color: var(--yith-delete-outline-text);
111
- }
112
- }
113
-
114
- @mixin button-with-icon($icon) {
115
-
116
- &:before {
117
- font-family: yith-icon;
118
- content: $icon;
119
- margin: 0 8px 0 -5px;
120
- font-size: 1.15em;
121
- font-weight: 400;
122
- vertical-align: top;
123
- }
124
  }
1
+ @mixin button {
2
+ display: inline-block;
3
+ height: auto;
4
+ line-height: 30px;
5
+ border-radius: 4px;
6
+ padding: 0 17px;
7
+ font-weight: 600;
8
+ cursor: pointer;
9
+ transition: all .3s ease-in-out;
10
+ text-decoration: none;
11
+ white-space: nowrap;
12
+
13
+ &:focus {
14
+ outline: none;
15
+ box-shadow: none;
16
+ }
17
+ }
18
+
19
+ @mixin button-primary {
20
+ background: var(--yith-primary);
21
+ color: var(--yith-primary-text);
22
+ border: 1px solid var(--yith-primary);
23
+
24
+ &:focus {
25
+ background: var(--yith-primary);
26
+ color: var(--yith-primary-text);
27
+ border: 1px solid var(--yith-primary);
28
+ box-shadow: 0 0 0 3px var(--yith-primary-focus);
29
+ }
30
+
31
+ &:hover, &:active {
32
+ background: var(--yith-primary-hover);
33
+ color: var(--yith-primary-text);
34
+ border: 1px solid var(--yith-primary-hover);
35
+ }
36
+ }
37
+
38
+ @mixin button-secondary {
39
+ background: var(--yith-outline-bg);
40
+ border: 1px solid var(--yith-outline-border);
41
+ color: var(--yith-outline-text);
42
+
43
+ &:focus {
44
+ background: var(--yith-outline-bg);
45
+ border: 1px solid var(--yith-outline-border);
46
+ color: var(--yith-outline-text);
47
+ box-shadow: 0 0 0 3px var(--yith-outline-focus);
48
+ }
49
+
50
+ &:hover, &:active {
51
+ background: var(--yith-outline-bg-hover);
52
+ border-color: var(--yith-outline-border-hover);
53
+ color: var(--yith-outline-text);
54
+ }
55
+ }
56
+
57
+ @mixin button-update {
58
+ background: var(--yith-update);
59
+ color: var(--yith-update-text);
60
+ border: 1px solid var(--yith-update);
61
+
62
+ &:focus {
63
+ background: var(--yith-update);
64
+ color: var(--yith-update-text);
65
+ border: 1px solid var(--yith-update);
66
+ box-shadow: 0 0 0 3px var(--yith-update-focus);
67
+ }
68
+
69
+ &:hover, &:active {
70
+ background: var(--yith-update-hover);
71
+ color: var(--yith-update-text);
72
+ border: 1px solid var(--yith-update-hover);
73
+ }
74
+ }
75
+
76
+ @mixin button-delete {
77
+ background: var(--yith-delete);
78
+ color: var(--yith-delete-text);
79
+ border: 1px solid var(--yith-delete);
80
+
81
+ &:focus {
82
+ background: var(--yith-delete);
83
+ color: var(--yith-delete-text);
84
+ border: 1px solid var(--yith-delete);
85
+ box-shadow: 0 0 0 3px var(--yith-delete-focus);
86
+ }
87
+
88
+ &:hover, &:active {
89
+ background: var(--yith-delete-hover);
90
+ color: var(--yith-delete-text);
91
+ border: 1px solid var(--yith-delete-hover);
92
+ }
93
+ }
94
+
95
+ @mixin button-delete-outline {
96
+ background: var(--yith-delete-outline-bg);
97
+ border: 1px solid var(--yith-delete-outline-border);
98
+ color: var(--yith-delete-outline-text);
99
+
100
+ &:focus {
101
+ background: var(--yith-delete-outline-bg);
102
+ border: 1px solid var(--yith-delete-outline-border);
103
+ color: var(--yith-delete-outline-text);
104
+ box-shadow: 0 0 0 3px var(--yith-delete-outline-focus);
105
+ }
106
+
107
+ &:hover, &:active {
108
+ background: var(--yith-delete-outline-bg-hover);
109
+ border-color: var(--yith-delete-outline-border-hover);
110
+ color: var(--yith-delete-outline-text);
111
+ }
112
+ }
113
+
114
+ @mixin button-with-icon($icon) {
115
+
116
+ &:before {
117
+ font-family: yith-icon;
118
+ content: $icon;
119
+ margin: 0 8px 0 -5px;
120
+ font-size: 1.15em;
121
+ font-weight: 400;
122
+ vertical-align: top;
123
+ }
124
  }
plugin-fw/assets/css/scss/yith-plugin-ui/mixins/_tables.scss CHANGED
@@ -1,159 +1,159 @@
1
- @mixin table-action-buttons {
2
-
3
- thead th.column-actions, tfoot th.column-actions {
4
- visibility: hidden;
5
- }
6
-
7
- th.column-actions, td.column-actions {
8
- text-align: right;
9
- }
10
-
11
- .yith-plugin-fw__action-button:not(.yith-plugin-fw__action-button--visible) {
12
- opacity: 0;
13
- transition: .3s;
14
- }
15
-
16
- tbody tr:hover .yith-plugin-fw__action-button:not(.yith-plugin-fw__action-button--visible) {
17
- opacity: 1;
18
- }
19
- }
20
-
21
- @mixin wp-table-commons {
22
-
23
- tfoot {
24
- display: none;
25
- }
26
-
27
- .check-column {
28
- width: 2em;
29
- }
30
-
31
- th.sortable a, th.sorted a {
32
- padding: 0 8px 0 0;
33
- color: inherit;
34
-
35
- &:hover {
36
- color: var(--yith-link);
37
- }
38
- }
39
-
40
- .sorting-indicator {
41
- visibility: visible;
42
-
43
- &:before {
44
- font-family: yith-icon;
45
- content: "\f116";
46
- color: inherit;
47
- font-size: 10px;
48
- top: 0;
49
- left: 0;
50
- }
51
- }
52
-
53
- th.sorted.asc .sorting-indicator:before,
54
- th.desc:hover span.sorting-indicator:before,
55
- th.desc a:focus span.sorting-indicator:before {
56
- content: "\f113";
57
- font-weight: 600;
58
- }
59
-
60
- th.sorted.desc .sorting-indicator:before,
61
- th.asc:hover span.sorting-indicator:before,
62
- th.asc a:focus span.sorting-indicator:before {
63
- content: "\f110";
64
- font-weight: 600;
65
- }
66
- @include table-action-buttons;
67
- }
68
-
69
- @mixin classic-table {
70
- border: 2px solid var(--yith-table-border-light);
71
- background: var(--yith-content-bg);
72
- box-shadow: none;
73
- border-spacing: 0;
74
-
75
- th, thead td, tfoot td {
76
- text-align: left;
77
- line-height: 1.3em;
78
- font-size: 14px;
79
- }
80
-
81
- thead th, thead td {
82
- border-bottom: 0;
83
- }
84
-
85
- tfoot th, tfoot td {
86
- border-top: 0;
87
- }
88
-
89
- tbody tr th, tbody tr td {
90
- vertical-align: middle;
91
- padding: 15px;
92
- }
93
-
94
- tbody tr:hover {
95
- background: var(--yith-table-row-highlight);
96
- }
97
-
98
- thead td, thead th, tfoot td, tfoot th {
99
- padding: 15px;
100
- font-weight: 600;
101
- }
102
-
103
- tbody > :nth-child(odd) {
104
- background-color: var(--yith-table-row-striped);
105
- }
106
- }
107
-
108
-
109
- @mixin boxed-table {
110
- border: 0;
111
- border-spacing: 0 20px;
112
- box-shadow: none;
113
- background: transparent;
114
-
115
- th, thead td, tfoot td {
116
- text-align: left;
117
- line-height: 1.3em;
118
- font-size: 14px;
119
- }
120
-
121
- thead th, thead td {
122
- border-bottom: 0;
123
- padding: 0 0 0 25px;
124
- font-weight: 600;
125
- }
126
-
127
- tbody tr {
128
- background: var(--yith-content-bg);
129
- border-radius: 5px;
130
- box-shadow: 0 0 0 1px var(--yith-light-border-color), 0 3px 11px 6px var(--yith-light-shadow);
131
- transition: background-color .2s ease-in-out;
132
- }
133
-
134
- tbody tr th, tbody tr td {
135
- background: transparent;
136
- vertical-align: middle;
137
- padding: 25px 0 25px 25px;
138
- }
139
-
140
- tbody tr td:last-child {
141
- padding-right: 25px;
142
- }
143
-
144
- tbody tr th:first-child,
145
- tbody tr td:first-child {
146
- border-radius: 5px 0 0 5px;
147
- }
148
-
149
- tbody tr th:last-child,
150
- tbody tr td:last-child {
151
- padding-right: 25px;
152
- border-radius: 0 5px 5px 0;
153
- }
154
-
155
-
156
- tbody tr:hover {
157
- background: var(--yith-table-row-highlight);
158
- }
159
  }
1
+ @mixin table-action-buttons {
2
+
3
+ thead th.column-actions, tfoot th.column-actions {
4
+ visibility: hidden;
5
+ }
6
+
7
+ th.column-actions, td.column-actions {
8
+ text-align: right;
9
+ }
10
+
11
+ .yith-plugin-fw__action-button:not(.yith-plugin-fw__action-button--visible) {
12
+ opacity: 0;
13
+ transition: .3s;
14
+ }
15
+
16
+ tbody tr:hover .yith-plugin-fw__action-button:not(.yith-plugin-fw__action-button--visible) {
17
+ opacity: 1;
18
+ }
19
+ }
20
+
21
+ @mixin wp-table-commons {
22
+
23
+ tfoot {
24
+ display: none;
25
+ }
26
+
27
+ .check-column {
28
+ width: 2em;
29
+ }
30
+
31
+ th.sortable a, th.sorted a {
32
+ padding: 0 8px 0 0;
33
+ color: inherit;
34
+
35
+ &:hover {
36
+ color: var(--yith-link);
37
+ }
38
+ }
39
+
40
+ .sorting-indicator {
41
+ visibility: visible;
42
+
43
+ &:before {
44
+ font-family: yith-icon;
45
+ content: "\f116";
46
+ color: inherit;
47
+ font-size: 10px;
48
+ top: 0;
49
+ left: 0;
50
+ }
51
+ }
52
+
53
+ th.sorted.asc .sorting-indicator:before,
54
+ th.desc:hover span.sorting-indicator:before,
55
+ th.desc a:focus span.sorting-indicator:before {
56
+ content: "\f113";
57
+ font-weight: 600;
58
+ }
59
+
60
+ th.sorted.desc .sorting-indicator:before,
61
+ th.asc:hover span.sorting-indicator:before,
62
+ th.asc a:focus span.sorting-indicator:before {
63
+ content: "\f110";
64
+ font-weight: 600;
65
+ }
66
+ @include table-action-buttons;
67
+ }
68
+
69
+ @mixin classic-table {
70
+ border: 2px solid var(--yith-table-border-light);
71
+ background: var(--yith-content-bg);
72
+ box-shadow: none;
73
+ border-spacing: 0;
74
+
75
+ th, thead td, tfoot td {
76
+ text-align: left;
77
+ line-height: 1.3em;
78
+ font-size: 14px;
79
+ }
80
+
81
+ thead th, thead td {
82
+ border-bottom: 0;
83
+ }
84
+
85
+ tfoot th, tfoot td {
86
+ border-top: 0;
87
+ }
88
+
89
+ tbody tr th, tbody tr td {
90
+ vertical-align: middle;
91
+ padding: 15px;
92
+ }
93
+
94
+ tbody tr:hover {
95
+ background: var(--yith-table-row-highlight);
96
+ }
97
+
98
+ thead td, thead th, tfoot td, tfoot th {
99
+ padding: 15px;
100
+ font-weight: 600;
101
+ }
102
+
103
+ tbody > :nth-child(odd) {
104
+ background-color: var(--yith-table-row-striped);
105
+ }
106
+ }
107
+
108
+
109
+ @mixin boxed-table {
110
+ border: 0;
111
+ border-spacing: 0 20px;
112
+ box-shadow: none;
113
+ background: transparent;
114
+
115
+ th, thead td, tfoot td {
116
+ text-align: left;
117
+ line-height: 1.3em;
118
+ font-size: 14px;
119
+ }
120
+
121
+ thead th, thead td {
122
+ border-bottom: 0;
123
+ padding: 0 0 0 25px;
124
+ font-weight: 600;
125
+ }
126
+
127
+ tbody tr {
128
+ background: var(--yith-content-bg);
129
+ border-radius: 5px;
130
+ box-shadow: 0 0 0 1px var(--yith-light-border-color), 0 3px 11px 6px var(--yith-light-shadow);
131
+ transition: background-color .2s ease-in-out;
132
+ }
133
+
134
+ tbody tr th, tbody tr td {
135
+ background: transparent;
136
+ vertical-align: middle;
137
+ padding: 25px 0 25px 25px;
138
+ }
139
+
140
+ tbody tr td:last-child {
141
+ padding-right: 25px;
142
+ }
143
+
144
+ tbody tr th:first-child,
145
+ tbody tr td:first-child {
146
+ border-radius: 5px 0 0 5px;
147
+ }
148
+
149
+ tbody tr th:last-child,
150
+ tbody tr td:last-child {
151
+ padding-right: 25px;
152
+ border-radius: 0 5px 5px 0;
153
+ }
154
+
155
+
156
+ tbody tr:hover {
157
+ background: var(--yith-table-row-highlight);
158
+ }
159
  }
plugin-fw/assets/css/yit-upgrader.css CHANGED
@@ -1,22 +1,22 @@
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
- height : calc(100% - 15px);
13
- width : calc(100% - 15px);
14
- overflow-x : hidden;
15
- overflow-y : auto;
16
- z-index : 999;
17
- background: #fcfcfc;
18
- }
19
-
20
- .yith-updating:before{
21
- animation: rotation 2s infinite linear;
22
  }
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
+ height : calc(100% - 15px);
13
+ width : calc(100% - 15px);
14
+ overflow-x : hidden;
15
+ overflow-y : auto;
16
+ z-index : 999;
17
+ background: #fcfcfc;
18
+ }
19
+
20
+ .yith-updating:before{
21
+ animation: rotation 2s infinite linear;
22
  }
plugin-fw/assets/css/yith-select2-no-wc.css CHANGED
@@ -1,741 +1,741 @@
1
- .select2-container {
2
- -webkit-box-sizing : border-box;
3
- box-sizing : border-box;
4
- display : inline-block;
5
- margin : 0;
6
- position : relative;
7
- vertical-align : middle
8
- }
9
-
10
- .select2-container .select2-selection--single {
11
- -webkit-box-sizing : border-box;
12
- box-sizing : border-box;
13
- cursor : pointer;
14
- display : block;
15
- height : 28px;
16
- margin : 0 0 -4px;
17
- -moz-user-select : none;
18
- -ms-user-select : none;
19
- user-select : none;
20
- -webkit-user-select : none
21
- }
22
-
23
- .select2-container .select2-selection--single .select2-selection__rendered {
24
- display : block;
25
- padding-left : 8px;
26
- padding-right : 20px;
27
- overflow : hidden;
28
- text-overflow : ellipsis;
29
- white-space : nowrap
30
- }
31
-
32
- .select2-container .select2-selection--single .select2-selection__clear {
33
- position : relative
34
- }
35
-
36
- .select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered {
37
- padding-right : 8px;
38
- padding-left : 20px
39
- }
40
-
41
- .select2-container .select2-selection--multiple {
42
- -webkit-box-sizing : border-box;
43
- box-sizing : border-box;
44
- cursor : pointer;
45
- display : block;
46
- min-height : 32px;
47
- -moz-user-select : none;
48
- -ms-user-select : none;
49
- user-select : none;
50
- -webkit-user-select : none
51
- }
52
-
53
- .select2-container .select2-selection--multiple .select2-selection__rendered {
54
- display : inline-block;
55
- overflow : hidden;
56
- padding-left : 8px;
57
- text-overflow : ellipsis;
58
- white-space : nowrap
59
- }
60
-
61
- .select2-container .select2-search--inline {
62
- float : left;
63
- padding : 0
64
- }
65
-
66
- .select2-container .select2-search--inline .select2-search__field {
67
- -webkit-box-sizing : border-box;
68
- box-sizing : border-box;
69
- border : none;
70
- font-size : 100%;
71
- margin : 0;
72
- padding : 0
73
- }
74
-
75
- .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
76
- -webkit-appearance : none
77
- }
78
-
79
- .select2-dropdown {
80
- background-color : #fff;
81
- border : 1px solid #aaa;
82
- border-radius : 4px;
83
- -webkit-box-sizing : border-box;
84
- box-sizing : border-box;
85
- display : block;
86
- position : absolute;
87
- left : -100000px;
88
- width : 100%;
89
- z-index : 1051
90
- }
91
-
92
- .select2-results {
93
- display : block
94
- }
95
-
96
- .select2-results__options {
97
- list-style : none;
98
- margin : 0;
99
- padding : 0
100
- }
101
-
102
- .select2-results__option {
103
- padding : 6px;
104
- -moz-user-select : none;
105
- -ms-user-select : none;
106
- user-select : none;
107
- -webkit-user-select : none
108
- }
109
-
110
- .select2-results__option[aria-selected], .select2-results__option[data-selected] {
111
- cursor : pointer
112
- }
113
-
114
- .select2-container--open .select2-dropdown {
115
- left : 0
116
- }
117
-
118
- .select2-container--open .select2-dropdown--above {
119
- border-bottom : none;
120
- border-bottom-left-radius : 0;
121
- border-bottom-right-radius : 0
122
- }
123
-
124
- .select2-container--open .select2-dropdown--below {
125
- border-top : none;
126
- border-top-left-radius : 0;
127
- border-top-right-radius : 0
128
- }
129
-
130
- .select2-search--dropdown {
131
- display : block;
132
- padding : 4px
133
- }
134
-
135
- .select2-search--dropdown .select2-search__field {
136
- padding : 4px;
137
- width : 100%;
138
- -webkit-box-sizing : border-box;
139
- box-sizing : border-box
140
- }
141
-
142
- .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
143
- -webkit-appearance : none
144
- }
145
-
146
- .select2-search--dropdown.select2-search--hide {
147
- display : none
148
- }
149
-
150
- .select2-close-mask {
151
- border : 0;
152
- margin : 0;
153
- padding : 0;
154
- display : block;
155
- position : fixed;
156
- left : 0;
157
- top : 0;
158
- min-height : 100%;
159
- min-width : 100%;
160
- height : auto;
161
- width : auto;
162
- opacity : 0;
163
- z-index : 99;
164
- background-color : #fff
165
- }
166
-
167
- .select2-hidden-accessible {
168
- border : 0 !important;
169
- clip : rect(0 0 0 0) !important;
170
- height : 1px !important;
171
- margin : -1px !important;
172
- overflow : hidden !important;
173
- padding : 0 !important;
174
- position : absolute !important;
175
- width : 1px !important
176
- }
177
-
178
- .select2-container--default .select2-selection--single {
179
- background-color : #fff;
180
- border : 1px solid #aaa;
181
- border-radius : 4px
182
- }
183
-
184
- .select2-container--default .select2-selection--single .select2-selection__rendered {
185
- color : #444;
186
- line-height : 28px
187
- }
188
-
189
- .select2-container--default .select2-selection--single .select2-selection__clear {
190
- cursor : pointer;
191
- float : right;
192
- font-weight : 700
193
- }
194
-
195
- .select2-container--default .select2-selection--single .select2-selection__placeholder {
196
- color : #999
197
- }
198
-
199
- .select2-container--default .select2-selection--single .select2-selection__arrow {
200
- height : 26px;
201
- position : absolute;
202
- top : 1px;
203
- right : 1px;
204
- width : 20px
205
- }
206
-
207
- .select2-container--default .select2-selection--single .select2-selection__arrow b {
208
- border-color : #888 transparent transparent transparent;
209
- border-style : solid;
210
- border-width : 5px 4px 0 4px;
211
- height : 0;
212
- left : 50%;
213
- margin-left : -4px;
214
- margin-top : -2px;
215
- position : absolute;
216
- top : 50%;
217
- width : 0
218
- }
219
-
220
- .select2-container--default[dir=rtl] .select2-selection--single .select2-selection__clear {
221
- float : left
222
- }
223
-
224
- .select2-container--default[dir=rtl] .select2-selection--single .select2-selection__arrow {
225
- left : 1px;
226
- right : auto
227
- }
228
-
229
- .select2-container--default.select2-container--disabled .select2-selection--single {
230
- background-color : #eee;
231
- cursor : default
232
- }
233
-
234
- .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
235
- display : none
236
- }
237
-
238
- .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
239
- border-color : transparent transparent #888 transparent;
240
- border-width : 0 4px 5px 4px
241
- }
242
-
243
- .select2-container--default .select2-selection--multiple {
244
- background-color : #fff;
245
- border : 1px solid #aaa;
246
- cursor : text;
247
- }
248
-
249
- .select2-container--default .select2-selection--multiple .select2-selection__rendered {
250
- -webkit-box-sizing : border-box;
251
- box-sizing : border-box;
252
- list-style : none;
253
- margin : 0;
254
- padding : 0 5px;
255
- width : 100%
256
- }
257
-
258
- .select2-container--default .select2-selection--multiple .select2-selection__rendered li {
259
- list-style : none;
260
- margin : 5px 5px 0 0
261
- }
262
-
263
- .select2-container--default .select2-selection--multiple .select2-selection__rendered li:before {
264
- content : '';
265
- display : none
266
- }
267
-
268
- .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
269
- color : #999;
270
- margin-top : 5px;
271
- float : left
272
- }
273
-
274
- .select2-container--default .select2-selection--multiple .select2-selection__clear {
275
- cursor : pointer;
276
- float : right;
277
- font-weight : 700;
278
- margin-top : 5px;
279
- margin-right : 10px
280
- }
281
-
282
- .select2-container--default .select2-selection--multiple .select2-selection__choice {
283
- background-color : #e4e4e4;
284
- border : 1px solid #aaa;
285
- border-radius : 4px;
286
- cursor : default;
287
- float : left;
288
- margin-right : 5px;
289
- margin-top : 5px;
290
- padding : 0 5px
291
- }
292
-
293
- .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
294
- color : #999;
295
- cursor : pointer;
296
- display : inline-block;
297
- font-weight : 700;
298
- margin-right : 2px
299
- }
300
-
301
- .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
302
- color : #333
303
- }
304
-
305
- .select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline, .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder {
306
- float : right
307
- }
308
-
309
- .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice {
310
- margin-left : 5px;
311
- margin-right : auto
312
- }
313
-
314
- .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove {
315
- margin-left : 2px;
316
- margin-right : auto
317
- }
318
-
319
- .select2-container--default.select2-container--focus .select2-selection--multiple {
320
- border : solid #000 1px;
321
- outline : 0
322
- }
323
-
324
- .select2-container--default.select2-container--disabled .select2-selection--multiple {
325
- background-color : #eee;
326
- cursor : default
327
- }
328
-
329
- .select2-container--default.select2-container--disabled .select2-selection__choice__remove {
330
- display : none
331
- }
332
-
333
- .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple, .select2-container--default.select2-container--open.select2-container--above .select2-selection--single {
334
- border-top-left-radius : 0;
335
- border-top-right-radius : 0
336
- }
337
-
338
- .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple, .select2-container--default.select2-container--open.select2-container--below .select2-selection--single {
339
- border-bottom-left-radius : 0;
340
- border-bottom-right-radius : 0
341
- }
342
-
343
- .select2-container--default .select2-search--dropdown .select2-search__field {
344
- border : 1px solid #aaa
345
- }
346
-
347
- .select2-container--default .select2-search--inline .select2-search__field {
348
- background : 0 0;
349
- border : none;
350
- outline : 0;
351
- -webkit-box-shadow : none;
352
- box-shadow : none;
353
- -webkit-appearance : textfield
354
- }
355
-
356
- .select2-container--default .select2-results > .select2-results__options {
357
- max-height : 200px;
358
- overflow-y : auto
359
- }
360
-
361
- .select2-container--default .select2-results__option[role=group] {
362
- padding : 0
363
- }
364
-
365
- .select2-container--default .select2-results__option[aria-disabled=true] {
366
- color : #999
367
- }
368
-
369
- .select2-container--default .select2-results__option[aria-selected=true], .select2-container--default .select2-results__option[data-selected=true] {
370
- background-color : #ddd
371
- }
372
-
373
- .select2-container--default .select2-results__option .select2-results__option {
374
- padding-left : 1em
375
- }
376
-
377
- .select2-container--default .select2-results__option .select2-results__option .select2-results__group {
378
- padding-left : 0
379
- }
380
-
381
- .select2-container--default .select2-results__option .select2-results__option .select2-results__option {
382
- margin-left : -1em;
383
- padding-left : 2em
384
- }
385
-
386
- .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
387
- margin-left : -2em;
388
- padding-left : 3em
389
- }
390
-
391
- .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
392
- margin-left : -3em;
393
- padding-left : 4em
394
- }
395
-
396
- .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
397
- margin-left : -4em;
398
- padding-left : 5em
399
- }
400
-
401
- .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
402
- margin-left : -5em;
403
- padding-left : 6em
404
- }
405
-
406
- .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-results__option--highlighted[data-selected] {
407
- background-color : #0073aa;
408
- color : #fff
409
- }
410
-
411
- .select2-container--default .select2-results__group {
412
- cursor : default;
413
- display : block;
414
- padding : 6px
415
- }
416
-
417
- .select2-container--classic .select2-selection--single {
418
- background-color : #f7f7f7;
419
- border : 1px solid #aaa;
420
- border-radius : 4px;
421
- outline : 0;
422
- background-image : -webkit-gradient(linear, left top, left bottom, color-stop(50%, #fff), to(#eee));
423
- background-image : -webkit-linear-gradient(top, #fff 50%, #eee 100%);
424
- background-image : linear-gradient(to bottom, #fff 50%, #eee 100%);
425
- background-repeat : repeat-x
426
- }
427
-
428
- .select2-container--classic .select2-selection--single:focus {
429
- border : 1px solid #0073aa
430
- }
431
-
432
- .select2-container--classic .select2-selection--single .select2-selection__rendered {
433
- color : #444;
434
- line-height : 28px
435
- }
436
-
437
- .select2-container--classic .select2-selection--single .select2-selection__clear {
438
- cursor : pointer;
439
- float : right;
440
- font-weight : 700;
441
- margin-right : 10px
442
- }
443
-
444
- .select2-container--classic .select2-selection--single .select2-selection__placeholder {
445
- color : #999
446
- }
447
-
448
- .select2-container--classic .select2-selection--single .select2-selection__arrow {
449
- background-color : #ddd;
450
- border : none;
451
- border-left : 1px solid #aaa;
452
- border-top-right-radius : 4px;
453
- border-bottom-right-radius : 4px;
454
- height : 26px;
455
- position : absolute;
456
- top : 1px;
457
- right : 1px;
458
- width : 20px;
459
- background-image : -webkit-gradient(linear, left top, left bottom, color-stop(50%, #eee), to(#ccc));
460
- background-image : -webkit-linear-gradient(top, #eee 50%, #ccc 100%);
461
- background-image : linear-gradient(to bottom, #eee 50%, #ccc 100%);
462
- background-repeat : repeat-x
463
- }
464
-
465
- .select2-container--classic .select2-selection--single .select2-selection__arrow b {
466
- border-color : #888 transparent transparent transparent;
467
- border-style : solid;
468
- border-width : 5px 4px 0 4px;
469
- height : 0;
470
- left : 50%;
471
- margin-left : -4px;
472
- margin-top : -2px;
473
- position : absolute;
474
- top : 50%;
475
- width : 0
476
- }
477
-
478
- .select2-container--classic[dir=rtl] .select2-selection--single .select2-selection__clear {
479
- float : left
480
- }
481
-
482
- .select2-container--classic[dir=rtl] .select2-selection--single .select2-selection__arrow {
483
- border : none;
484
- border-right : 1px solid #aaa;
485
- border-radius : 0;
486
- border-top-left-radius : 4px;
487
- border-bottom-left-radius : 4px;
488
- left : 1px;
489
- right : auto
490
- }
491
-
492
- .select2-container--classic.select2-container--open .select2-selection--single {
493
- border : 1px solid #0073aa
494
- }
495
-
496
- .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
497
- background : 0 0;
498
- border : none
499
- }
500
-
501
- .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
502
- border-color : transparent transparent #888 transparent;
503
- border-width : 0 4px 5px 4px
504
- }
505
-
506
- .select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
507
- border-top : none;
508
- border-top-left-radius : 0;
509
- border-top-right-radius : 0;
510
- background-image : -webkit-gradient(linear, left top, left bottom, from(white), color-stop(50%, #eee));
511
- background-image : -webkit-linear-gradient(top, #fff 0, #eee 50%);
512
- background-image : linear-gradient(to bottom, #fff 0, #eee 50%);
513
- background-repeat : repeat-x
514
- }
515
-
516
- .select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
517
- border-bottom : none;
518
- border-bottom-left-radius : 0;
519
- border-bottom-right-radius : 0;
520
- background-image : -webkit-gradient(linear, left top, left bottom, color-stop(50%, #eee), to(white));
521
- background-image : -webkit-linear-gradient(top, #eee 50%, #fff 100%);
522
- background-image : linear-gradient(to bottom, #eee 50%, #fff 100%);
523
- background-repeat : repeat-x
524
- }
525
-
526
- .select2-container--classic .select2-selection--multiple {
527
- background-color : #fff;
528
- border : 1px solid #aaa;
529
- border-radius : 4px;
530
- cursor : text;
531
- outline : 0
532
- }
533
-
534
- .select2-container--classic .select2-selection--multiple:focus {
535
- border : 1px solid #0073aa
536
- }
537
-
538
- .select2-container--classic .select2-selection--multiple .select2-selection__rendered {
539
- list-style : none;
540
- margin : 0;
541
- padding : 0 5px
542
- }
543
-
544
- .select2-container--classic .select2-selection--multiple .select2-selection__clear {
545
- display : none
546
- }
547
-
548
- .select2-container--classic .select2-selection--multiple .select2-selection__choice {
549
- background-color : #e4e4e4;
550
- border : 1px solid #aaa;
551
- border-radius : 4px;
552
- cursor : default;
553
- float : left;
554
- margin-right : 5px;
555
- margin-top : 5px;
556
- padding : 0 5px
557
- }
558
-
559
- .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
560
- color : #888;
561
- cursor : pointer;
562
- display : inline-block;
563
- font-weight : 700;
564
- margin-right : 2px
565
- }
566
-
567
- .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
568
- color : #555
569
- }
570
-
571
- .select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice {
572
- float : right
573
- }
574
-
575
- .select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice {
576
- margin-left : 5px;
577
- margin-right : auto
578
- }
579
-
580
- .select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove {
581
- margin-left : 2px;
582
- margin-right : auto
583
- }
584
-
585
- .select2-container--classic.select2-container--open .select2-selection--multiple {
586
- border : 1px solid #0073aa
587
- }
588
-
589
- .select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
590
- border-top : none;
591
- border-top-left-radius : 0;
592
- border-top-right-radius : 0
593
- }
594
-
595
- .select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
596
- border-bottom : none;
597
- border-bottom-left-radius : 0;
598
- border-bottom-right-radius : 0
599
- }
600
-
601
- .select2-container--classic .select2-search--dropdown .select2-search__field {
602
- border : 1px solid #aaa;
603
- outline : 0
604
- }
605
-
606
- .select2-container--classic .select2-search--inline .select2-search__field {
607
- outline : 0;
608
- -webkit-box-shadow : none;
609
- box-shadow : none
610
- }
611
-
612
- .select2-container--classic .select2-dropdown {
613
- background-color : #fff;
614
- border : 1px solid transparent
615
- }
616
-
617
- .select2-container--classic .select2-dropdown--above {
618
- border-bottom : none
619
- }
620
-
621
- .select2-container--classic .select2-dropdown--below {
622
- border-top : none
623
- }
624
-
625
- .select2-container--classic .select2-results > .select2-results__options {
626
- max-height : 200px;
627
- overflow-y : auto
628
- }
629
-
630
- .select2-container--classic .select2-results__option[role=group] {
631
- padding : 0
632
- }
633
-
634
- .select2-container--classic .select2-results__option[aria-disabled=true] {
635
- color : grey
636
- }
637
-
638
- .select2-container--classic .select2-results__option--highlighted[aria-selected], .select2-container--classic .select2-results__option--highlighted[data-selected] {
639
- background-color : #3875d7;
640
- color : #fff
641
- }
642
-
643
- .select2-container--classic .select2-results__group {
644
- cursor : default;
645
- display : block;
646
- padding : 6px
647
- }
648
-
649
- .select2-container--classic.select2-container--open .select2-dropdown {
650
- border-color : #0073aa
651
- }
652
-
653
-
654
- .select2-drop, .select2-dropdown {
655
- z-index : 999999 !important
656
- }
657
-
658
- .select2-results {
659
- line-height : 1.5em
660
- }
661
-
662
- .select2-results .select2-results__group, .select2-results .select2-results__option {
663
- margin : 0;
664
- padding : 8px
665
- }
666
-
667
- .select2-results .description {
668
- display : block;
669
- color : #999;
670
- padding-top : 4px
671
- }
672
-
673
- .select2-dropdown {
674
- border-color : #ddd
675
- }
676
-
677
- .select2-dropdown--below {
678
- -webkit-box-shadow : 0 1px 1px rgba(0, 0, 0, .1);
679
- box-shadow : 0 1px 1px rgba(0, 0, 0, .1)
680
- }
681
-
682
- .select2-dropdown--above {
683
- -webkit-box-shadow : 0 -1px 1px rgba(0, 0, 0, .1);
684
- box-shadow : 0 -1px 1px rgba(0, 0, 0, .1)
685
- }
686
-
687
- .select2-container .select2-selection__rendered.ui-sortable li {
688
- cursor : move
689
- }
690
-
691
- .select2-container .select2-selection {
692
- border-color : #ddd
693
- }
694
-
695
- .select2-container .select2-search__field {
696
- min-width : 150px
697
- }
698
-
699
- .select2-container .select2-selection--single {
700
- height : 32px
701
- }
702
-
703
- .select2-container .select2-selection--single .select2-selection__rendered {
704
- line-height : 32px;
705
- padding-right : 24px
706
- }
707
-
708
- .select2-container .select2-selection--single .select2-selection__arrow {
709
- right : 3px;
710
- height : 30px
711
- }
712
-
713
- .select2-container .select2-selection--multiple {
714
- min-height : 28px;
715
- border-radius : 0;
716
- line-height : 1.5
717
- }
718
-
719
- .select2-container .select2-selection--multiple li {
720
- margin : 0
721
- }
722
-
723
- .select2-container .select2-selection--multiple .select2-selection__choice {
724
- padding : 2px 6px
725
- }
726
-
727
- .select2-container .select2-selection--multiple .select2-selection__choice .description {
728
- display : none
729
- }
730
-
731
- .select2-container .select2-selection__clear {
732
- color : #999;
733
- margin-top : -1px
734
- }
735
-
736
- .select2-container .select2-search--inline .select2-search__field {
737
- font-family : inherit;
738
- font-size : inherit;
739
- font-weight : inherit;
740
- padding : 3px 0
741
  }
1
+ .select2-container {
2
+ -webkit-box-sizing : border-box;
3
+ box-sizing : border-box;
4
+ display : inline-block;
5
+ margin : 0;
6
+ position : relative;
7
+ vertical-align : middle
8
+ }
9
+
10
+ .select2-container .select2-selection--single {
11
+ -webkit-box-sizing : border-box;
12
+ box-sizing : border-box;
13
+ cursor : pointer;
14
+ display : block;
15
+ height : 28px;
16
+ margin : 0 0 -4px;
17
+ -moz-user-select : none;
18
+ -ms-user-select : none;
19
+ user-select : none;
20
+ -webkit-user-select : none
21
+ }
22
+
23
+ .select2-container .select2-selection--single .select2-selection__rendered {
24
+ display : block;
25
+ padding-left : 8px;
26
+ padding-right : 20px;
27
+ overflow : hidden;
28
+ text-overflow : ellipsis;
29
+ white-space : nowrap
30
+ }
31
+
32
+ .select2-container .select2-selection--single .select2-selection__clear {
33
+ position : relative
34
+ }
35
+
36
+ .select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered {
37
+ padding-right : 8px;
38
+ padding-left : 20px
39
+ }
40
+
41
+ .select2-container .select2-selection--multiple {
42
+ -webkit-box-sizing : border-box;
43
+ box-sizing : border-box;
44
+ cursor : pointer;
45
+ display : block;
46
+ min-height : 32px;
47
+ -moz-user-select : none;
48
+ -ms-user-select : none;
49
+ user-select : none;
50
+ -webkit-user-select : none
51
+ }
52
+
53
+ .select2-container .select2-selection--multiple .select2-selection__rendered {
54
+ display : inline-block;
55
+ overflow : hidden;
56
+ padding-left : 8px;
57
+ text-overflow : ellipsis;
58
+ white-space : nowrap
59
+ }
60
+
61
+ .select2-container .select2-search--inline {
62
+ float : left;
63
+ padding : 0
64
+ }
65
+
66
+ .select2-container .select2-search--inline .select2-search__field {
67
+ -webkit-box-sizing : border-box;
68
+ box-sizing : border-box;
69
+ border : none;
70
+ font-size : 100%;
71
+ margin : 0;
72
+ padding : 0
73
+ }
74
+
75
+ .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
76
+ -webkit-appearance : none
77
+ }
78
+
79
+ .select2-dropdown {
80
+ background-color : #fff;
81
+ border : 1px solid #aaa;
82
+ border-radius : 4px;
83
+ -webkit-box-sizing : border-box;
84
+ box-sizing : border-box;
85
+ display : block;
86
+ position : absolute;
87
+ left : -100000px;
88
+ width : 100%;
89
+ z-index : 1051
90
+ }
91
+
92
+ .select2-results {
93
+ display : block
94
+ }
95
+
96
+ .select2-results__options {
97
+ list-style : none;
98
+ margin : 0;
99
+ padding : 0
100
+ }
101
+
102
+ .select2-results__option {
103
+ padding : 6px;
104
+ -moz-user-select : none;
105
+ -ms-user-select : none;
106
+ user-select : none;
107
+ -webkit-user-select : none
108
+ }
109
+
110
+ .select2-results__option[aria-selected], .select2-results__option[data-selected] {
111
+ cursor : pointer
112
+ }
113
+
114
+ .select2-container--open .select2-dropdown {
115
+ left : 0
116
+ }
117
+
118
+ .select2-container--open .select2-dropdown--above {
119
+ border-bottom : none;
120
+ border-bottom-left-radius : 0;
121
+ border-bottom-right-radius : 0
122
+ }
123
+
124
+ .select2-container--open .select2-dropdown--below {
125
+ border-top : none;
126
+ border-top-left-radius : 0;
127
+ border-top-right-radius : 0
128
+ }
129
+
130
+ .select2-search--dropdown {
131
+ display : block;
132
+ padding : 4px
133
+ }
134
+
135
+ .select2-search--dropdown .select2-search__field {
136
+ padding : 4px;
137
+ width : 100%;
138
+ -webkit-box-sizing : border-box;
139
+ box-sizing : border-box
140
+ }
141
+
142
+ .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
143
+ -webkit-appearance : none
144
+ }
145
+
146
+ .select2-search--dropdown.select2-search--hide {
147
+ display : none
148
+ }
149
+
150
+ .select2-close-mask {
151
+ border : 0;
152
+ margin : 0;
153
+ padding : 0;
154
+ display : block;
155
+ position : fixed;
156
+ left : 0;
157
+ top : 0;
158
+ min-height : 100%;
159
+ min-width : 100%;
160
+ height : auto;
161
+ width : auto;
162
+ opacity : 0;
163
+ z-index : 99;
164
+ background-color : #fff
165
+ }
166
+
167
+ .select2-hidden-accessible {
168
+ border : 0 !important;
169
+ clip : rect(0 0 0 0) !important;
170
+ height : 1px !important;
171
+ margin : -1px !important;
172
+ overflow : hidden !important;
173
+ padding : 0 !important;
174
+ position : absolute !important;
175
+ width : 1px !important
176
+ }
177
+
178
+ .select2-container--default .select2-selection--single {
179
+ background-color : #fff;
180
+ border : 1px solid #aaa;
181
+ border-radius : 4px
182
+ }
183
+
184
+ .select2-container--default .select2-selection--single .select2-selection__rendered {
185
+ color : #444;
186
+ line-height : 28px
187
+ }
188
+
189
+ .select2-container--default .select2-selection--single .select2-selection__clear {
190
+ cursor : pointer;
191
+ float : right;
192
+ font-weight : 700
193
+ }
194
+
195
+ .select2-container--default .select2-selection--single .select2-selection__placeholder {
196
+ color : #999
197
+ }
198
+
199
+ .select2-container--default .select2-selection--single .select2-selection__arrow {
200
+ height : 26px;
201
+ position : absolute;
202
+ top : 1px;
203
+ right : 1px;
204
+ width : 20px
205
+ }
206
+
207
+ .select2-container--default .select2-selection--single .select2-selection__arrow b {
208
+ border-color : #888 transparent transparent transparent;
209
+ border-style : solid;
210
+ border-width : 5px 4px 0 4px;
211
+ height : 0;
212
+ left : 50%;
213
+ margin-left : -4px;
214
+ margin-top : -2px;
215
+ position : absolute;
216
+ top : 50%;
217
+ width : 0
218
+ }
219
+
220
+ .select2-container--default[dir=rtl] .select2-selection--single .select2-selection__clear {
221
+ float : left
222
+ }
223
+
224
+ .select2-container--default[dir=rtl] .select2-selection--single .select2-selection__arrow {
225
+ left : 1px;
226
+ right : auto
227
+ }
228
+
229
+ .select2-container--default.select2-container--disabled .select2-selection--single {
230
+ background-color : #eee;
231
+ cursor : default
232
+ }
233
+
234
+ .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
235
+ display : none
236
+ }
237
+
238
+ .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
239
+ border-color : transparent transparent #888 transparent;
240
+ border-width : 0 4px 5px 4px
241
+ }
242
+
243
+ .select2-container--default .select2-selection--multiple {
244
+ background-color : #fff;
245
+ border : 1px solid #aaa;
246
+ cursor : text;
247
+ }
248
+
249
+ .select2-container--default .select2-selection--multiple .select2-selection__rendered {
250
+ -webkit-box-sizing : border-box;
251
+ box-sizing : border-box;
252
+ list-style : none;
253
+ margin : 0;
254
+ padding : 0 5px;
255
+ width : 100%
256
+ }
257
+
258
+ .select2-container--default .select2-selection--multiple .select2-selection__rendered li {
259
+ list-style : none;
260
+ margin : 5px 5px 0 0
261
+ }
262
+
263
+ .select2-container--default .select2-selection--multiple .select2-selection__rendered li:before {
264
+ content : '';
265
+ display : none
266
+ }
267
+
268
+ .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
269
+ color : #999;
270
+ margin-top : 5px;
271
+ float : left
272
+ }
273
+
274
+ .select2-container--default .select2-selection--multiple .select2-selection__clear {
275
+ cursor : pointer;
276
+ float : right;
277
+ font-weight : 700;
278
+ margin-top : 5px;
279
+ margin-right : 10px
280
+ }
281
+
282
+ .select2-container--default .select2-selection--multiple .select2-selection__choice {
283
+ background-color : #e4e4e4;
284
+ border : 1px solid #aaa;
285
+ border-radius : 4px;
286
+ cursor : default;
287
+ float : left;
288
+ margin-right : 5px;
289
+ margin-top : 5px;
290
+ padding : 0 5px
291
+ }
292
+
293
+ .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
294
+ color : #999;
295
+ cursor : pointer;
296
+ display : inline-block;
297
+ font-weight : 700;
298
+ margin-right : 2px
299
+ }
300
+
301
+ .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
302
+ color : #333
303
+ }
304
+
305
+ .select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline, .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder {
306
+ float : right
307
+ }
308
+
309
+ .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice {
310
+ margin-left : 5px;
311
+ margin-right : auto
312
+ }
313
+
314
+ .select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove {
315
+ margin-left : 2px;
316
+ margin-right : auto
317
+ }
318
+
319
+ .select2-container--default.select2-container--focus .select2-selection--multiple {
320
+ border : solid #000 1px;
321
+ outline : 0
322
+ }
323
+
324
+ .select2-container--default.select2-container--disabled .select2-selection--multiple {
325
+ background-color : #eee;
326
+ cursor : default
327
+ }
328
+
329
+ .select2-container--default.select2-container--disabled .select2-selection__choice__remove {
330
+ display : none
331
+ }
332
+
333
+ .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple, .select2-container--default.select2-container--open.select2-container--above .select2-selection--single {
334
+ border-top-left-radius : 0;
335
+ border-top-right-radius : 0
336
+ }
337
+
338
+ .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple, .select2-container--default.select2-container--open.select2-container--below .select2-selection--single {
339
+ border-bottom-left-radius : 0;
340
+ border-bottom-right-radius : 0
341
+ }
342
+
343
+ .select2-container--default .select2-search--dropdown .select2-search__field {
344
+ border : 1px solid #aaa
345
+ }
346
+
347
+ .select2-container--default .select2-search--inline .select2-search__field {
348
+ background : 0 0;
349
+ border : none;
350
+ outline : 0;
351
+ -webkit-box-shadow : none;
352
+ box-shadow : none;
353
+ -webkit-appearance : textfield
354
+ }
355
+
356
+ .select2-container--default .select2-results > .select2-results__options {
357
+ max-height : 200px;
358
+ overflow-y : auto
359
+ }
360
+
361
+ .select2-container--default .select2-results__option[role=group] {
362
+ padding : 0
363
+ }
364
+
365
+ .select2-container--default .select2-results__option[aria-disabled=true] {
366
+ color : #999
367
+ }
368
+
369
+ .select2-container--default .select2-results__option[aria-selected=true], .select2-container--default .select2-results__option[data-selected=true] {
370
+ background-color : #ddd
371
+ }
372
+
373
+ .select2-container--default .select2-results__option .select2-results__option {
374
+ padding-left : 1em
375
+ }
376
+
377
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__group {
378
+ padding-left : 0
379
+ }
380
+
381
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option {
382
+ margin-left : -1em;
383
+ padding-left : 2em
384
+ }
385
+
386
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
387
+ margin-left : -2em;
388
+ padding-left : 3em
389
+ }
390
+
391
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
392
+ margin-left : -3em;
393
+ padding-left : 4em
394
+ }
395
+
396
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
397
+ margin-left : -4em;
398
+ padding-left : 5em
399
+ }
400
+
401
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
402
+ margin-left : -5em;
403
+ padding-left : 6em
404
+ }
405
+
406
+ .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-results__option--highlighted[data-selected] {
407
+ background-color : #0073aa;
408
+ color : #fff
409
+ }
410
+
411
+ .select2-container--default .select2-results__group {
412
+ cursor : default;
413
+ display : block;
414
+ padding : 6px
415
+ }
416
+
417
+ .select2-container--classic .select2-selection--single {
418
+ background-color : #f7f7f7;
419
+ border : 1px solid #aaa;
420
+ border-radius : 4px;
421
+ outline : 0;
422
+ background-image : -webkit-gradient(linear, left top, left bottom, color-stop(50%, #fff), to(#eee));
423
+ background-image : -webkit-linear-gradient(top, #fff 50%, #eee 100%);
424
+ background-image : linear-gradient(to bottom, #fff 50%, #eee 100%);
425
+ background-repeat : repeat-x
426
+ }
427
+
428
+ .select2-container--classic .select2-selection--single:focus {
429
+ border : 1px solid #0073aa
430
+ }
431
+
432
+ .select2-container--classic .select2-selection--single .select2-selection__rendered {
433
+ color : #444;
434
+ line-height : 28px
435
+ }
436
+
437
+ .select2-container--classic .select2-selection--single .select2-selection__clear {
438
+ cursor : pointer;
439
+ float : right;
440
+ font-weight : 700;
441
+ margin-right : 10px
442
+ }
443
+
444
+ .select2-container--classic .select2-selection--single .select2-selection__placeholder {
445
+ color : #999
446
+ }
447
+
448
+ .select2-container--classic .select2-selection--single .select2-selection__arrow {
449
+ background-color : #ddd;
450
+ border : none;
451
+ border-left : 1px solid #aaa;
452
+ border-top-right-radius : 4px;
453
+ border-bottom-right-radius : 4px;
454
+ height : 26px;
455
+ position : absolute;
456
+ top : 1px;
457
+ right : 1px;
458
+ width : 20px;
459
+ background-image : -webkit-gradient(linear, left top, left bottom, color-stop(50%, #eee), to(#ccc));
460
+ background-image : -webkit-linear-gradient(top, #eee 50%, #ccc 100%);
461
+ background-image : linear-gradient(to bottom, #eee 50%, #ccc 100%);
462
+ background-repeat : repeat-x
463
+ }
464
+
465
+ .select2-container--classic .select2-selection--single .select2-selection__arrow b {
466
+ border-color : #888 transparent transparent transparent;
467
+ border-style : solid;
468
+ border-width : 5px 4px 0 4px;
469
+ height : 0;
470
+ left : 50%;
471
+ margin-left : -4px;
472
+ margin-top : -2px;
473
+ position : absolute;
474
+ top : 50%;
475
+ width : 0
476
+ }
477
+
478
+ .select2-container--classic[dir=rtl] .select2-selection--single .select2-selection__clear {
479
+ float : left
480
+ }
481
+
482
+ .select2-container--classic[dir=rtl] .select2-selection--single .select2-selection__arrow {
483
+ border : none;
484
+ border-right : 1px solid #aaa;
485
+ border-radius : 0;
486
+ border-top-left-radius : 4px;
487
+ border-bottom-left-radius : 4px;
488
+ left : 1px;
489
+ right : auto
490
+ }
491
+
492
+ .select2-container--classic.select2-container--open .select2-selection--single {
493
+ border : 1px solid #0073aa
494
+ }
495
+
496
+ .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
497
+ background : 0 0;
498
+ border : none
499
+ }
500
+
501
+ .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
502
+ border-color : transparent transparent #888 transparent;
503
+ border-width : 0 4px 5px 4px
504
+ }
505
+
506
+ .select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
507
+ border-top : none;
508
+ border-top-left-radius : 0;
509
+ border-top-right-radius : 0;
510
+ background-image : -webkit-gradient(linear, left top, left bottom, from(white), color-stop(50%, #eee));
511
+ background-image : -webkit-linear-gradient(top, #fff 0, #eee 50%);
512
+ background-image : linear-gradient(to bottom, #fff 0, #eee 50%);
513
+ background-repeat : repeat-x
514
+ }
515
+
516
+ .select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
517
+ border-bottom : none;
518
+ border-bottom-left-radius : 0;
519
+ border-bottom-right-radius : 0;
520
+ background-image : -webkit-gradient(linear, left top, left bottom, color-stop(50%, #eee), to(white));
521
+ background-image : -webkit-linear-gradient(top, #eee 50%, #fff 100%);
522
+ background-image : linear-gradient(to bottom, #eee 50%, #fff 100%);
523
+ background-repeat : repeat-x
524
+ }
525
+
526
+ .select2-container--classic .select2-selection--multiple {
527
+ background-color : #fff;
528
+ border : 1px solid #aaa;
529
+ border-radius : 4px;
530
+ cursor : text;
531
+ outline : 0
532
+ }
533
+
534
+ .select2-container--classic .select2-selection--multiple:focus {
535
+ border : 1px solid #0073aa
536
+ }
537
+
538
+ .select2-container--classic .select2-selection--multiple .select2-selection__rendered {
539
+ list-style : none;
540
+ margin : 0;
541
+ padding : 0 5px
542
+ }
543
+
544
+ .select2-container--classic .select2-selection--multiple .select2-selection__clear {
545
+ display : none
546
+ }
547
+
548
+ .select2-container--classic .select2-selection--multiple .select2-selection__choice {
549
+ background-color : #e4e4e4;
550
+ border : 1px solid #aaa;
551
+ border-radius : 4px;
552
+ cursor : default;
553
+ float : left;
554
+ margin-right : 5px;
555
+ margin-top : 5px;
556
+ padding : 0 5px
557
+ }
558
+
559
+ .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
560
+ color : #888;
561
+ cursor : pointer;
562
+ display : inline-block;
563
+ font-weight : 700;
564
+ margin-right : 2px
565
+ }
566
+
567
+ .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
568
+ color : #555
569
+ }
570
+
571
+ .select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice {
572
+ float : right
573
+ }
574
+
575
+ .select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice {
576
+ margin-left : 5px;
577
+ margin-right : auto
578
+ }
579
+
580
+ .select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove {
581
+ margin-left : 2px;
582
+ margin-right : auto
583
+ }
584
+
585
+ .select2-container--classic.select2-container--open .select2-selection--multiple {
586
+ border : 1px solid #0073aa
587
+ }
588
+
589
+ .select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
590
+ border-top : none;
591
+ border-top-left-radius : 0;
592
+ border-top-right-radius : 0
593
+ }
594
+
595
+ .select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
596
+ border-bottom : none;
597
+ border-bottom-left-radius : 0;
598
+ border-bottom-right-radius : 0
599
+ }
600
+
601
+ .select2-container--classic .select2-search--dropdown .select2-search__field {
602
+ border : 1px solid #aaa;
603
+ outline : 0
604
+ }
605
+
606
+ .select2-container--classic .select2-search--inline .select2-search__field {
607
+ outline : 0;
608
+ -webkit-box-shadow : none;
609
+ box-shadow : none
610
+ }
611
+
612
+ .select2-container--classic .select2-dropdown {
613
+ background-color : #fff;
614
+ border : 1px solid transparent
615
+ }
616
+
617
+ .select2-container--classic .select2-dropdown--above {
618
+ border-bottom : none
619
+ }
620
+
621
+ .select2-container--classic .select2-dropdown--below {
622
+ border-top : none
623
+ }
624
+
625
+ .select2-container--classic .select2-results > .select2-results__options {
626
+ max-height : 200px;
627
+ overflow-y : auto
628
+ }
629
+
630
+ .select2-container--classic .select2-results__option[role=group] {
631
+ padding : 0
632
+ }
633
+
634
+ .select2-container--classic .select2-results__option[aria-disabled=true] {
635
+ color : grey
636
+ }
637
+
638
+ .select2-container--classic .select2-results__option--highlighted[aria-selected], .select2-container--classic .select2-results__option--highlighted[data-selected] {
639
+ background-color : #3875d7;
640
+ color : #fff
641
+ }
642
+
643
+ .select2-container--classic .select2-results__group {
644
+ cursor : default;
645
+ display : block;
646
+ padding : 6px
647
+ }
648
+
649
+ .select2-container--classic.select2-container--open .select2-dropdown {
650
+ border-color : #0073aa
651
+ }
652
+
653
+
654
+ .select2-drop, .select2-dropdown {
655
+ z-index : 999999 !important
656
+ }
657
+
658
+ .select2-results {
659
+ line-height : 1.5em
660
+ }
661
+
662
+ .select2-results .select2-results__group, .select2-results .select2-results__option {
663
+ margin : 0;
664
+ padding : 8px
665
+ }
666
+
667
+ .select2-results .description {
668
+ display : block;
669
+ color : #999;
670
+ padding-top : 4px
671
+ }
672
+
673
+ .select2-dropdown {
674
+ border-color : #ddd
675
+ }
676
+
677
+ .select2-dropdown--below {
678
+ -webkit-box-shadow : 0 1px 1px rgba(0, 0, 0, .1);
679
+ box-shadow : 0 1px 1px rgba(0, 0, 0, .1)
680
+ }
681
+
682
+ .select2-dropdown--above {
683
+ -webkit-box-shadow : 0 -1px 1px rgba(0, 0, 0, .1);
684
+ box-shadow : 0 -1px 1px rgba(0, 0, 0, .1)
685
+ }
686
+
687
+ .select2-container .select2-selection__rendered.ui-sortable li {
688
+ cursor : move
689
+ }
690
+
691
+ .select2-container .select2-selection {
692
+ border-color : #ddd
693
+ }
694
+
695
+ .select2-container .select2-search__field {
696
+ min-width : 150px
697
+ }
698
+
699
+ .select2-container .select2-selection--single {
700
+ height : 32px
701
+ }
702
+
703
+ .select2-container .select2-selection--single .select2-selection__rendered {
704
+ line-height : 32px;
705
+ padding-right : 24px
706
+ }
707
+
708
+ .select2-container .select2-selection--single .select2-selection__arrow {
709
+ right : 3px;
710
+ height : 30px
711
+ }
712
+
713
+ .select2-container .select2-selection--multiple {
714
+ min-height : 28px;
715
+ border-radius : 0;
716
+ line-height : 1.5
717
+ }
718
+
719
+ .select2-container .select2-selection--multiple li {
720
+ margin : 0
721
+ }
722
+
723
+ .select2-container .select2-selection--multiple .select2-selection__choice {
724
+ padding : 2px 6px
725
+ }
726
+
727
+ .select2-container .select2-selection--multiple .select2-selection__choice .description {
728
+ display : none
729
+ }
730
+
731
+ .select2-container .select2-selection__clear {
732
+ color : #999;
733
+ margin-top : -1px
734
+ }
735
+
736
+ .select2-container .select2-search--inline .select2-search__field {
737
+ font-family : inherit;
738
+ font-size : inherit;
739
+ font-weight : inherit;
740
+ padding : 3px 0
741
  }
plugin-fw/assets/js/codemirror/codemirror.js CHANGED
@@ -1,5806 +1,5806 @@
1
- /*
2
- * CodeMirror version 3.15
3
- * https://codemirror.net/
4
- * Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
5
- *
6
- * Released under the MIT license
7
- * https://codemirror.net/LICENSE
8
- */
9
-
10
- // CodeMirror is the only global var we claim
11
- window.CodeMirror = (function() {
12
- "use strict";
13
-
14
- // BROWSER SNIFFING
15
-
16
- // Crude, but necessary to handle a number of hard-to-feature-detect
17
- // bugs and behavior differences.
18
- var gecko = /gecko\/\d/i.test(navigator.userAgent);
19
- var ie = /MSIE \d/.test(navigator.userAgent);
20
- var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
21
- var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
22
- var webkit = /WebKit\//.test(navigator.userAgent);
23
- var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
24
- var chrome = /Chrome\//.test(navigator.userAgent);
25
- var opera = /Opera\//.test(navigator.userAgent);
26
- var safari = /Apple Computer/.test(navigator.vendor);
27
- var khtml = /KHTML\//.test(navigator.userAgent);
28
- var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
29
- var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
30
- var phantom = /PhantomJS/.test(navigator.userAgent);
31
-
32
- var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
33
- // This is woefully incomplete. Suggestions for alternative methods welcome.
34
- var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
35
- var mac = ios || /Mac/.test(navigator.platform);
36
- var windows = /windows/i.test(navigator.platform);
37
-
38
- var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
39
- if (opera_version) opera_version = Number(opera_version[1]);
40
- if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
41
- // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
42
- var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
43
- var captureMiddleClick = gecko || (ie && !ie_lt9);
44
-
45
- // Optimize some code when these features are not used
46
- var sawReadOnlySpans = false, sawCollapsedSpans = false;
47
-
48
- // CONSTRUCTOR
49
-
50
- function CodeMirror(place, options) {
51
- if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
52
-
53
- this.options = options = options || {};
54
- // Determine effective options based on given values and defaults.
55
- for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
56
- options[opt] = defaults[opt];
57
- setGuttersForLineNumbers(options);
58
-
59
- var docStart = typeof options.value == "string" ? 0 : options.value.first;
60
- var display = this.display = makeDisplay(place, docStart);
61
- display.wrapper.CodeMirror = this;
62
- updateGutters(this);
63
- if (options.autofocus && !mobile) focusInput(this);
64
-
65
- this.state = {keyMaps: [],
66
- overlays: [],
67
- modeGen: 0,
68
- overwrite: false, focused: false,
69
- suppressEdits: false, pasteIncoming: false,
70
- draggingText: false,
71
- highlight: new Delayed()};
72
-
73
- themeChanged(this);
74
- if (options.lineWrapping)
75
- this.display.wrapper.className += " CodeMirror-wrap";
76
-
77
- var doc = options.value;
78
- if (typeof doc == "string") doc = new Doc(options.value, options.mode);
79
- operation(this, attachDoc)(this, doc);
80
-
81
- // Override magic textarea content restore that IE sometimes does
82
- // on our hidden textarea on reload
83
- if (ie) setTimeout(bind(resetInput, this, true), 20);
84
-
85
- registerEventHandlers(this);
86
- // IE throws unspecified error in certain cases, when
87
- // trying to access activeElement before onload
88
- var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
89
- if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
90
- else onBlur(this);
91
-
92
- operation(this, function() {
93
- for (var opt in optionHandlers)
94
- if (optionHandlers.propertyIsEnumerable(opt))
95
- optionHandlers[opt](this, options[opt], Init);
96
- for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
97
- })();
98
- }
99
-
100
- // DISPLAY CONSTRUCTOR
101
-
102
- function makeDisplay(place, docStart) {
103
- var d = {};
104
-
105
- var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
106
- if (webkit) input.style.width = "1000px";
107
- else input.setAttribute("wrap", "off");
108
- // if border: 0; -- iOS fails to open keyboard (issue #1287)
109
- if (ios) input.style.border = "1px solid black";
110
- input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
111
-
112
- // Wraps and hides input textarea
113
- d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
114
- // The actual fake scrollbars.
115
- d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
116
- d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
117
- d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
118
- d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
119
- // DIVs containing the selection and the actual code
120
- d.lineDiv = elt("div", null, "CodeMirror-code");
121
- d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
122
- // Blinky cursor, and element used to ensure cursor fits at the end of a line
123
- d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
124
- // Secondary cursor, shown when on a 'jump' in bi-directional text
125
- d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
126
- // Used to measure text size
127
- d.measure = elt("div", null, "CodeMirror-measure");
128
- // Wraps everything that needs to exist inside the vertically-padded coordinate system
129
- d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
130
- null, "position: relative; outline: none");
131
- // Moved around its parent to cover visible view
132
- d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
133
- // Set to the height of the text, causes scrolling
134
- d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
135
- // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
136
- d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
137
- // Will contain the gutters, if any
138
- d.gutters = elt("div", null, "CodeMirror-gutters");
139
- d.lineGutter = null;
140
- // Provides scrolling
141
- d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
142
- d.scroller.setAttribute("tabIndex", "-1");
143
- // The element in which the editor lives.
144
- d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
145
- d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
146
- // Work around IE7 z-index bug
147
- if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
148
- if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
149
-
150
- // Needed to hide big blue blinking cursor on Mobile Safari
151
- if (ios) input.style.width = "0px";
152
- if (!webkit) d.scroller.draggable = true;
153
- // Needed to handle Tab key in KHTML
154
- if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
155
- // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
156
- else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
157
-
158
- // Current visible range (may be bigger than the view window).
159
- d.viewOffset = d.lastSizeC = 0;
160
- d.showingFrom = d.showingTo = docStart;
161
-
162
- // Used to only resize the line number gutter when necessary (when
163
- // the amount of lines crosses a boundary that makes its width change)
164
- d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
165
- // See readInput and resetInput
166
- d.prevInput = "";
167
- // Set to true when a non-horizontal-scrolling widget is added. As
168
- // an optimization, widget aligning is skipped when d is false.
169
- d.alignWidgets = false;
170
- // Flag that indicates whether we currently expect input to appear
171
- // (after some event like 'keypress' or 'input') and are polling
172
- // intensively.
173
- d.pollingFast = false;
174
- // Self-resetting timeout for the poller
175
- d.poll = new Delayed();
176
-
177
- d.cachedCharWidth = d.cachedTextHeight = null;
178
- d.measureLineCache = [];
179
- d.measureLineCachePos = 0;
180
-
181
- // Tracks when resetInput has punted to just putting a short
182
- // string instead of the (large) selection.
183
- d.inaccurateSelection = false;
184
-
185
- // Tracks the maximum line length so that the horizontal scrollbar
186
- // can be kept static when scrolling.
187
- d.maxLine = null;
188
- d.maxLineLength = 0;
189
- d.maxLineChanged = false;
190
-
191
- // Used for measuring wheel scrolling granularity
192
- d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
193
-
194
- return d;
195
- }
196
-
197
- // STATE UPDATES
198
-
199
- // Used to get the editor into a consistent state again when options change.
200
-
201
- function loadMode(cm) {
202
- cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
203
- cm.doc.iter(function(line) {
204
- if (line.stateAfter) line.stateAfter = null;
205
- if (line.styles) line.styles = null;
206
- });
207
- cm.doc.frontier = cm.doc.first;
208
- startWorker(cm, 100);
209
- cm.state.modeGen++;
210
- if (cm.curOp) regChange(cm);
211
- }
212
-
213
- function wrappingChanged(cm) {
214
- if (cm.options.lineWrapping) {
215
- cm.display.wrapper.className += " CodeMirror-wrap";
216
- cm.display.sizer.style.minWidth = "";
217
- } else {
218
- cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
219
- computeMaxLength(cm);
220
- }
221
- estimateLineHeights(cm);
222
- regChange(cm);
223
- clearCaches(cm);
224
- setTimeout(function(){updateScrollbars(cm);}, 100);
225
- }
226
-
227
- function estimateHeight(cm) {
228
- var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
229
- var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
230
- return function(line) {
231
- if (lineIsHidden(cm.doc, line))
232
- return 0;
233
- else if (wrapping)
234
- return (Math.ceil(line.text.length / perLine) || 1) * th;
235
- else
236
- return th;
237
- };
238
- }
239
-
240
- function estimateLineHeights(cm) {
241
- var doc = cm.doc, est = estimateHeight(cm);
242
- doc.iter(function(line) {
243
- var estHeight = est(line);
244
- if (estHeight != line.height) updateLineHeight(line, estHeight);
245
- });
246
- }
247
-
248
- function keyMapChanged(cm) {
249
- var map = keyMap[cm.options.keyMap], style = map.style;
250
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
251
- (style ? " cm-keymap-" + style : "");
252
- cm.state.disableInput = map.disableInput;
253
- }
254
-
255
- function themeChanged(cm) {
256
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
257
- cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
258
- clearCaches(cm);
259
- }
260
-
261
- function guttersChanged(cm) {
262
- updateGutters(cm);
263
- regChange(cm);
264
- setTimeout(function(){alignHorizontally(cm);}, 20);
265
- }
266
-
267
- function updateGutters(cm) {
268
- var gutters = cm.display.gutters, specs = cm.options.gutters;
269
- removeChildren(gutters);
270
- for (var i = 0; i < specs.length; ++i) {
271
- var gutterClass = specs[i];
272
- var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
273
- if (gutterClass == "CodeMirror-linenumbers") {
274
- cm.display.lineGutter = gElt;
275
- gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
276
- }
277
- }
278
- gutters.style.display = i ? "" : "none";
279
- }
280
-
281
- function lineLength(doc, line) {
282
- if (line.height == 0) return 0;
283
- var len = line.text.length, merged, cur = line;
284
- while (merged = collapsedSpanAtStart(cur)) {
285
- var found = merged.find();
286
- cur = getLine(doc, found.from.line);
287
- len += found.from.ch - found.to.ch;
288
- }
289
- cur = line;
290
- while (merged = collapsedSpanAtEnd(cur)) {
291
- var found = merged.find();
292
- len -= cur.text.length - found.from.ch;
293
- cur = getLine(doc, found.to.line);
294
- len += cur.text.length - found.to.ch;
295
- }
296
- return len;
297
- }
298
-
299
- function computeMaxLength(cm) {
300
- var d = cm.display, doc = cm.doc;
301
- d.maxLine = getLine(doc, doc.first);
302
- d.maxLineLength = lineLength(doc, d.maxLine);
303
- d.maxLineChanged = true;
304
- doc.iter(function(line) {
305
- var len = lineLength(doc, line);
306
- if (len > d.maxLineLength) {
307
- d.maxLineLength = len;
308
- d.maxLine = line;
309
- }
310
- });
311
- }
312
-
313
- // Make sure the gutters options contains the element
314
- // "CodeMirror-linenumbers" when the lineNumbers option is true.
315
- function setGuttersForLineNumbers(options) {
316
- var found = false;
317
- for (var i = 0; i < options.gutters.length; ++i) {
318
- if (options.gutters[i] == "CodeMirror-linenumbers") {
319
- if (options.lineNumbers) found = true;
320
- else options.gutters.splice(i--, 1);
321
- }
322
- }
323
- if (!found && options.lineNumbers)
324
- options.gutters.push("CodeMirror-linenumbers");
325
- }
326
-
327
- // SCROLLBARS
328
-
329
- // Re-synchronize the fake scrollbars with the actual size of the
330
- // content. Optionally force a scrollTop.
331
- function updateScrollbars(cm) {
332
- var d = cm.display, docHeight = cm.doc.height;
333
- var totalHeight = docHeight + paddingVert(d);
334
- d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
335
- d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
336
- var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
337
- var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
338
- var needsV = scrollHeight > (d.scroller.clientHeight + 1);
339
- if (needsV) {
340
- d.scrollbarV.style.display = "block";
341
- d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
342
- d.scrollbarV.firstChild.style.height =
343
- (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
344
- } else d.scrollbarV.style.display = "";
345
- if (needsH) {
346
- d.scrollbarH.style.display = "block";
347
- d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
348
- d.scrollbarH.firstChild.style.width =
349
- (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
350
- } else d.scrollbarH.style.display = "";
351
- if (needsH && needsV) {
352
- d.scrollbarFiller.style.display = "block";
353
- d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
354
- } else d.scrollbarFiller.style.display = "";
355
- if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
356
- d.gutterFiller.style.display = "block";
357
- d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
358
- d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
359
- } else d.gutterFiller.style.display = "";
360
-
361
- if (mac_geLion && scrollbarWidth(d.measure) === 0)
362
- d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
363
- }
364
-
365
- function visibleLines(display, doc, viewPort) {
366
- var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
367
- if (typeof viewPort == "number") top = viewPort;
368
- else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
369
- top = Math.floor(top - paddingTop(display));
370
- var bottom = Math.ceil(top + height);
371
- return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
372
- }
373
-
374
- // LINE NUMBERS
375
-
376
- function alignHorizontally(cm) {
377
- var display = cm.display;
378
- if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
379
- var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
380
- var gutterW = display.gutters.offsetWidth, l = comp + "px";
381
- for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
382
- for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
383
- }
384
- if (cm.options.fixedGutter)
385
- display.gutters.style.left = (comp + gutterW) + "px";
386
- }
387
-
388
- function maybeUpdateLineNumberWidth(cm) {
389
- if (!cm.options.lineNumbers) return false;
390
- var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
391
- if (last.length != display.lineNumChars) {
392
- var test = display.measure.appendChild(elt("div", [elt("div", last)],
393
- "CodeMirror-linenumber CodeMirror-gutter-elt"));
394
- var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
395
- display.lineGutter.style.width = "";
396
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
397
- display.lineNumWidth = display.lineNumInnerWidth + padding;
398
- display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
399
- display.lineGutter.style.width = display.lineNumWidth + "px";
400
- return true;
401
- }
402
- return false;
403
- }
404
-
405
- function lineNumberFor(options, i) {
406
- return String(options.lineNumberFormatter(i + options.firstLineNumber));
407
- }
408
- function compensateForHScroll(display) {
409
- return getRect(display.scroller).left - getRect(display.sizer).left;
410
- }
411
-
412
- // DISPLAY DRAWING
413
-
414
- function updateDisplay(cm, changes, viewPort, forced) {
415
- var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
416
- var visible = visibleLines(cm.display, cm.doc, viewPort);
417
- for (;;) {
418
- if (!updateDisplayInner(cm, changes, visible, forced)) break;
419
- forced = false;
420
- updated = true;
421
- updateSelection(cm);
422
- updateScrollbars(cm);
423
-
424
- // Clip forced viewport to actual scrollable area
425
- if (viewPort)
426
- viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
427
- typeof viewPort == "number" ? viewPort : viewPort.top);
428
- visible = visibleLines(cm.display, cm.doc, viewPort);
429
- if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
430
- break;
431
- changes = [];
432
- }
433
-
434
- if (updated) {
435
- signalLater(cm, "update", cm);
436
- if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
437
- signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
438
- }
439
- return updated;
440
- }
441
-
442
- // Uses a set of changes plus the current scroll position to
443
- // determine which DOM updates have to be made, and makes the
444
- // updates.
445
- function updateDisplayInner(cm, changes, visible, forced) {
446
- var display = cm.display, doc = cm.doc;
447
- if (!display.wrapper.clientWidth) {
448
- display.showingFrom = display.showingTo = doc.first;
449
- display.viewOffset = 0;
450
- return;
451
- }
452
-
453
- // Bail out if the visible area is already rendered and nothing changed.
454
- if (!forced && changes.length == 0 &&
455
- visible.from > display.showingFrom && visible.to < display.showingTo)
456
- return;
457
-
458
- if (maybeUpdateLineNumberWidth(cm))
459
- changes = [{from: doc.first, to: doc.first + doc.size}];
460
- var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
461
- display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
462
-
463
- // Used to determine which lines need their line numbers updated
464
- var positionsChangedFrom = Infinity;
465
- if (cm.options.lineNumbers)
466
- for (var i = 0; i < changes.length; ++i)
467
- if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
468
-
469
- var end = doc.first + doc.size;
470
- var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
471
- var to = Math.min(end, visible.to + cm.options.viewportMargin);
472
- if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
473
- if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
474
- if (sawCollapsedSpans) {
475
- from = lineNo(visualLine(doc, getLine(doc, from)));
476
- while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
477
- }
478
-
479
- // Create a range of theoretically intact lines, and punch holes
480
- // in that using the change info.
481
- var intact = [{from: Math.max(display.showingFrom, doc.first),
482
- to: Math.min(display.showingTo, end)}];
483
- if (intact[0].from >= intact[0].to) intact = [];
484
- else intact = computeIntact(intact, changes);
485
- // When merged lines are present, we might have to reduce the
486
- // intact ranges because changes in continued fragments of the
487
- // intact lines do require the lines to be redrawn.
488
- if (sawCollapsedSpans)
489
- for (var i = 0; i < intact.length; ++i) {
490
- var range = intact[i], merged;
491
- while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
492
- var newTo = merged.find().from.line;
493
- if (newTo > range.from) range.to = newTo;
494
- else { intact.splice(i--, 1); break; }
495
- }
496
- }
497
-
498
- // Clip off the parts that won't be visible
499
- var intactLines = 0;
500
- for (var i = 0; i < intact.length; ++i) {
501
- var range = intact[i];
502
- if (range.from < from) range.from = from;
503
- if (range.to > to) range.to = to;
504
- if (range.from >= range.to) intact.splice(i--, 1);
505
- else intactLines += range.to - range.from;
506
- }
507
- if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
508
- updateViewOffset(cm);
509
- return;
510
- }
511
- intact.sort(function(a, b) {return a.from - b.from;});
512
-
513
- // Avoid crashing on IE's "unspecified error" when in iframes
514
- try {
515
- var focused = document.activeElement;
516
- } catch(e) {}
517
- if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
518
- patchDisplay(cm, from, to, intact, positionsChangedFrom);
519
- display.lineDiv.style.display = "";
520
- if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
521
-
522
- var different = from != display.showingFrom || to != display.showingTo ||
523
- display.lastSizeC != display.wrapper.clientHeight;
524
- // This is just a bogus formula that detects when the editor is
525
- // resized or the font size changes.
526
- if (different) {
527
- display.lastSizeC = display.wrapper.clientHeight;
528
- startWorker(cm, 400);
529
- }
530
- display.showingFrom = from; display.showingTo = to;
531
-
532
- updateHeightsInViewport(cm);
533
- updateViewOffset(cm);
534
-
535
- return true;
536
- }
537
-
538
- function updateHeightsInViewport(cm) {
539
- var display = cm.display;
540
- var prevBottom = display.lineDiv.offsetTop;
541
- for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
542
- if (ie_lt8) {
543
- var bot = node.offsetTop + node.offsetHeight;
544
- height = bot - prevBottom;
545
- prevBottom = bot;
546
- } else {
547
- var box = getRect(node);
548
- height = box.bottom - box.top;
549
- }
550
- var diff = node.lineObj.height - height;
551
- if (height < 2) height = textHeight(display);
552
- if (diff > .001 || diff < -.001) {
553
- updateLineHeight(node.lineObj, height);
554
- var widgets = node.lineObj.widgets;
555
- if (widgets) for (var i = 0; i < widgets.length; ++i)
556
- widgets[i].height = widgets[i].node.offsetHeight;
557
- }
558
- }
559
- }
560
-
561
- function updateViewOffset(cm) {
562
- var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
563
- // Position the mover div to align with the current virtual scroll position
564
- cm.display.mover.style.top = off + "px";
565
- }
566
-
567
- function computeIntact(intact, changes) {
568
- for (var i = 0, l = changes.length || 0; i < l; ++i) {
569
- var change = changes[i], intact2 = [], diff = change.diff || 0;
570
- for (var j = 0, l2 = intact.length; j < l2; ++j) {
571
- var range = intact[j];
572
- if (change.to <= range.from && change.diff) {
573
- intact2.push({from: range.from + diff, to: range.to + diff});
574
- } else if (change.to <= range.from || change.from >= range.to) {
575
- intact2.push(range);
576
- } else {
577
- if (change.from > range.from)
578
- intact2.push({from: range.from, to: change.from});
579
- if (change.to < range.to)
580
- intact2.push({from: change.to + diff, to: range.to + diff});
581
- }
582
- }
583
- intact = intact2;
584
- }
585
- return intact;
586
- }
587
-
588
- function getDimensions(cm) {
589
- var d = cm.display, left = {}, width = {};
590
- for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
591
- left[cm.options.gutters[i]] = n.offsetLeft;
592
- width[cm.options.gutters[i]] = n.offsetWidth;
593
- }
594
- return {fixedPos: compensateForHScroll(d),
595
- gutterTotalWidth: d.gutters.offsetWidth,
596
- gutterLeft: left,
597
- gutterWidth: width,
598
- wrapperWidth: d.wrapper.clientWidth};
599
- }
600
-
601
- function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
602
- var dims = getDimensions(cm);
603
- var display = cm.display, lineNumbers = cm.options.lineNumbers;
604
- if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
605
- removeChildren(display.lineDiv);
606
- var container = display.lineDiv, cur = container.firstChild;
607
-
608
- function rm(node) {
609
- var next = node.nextSibling;
610
- if (webkit && mac && cm.display.currentWheelTarget == node) {
611
- node.style.display = "none";
612
- node.lineObj = null;
613
- } else {
614
- node.parentNode.removeChild(node);
615
- }
616
- return next;
617
- }
618
-
619
- var nextIntact = intact.shift(), lineN = from;
620
- cm.doc.iter(from, to, function(line) {
621
- if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
622
- if (lineIsHidden(cm.doc, line)) {
623
- if (line.height != 0) updateLineHeight(line, 0);
624
- if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
625
- var w = line.widgets[i];
626
- if (w.showIfHidden) {
627
- var prev = cur.previousSibling;
628
- if (/pre/i.test(prev.nodeName)) {
629
- var wrap = elt("div", null, null, "position: relative");
630
- prev.parentNode.replaceChild(wrap, prev);
631
- wrap.appendChild(prev);
632
- prev = wrap;
633
- }
634
- var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
635
- if (!w.handleMouseEvents) wnode.ignoreEvents = true;
636
- positionLineWidget(w, wnode, prev, dims);
637
- }
638
- }
639
- } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
640
- // This line is intact. Skip to the actual node. Update its
641
- // line number if needed.
642
- while (cur.lineObj != line) cur = rm(cur);
643
- if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
644
- setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
645
- cur = cur.nextSibling;
646
- } else {
647
- // For lines with widgets, make an attempt to find and reuse
648
- // the existing element, so that widgets aren't needlessly
649
- // removed and re-inserted into the dom
650
- if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
651
- if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
652
- // This line needs to be generated.
653
- var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
654
- if (lineNode != reuse) {
655
- container.insertBefore(lineNode, cur);
656
- } else {
657
- while (cur != reuse) cur = rm(cur);
658
- cur = cur.nextSibling;
659
- }
660
-
661
- lineNode.lineObj = line;
662
- }
663
- ++lineN;
664
- });
665
- while (cur) cur = rm(cur);
666
- }
667
-
668
- function buildLineElement(cm, line, lineNo, dims, reuse) {
669
- var lineElement = lineContent(cm, line);
670
- var markers = line.gutterMarkers, display = cm.display, wrap;
671
-
672
- if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
673
- return lineElement;
674
-
675
- // Lines with gutter elements, widgets or a background class need
676
- // to be wrapped again, and have the extra elements added to the
677
- // wrapper div
678
-
679
- if (reuse) {
680
- reuse.alignable = null;
681
- var isOk = true, widgetsSeen = 0, insertBefore = null;
682
- for (var n = reuse.firstChild, next; n; n = next) {
683
- next = n.nextSibling;
684
- if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
685
- reuse.removeChild(n);
686
- } else {
687
- for (var i = 0; i < line.widgets.length; ++i) {
688
- var widget = line.widgets[i];
689
- if (widget.node == n.firstChild) {
690
- if (!widget.above && !insertBefore) insertBefore = n;
691
- positionLineWidget(widget, n, reuse, dims);
692
- ++widgetsSeen;
693
- break;
694
- }
695
- }
696
- if (i == line.widgets.length) { isOk = false; break; }
697
- }
698
- }
699
- reuse.insertBefore(lineElement, insertBefore);
700
- if (isOk && widgetsSeen == line.widgets.length) {
701
- wrap = reuse;
702
- reuse.className = line.wrapClass || "";
703
- }
704
- }
705
- if (!wrap) {
706
- wrap = elt("div", null, line.wrapClass, "position: relative");
707
- wrap.appendChild(lineElement);
708
- }
709
- // Kludge to make sure the styled element lies behind the selection (by z-index)
710
- if (line.bgClass)
711
- wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
712
- if (cm.options.lineNumbers || markers) {
713
- var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
714
- (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
715
- wrap.firstChild);
716
- if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
717
- if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
718
- wrap.lineNumber = gutterWrap.appendChild(
719
- elt("div", lineNumberFor(cm.options, lineNo),
720
- "CodeMirror-linenumber CodeMirror-gutter-elt",
721
- "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
722
- + display.lineNumInnerWidth + "px"));
723
- if (markers)
724
- for (var k = 0; k < cm.options.gutters.length; ++k) {
725
- var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
726
- if (found)
727
- gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
728
- dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
729
- }
730
- }
731
- if (ie_lt8) wrap.style.zIndex = 2;
732
- if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
733
- var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
734
- if (!widget.handleMouseEvents) node.ignoreEvents = true;
735
- positionLineWidget(widget, node, wrap, dims);
736
- if (widget.above)
737
- wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
738
- else
739
- wrap.appendChild(node);
740
- signalLater(widget, "redraw");
741
- }
742
- return wrap;
743
- }
744
-
745
- function positionLineWidget(widget, node, wrap, dims) {
746
- if (widget.noHScroll) {
747
- (wrap.alignable || (wrap.alignable = [])).push(node);
748
- var width = dims.wrapperWidth;
749
- node.style.left = dims.fixedPos + "px";
750
- if (!widget.coverGutter) {
751
- width -= dims.gutterTotalWidth;
752
- node.style.paddingLeft = dims.gutterTotalWidth + "px";
753
- }
754
- node.style.width = width + "px";
755
- }
756
- if (widget.coverGutter) {
757
- node.style.zIndex = 5;
758
- node.style.position = "relative";
759
- if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
760
- }
761
- }
762
-
763
- // SELECTION / CURSOR
764
-
765
- function updateSelection(cm) {
766
- var display = cm.display;
767
- var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
768
- if (collapsed || cm.options.showCursorWhenSelecting)
769
- updateSelectionCursor(cm);
770
- else
771
- display.cursor.style.display = display.otherCursor.style.display = "none";
772
- if (!collapsed)
773
- updateSelectionRange(cm);
774
- else
775
- display.selectionDiv.style.display = "none";
776
-
777
- // Move the hidden textarea near the cursor to prevent scrolling artifacts
778
- if (cm.options.moveInputWithCursor) {
779
- var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
780
- var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
781
- display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
782
- headPos.top + lineOff.top - wrapOff.top)) + "px";
783
- display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
784
- headPos.left + lineOff.left - wrapOff.left)) + "px";
785
- }
786
- }
787
-
788
- // No selection, plain cursor
789
- function updateSelectionCursor(cm) {
790
- var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
791
- display.cursor.style.left = pos.left + "px";
792
- display.cursor.style.top = pos.top + "px";
793
- display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
794
- display.cursor.style.display = "";
795
-
796
- if (pos.other) {
797
- display.otherCursor.style.display = "";
798
- display.otherCursor.style.left = pos.other.left + "px";
799
- display.otherCursor.style.top = pos.other.top + "px";
800
- display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
801
- } else { display.otherCursor.style.display = "none"; }
802
- }
803
-
804
- // Highlight selection
805
- function updateSelectionRange(cm) {
806
- var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
807
- var fragment = document.createDocumentFragment();
808
- var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
809
-
810
- function add(left, top, width, bottom) {
811
- if (top < 0) top = 0;
812
- fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
813
- "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
814
- "px; height: " + (bottom - top) + "px"));
815
- }
816
-
817
- function drawForLine(line, fromArg, toArg) {
818
- var lineObj = getLine(doc, line);
819
- var lineLen = lineObj.text.length;
820
- var start, end;
821
- function coords(ch, bias) {
822
- return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
823
- }
824
-
825
- iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
826
- var leftPos = coords(from, "left"), rightPos, left, right;
827
- if (from == to) {
828
- rightPos = leftPos;
829
- left = right = leftPos.left;
830
- } else {
831
- rightPos = coords(to - 1, "right");
832
- if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
833
- left = leftPos.left;
834
- right = rightPos.right;
835
- }
836
- if (fromArg == null && from == 0) left = pl;
837
- if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
838
- add(left, leftPos.top, null, leftPos.bottom);
839
- left = pl;
840
- if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
841
- }
842
- if (toArg == null && to == lineLen) right = clientWidth;
843
- if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
844
- start = leftPos;
845
- if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
846
- end = rightPos;
847
- if (left < pl + 1) left = pl;
848
- add(left, rightPos.top, right - left, rightPos.bottom);
849
- });
850
- return {start: start, end: end};
851
- }
852
-
853
- if (sel.from.line == sel.to.line) {
854
- drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
855
- } else {
856
- var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
857
- var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
858
- var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
859
- var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
860
- if (singleVLine) {
861
- if (leftEnd.top < rightStart.top - 2) {
862
- add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
863
- add(pl, rightStart.top, rightStart.left, rightStart.bottom);
864
- } else {
865
- add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
866
- }
867
- }
868
- if (leftEnd.bottom < rightStart.top)
869
- add(pl, leftEnd.bottom, null, rightStart.top);
870
- }
871
-
872
- removeChildrenAndAdd(display.selectionDiv, fragment);
873
- display.selectionDiv.style.display = "";
874
- }
875
-
876
- // Cursor-blinking
877
- function restartBlink(cm) {
878
- if (!cm.state.focused) return;
879
- var display = cm.display;
880
- clearInterval(display.blinker);
881
- var on = true;
882
- display.cursor.style.visibility = display.otherCursor.style.visibility = "";
883
- display.blinker = setInterval(function() {
884
- display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
885
- }, cm.options.cursorBlinkRate);
886
- }
887
-
888
- // HIGHLIGHT WORKER
889
-
890
- function startWorker(cm, time) {
891
- if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
892
- cm.state.highlight.set(time, bind(highlightWorker, cm));
893
- }
894
-
895
- function highlightWorker(cm) {
896
- var doc = cm.doc;
897
- if (doc.frontier < doc.first) doc.frontier = doc.first;
898
- if (doc.frontier >= cm.display.showingTo) return;
899
- var end = +new Date + cm.options.workTime;
900
- var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
901
- var changed = [], prevChange;
902
- doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
903
- if (doc.frontier >= cm.display.showingFrom) { // Visible
904
- var oldStyles = line.styles;
905
- line.styles = highlightLine(cm, line, state);
906
- var ischange = !oldStyles || oldStyles.length != line.styles.length;
907
- for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
908
- if (ischange) {
909
- if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
910
- else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
911
- }
912
- line.stateAfter = copyState(doc.mode, state);
913
- } else {
914
- processLine(cm, line, state);
915
- line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
916
- }
917
- ++doc.frontier;
918
- if (+new Date > end) {
919
- startWorker(cm, cm.options.workDelay);
920
- return true;
921
- }
922
- });
923
- if (changed.length)
924
- operation(cm, function() {
925
- for (var i = 0; i < changed.length; ++i)
926
- regChange(this, changed[i].start, changed[i].end);
927
- })();
928
- }
929
-
930
- // Finds the line to start with when starting a parse. Tries to
931
- // find a line with a stateAfter, so that it can start with a
932
- // valid state. If that fails, it returns the line with the
933
- // smallest indentation, which tends to need the least context to
934
- // parse correctly.
935
- function findStartLine(cm, n, precise) {
936
- var minindent, minline, doc = cm.doc;
937
- for (var search = n, lim = n - 100; search > lim; --search) {
938
- if (search <= doc.first) return doc.first;
939
- var line = getLine(doc, search - 1);
940
- if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
941
- var indented = countColumn(line.text, null, cm.options.tabSize);
942
- if (minline == null || minindent > indented) {
943
- minline = search - 1;
944
- minindent = indented;
945
- }
946
- }
947
- return minline;
948
- }
949
-
950
- function getStateBefore(cm, n, precise) {
951
- var doc = cm.doc, display = cm.display;
952
- if (!doc.mode.startState) return true;
953
- var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
954
- if (!state) state = startState(doc.mode);
955
- else state = copyState(doc.mode, state);
956
- doc.iter(pos, n, function(line) {
957
- processLine(cm, line, state);
958
- var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
959
- line.stateAfter = save ? copyState(doc.mode, state) : null;
960
- ++pos;
961
- });
962
- return state;
963
- }
964
-
965
- // POSITION MEASUREMENT
966
-
967
- function paddingTop(display) {return display.lineSpace.offsetTop;}
968
- function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
969
- function paddingLeft(display) {
970
- var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
971
- return e.offsetLeft;
972
- }
973
-
974
- function measureChar(cm, line, ch, data, bias) {
975
- var dir = -1;
976
- data = data || measureLine(cm, line);
977
-
978
- for (var pos = ch;; pos += dir) {
979
- var r = data[pos];
980
- if (r) break;
981
- if (dir < 0 && pos == 0) dir = 1;
982
- }
983
- bias = pos > ch ? "left" : pos < ch ? "right" : bias;
984
- if (bias == "left" && r.leftSide) r = r.leftSide;
985
- else if (bias == "right" && r.rightSide) r = r.rightSide;
986
- return {left: pos < ch ? r.right : r.left,
987
- right: pos > ch ? r.left : r.right,
988
- top: r.top,
989
- bottom: r.bottom};
990
- }
991
-
992
- function findCachedMeasurement(cm, line) {
993
- var cache = cm.display.measureLineCache;
994
- for (var i = 0; i < cache.length; ++i) {
995
- var memo = cache[i];
996
- if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
997
- cm.display.scroller.clientWidth == memo.width &&
998
- memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
999
- return memo;
1000
- }
1001
- }
1002
-
1003
- function clearCachedMeasurement(cm, line) {
1004
- var exists = findCachedMeasurement(cm, line);
1005
- if (exists) exists.text = exists.measure = exists.markedSpans = null;
1006
- }
1007
-
1008
- function measureLine(cm, line) {
1009
- // First look in the cache
1010
- var cached = findCachedMeasurement(cm, line);
1011
- if (cached) return cached.measure;
1012
-
1013
- // Failing that, recompute and store result in cache
1014
- var measure = measureLineInner(cm, line);
1015
- var cache = cm.display.measureLineCache;
1016
- var memo = {text: line.text, width: cm.display.scroller.clientWidth,
1017
- markedSpans: line.markedSpans, measure: measure,
1018
- classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
1019
- if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1020
- else cache.push(memo);
1021
- return measure;
1022
- }
1023
-
1024
- function measureLineInner(cm, line) {
1025
- var display = cm.display, measure = emptyArray(line.text.length);
1026
- var pre = lineContent(cm, line, measure, true);
1027
-
1028
- // IE does not cache element positions of inline elements between
1029
- // calls to getBoundingClientRect. This makes the loop below,
1030
- // which gathers the positions of all the characters on the line,
1031
- // do an amount of layout work quadratic to the number of
1032
- // characters. When line wrapping is off, we try to improve things
1033
- // by first subdividing the line into a bunch of inline blocks, so
1034
- // that IE can reuse most of the layout information from caches
1035
- // for those blocks. This does interfere with line wrapping, so it
1036
- // doesn't work when wrapping is on, but in that case the
1037
- // situation is slightly better, since IE does cache line-wrapping
1038
- // information and only recomputes per-line.
1039
- if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1040
- var fragment = document.createDocumentFragment();
1041
- var chunk = 10, n = pre.childNodes.length;
1042
- for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
1043
- var wrap = elt("div", null, null, "display: inline-block");
1044
- for (var j = 0; j < chunk && n; ++j) {
1045
- wrap.appendChild(pre.firstChild);
1046
- --n;
1047
- }
1048
- fragment.appendChild(wrap);
1049
- }
1050
- pre.appendChild(fragment);
1051
- }
1052
-
1053
- removeChildrenAndAdd(display.measure, pre);
1054
-
1055
- var outer = getRect(display.lineDiv);
1056
- var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
1057
- // Work around an IE7/8 bug where it will sometimes have randomly
1058
- // replaced our pre with a clone at this point.
1059
- if (ie_lt9 && display.measure.first != pre)
1060
- removeChildrenAndAdd(display.measure, pre);
1061
-
1062
- function measureRect(rect) {
1063
- var top = rect.top - outer.top, bot = rect.bottom - outer.top;
1064
- if (bot > maxBot) bot = maxBot;
1065
- if (top < 0) top = 0;
1066
- for (var i = vranges.length - 2; i >= 0; i -= 2) {
1067
- var rtop = vranges[i], rbot = vranges[i+1];
1068
- if (rtop > bot || rbot < top) continue;
1069
- if (rtop <= top && rbot >= bot ||
1070
- top <= rtop && bot >= rbot ||
1071
- Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1072
- vranges[i] = Math.min(top, rtop);
1073
- vranges[i+1] = Math.max(bot, rbot);
1074
- break;
1075
- }
1076
- }
1077
- if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1078
- return {left: rect.left - outer.left,
1079
- right: rect.right - outer.left,
1080
- top: i, bottom: null};
1081
- }
1082
- function finishRect(rect) {
1083
- rect.bottom = vranges[rect.top+1];
1084
- rect.top = vranges[rect.top];
1085
- }
1086
-
1087
- for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1088
- var node = cur, rect = null;
1089
- // A widget might wrap, needs special care
1090
- if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1091
- if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1092
- var rects = node.getClientRects();
1093
- if (rects.length > 1) {
1094
- rect = data[i] = measureRect(rects[0]);
1095
- rect.rightSide = measureRect(rects[rects.length - 1]);
1096
- }
1097
- }
1098
- if (!rect) rect = data[i] = measureRect(getRect(node));
1099
- if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1100
- if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1101
- }
1102
- for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1103
- finishRect(cur);
1104
- if (cur.leftSide) finishRect(cur.leftSide);
1105
- if (cur.rightSide) finishRect(cur.rightSide);
1106
- }
1107
- return data;
1108
- }
1109
-
1110
- function measureLineWidth(cm, line) {
1111
- var hasBadSpan = false;
1112
- if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
1113
- var sp = line.markedSpans[i];
1114
- if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1115
- }
1116
- var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1117
- if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1118
-
1119
- var pre = lineContent(cm, line, null, true);
1120
- var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1121
- removeChildrenAndAdd(cm.display.measure, pre);
1122
- return getRect(end).right - getRect(cm.display.lineDiv).left;
1123
- }
1124
-
1125
- function clearCaches(cm) {
1126
- cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
1127
- cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
1128
- if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
1129
- cm.display.lineNumChars = null;
1130
- }
1131
-
1132
- function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
1133
- function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
1134
-
1135
- // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1136
- function intoCoordSystem(cm, lineObj, rect, context) {
1137
- if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1138
- var size = widgetHeight(lineObj.widgets[i]);
1139
- rect.top += size; rect.bottom += size;
1140
- }
1141
- if (context == "line") return rect;
1142
- if (!context) context = "local";
1143
- var yOff = heightAtLine(cm, lineObj);
1144
- if (context == "local") yOff += paddingTop(cm.display);
1145
- else yOff -= cm.display.viewOffset;
1146
- if (context == "page" || context == "window") {
1147
- var lOff = getRect(cm.display.lineSpace);
1148
- yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1149
- var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1150
- rect.left += xOff; rect.right += xOff;
1151
- }
1152
- rect.top += yOff; rect.bottom += yOff;
1153
- return rect;
1154
- }
1155
-
1156
- // Context may be "window", "page", "div", or "local"/null
1157
- // Result is in "div" coords
1158
- function fromCoordSystem(cm, coords, context) {
1159
- if (context == "div") return coords;
1160
- var left = coords.left, top = coords.top;
1161
- // First move into "page" coordinate system
1162
- if (context == "page") {
1163
- left -= pageScrollX();
1164
- top -= pageScrollY();
1165
- } else if (context == "local" || !context) {
1166
- var localBox = getRect(cm.display.sizer);
1167
- left += localBox.left;
1168
- top += localBox.top;
1169
- }
1170
-
1171
- var lineSpaceBox = getRect(cm.display.lineSpace);
1172
- return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1173
- }
1174
-
1175
- function charCoords(cm, pos, context, lineObj, bias) {
1176
- if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1177
- return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
1178
- }
1179
-
1180
- function cursorCoords(cm, pos, context, lineObj, measurement) {
1181
- lineObj = lineObj || getLine(cm.doc, pos.line);
1182
- if (!measurement) measurement = measureLine(cm, lineObj);
1183
- function get(ch, right) {
1184
- var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
1185
- if (right) m.left = m.right; else m.right = m.left;
1186
- return intoCoordSystem(cm, lineObj, m, context);
1187
- }
1188
- function getBidi(ch, partPos) {
1189
- var part = order[partPos], right = part.level % 2;
1190
- if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
1191
- part = order[--partPos];
1192
- ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
1193
- right = true;
1194
- } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
1195
- part = order[++partPos];
1196
- ch = bidiLeft(part) - part.level % 2;
1197
- right = false;
1198
- }
1199
- if (right && ch == part.to && ch > part.from) return get(ch - 1);
1200
- return get(ch, right);
1201
- }
1202
- var order = getOrder(lineObj), ch = pos.ch;
1203
- if (!order) return get(ch);
1204
- var partPos = getBidiPartAt(order, ch);
1205
- var val = getBidi(ch, partPos);
1206
- if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1207
- return val;
1208
- }
1209
-
1210
- function PosWithInfo(line, ch, outside, xRel) {
1211
- var pos = new Pos(line, ch);
1212
- pos.xRel = xRel;
1213
- if (outside) pos.outside = true;
1214
- return pos;
1215
- }
1216
-
1217
- // Coords must be lineSpace-local
1218
- function coordsChar(cm, x, y) {
1219
- var doc = cm.doc;
1220
- y += cm.display.viewOffset;
1221
- if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1222
- var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1223
- if (lineNo > last)
1224
- return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
1225
- if (x < 0) x = 0;
1226
-
1227
- for (;;) {
1228
- var lineObj = getLine(doc, lineNo);
1229
- var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1230
- var merged = collapsedSpanAtEnd(lineObj);
1231
- var mergedPos = merged && merged.find();
1232
- if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1233
- lineNo = mergedPos.to.line;
1234
- else
1235
- return found;
1236
- }
1237
- }
1238
-
1239
- function coordsCharInner(cm, lineObj, lineNo, x, y) {
1240
- var innerOff = y - heightAtLine(cm, lineObj);
1241
- var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
1242
- var measurement = measureLine(cm, lineObj);
1243
-
1244
- function getX(ch) {
1245
- var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
1246
- lineObj, measurement);
1247
- wrongLine = true;
1248
- if (innerOff > sp.bottom) return sp.left - adjust;
1249
- else if (innerOff < sp.top) return sp.left + adjust;
1250
- else wrongLine = false;
1251
- return sp.left;
1252
- }
1253
-
1254
- var bidi = getOrder(lineObj), dist = lineObj.text.length;
1255
- var from = lineLeft(lineObj), to = lineRight(lineObj);
1256
- var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1257
-
1258
- if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
1259
- // Do a binary search between these bounds.
1260
- for (;;) {
1261
- if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1262
- var ch = x < fromX || x - fromX <= toX - x ? from : to;
1263
- var xDiff = x - (ch == from ? fromX : toX);
1264
- while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1265
- var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1266
- xDiff < 0 ? -1 : xDiff ? 1 : 0);
1267
- return pos;
1268
- }
1269
- var step = Math.ceil(dist / 2), middle = from + step;
1270
- if (bidi) {
1271
- middle = from;
1272
- for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
1273
- }
1274
- var middleX = getX(middle);
1275
- if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
1276
- else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
1277
- }
1278
- }
1279
-
1280
- var measureText;
1281
- function textHeight(display) {
1282
- if (display.cachedTextHeight != null) return display.cachedTextHeight;
1283
- if (measureText == null) {
1284
- measureText = elt("pre");
1285
- // Measure a bunch of lines, for browsers that compute
1286
- // fractional heights.
1287
- for (var i = 0; i < 49; ++i) {
1288
- measureText.appendChild(document.createTextNode("x"));
1289
- measureText.appendChild(elt("br"));
1290
- }
1291
- measureText.appendChild(document.createTextNode("x"));
1292
- }
1293
- removeChildrenAndAdd(display.measure, measureText);
1294
- var height = measureText.offsetHeight / 50;
1295
- if (height > 3) display.cachedTextHeight = height;
1296
- removeChildren(display.measure);
1297
- return height || 1;
1298
- }
1299
-
1300
- function charWidth(display) {
1301
- if (display.cachedCharWidth != null) return display.cachedCharWidth;
1302
- var anchor = elt("span", "x");
1303
- var pre = elt("pre", [anchor]);
1304
- removeChildrenAndAdd(display.measure, pre);
1305
- var width = anchor.offsetWidth;
1306
- if (width > 2) display.cachedCharWidth = width;
1307
- return width || 10;
1308
- }
1309
-
1310
- // OPERATIONS
1311
-
1312
- // Operations are used to wrap changes in such a way that each
1313
- // change won't have to update the cursor and display (which would
1314
- // be awkward, slow, and error-prone), but instead updates are
1315
- // batched and then all combined and executed at once.
1316
-
1317
- var nextOpId = 0;
1318
- function startOperation(cm) {
1319
- cm.curOp = {
1320
- // An array of ranges of lines that have to be updated. See
1321
- // updateDisplay.
1322
- changes: [],
1323
- forceUpdate: false,
1324
- updateInput: null,
1325
- userSelChange: null,
1326
- textChanged: null,
1327
- selectionChanged: false,
1328
- cursorActivity: false,
1329
- updateMaxLine: false,
1330
- updateScrollPos: false,
1331
- id: ++nextOpId
1332
- };
1333
- if (!delayedCallbackDepth++) delayedCallbacks = [];
1334
- }
1335
-
1336
- function endOperation(cm) {
1337
- var op = cm.curOp, doc = cm.doc, display = cm.display;
1338
- cm.curOp = null;
1339
-
1340
- if (op.updateMaxLine) computeMaxLength(cm);
1341
- if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
1342
- var width = measureLineWidth(cm, display.maxLine);
1343
- display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
1344
- display.maxLineChanged = false;
1345
- var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
1346
- if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
1347
- setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
1348
- }
1349
- var newScrollPos, updated;
1350
- if (op.updateScrollPos) {
1351
- newScrollPos = op.updateScrollPos;
1352
- } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
1353
- var coords = cursorCoords(cm, doc.sel.head);
1354
- newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
1355
- }
1356
- if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1357
- updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1358
- if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1359
- }
1360
- if (!updated && op.selectionChanged) updateSelection(cm);
1361
- if (op.updateScrollPos) {
1362
- display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
1363
- display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
1364
- alignHorizontally(cm);
1365
- if (op.scrollToPos)
1366
- scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
1367
- } else if (newScrollPos) {
1368
- scrollCursorIntoView(cm);
1369
- }
1370
- if (op.selectionChanged) restartBlink(cm);
1371
-
1372
- if (cm.state.focused && op.updateInput)
1373
- resetInput(cm, op.userSelChange);
1374
-
1375
- var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
1376
- if (hidden) for (var i = 0; i < hidden.length; ++i)
1377
- if (!hidden[i].lines.length) signal(hidden[i], "hide");
1378
- if (unhidden) for (var i = 0; i < unhidden.length; ++i)
1379
- if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
1380
-
1381
- var delayed;
1382
- if (!--delayedCallbackDepth) {
1383
- delayed = delayedCallbacks;
1384
- delayedCallbacks = null;
1385
- }
1386
- if (op.textChanged)
1387
- signal(cm, "change", cm, op.textChanged);
1388
- if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1389
- if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
1390
- }
1391
-
1392
- // Wraps a function in an operation. Returns the wrapped function.
1393
- function operation(cm1, f) {
1394
- return function() {
1395
- var cm = cm1 || this, withOp = !cm.curOp;
1396
- if (withOp) startOperation(cm);
1397
- try { var result = f.apply(cm, arguments); }
1398
- finally { if (withOp) endOperation(cm); }
1399
- return result;
1400
- };
1401
- }
1402
- function docOperation(f) {
1403
- return function() {
1404
- var withOp = this.cm && !this.cm.curOp, result;
1405
- if (withOp) startOperation(this.cm);
1406
- try { result = f.apply(this, arguments); }
1407
- finally { if (withOp) endOperation(this.cm); }
1408
- return result;
1409
- };
1410
- }
1411
- function runInOp(cm, f) {
1412
- var withOp = !cm.curOp, result;
1413
- if (withOp) startOperation(cm);
1414
- try { result = f(); }
1415
- finally { if (withOp) endOperation(cm); }
1416
- return result;
1417
- }
1418
-
1419
- function regChange(cm, from, to, lendiff) {
1420
- if (from == null) from = cm.doc.first;
1421
- if (to == null) to = cm.doc.first + cm.doc.size;
1422
- cm.curOp.changes.push({from: from, to: to, diff: lendiff});
1423
- }
1424
-
1425
- // INPUT HANDLING
1426
-
1427
- function slowPoll(cm) {
1428
- if (cm.display.pollingFast) return;
1429
- cm.display.poll.set(cm.options.pollInterval, function() {
1430
- readInput(cm);
1431
- if (cm.state.focused) slowPoll(cm);
1432
- });
1433
- }
1434
-
1435
- function fastPoll(cm) {
1436
- var missed = false;
1437
- cm.display.pollingFast = true;
1438
- function p() {
1439
- var changed = readInput(cm);
1440
- if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
1441
- else {cm.display.pollingFast = false; slowPoll(cm);}
1442
- }
1443
- cm.display.poll.set(20, p);
1444
- }
1445
-
1446
- // prevInput is a hack to work with IME. If we reset the textarea
1447
- // on every change, that breaks IME. So we look for changes
1448
- // compared to the previous content instead. (Modern browsers have
1449
- // events that indicate IME taking place, but these are not widely
1450
- // supported or compatible enough yet to rely on.)
1451
- function readInput(cm) {
1452
- var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1453
- if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1454
- var text = input.value;
1455
- if (text == prevInput && posEq(sel.from, sel.to)) return false;
1456
- if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1457
- resetInput(cm, true);
1458
- return false;
1459
- }
1460
-
1461
- var withOp = !cm.curOp;
1462
- if (withOp) startOperation(cm);
1463
- sel.shift = false;
1464
- var same = 0, l = Math.min(prevInput.length, text.length);
1465
- while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1466
- var from = sel.from, to = sel.to;
1467
- if (same < prevInput.length)
1468
- from = Pos(from.line, from.ch - (prevInput.length - same));
1469
- else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1470
- to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1471
-
1472
- var updateInput = cm.curOp.updateInput;
1473
- var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1474
- origin: cm.state.pasteIncoming ? "paste" : "+input"};
1475
- makeChange(cm.doc, changeEvent, "end");
1476
- cm.curOp.updateInput = updateInput;
1477
- signalLater(cm, "inputRead", cm, changeEvent);
1478
-
1479
- if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1480
- else cm.display.prevInput = text;
1481
- if (withOp) endOperation(cm);
1482
- cm.state.pasteIncoming = false;
1483
- return true;
1484
- }
1485
-
1486
- function resetInput(cm, user) {
1487
- var minimal, selected, doc = cm.doc;
1488
- if (!posEq(doc.sel.from, doc.sel.to)) {
1489
- cm.display.prevInput = "";
1490
- minimal = hasCopyEvent &&
1491
- (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
1492
- var content = minimal ? "-" : selected || cm.getSelection();
1493
- cm.display.input.value = content;
1494
- if (cm.state.focused) selectInput(cm.display.input);
1495
- if (ie && !ie_lt9) cm.display.inputHasSelection = content;
1496
- } else if (user) {
1497
- cm.display.prevInput = cm.display.input.value = "";
1498
- if (ie && !ie_lt9) cm.display.inputHasSelection = null;
1499
- }
1500
- cm.display.inaccurateSelection = minimal;
1501
- }
1502
-
1503
- function focusInput(cm) {
1504
- if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
1505
- cm.display.input.focus();
1506
- }
1507
-
1508
- function isReadOnly(cm) {
1509
- return cm.options.readOnly || cm.doc.cantEdit;
1510
- }
1511
-
1512
- // EVENT HANDLERS
1513
-
1514
- function registerEventHandlers(cm) {
1515
- var d = cm.display;
1516
- on(d.scroller, "mousedown", operation(cm, onMouseDown));
1517
- if (ie)
1518
- on(d.scroller, "dblclick", operation(cm, function(e) {
1519
- if (signalDOMEvent(cm, e)) return;
1520
- var pos = posFromMouse(cm, e);
1521
- if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1522
- e_preventDefault(e);
1523
- var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
1524
- extendSelection(cm.doc, word.from, word.to);
1525
- }));
1526
- else
1527
- on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1528
- on(d.lineSpace, "selectstart", function(e) {
1529
- if (!eventInWidget(d, e)) e_preventDefault(e);
1530
- });
1531
- // Gecko browsers fire contextmenu *after* opening the menu, at
1532
- // which point we can't mess with it anymore. Context menu is
1533
- // handled in onMouseDown for Gecko.
1534
- if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
1535
-
1536
- on(d.scroller, "scroll", function() {
1537
- if (d.scroller.clientHeight) {
1538
- setScrollTop(cm, d.scroller.scrollTop);
1539
- setScrollLeft(cm, d.scroller.scrollLeft, true);
1540
- signal(cm, "scroll", cm);
1541
- }
1542
- });
1543
- on(d.scrollbarV, "scroll", function() {
1544
- if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
1545
- });
1546
- on(d.scrollbarH, "scroll", function() {
1547
- if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
1548
- });
1549
-
1550
- on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
1551
- on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
1552
-
1553
- function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
1554
- on(d.scrollbarH, "mousedown", reFocus);
1555
- on(d.scrollbarV, "mousedown", reFocus);
1556
- // Prevent wrapper from ever scrolling
1557
- on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1558
-
1559
- var resizeTimer;
1560
- function onResize() {
1561
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
1562
- resizeTimer = null;
1563
- // Might be a text scaling operation, clear size caches.
1564
- d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1565
- clearCaches(cm);
1566
- runInOp(cm, bind(regChange, cm));
1567
- }, 100);
1568
- }
1569
- on(window, "resize", onResize);
1570
- // Above handler holds on to the editor and its data structures.
1571
- // Here we poll to unregister it when the editor is no longer in
1572
- // the document, so that it can be garbage-collected.
1573
- function unregister() {
1574
- for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
1575
- if (p) setTimeout(unregister, 5000);
1576
- else off(window, "resize", onResize);
1577
- }
1578
- setTimeout(unregister, 5000);
1579
-
1580
- on(d.input, "keyup", operation(cm, function(e) {
1581
- if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1582
- if (e.keyCode == 16) cm.doc.sel.shift = false;
1583
- }));
1584
- on(d.input, "input", bind(fastPoll, cm));
1585
- on(d.input, "keydown", operation(cm, onKeyDown));
1586
- on(d.input, "keypress", operation(cm, onKeyPress));
1587
- on(d.input, "focus", bind(onFocus, cm));
1588
- on(d.input, "blur", bind(onBlur, cm));
1589
-
1590
- function drag_(e) {
1591
- if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1592
- e_stop(e);
1593
- }
1594
- if (cm.options.dragDrop) {
1595
- on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
1596
- on(d.scroller, "dragenter", drag_);
1597
- on(d.scroller, "dragover", drag_);
1598
- on(d.scroller, "drop", operation(cm, onDrop));
1599
- }
1600
- on(d.scroller, "paste", function(e){
1601
- if (eventInWidget(d, e)) return;
1602
- focusInput(cm);
1603
- fastPoll(cm);
1604
- });
1605
- on(d.input, "paste", function() {
1606
- cm.state.pasteIncoming = true;
1607
- fastPoll(cm);
1608
- });
1609
-
1610
- function prepareCopy() {
1611
- if (d.inaccurateSelection) {
1612
- d.prevInput = "";
1613
- d.inaccurateSelection = false;
1614
- d.input.value = cm.getSelection();
1615
- selectInput(d.input);
1616
- }
1617
- }
1618
- on(d.input, "cut", prepareCopy);
1619
- on(d.input, "copy", prepareCopy);
1620
-
1621
- // Needed to handle Tab key in KHTML
1622
- if (khtml) on(d.sizer, "mouseup", function() {
1623
- if (document.activeElement == d.input) d.input.blur();
1624
- focusInput(cm);
1625
- });
1626
- }
1627
-
1628
- function eventInWidget(display, e) {
1629
- for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1630
- if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1631
- }
1632
- }
1633
-
1634
- function posFromMouse(cm, e, liberal) {
1635
- var display = cm.display;
1636
- if (!liberal) {
1637
- var target = e_target(e);
1638
- if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1639
- target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1640
- target == display.scrollbarFiller || target == display.gutterFiller) return null;
1641
- }
1642
- var x, y, space = getRect(display.lineSpace);
1643
- // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1644
- try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1645
- return coordsChar(cm, x - space.left, y - space.top);
1646
- }
1647
-
1648
- var lastClick, lastDoubleClick;
1649
- function onMouseDown(e) {
1650
- if (signalDOMEvent(this, e)) return;
1651
- var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1652
- sel.shift = e.shiftKey;
1653
-
1654
- if (eventInWidget(display, e)) {
1655
- if (!webkit) {
1656
- display.scroller.draggable = false;
1657
- setTimeout(function(){display.scroller.draggable = true;}, 100);
1658
- }
1659
- return;
1660
- }
1661
- if (clickInGutter(cm, e)) return;
1662
- var start = posFromMouse(cm, e);
1663
-
1664
- switch (e_button(e)) {
1665
- case 3:
1666
- if (captureMiddleClick) onContextMenu.call(cm, cm, e);
1667
- return;
1668
- case 2:
1669
- if (start) extendSelection(cm.doc, start);
1670
- setTimeout(bind(focusInput, cm), 20);
1671
- e_preventDefault(e);
1672
- return;
1673
- }
1674
- // For button 1, if it was clicked inside the editor
1675
- // (posFromMouse returning non-null), we have to adjust the
1676
- // selection.
1677
- if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
1678
-
1679
- if (!cm.state.focused) onFocus(cm);
1680
-
1681
- var now = +new Date, type = "single";
1682
- if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
1683
- type = "triple";
1684
- e_preventDefault(e);
1685
- setTimeout(bind(focusInput, cm), 20);
1686
- selectLine(cm, start.line);
1687
- } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
1688
- type = "double";
1689
- lastDoubleClick = {time: now, pos: start};
1690
- e_preventDefault(e);
1691
- var word = findWordAt(getLine(doc, start.line).text, start);
1692
- extendSelection(cm.doc, word.from, word.to);
1693
- } else { lastClick = {time: now, pos: start}; }
1694
-
1695
- var last = start;
1696
- if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
1697
- !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
1698
- var dragEnd = operation(cm, function(e2) {
1699
- if (webkit) display.scroller.draggable = false;
1700
- cm.state.draggingText = false;
1701
- off(document, "mouseup", dragEnd);
1702
- off(display.scroller, "drop", dragEnd);
1703
- if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
1704
- e_preventDefault(e2);
1705
- extendSelection(cm.doc, start);
1706
- focusInput(cm);
1707
- }
1708
- });
1709
- // Let the drag handler handle this.
1710
- if (webkit) display.scroller.draggable = true;
1711
- cm.state.draggingText = dragEnd;
1712
- // IE's approach to draggable
1713
- if (display.scroller.dragDrop) display.scroller.dragDrop();
1714
- on(document, "mouseup", dragEnd);
1715
- on(display.scroller, "drop", dragEnd);
1716
- return;
1717
- }
1718
- e_preventDefault(e);
1719
- if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
1720
-
1721
- var startstart = sel.from, startend = sel.to, lastPos = start;
1722
-
1723
- function doSelect(cur) {
1724
- if (posEq(lastPos, cur)) return;
1725
- lastPos = cur;
1726
-
1727
- if (type == "single") {
1728
- extendSelection(cm.doc, clipPos(doc, start), cur);
1729
- return;
1730
- }
1731
-
1732
- startstart = clipPos(doc, startstart);
1733
- startend = clipPos(doc, startend);
1734
- if (type == "double") {
1735
- var word = findWordAt(getLine(doc, cur.line).text, cur);
1736
- if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
1737
- else extendSelection(cm.doc, startstart, word.to);
1738
- } else if (type == "triple") {
1739
- if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
1740
- else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
1741
- }
1742
- }
1743
-
1744
- var editorSize = getRect(display.wrapper);
1745
- // Used to ensure timeout re-tries don't fire when another extend
1746
- // happened in the meantime (clearTimeout isn't reliable -- at
1747
- // least on Chrome, the timeouts still happen even when cleared,
1748
- // if the clear happens after their scheduled firing time).
1749
- var counter = 0;
1750
-
1751
- function extend(e) {
1752
- var curCount = ++counter;
1753
- var cur = posFromMouse(cm, e, true);
1754
- if (!cur) return;
1755
- if (!posEq(cur, last)) {
1756
- if (!cm.state.focused) onFocus(cm);
1757
- last = cur;
1758
- doSelect(cur);
1759
- var visible = visibleLines(display, doc);
1760
- if (cur.line >= visible.to || cur.line < visible.from)
1761
- setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
1762
- } else {
1763
- var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
1764
- if (outside) setTimeout(operation(cm, function() {
1765
- if (counter != curCount) return;
1766
- display.scroller.scrollTop += outside;
1767
- extend(e);
1768
- }), 50);
1769
- }
1770
- }
1771
-
1772
- function done(e) {
1773
- counter = Infinity;
1774
- e_preventDefault(e);
1775
- focusInput(cm);
1776
- off(document, "mousemove", move);
1777
- off(document, "mouseup", up);
1778
- }
1779
-
1780
- var move = operation(cm, function(e) {
1781
- if (!ie && !e_button(e)) done(e);
1782
- else extend(e);
1783
- });
1784
- var up = operation(cm, done);
1785
- on(document, "mousemove", move);
1786
- on(document, "mouseup", up);
1787
- }
1788
-
1789
- function clickInGutter(cm, e) {
1790
- var display = cm.display;
1791
- try { var mX = e.clientX, mY = e.clientY; }
1792
- catch(e) { return false; }
1793
-
1794
- if (mX >= Math.floor(getRect(display.gutters).right)) return false;
1795
- e_preventDefault(e);
1796
- if (!hasHandler(cm, "gutterClick")) return true;
1797
-
1798
- var lineBox = getRect(display.lineDiv);
1799
- if (mY > lineBox.bottom) return true;
1800
- mY -= lineBox.top - display.viewOffset;
1801
-
1802
- for (var i = 0; i < cm.options.gutters.length; ++i) {
1803
- var g = display.gutters.childNodes[i];
1804
- if (g && getRect(g).right >= mX) {
1805
- var line = lineAtHeight(cm.doc, mY);
1806
- var gutter = cm.options.gutters[i];
1807
- signalLater(cm, "gutterClick", cm, line, gutter, e);
1808
- break;
1809
- }
1810
- }
1811
- return true;
1812
- }
1813
-
1814
- // Kludge to work around strange IE behavior where it'll sometimes
1815
- // re-fire a series of drag-related events right after the drop (#1551)
1816
- var lastDrop = 0;
1817
-
1818
- function onDrop(e) {
1819
- var cm = this;
1820
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1821
- return;
1822
- e_preventDefault(e);
1823
- if (ie) lastDrop = +new Date;
1824
- var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1825
- if (!pos || isReadOnly(cm)) return;
1826
- if (files && files.length && window.FileReader && window.File) {
1827
- var n = files.length, text = Array(n), read = 0;
1828
- var loadFile = function(file, i) {
1829
- var reader = new FileReader;
1830
- reader.onload = function() {
1831
- text[i] = reader.result;
1832
- if (++read == n) {
1833
- pos = clipPos(cm.doc, pos);
1834
- makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
1835
- }
1836
- };
1837
- reader.readAsText(file);
1838
- };
1839
- for (var i = 0; i < n; ++i) loadFile(files[i], i);
1840
- } else {
1841
- // Don't do a replace if the drop happened inside of the selected text.
1842
- if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
1843
- cm.state.draggingText(e);
1844
- // Ensure the editor is re-focused
1845
- setTimeout(bind(focusInput, cm), 20);
1846
- return;
1847
- }
1848
- try {
1849
- var text = e.dataTransfer.getData("Text");
1850
- if (text) {
1851
- var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
1852
- setSelection(cm.doc, pos, pos);
1853
- if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
1854
- cm.replaceSelection(text, null, "paste");
1855
- focusInput(cm);
1856
- onFocus(cm);
1857
- }
1858
- }
1859
- catch(e){}
1860
- }
1861
- }
1862
-
1863
- function onDragStart(cm, e) {
1864
- if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1865
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1866
-
1867
- var txt = cm.getSelection();
1868
- e.dataTransfer.setData("Text", txt);
1869
-
1870
- // Use dummy image instead of default browsers image.
1871
- // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1872
- if (e.dataTransfer.setDragImage && !safari) {
1873
- var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1874
- if (opera) {
1875
- img.width = img.height = 1;
1876
- cm.display.wrapper.appendChild(img);
1877
- // Force a relayout, or Opera won't use our image for some obscure reason
1878
- img._top = img.offsetTop;
1879
- }
1880
- e.dataTransfer.setDragImage(img, 0, 0);
1881
- if (opera) img.parentNode.removeChild(img);
1882
- }
1883
- }
1884
-
1885
- function setScrollTop(cm, val) {
1886
- if (Math.abs(cm.doc.scrollTop - val) < 2) return;
1887
- cm.doc.scrollTop = val;
1888
- if (!gecko) updateDisplay(cm, [], val);
1889
- if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1890
- if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1891
- if (gecko) updateDisplay(cm, []);
1892
- startWorker(cm, 100);
1893
- }
1894
- function setScrollLeft(cm, val, isScroller) {
1895
- if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1896
- val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
1897
- cm.doc.scrollLeft = val;
1898
- alignHorizontally(cm);
1899
- if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
1900
- if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
1901
- }
1902
-
1903
- // Since the delta values reported on mouse wheel events are
1904
- // unstandardized between browsers and even browser versions, and
1905
- // generally horribly unpredictable, this code starts by measuring
1906
- // the scroll effect that the first few mouse wheel events have,
1907
- // and, from that, detects the way it can convert deltas to pixel
1908
- // offsets afterwards.
1909
- //
1910
- // The reason we want to know the amount a wheel event will scroll
1911
- // is that it gives us a chance to update the display before the
1912
- // actual scrolling happens, reducing flickering.
1913
-
1914
- var wheelSamples = 0, wheelPixelsPerUnit = null;
1915
- // Fill in a browser-detected starting value on browsers where we
1916
- // know one. These don't have to be accurate -- the result of them
1917
- // being wrong would just be a slight flicker on the first wheel
1918
- // scroll (if it is large enough).
1919
- if (ie) wheelPixelsPerUnit = -.53;
1920
- else if (gecko) wheelPixelsPerUnit = 15;
1921
- else if (chrome) wheelPixelsPerUnit = -.7;
1922
- else if (safari) wheelPixelsPerUnit = -1/3;
1923
-
1924
- function onScrollWheel(cm, e) {
1925
- var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
1926
- if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
1927
- if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
1928
- else if (dy == null) dy = e.wheelDelta;
1929
-
1930
- var display = cm.display, scroll = display.scroller;
1931
- // Quit if there's nothing to scroll here
1932
- if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
1933
- dy && scroll.scrollHeight > scroll.clientHeight)) return;
1934
-
1935
- // Webkit browsers on OS X abort momentum scrolls when the target
1936
- // of the scroll event is removed from the scrollable element.
1937
- // This hack (see related code in patchDisplay) makes sure the
1938
- // element is kept around.
1939
- if (dy && mac && webkit) {
1940
- for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
1941
- if (cur.lineObj) {
1942
- cm.display.currentWheelTarget = cur;
1943
- break;
1944
- }
1945
- }
1946
- }
1947
-
1948
- // On some browsers, horizontal scrolling will cause redraws to
1949
- // happen before the gutter has been realigned, causing it to
1950
- // wriggle around in a most unseemly way. When we have an
1951
- // estimated pixels/delta value, we just handle horizontal
1952
- // scrolling entirely here. It'll be slightly off from native, but
1953
- // better than glitching out.
1954
- if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
1955
- if (dy)
1956
- setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
1957
- setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
1958
- e_preventDefault(e);
1959
- display.wheelStartX = null; // Abort measurement, if in progress
1960
- return;
1961
- }
1962
-
1963
- if (dy && wheelPixelsPerUnit != null) {
1964
- var pixels = dy * wheelPixelsPerUnit;
1965
- var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
1966
- if (pixels < 0) top = Math.max(0, top + pixels - 50);
1967
- else bot = Math.min(cm.doc.height, bot + pixels + 50);
1968
- updateDisplay(cm, [], {top: top, bottom: bot});
1969
- }
1970
-
1971
- if (wheelSamples < 20) {
1972
- if (display.wheelStartX == null) {
1973
- display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
1974
- display.wheelDX = dx; display.wheelDY = dy;
1975
- setTimeout(function() {
1976
- if (display.wheelStartX == null) return;
1977
- var movedX = scroll.scrollLeft - display.wheelStartX;
1978
- var movedY = scroll.scrollTop - display.wheelStartY;
1979
- var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
1980
- (movedX && display.wheelDX && movedX / display.wheelDX);
1981
- display.wheelStartX = display.wheelStartY = null;
1982
- if (!sample) return;
1983
- wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
1984
- ++wheelSamples;
1985
- }, 200);
1986
- } else {
1987
- display.wheelDX += dx; display.wheelDY += dy;
1988
- }
1989
- }
1990
- }
1991
-
1992
- function doHandleBinding(cm, bound, dropShift) {
1993
- if (typeof bound == "string") {
1994
- bound = commands[bound];
1995
- if (!bound) return false;
1996
- }
1997
- // Ensure previous input has been read, so that the handler sees a
1998
- // consistent view of the document
1999
- if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
2000
- var doc = cm.doc, prevShift = doc.sel.shift, done = false;
2001
- try {
2002
- if (isReadOnly(cm)) cm.state.suppressEdits = true;
2003
- if (dropShift) doc.sel.shift = false;
2004
- done = bound(cm) != Pass;
2005
- } finally {
2006
- doc.sel.shift = prevShift;
2007
- cm.state.suppressEdits = false;
2008
- }
2009
- return done;
2010
- }
2011
-
2012
- function allKeyMaps(cm) {
2013
- var maps = cm.state.keyMaps.slice(0);
2014
- if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
2015
- maps.push(cm.options.keyMap);
2016
- return maps;
2017
- }
2018
-
2019
- var maybeTransition;
2020
- function handleKeyBinding(cm, e) {
2021
- // Handle auto keymap transitions
2022
- var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
2023
- clearTimeout(maybeTransition);
2024
- if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
2025
- if (getKeyMap(cm.options.keyMap) == startMap) {
2026
- cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2027
- keyMapChanged(cm);
2028
- }
2029
- }, 50);
2030
-
2031
- var name = keyName(e, true), handled = false;
2032
- if (!name) return false;
2033
- var keymaps = allKeyMaps(cm);
2034
-
2035
- if (e.shiftKey) {
2036
- // First try to resolve full name (including 'Shift-'). Failing
2037
- // that, see if there is a cursor-motion command (starting with
2038
- // 'go') bound to the keyname without 'Shift-'.
2039
- handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2040
- || lookupKey(name, keymaps, function(b) {
2041
- if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
2042
- return doHandleBinding(cm, b);
2043
- });
2044
- } else {
2045
- handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
2046
- }
2047
-
2048
- if (handled) {
2049
- e_preventDefault(e);
2050
- restartBlink(cm);
2051
- if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2052
- signalLater(cm, "keyHandled", cm, name, e);
2053
- }
2054
- return handled;
2055
- }
2056
-
2057
- function handleCharBinding(cm, e, ch) {
2058
- var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
2059
- function(b) { return doHandleBinding(cm, b, true); });
2060
- if (handled) {
2061
- e_preventDefault(e);
2062
- restartBlink(cm);
2063
- signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2064
- }
2065
- return handled;
2066
- }
2067
-
2068
- var lastStoppedKey = null;
2069
- function onKeyDown(e) {
2070
- var cm = this;
2071
- if (!cm.state.focused) onFocus(cm);
2072
- if (ie && e.keyCode == 27) { e.returnValue = false; }
2073
- if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2074
- var code = e.keyCode;
2075
- // IE does strange things with escape.
2076
- cm.doc.sel.shift = code == 16 || e.shiftKey;
2077
- // First give onKeyEvent option a chance to handle this.
2078
- var handled = handleKeyBinding(cm, e);
2079
- if (opera) {
2080
- lastStoppedKey = handled ? code : null;
2081
- // Opera has no cut event... we try to at least catch the key combo
2082
- if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
2083
- cm.replaceSelection("");
2084
- }
2085
- }
2086
-
2087
- function onKeyPress(e) {
2088
- var cm = this;
2089
- if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2090
- var keyCode = e.keyCode, charCode = e.charCode;
2091
- if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2092
- if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2093
- var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2094
- if (this.options.electricChars && this.doc.mode.electricChars &&
2095
- this.options.smartIndent && !isReadOnly(this) &&
2096
- this.doc.mode.electricChars.indexOf(ch) > -1)
2097
- setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
2098
- if (handleCharBinding(cm, e, ch)) return;
2099
- if (ie && !ie_lt9) cm.display.inputHasSelection = null;
2100
- fastPoll(cm);
2101
- }
2102
-
2103
- function onFocus(cm) {
2104
- if (cm.options.readOnly == "nocursor") return;
2105
- if (!cm.state.focused) {
2106
- signal(cm, "focus", cm);
2107
- cm.state.focused = true;
2108
- if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
2109
- cm.display.wrapper.className += " CodeMirror-focused";
2110
- resetInput(cm, true);
2111
- }
2112
- slowPoll(cm);
2113
- restartBlink(cm);
2114
- }
2115
- function onBlur(cm) {
2116
- if (cm.state.focused) {
2117
- signal(cm, "blur", cm);
2118
- cm.state.focused = false;
2119
- cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
2120
- }
2121
- clearInterval(cm.display.blinker);
2122
- setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
2123
- }
2124
-
2125
- var detectingSelectAll;
2126
- function onContextMenu(cm, e) {
2127
- if (signalDOMEvent(cm, e, "contextmenu")) return;
2128
- var display = cm.display, sel = cm.doc.sel;
2129
- if (eventInWidget(display, e)) return;
2130
-
2131
- var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
2132
- if (!pos || opera) return; // Opera is difficult.
2133
- if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
2134
- operation(cm, setSelection)(cm.doc, pos, pos);
2135
-
2136
- var oldCSS = display.input.style.cssText;
2137
- display.inputDiv.style.position = "absolute";
2138
- display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
2139
- "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2140
- "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
2141
- focusInput(cm);
2142
- resetInput(cm, true);
2143
- // Adds "Select all" to context menu in FF
2144
- if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2145
-
2146
- function prepareSelectAllHack() {
2147
- if (display.input.selectionStart != null) {
2148
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
2149
- display.prevInput = " ";
2150
- display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2151
- }
2152
- }
2153
- function rehide() {
2154
- display.inputDiv.style.position = "relative";
2155
- display.input.style.cssText = oldCSS;
2156
- if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
2157
- slowPoll(cm);
2158
-
2159
- // Try to detect the user choosing select-all
2160
- if (display.input.selectionStart != null) {
2161
- if (!ie || ie_lt9) prepareSelectAllHack();
2162
- clearTimeout(detectingSelectAll);
2163
- var i = 0, poll = function(){
2164
- if (display.prevInput == " " && display.input.selectionStart == 0)
2165
- operation(cm, commands.selectAll)(cm);
2166
- else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2167
- else resetInput(cm);
2168
- };
2169
- detectingSelectAll = setTimeout(poll, 200);
2170
- }
2171
- }
2172
-
2173
- if (ie && !ie_lt9) prepareSelectAllHack();
2174
- if (captureMiddleClick) {
2175
- e_stop(e);
2176
- var mouseup = function() {
2177
- off(window, "mouseup", mouseup);
2178
- setTimeout(rehide, 20);
2179
- };
2180
- on(window, "mouseup", mouseup);
2181
- } else {
2182
- setTimeout(rehide, 50);
2183
- }
2184
- }
2185
-
2186
- // UPDATING
2187
-
2188
- var changeEnd = CodeMirror.changeEnd = function(change) {
2189
- if (!change.text) return change.to;
2190
- return Pos(change.from.line + change.text.length - 1,
2191
- lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2192
- };
2193
-
2194
- // Make sure a position will be valid after the given change.
2195
- function clipPostChange(doc, change, pos) {
2196
- if (!posLess(change.from, pos)) return clipPos(doc, pos);
2197
- var diff = (change.text.length - 1) - (change.to.line - change.from.line);
2198
- if (pos.line > change.to.line + diff) {
2199
- var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
2200
- if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
2201
- return clipToLen(pos, getLine(doc, preLine).text.length);
2202
- }
2203
- if (pos.line == change.to.line + diff)
2204
- return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
2205
- getLine(doc, change.to.line).text.length - change.to.ch);
2206
- var inside = pos.line - change.from.line;
2207
- return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
2208
- }
2209
-
2210
- // Hint can be null|"end"|"start"|"around"|{anchor,head}
2211
- function computeSelAfterChange(doc, change, hint) {
2212
- if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
2213
- return {anchor: clipPostChange(doc, change, hint.anchor),
2214
- head: clipPostChange(doc, change, hint.head)};
2215
-
2216
- if (hint == "start") return {anchor: change.from, head: change.from};
2217
-
2218
- var end = changeEnd(change);
2219
- if (hint == "around") return {anchor: change.from, head: end};
2220
- if (hint == "end") return {anchor: end, head: end};
2221
-
2222
- // hint is null, leave the selection alone as much as possible
2223
- var adjustPos = function(pos) {
2224
- if (posLess(pos, change.from)) return pos;
2225
- if (!posLess(change.to, pos)) return end;
2226
-
2227
- var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
2228
- if (pos.line == change.to.line) ch += end.ch - change.to.ch;
2229
- return Pos(line, ch);
2230
- };
2231
- return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2232
- }
2233
-
2234
- function filterChange(doc, change, update) {
2235
- var obj = {
2236
- canceled: false,
2237
- from: change.from,
2238
- to: change.to,
2239
- text: change.text,
2240
- origin: change.origin,
2241
- cancel: function() { this.canceled = true; }
2242
- };
2243
- if (update) obj.update = function(from, to, text, origin) {
2244
- if (from) this.from = clipPos(doc, from);
2245
- if (to) this.to = clipPos(doc, to);
2246
- if (text) this.text = text;
2247
- if (origin !== undefined) this.origin = origin;
2248
- };
2249
- signal(doc, "beforeChange", doc, obj);
2250
- if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2251
-
2252
- if (obj.canceled) return null;
2253
- return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
2254
- }
2255
-
2256
- // Replace the range from from to to by the strings in replacement.
2257
- // change is a {from, to, text [, origin]} object
2258
- function makeChange(doc, change, selUpdate, ignoreReadOnly) {
2259
- if (doc.cm) {
2260
- if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
2261
- if (doc.cm.state.suppressEdits) return;
2262
- }
2263
-
2264
- if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2265
- change = filterChange(doc, change, true);
2266
- if (!change) return;
2267
- }
2268
-
2269
- // Possibly split or suppress the update based on the presence
2270
- // of read-only spans in its range.
2271
- var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
2272
- if (split) {
2273
- for (var i = split.length - 1; i >= 1; --i)
2274
- makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
2275
- if (split.length)
2276
- makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
2277
- } else {
2278
- makeChangeNoReadonly(doc, change, selUpdate);
2279
- }
2280
- }
2281
-
2282
- function makeChangeNoReadonly(doc, change, selUpdate) {
2283
- var selAfter = computeSelAfterChange(doc, change, selUpdate);
2284
- addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
2285
-
2286
- makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
2287
- var rebased = [];
2288
-
2289
- linkedDocs(doc, function(doc, sharedHist) {
2290
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2291
- rebaseHist(doc.history, change);
2292
- rebased.push(doc.history);
2293
- }
2294
- makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
2295
- });
2296
- }
2297
-
2298
- function makeChangeFromHistory(doc, type) {
2299
- if (doc.cm && doc.cm.state.suppressEdits) return;
2300
-
2301
- var hist = doc.history;
2302
- var event = (type == "undo" ? hist.done : hist.undone).pop();
2303
- if (!event) return;
2304
-
2305
- var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2306
- anchorAfter: event.anchorBefore, headAfter: event.headBefore,
2307
- generation: hist.generation};
2308
- (type == "undo" ? hist.undone : hist.done).push(anti);
2309
- hist.generation = event.generation || ++hist.maxGeneration;
2310
-
2311
- var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
2312
-
2313
- for (var i = event.changes.length - 1; i >= 0; --i) {
2314
- var change = event.changes[i];
2315
- change.origin = type;
2316
- if (filter && !filterChange(doc, change, false)) {
2317
- (type == "undo" ? hist.done : hist.undone).length = 0;
2318
- return;
2319
- }
2320
-
2321
- anti.changes.push(historyChangeFromChange(doc, change));
2322
-
2323
- var after = i ? computeSelAfterChange(doc, change, null)
2324
- : {anchor: event.anchorBefore, head: event.headBefore};
2325
- makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
2326
- var rebased = [];
2327
-
2328
- linkedDocs(doc, function(doc, sharedHist) {
2329
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2330
- rebaseHist(doc.history, change);
2331
- rebased.push(doc.history);
2332
- }
2333
- makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
2334
- });
2335
- }
2336
- }
2337
-
2338
- function shiftDoc(doc, distance) {
2339
- function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
2340
- doc.first += distance;
2341
- if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
2342
- doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
2343
- doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
2344
- }
2345
-
2346
- function makeChangeSingleDoc(doc, change, selAfter, spans) {
2347
- if (doc.cm && !doc.cm.curOp)
2348
- return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
2349
-
2350
- if (change.to.line < doc.first) {
2351
- shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
2352
- return;
2353
- }
2354
- if (change.from.line > doc.lastLine()) return;
2355
-
2356
- // Clip the change to the size of this doc
2357
- if (change.from.line < doc.first) {
2358
- var shift = change.text.length - 1 - (doc.first - change.from.line);
2359
- shiftDoc(doc, shift);
2360
- change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
2361
- text: [lst(change.text)], origin: change.origin};
2362
- }
2363
- var last = doc.lastLine();
2364
- if (change.to.line > last) {
2365
- change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
2366
- text: [change.text[0]], origin: change.origin};
2367
- }
2368
-
2369
- change.removed = getBetween(doc, change.from, change.to);
2370
-
2371
- if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
2372
- if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
2373
- else updateDoc(doc, change, spans, selAfter);
2374
- }
2375
-
2376
- function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
2377
- var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
2378
-
2379
- var recomputeMaxLength = false, checkWidthStart = from.line;
2380
- if (!cm.options.lineWrapping) {
2381
- checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
2382
- doc.iter(checkWidthStart, to.line + 1, function(line) {
2383
- if (line == display.maxLine) {
2384
- recomputeMaxLength = true;
2385
- return true;
2386
- }
2387
- });
2388
- }
2389
-
2390
- if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
2391
- cm.curOp.cursorActivity = true;
2392
-
2393
- updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
2394
-
2395
- if (!cm.options.lineWrapping) {
2396
- doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
2397
- var len = lineLength(doc, line);
2398
- if (len > display.maxLineLength) {
2399
- display.maxLine = line;
2400
- display.maxLineLength = len;
2401
- display.maxLineChanged = true;
2402
- recomputeMaxLength = false;
2403
- }
2404
- });
2405
- if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
2406
- }
2407
-
2408
- // Adjust frontier, schedule worker
2409
- doc.frontier = Math.min(doc.frontier, from.line);
2410
- startWorker(cm, 400);
2411
-
2412
- var lendiff = change.text.length - (to.line - from.line) - 1;
2413
- // Remember that these lines changed, for updating the display
2414
- regChange(cm, from.line, to.line + 1, lendiff);
2415
-
2416
- if (hasHandler(cm, "change")) {
2417
- var changeObj = {from: from, to: to,
2418
- text: change.text,
2419
- removed: change.removed,
2420
- origin: change.origin};
2421
- if (cm.curOp.textChanged) {
2422
- for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
2423
- cur.next = changeObj;
2424
- } else cm.curOp.textChanged = changeObj;
2425
- }
2426
- }
2427
-
2428
- function replaceRange(doc, code, from, to, origin) {
2429
- if (!to) to = from;
2430
- if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
2431
- if (typeof code == "string") code = splitLines(code);
2432
- makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
2433
- }
2434
-
2435
- // POSITION OBJECT
2436
-
2437
- function Pos(line, ch) {
2438
- if (!(this instanceof Pos)) return new Pos(line, ch);
2439
- this.line = line; this.ch = ch;
2440
- }
2441
- CodeMirror.Pos = Pos;
2442
-
2443
- function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2444
- function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2445
- function copyPos(x) {return Pos(x.line, x.ch);}
2446
-
2447
- // SELECTION
2448
-
2449
- function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2450
- function clipPos(doc, pos) {
2451
- if (pos.line < doc.first) return Pos(doc.first, 0);
2452
- var last = doc.first + doc.size - 1;
2453
- if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2454
- return clipToLen(pos, getLine(doc, pos.line).text.length);
2455
- }
2456
- function clipToLen(pos, linelen) {
2457
- var ch = pos.ch;
2458
- if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2459
- else if (ch < 0) return Pos(pos.line, 0);
2460
- else return pos;
2461
- }
2462
- function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2463
-
2464
- // If shift is held, this will move the selection anchor. Otherwise,
2465
- // it'll set the whole selection.
2466
- function extendSelection(doc, pos, other, bias) {
2467
- if (doc.sel.shift || doc.sel.extend) {
2468
- var anchor = doc.sel.anchor;
2469
- if (other) {
2470
- var posBefore = posLess(pos, anchor);
2471
- if (posBefore != posLess(other, anchor)) {
2472
- anchor = pos;
2473
- pos = other;
2474
- } else if (posBefore != posLess(pos, other)) {
2475
- pos = other;
2476
- }
2477
- }
2478
- setSelection(doc, anchor, pos, bias);
2479
- } else {
2480
- setSelection(doc, pos, other || pos, bias);
2481
- }
2482
- if (doc.cm) doc.cm.curOp.userSelChange = true;
2483
- }
2484
-
2485
- function filterSelectionChange(doc, anchor, head) {
2486
- var obj = {anchor: anchor, head: head};
2487
- signal(doc, "beforeSelectionChange", doc, obj);
2488
- if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2489
- obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
2490
- return obj;
2491
- }
2492
-
2493
- // Update the selection. Last two args are only used by
2494
- // updateDoc, since they have to be expressed in the line
2495
- // numbers before the update.
2496
- function setSelection(doc, anchor, head, bias, checkAtomic) {
2497
- if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
2498
- var filtered = filterSelectionChange(doc, anchor, head);
2499
- head = filtered.head;
2500
- anchor = filtered.anchor;
2501
- }
2502
-
2503
- var sel = doc.sel;
2504
- sel.goalColumn = null;
2505
- // Skip over atomic spans.
2506
- if (checkAtomic || !posEq(anchor, sel.anchor))
2507
- anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
2508
- if (checkAtomic || !posEq(head, sel.head))
2509
- head = skipAtomic(doc, head, bias, checkAtomic != "push");
2510
-
2511
- if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
2512
-
2513
- sel.anchor = anchor; sel.head = head;
2514
- var inv = posLess(head, anchor);
2515
- sel.from = inv ? head : anchor;
2516
- sel.to = inv ? anchor : head;
2517
-
2518
- if (doc.cm)
2519
- doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
2520
- doc.cm.curOp.cursorActivity = true;
2521
-
2522
- signalLater(doc, "cursorActivity", doc);
2523
- }
2524
-
2525
- function reCheckSelection(cm) {
2526
- setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
2527
- }
2528
-
2529
- function skipAtomic(doc, pos, bias, mayClear) {
2530
- var flipped = false, curPos = pos;
2531
- var dir = bias || 1;
2532
- doc.cantEdit = false;
2533
- search: for (;;) {
2534
- var line = getLine(doc, curPos.line);
2535
- if (line.markedSpans) {
2536
- for (var i = 0; i < line.markedSpans.length; ++i) {
2537
- var sp = line.markedSpans[i], m = sp.marker;
2538
- if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2539
- (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2540
- if (mayClear) {
2541
- signal(m, "beforeCursorEnter");
2542
- if (m.explicitlyCleared) {
2543
- if (!line.markedSpans) break;
2544
- else {--i; continue;}
2545
- }
2546
- }
2547
- if (!m.atomic) continue;
2548
- var newPos = m.find()[dir < 0 ? "from" : "to"];
2549
- if (posEq(newPos, curPos)) {
2550
- newPos.ch += dir;
2551
- if (newPos.ch < 0) {
2552
- if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2553
- else newPos = null;
2554
- } else if (newPos.ch > line.text.length) {
2555
- if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2556
- else newPos = null;
2557
- }
2558
- if (!newPos) {
2559
- if (flipped) {
2560
- // Driven in a corner -- no valid cursor position found at all
2561
- // -- try again *with* clearing, if we didn't already
2562
- if (!mayClear) return skipAtomic(doc, pos, bias, true);
2563
- // Otherwise, turn off editing until further notice, and return the start of the doc
2564
- doc.cantEdit = true;
2565
- return Pos(doc.first, 0);
2566
- }
2567
- flipped = true; newPos = pos; dir = -dir;
2568
- }
2569
- }
2570
- curPos = newPos;
2571
- continue search;
2572
- }
2573
- }
2574
- }
2575
- return curPos;
2576
- }
2577
- }
2578
-
2579
- // SCROLLING
2580
-
2581
- function scrollCursorIntoView(cm) {
2582
- var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
2583
- if (!cm.state.focused) return;
2584
- var display = cm.display, box = getRect(display.sizer), doScroll = null;
2585
- if (coords.top + box.top < 0) doScroll = true;
2586
- else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2587
- if (doScroll != null && !phantom) {
2588
- var hidden = display.cursor.style.display == "none";
2589
- if (hidden) {
2590
- display.cursor.style.display = "";
2591
- display.cursor.style.left = coords.left + "px";
2592
- display.cursor.style.top = (coords.top - display.viewOffset) + "px";
2593
- }
2594
- display.cursor.scrollIntoView(doScroll);
2595
- if (hidden) display.cursor.style.display = "none";
2596
- }
2597
- }
2598
-
2599
- function scrollPosIntoView(cm, pos, margin) {
2600
- if (margin == null) margin = 0;
2601
- for (;;) {
2602
- var changed = false, coords = cursorCoords(cm, pos);
2603
- var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
2604
- var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
2605
- if (scrollPos.scrollTop != null) {
2606
- setScrollTop(cm, scrollPos.scrollTop);
2607
- if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
2608
- }
2609
- if (scrollPos.scrollLeft != null) {
2610
- setScrollLeft(cm, scrollPos.scrollLeft);
2611
- if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
2612
- }
2613
- if (!changed) return coords;
2614
- }
2615
- }
2616
-
2617
- function scrollIntoView(cm, x1, y1, x2, y2) {
2618
- var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
2619
- if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
2620
- if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
2621
- }
2622
-
2623
- function calculateScrollPos(cm, x1, y1, x2, y2) {
2624
- var display = cm.display, snapMargin = textHeight(cm.display);
2625
- if (y1 < 0) y1 = 0;
2626
- var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2627
- var docBottom = cm.doc.height + paddingVert(display);
2628
- var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
2629
- if (y1 < screentop) {
2630
- result.scrollTop = atTop ? 0 : y1;
2631
- } else if (y2 > screentop + screen) {
2632
- var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
2633
- if (newTop != screentop) result.scrollTop = newTop;
2634
- }
2635
-
2636
- var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
2637
- x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
2638
- var gutterw = display.gutters.offsetWidth;
2639
- var atLeft = x1 < gutterw + 10;
2640
- if (x1 < screenleft + gutterw || atLeft) {
2641
- if (atLeft) x1 = 0;
2642
- result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
2643
- } else if (x2 > screenw + screenleft - 3) {
2644
- result.scrollLeft = x2 + 10 - screenw;
2645
- }
2646
- return result;
2647
- }
2648
-
2649
- function updateScrollPos(cm, left, top) {
2650
- cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
2651
- scrollTop: top == null ? cm.doc.scrollTop : top};
2652
- }
2653
-
2654
- function addToScrollPos(cm, left, top) {
2655
- var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
2656
- var scroll = cm.display.scroller;
2657
- pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
2658
- pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
2659
- }
2660
-
2661
- // API UTILITIES
2662
-
2663
- function indentLine(cm, n, how, aggressive) {
2664
- var doc = cm.doc;
2665
- if (how == null) how = "add";
2666
- if (how == "smart") {
2667
- if (!cm.doc.mode.indent) how = "prev";
2668
- else var state = getStateBefore(cm, n);
2669
- }
2670
-
2671
- var tabSize = cm.options.tabSize;
2672
- var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
2673
- var curSpaceString = line.text.match(/^\s*/)[0], indentation;
2674
- if (how == "smart") {
2675
- indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2676
- if (indentation == Pass) {
2677
- if (!aggressive) return;
2678
- how = "prev";
2679
- }
2680
- }
2681
- if (how == "prev") {
2682
- if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
2683
- else indentation = 0;
2684
- } else if (how == "add") {
2685
- indentation = curSpace + cm.options.indentUnit;
2686
- } else if (how == "subtract") {
2687
- indentation = curSpace - cm.options.indentUnit;
2688
- } else if (typeof how == "number") {
2689
- indentation = curSpace + how;
2690
- }
2691
- indentation = Math.max(0, indentation);
2692
-
2693
- var indentString = "", pos = 0;
2694
- if (cm.options.indentWithTabs)
2695
- for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
2696
- if (pos < indentation) indentString += spaceStr(indentation - pos);
2697
-
2698
- if (indentString != curSpaceString)
2699
- replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
2700
- line.stateAfter = null;
2701
- }
2702
-
2703
- function changeLine(cm, handle, op) {
2704
- var no = handle, line = handle, doc = cm.doc;
2705
- if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
2706
- else no = lineNo(handle);
2707
- if (no == null) return null;
2708
- if (op(line, no)) regChange(cm, no, no + 1);
2709
- else return null;
2710
- return line;
2711
- }
2712
-
2713
- function findPosH(doc, pos, dir, unit, visually) {
2714
- var line = pos.line, ch = pos.ch, origDir = dir;
2715
- var lineObj = getLine(doc, line);
2716
- var possible = true;
2717
- function findNextLine() {
2718
- var l = line + dir;
2719
- if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
2720
- line = l;
2721
- return lineObj = getLine(doc, l);
2722
- }
2723
- function moveOnce(boundToLine) {
2724
- var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
2725
- if (next == null) {
2726
- if (!boundToLine && findNextLine()) {
2727
- if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
2728
- else ch = dir < 0 ? lineObj.text.length : 0;
2729
- } else return (possible = false);
2730
- } else ch = next;
2731
- return true;
2732
- }
2733
-
2734
- if (unit == "char") moveOnce();
2735
- else if (unit == "column") moveOnce(true);
2736
- else if (unit == "word" || unit == "group") {
2737
- var sawType = null, group = unit == "group";
2738
- for (var first = true;; first = false) {
2739
- if (dir < 0 && !moveOnce(!first)) break;
2740
- var cur = lineObj.text.charAt(ch) || "\n";
2741
- var type = isWordChar(cur) ? "w"
2742
- : !group ? null
2743
- : /\s/.test(cur) ? null
2744
- : "p";
2745
- if (sawType && sawType != type) {
2746
- if (dir < 0) {dir = 1; moveOnce();}
2747
- break;
2748
- }
2749
- if (type) sawType = type;
2750
- if (dir > 0 && !moveOnce(!first)) break;
2751
- }
2752
- }
2753
- var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2754
- if (!possible) result.hitSide = true;
2755
- return result;
2756
- }
2757
-
2758
- function findPosV(cm, pos, dir, unit) {
2759
- var doc = cm.doc, x = pos.left, y;
2760
- if (unit == "page") {
2761
- var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
2762
- y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
2763
- } else if (unit == "line") {
2764
- y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
2765
- }
2766
- for (;;) {
2767
- var target = coordsChar(cm, x, y);
2768
- if (!target.outside) break;
2769
- if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
2770
- y += dir * 5;
2771
- }
2772
- return target;
2773
- }
2774
-
2775
- function findWordAt(line, pos) {
2776
- var start = pos.ch, end = pos.ch;
2777
- if (line) {
2778
- if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
2779
- var startChar = line.charAt(start);
2780
- var check = isWordChar(startChar) ? isWordChar
2781
- : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2782
- : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
2783
- while (start > 0 && check(line.charAt(start - 1))) --start;
2784
- while (end < line.length && check(line.charAt(end))) ++end;
2785
- }
2786
- return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
2787
- }
2788
-
2789
- function selectLine(cm, line) {
2790
- extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
2791
- }
2792
-
2793
- // PROTOTYPE
2794
-
2795
- // The publicly visible API. Note that operation(null, f) means
2796
- // 'wrap f in an operation, performed on its `this` parameter'
2797
-
2798
- CodeMirror.prototype = {
2799
- constructor: CodeMirror,
2800
- focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2801
-
2802
- setOption: function(option, value) {
2803
- var options = this.options, old = options[option];
2804
- if (options[option] == value && option != "mode") return;
2805
- options[option] = value;
2806
- if (optionHandlers.hasOwnProperty(option))
2807
- operation(this, optionHandlers[option])(this, value, old);
2808
- },
2809
-
2810
- getOption: function(option) {return this.options[option];},
2811
- getDoc: function() {return this.doc;},
2812
-
2813
- addKeyMap: function(map, bottom) {
2814
- this.state.keyMaps[bottom ? "push" : "unshift"](map);
2815
- },
2816
- removeKeyMap: function(map) {
2817
- var maps = this.state.keyMaps;
2818
- for (var i = 0; i < maps.length; ++i)
2819
- if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2820
- maps.splice(i, 1);
2821
- return true;
2822
- }
2823
- },
2824
-
2825
- addOverlay: operation(null, function(spec, options) {
2826
- var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
2827
- if (mode.startState) throw new Error("Overlays may not be stateful.");
2828
- this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
2829
- this.state.modeGen++;
2830
- regChange(this);
2831
- }),
2832
- removeOverlay: operation(null, function(spec) {
2833
- var overlays = this.state.overlays;
2834
- for (var i = 0; i < overlays.length; ++i) {
2835
- var cur = overlays[i].modeSpec;
2836
- if (cur == spec || typeof spec == "string" && cur.name == spec) {
2837
- overlays.splice(i, 1);
2838
- this.state.modeGen++;
2839
- regChange(this);
2840
- return;
2841
- }
2842
- }
2843
- }),
2844
-
2845
- indentLine: operation(null, function(n, dir, aggressive) {
2846
- if (typeof dir != "string" && typeof dir != "number") {
2847
- if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2848
- else dir = dir ? "add" : "subtract";
2849
- }
2850
- if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
2851
- }),
2852
- indentSelection: operation(null, function(how) {
2853
- var sel = this.doc.sel;
2854
- if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
2855
- var e = sel.to.line - (sel.to.ch ? 0 : 1);
2856
- for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
2857
- }),
2858
-
2859
- // Fetch the parser token for a given character. Useful for hacks
2860
- // that want to inspect the mode state (say, for completion).
2861
- getTokenAt: function(pos, precise) {
2862
- var doc = this.doc;
2863
- pos = clipPos(doc, pos);
2864
- var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2865
- var line = getLine(doc, pos.line);
2866
- var stream = new StringStream(line.text, this.options.tabSize);
2867
- while (stream.pos < pos.ch && !stream.eol()) {
2868
- stream.start = stream.pos;
2869
- var style = mode.token(stream, state);
2870
- }
2871
- return {start: stream.start,
2872
- end: stream.pos,
2873
- string: stream.current(),
2874
- className: style || null, // Deprecated, use 'type' instead
2875
- type: style || null,
2876
- state: state};
2877
- },
2878
-
2879
- getTokenTypeAt: function(pos) {
2880
- pos = clipPos(this.doc, pos);
2881
- var styles = getLineStyles(this, getLine(this.doc, pos.line));
2882
- var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2883
- if (ch == 0) return styles[2];
2884
- for (;;) {
2885
- var mid = (before + after) >> 1;
2886
- if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2887
- else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2888
- else return styles[mid * 2 + 2];
2889
- }
2890
- },
2891
-
2892
- getModeAt: function(pos) {
2893
- var mode = this.doc.mode;
2894
- if (!mode.innerMode) return mode;
2895
- return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2896
- },
2897
-
2898
- getHelper: function(pos, type) {
2899
- if (!helpers.hasOwnProperty(type)) return;
2900
- var help = helpers[type], mode = this.getModeAt(pos);
2901
- return mode[type] && help[mode[type]] ||
2902
- mode.helperType && help[mode.helperType] ||
2903
- help[mode.name];
2904
- },
2905
-
2906
- getStateAfter: function(line, precise) {
2907
- var doc = this.doc;
2908
- line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2909
- return getStateBefore(this, line + 1, precise);
2910
- },
2911
-
2912
- cursorCoords: function(start, mode) {
2913
- var pos, sel = this.doc.sel;
2914
- if (start == null) pos = sel.head;
2915
- else if (typeof start == "object") pos = clipPos(this.doc, start);
2916
- else pos = start ? sel.from : sel.to;
2917
- return cursorCoords(this, pos, mode || "page");
2918
- },
2919
-
2920
- charCoords: function(pos, mode) {
2921
- return charCoords(this, clipPos(this.doc, pos), mode || "page");
2922
- },
2923
-
2924
- coordsChar: function(coords, mode) {
2925
- coords = fromCoordSystem(this, coords, mode || "page");
2926
- return coordsChar(this, coords.left, coords.top);
2927
- },
2928
-
2929
- lineAtHeight: function(height, mode) {
2930
- height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
2931
- return lineAtHeight(this.doc, height + this.display.viewOffset);
2932
- },
2933
- heightAtLine: function(line, mode) {
2934
- var end = false, last = this.doc.first + this.doc.size - 1;
2935
- if (line < this.doc.first) line = this.doc.first;
2936
- else if (line > last) { line = last; end = true; }
2937
- var lineObj = getLine(this.doc, line);
2938
- return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
2939
- (end ? lineObj.height : 0);
2940
- },
2941
-
2942
- defaultTextHeight: function() { return textHeight(this.display); },
2943
- defaultCharWidth: function() { return charWidth(this.display); },
2944
-
2945
- setGutterMarker: operation(null, function(line, gutterID, value) {
2946
- return changeLine(this, line, function(line) {
2947
- var markers = line.gutterMarkers || (line.gutterMarkers = {});
2948
- markers[gutterID] = value;
2949
- if (!value && isEmpty(markers)) line.gutterMarkers = null;
2950
- return true;
2951
- });
2952
- }),
2953
-
2954
- clearGutter: operation(null, function(gutterID) {
2955
- var cm = this, doc = cm.doc, i = doc.first;
2956
- doc.iter(function(line) {
2957
- if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
2958
- line.gutterMarkers[gutterID] = null;
2959
- regChange(cm, i, i + 1);
2960
- if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
2961
- }
2962
- ++i;
2963
- });
2964
- }),
2965
-
2966
- addLineClass: operation(null, function(handle, where, cls) {
2967
- return changeLine(this, handle, function(line) {
2968
- var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2969
- if (!line[prop]) line[prop] = cls;
2970
- else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
2971
- else line[prop] += " " + cls;
2972
- return true;
2973
- });
2974
- }),
2975
-
2976
- removeLineClass: operation(null, function(handle, where, cls) {
2977
- return changeLine(this, handle, function(line) {
2978
- var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2979
- var cur = line[prop];
2980
- if (!cur) return false;
2981
- else if (cls == null) line[prop] = null;
2982
- else {
2983
- var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2984
- if (!found) return false;
2985
- var end = found.index + found[0].length;
2986
- line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
2987
- }
2988
- return true;
2989
- });
2990
- }),
2991
-
2992
- addLineWidget: operation(null, function(handle, node, options) {
2993
- return addLineWidget(this, handle, node, options);
2994
- }),
2995
-
2996
- removeLineWidget: function(widget) { widget.clear(); },
2997
-
2998
- lineInfo: function(line) {
2999
- if (typeof line == "number") {
3000
- if (!isLine(this.doc, line)) return null;
3001
- var n = line;
3002
- line = getLine(this.doc, line);
3003
- if (!line) return null;
3004
- } else {
3005
- var n = lineNo(line);
3006
- if (n == null) return null;
3007
- }
3008
- return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
3009
- textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
3010
- widgets: line.widgets};
3011
- },
3012
-
3013
- getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
3014
-
3015
- addWidget: function(pos, node, scroll, vert, horiz) {
3016
- var display = this.display;
3017
- pos = cursorCoords(this, clipPos(this.doc, pos));
3018
- var top = pos.bottom, left = pos.left;
3019
- node.style.position = "absolute";
3020
- display.sizer.appendChild(node);
3021
- if (vert == "over") {
3022
- top = pos.top;
3023
- } else if (vert == "above" || vert == "near") {
3024
- var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
3025
- hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
3026
- // Default to positioning above (if specified and possible); otherwise default to positioning below
3027
- if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
3028
- top = pos.top - node.offsetHeight;
3029
- else if (pos.bottom + node.offsetHeight <= vspace)
3030
- top = pos.bottom;
3031
- if (left + node.offsetWidth > hspace)
3032
- left = hspace - node.offsetWidth;
3033
- }
3034
- node.style.top = top + "px";
3035
- node.style.left = node.style.right = "";
3036
- if (horiz == "right") {
3037
- left = display.sizer.clientWidth - node.offsetWidth;
3038
- node.style.right = "0px";
3039
- } else {
3040
- if (horiz == "left") left = 0;
3041
- else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
3042
- node.style.left = left + "px";
3043
- }
3044
- if (scroll)
3045
- scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
3046
- },
3047
-
3048
- triggerOnKeyDown: operation(null, onKeyDown),
3049
-
3050
- execCommand: function(cmd) {return commands[cmd](this);},
3051
-
3052
- findPosH: function(from, amount, unit, visually) {
3053
- var dir = 1;
3054
- if (amount < 0) { dir = -1; amount = -amount; }
3055
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3056
- cur = findPosH(this.doc, cur, dir, unit, visually);
3057
- if (cur.hitSide) break;
3058
- }
3059
- return cur;
3060
- },
3061
-
3062
- moveH: operation(null, function(dir, unit) {
3063
- var sel = this.doc.sel, pos;
3064
- if (sel.shift || sel.extend || posEq(sel.from, sel.to))
3065
- pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
3066
- else
3067
- pos = dir < 0 ? sel.from : sel.to;
3068
- extendSelection(this.doc, pos, pos, dir);
3069
- }),
3070
-
3071
- deleteH: operation(null, function(dir, unit) {
3072
- var sel = this.doc.sel;
3073
- if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
3074
- else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
3075
- this.curOp.userSelChange = true;
3076
- }),
3077
-
3078
- findPosV: function(from, amount, unit, goalColumn) {
3079
- var dir = 1, x = goalColumn;
3080
- if (amount < 0) { dir = -1; amount = -amount; }
3081
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3082
- var coords = cursorCoords(this, cur, "div");
3083
- if (x == null) x = coords.left;
3084
- else coords.left = x;
3085
- cur = findPosV(this, coords, dir, unit);
3086
- if (cur.hitSide) break;
3087
- }
3088
- return cur;
3089
- },
3090
-
3091
- moveV: operation(null, function(dir, unit) {
3092
- var sel = this.doc.sel;
3093
- var pos = cursorCoords(this, sel.head, "div");
3094
- if (sel.goalColumn != null) pos.left = sel.goalColumn;
3095
- var target = findPosV(this, pos, dir, unit);
3096
-
3097
- if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3098
- extendSelection(this.doc, target, target, dir);
3099
- sel.goalColumn = pos.left;
3100
- }),
3101
-
3102
- toggleOverwrite: function(value) {
3103
- if (value != null && value == this.state.overwrite) return;
3104
- if (this.state.overwrite = !this.state.overwrite)
3105
- this.display.cursor.className += " CodeMirror-overwrite";
3106
- else
3107
- this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
3108
- },
3109
- hasFocus: function() { return this.state.focused; },
3110
-
3111
- scrollTo: operation(null, function(x, y) {
3112
- updateScrollPos(this, x, y);
3113
- }),
3114
- getScrollInfo: function() {
3115
- var scroller = this.display.scroller, co = scrollerCutOff;
3116
- return {left: scroller.scrollLeft, top: scroller.scrollTop,
3117
- height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
3118
- clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
3119
- },
3120
-
3121
- scrollIntoView: operation(null, function(pos, margin) {
3122
- if (typeof pos == "number") pos = Pos(pos, 0);
3123
- if (!margin) margin = 0;
3124
- var coords = pos;
3125
-
3126
- if (!pos || pos.line != null) {
3127
- this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
3128
- this.curOp.scrollToPosMargin = margin;
3129
- coords = cursorCoords(this, this.curOp.scrollToPos);
3130
- }
3131
- var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
3132
- updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
3133
- }),
3134
-
3135
- setSize: operation(null, function(width, height) {
3136
- function interpret(val) {
3137
- return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
3138
- }
3139
- if (width != null) this.display.wrapper.style.width = interpret(width);
3140
- if (height != null) this.display.wrapper.style.height = interpret(height);
3141
- if (this.options.lineWrapping)
3142
- this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3143
- this.curOp.forceUpdate = true;
3144
- }),
3145
-
3146
- operation: function(f){return runInOp(this, f);},
3147
-
3148
- refresh: operation(null, function() {
3149
- clearCaches(this);
3150
- updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
3151
- regChange(this);
3152
- }),
3153
-
3154
- swapDoc: operation(null, function(doc) {
3155
- var old = this.doc;
3156
- old.cm = null;
3157
- attachDoc(this, doc);
3158
- clearCaches(this);
3159
- resetInput(this, true);
3160
- updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
3161
- return old;
3162
- }),
3163
-
3164
- getInputField: function(){return this.display.input;},
3165
- getWrapperElement: function(){return this.display.wrapper;},
3166
- getScrollerElement: function(){return this.display.scroller;},
3167
- getGutterElement: function(){return this.display.gutters;}
3168
- };
3169
- eventMixin(CodeMirror);
3170
-
3171
- // OPTION DEFAULTS
3172
-
3173
- var optionHandlers = CodeMirror.optionHandlers = {};
3174
-
3175
- // The default configuration options.
3176
- var defaults = CodeMirror.defaults = {};
3177
-
3178
- function option(name, deflt, handle, notOnInit) {
3179
- CodeMirror.defaults[name] = deflt;
3180
- if (handle) optionHandlers[name] =
3181
- notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
3182
- }
3183
-
3184
- var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
3185
-
3186
- // These two are, on init, called from the constructor because they
3187
- // have to be initialized before the editor can start at all.
3188
- option("value", "", function(cm, val) {
3189
- cm.setValue(val);
3190
- }, true);
3191
- option("mode", null, function(cm, val) {
3192
- cm.doc.modeOption = val;
3193
- loadMode(cm);
3194
- }, true);
3195
-
3196
- option("indentUnit", 2, loadMode, true);
3197
- option("indentWithTabs", false);
3198
- option("smartIndent", true);
3199
- option("tabSize", 4, function(cm) {
3200
- loadMode(cm);
3201
- clearCaches(cm);
3202
- regChange(cm);
3203
- }, true);
3204
- option("electricChars", true);
3205
- option("rtlMoveVisually", !windows);
3206
-
3207
- option("theme", "default", function(cm) {
3208
- themeChanged(cm);
3209
- guttersChanged(cm);
3210
- }, true);
3211
- option("keyMap", "default", keyMapChanged);
3212
- option("extraKeys", null);
3213
-
3214
- option("onKeyEvent", null);
3215
- option("onDragEvent", null);
3216
-
3217
- option("lineWrapping", false, wrappingChanged, true);
3218
- option("gutters", [], function(cm) {
3219
- setGuttersForLineNumbers(cm.options);
3220
- guttersChanged(cm);
3221
- }, true);
3222
- option("fixedGutter", true, function(cm, val) {
3223
- cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3224
- cm.refresh();
3225
- }, true);
3226
- option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3227
- option("lineNumbers", false, function(cm) {
3228
- setGuttersForLineNumbers(cm.options);
3229
- guttersChanged(cm);
3230
- }, true);
3231
- option("firstLineNumber", 1, guttersChanged, true);
3232
- option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
3233
- option("showCursorWhenSelecting", false, updateSelection, true);
3234
-
3235
- option("readOnly", false, function(cm, val) {
3236
- if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
3237
- else if (!val) resetInput(cm, true);
3238
- });
3239
- option("dragDrop", true);
3240
-
3241
- option("cursorBlinkRate", 530);
3242
- option("cursorScrollMargin", 0);
3243
- option("cursorHeight", 1);
3244
- option("workTime", 100);
3245
- option("workDelay", 100);
3246
- option("flattenSpans", true);
3247
- option("pollInterval", 100);
3248
- option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
3249
- option("historyEventDelay", 500);
3250
- option("viewportMargin", 10, function(cm){cm.refresh();}, true);
3251
- option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
3252
- option("moveInputWithCursor", true, function(cm, val) {
3253
- if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
3254
- });
3255
-
3256
- option("tabindex", null, function(cm, val) {
3257
- cm.display.input.tabIndex = val || "";
3258
- });
3259
- option("autofocus", null);
3260
-
3261
- // MODE DEFINITION AND QUERYING
3262
-
3263
- // Known modes, by name and by MIME
3264
- var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
3265
-
3266
- CodeMirror.defineMode = function(name, mode) {
3267
- if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
3268
- if (arguments.length > 2) {
3269
- mode.dependencies = [];
3270
- for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
3271
- }
3272
- modes[name] = mode;
3273
- };
3274
-
3275
- CodeMirror.defineMIME = function(mime, spec) {
3276
- mimeModes[mime] = spec;
3277
- };
3278
-
3279
- CodeMirror.resolveMode = function(spec) {
3280
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3281
- spec = mimeModes[spec];
3282
- } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
3283
- var found = mimeModes[spec.name];
3284
- spec = createObj(found, spec);
3285
- spec.name = found.name;
3286
- } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
3287
- return CodeMirror.resolveMode("application/xml");
3288
- }
3289
- if (typeof spec == "string") return {name: spec};
3290
- else return spec || {name: "null"};
3291
- };
3292
-
3293
- CodeMirror.getMode = function(options, spec) {
3294
- var spec = CodeMirror.resolveMode(spec);
3295
- var mfactory = modes[spec.name];
3296
- if (!mfactory) return CodeMirror.getMode(options, "text/plain");
3297
- var modeObj = mfactory(options, spec);
3298
- if (modeExtensions.hasOwnProperty(spec.name)) {
3299
- var exts = modeExtensions[spec.name];
3300
- for (var prop in exts) {
3301
- if (!exts.hasOwnProperty(prop)) continue;
3302
- if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
3303
- modeObj[prop] = exts[prop];
3304
- }
3305
- }
3306
- modeObj.name = spec.name;
3307
-
3308
- return modeObj;
3309
- };
3310
-
3311
- CodeMirror.defineMode("null", function() {
3312
- return {token: function(stream) {stream.skipToEnd();}};
3313
- });
3314
- CodeMirror.defineMIME("text/plain", "null");
3315
-
3316
- var modeExtensions = CodeMirror.modeExtensions = {};
3317
- CodeMirror.extendMode = function(mode, properties) {
3318
- var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
3319
- copyObj(properties, exts);
3320
- };
3321
-
3322
- // EXTENSIONS
3323
-
3324
- CodeMirror.defineExtension = function(name, func) {
3325
- CodeMirror.prototype[name] = func;
3326
- };
3327
- CodeMirror.defineDocExtension = function(name, func) {
3328
- Doc.prototype[name] = func;
3329
- };
3330
- CodeMirror.defineOption = option;
3331
-
3332
- var initHooks = [];
3333
- CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
3334
-
3335
- var helpers = CodeMirror.helpers = {};
3336
- CodeMirror.registerHelper = function(type, name, value) {
3337
- if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3338
- helpers[type][name] = value;
3339
- };
3340
-
3341
- // UTILITIES
3342
-
3343
- CodeMirror.isWordChar = isWordChar;
3344
-
3345
- // MODE STATE HANDLING
3346
-
3347
- // Utility functions for working with state. Exported because modes
3348
- // sometimes need to do this.
3349
- function copyState(mode, state) {
3350
- if (state === true) return state;
3351
- if (mode.copyState) return mode.copyState(state);
3352
- var nstate = {};
3353
- for (var n in state) {
3354
- var val = state[n];
3355
- if (val instanceof Array) val = val.concat([]);
3356
- nstate[n] = val;
3357
- }
3358
- return nstate;
3359
- }
3360
- CodeMirror.copyState = copyState;
3361
-
3362
- function startState(mode, a1, a2) {
3363
- return mode.startState ? mode.startState(a1, a2) : true;
3364
- }
3365
- CodeMirror.startState = startState;
3366
-
3367
- CodeMirror.innerMode = function(mode, state) {
3368
- while (mode.innerMode) {
3369
- var info = mode.innerMode(state);
3370
- if (!info || info.mode == mode) break;
3371
- state = info.state;
3372
- mode = info.mode;
3373
- }
3374
- return info || {mode: mode, state: state};
3375
- };
3376
-
3377
- // STANDARD COMMANDS
3378
-
3379
- var commands = CodeMirror.commands = {
3380
- selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
3381
- killLine: function(cm) {
3382
- var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
3383
- if (!sel && cm.getLine(from.line).length == from.ch)
3384
- cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
3385
- else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
3386
- },
3387
- deleteLine: function(cm) {
3388
- var l = cm.getCursor().line;
3389
- cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3390
- },
3391
- delLineLeft: function(cm) {
3392
- var cur = cm.getCursor();
3393
- cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3394
- },
3395
- undo: function(cm) {cm.undo();},
3396
- redo: function(cm) {cm.redo();},
3397
- goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3398
- goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
3399
- goLineStart: function(cm) {
3400
- cm.extendSelection(lineStart(cm, cm.getCursor().line));
3401
- },
3402
- goLineStartSmart: function(cm) {
3403
- var cur = cm.getCursor(), start = lineStart(cm, cur.line);
3404
- var line = cm.getLineHandle(start.line);
3405
- var order = getOrder(line);
3406
- if (!order || order[0].level == 0) {
3407
- var firstNonWS = Math.max(0, line.text.search(/\S/));
3408
- var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
3409
- cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
3410
- } else cm.extendSelection(start);
3411
- },
3412
- goLineEnd: function(cm) {
3413
- cm.extendSelection(lineEnd(cm, cm.getCursor().line));
3414
- },
3415
- goLineRight: function(cm) {
3416
- var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3417
- cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
3418
- },
3419
- goLineLeft: function(cm) {
3420
- var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3421
- cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
3422
- },
3423
- goLineUp: function(cm) {cm.moveV(-1, "line");},
3424
- goLineDown: function(cm) {cm.moveV(1, "line");},
3425
- goPageUp: function(cm) {cm.moveV(-1, "page");},
3426
- goPageDown: function(cm) {cm.moveV(1, "page");},
3427
- goCharLeft: function(cm) {cm.moveH(-1, "char");},
3428
- goCharRight: function(cm) {cm.moveH(1, "char");},
3429
- goColumnLeft: function(cm) {cm.moveH(-1, "column");},
3430
- goColumnRight: function(cm) {cm.moveH(1, "column");},
3431
- goWordLeft: function(cm) {cm.moveH(-1, "word");},
3432
- goGroupRight: function(cm) {cm.moveH(1, "group");},
3433
- goGroupLeft: function(cm) {cm.moveH(-1, "group");},
3434
- goWordRight: function(cm) {cm.moveH(1, "word");},
3435
- delCharBefore: function(cm) {cm.deleteH(-1, "char");},
3436
- delCharAfter: function(cm) {cm.deleteH(1, "char");},
3437
- delWordBefore: function(cm) {cm.deleteH(-1, "word");},
3438
- delWordAfter: function(cm) {cm.deleteH(1, "word");},
3439
- delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
3440
- delGroupAfter: function(cm) {cm.deleteH(1, "group");},
3441
- indentAuto: function(cm) {cm.indentSelection("smart");},
3442
- indentMore: function(cm) {cm.indentSelection("add");},
3443
- indentLess: function(cm) {cm.indentSelection("subtract");},
3444
- insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
3445
- defaultTab: function(cm) {
3446
- if (cm.somethingSelected()) cm.indentSelection("add");
3447
- else cm.replaceSelection("\t", "end", "+input");
3448
- },
3449
- transposeChars: function(cm) {
3450
- var cur = cm.getCursor(), line = cm.getLine(cur.line);
3451
- if (cur.ch > 0 && cur.ch < line.length - 1)
3452
- cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
3453
- Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
3454
- },
3455
- newlineAndIndent: function(cm) {
3456
- operation(cm, function() {
3457
- cm.replaceSelection("\n", "end", "+input");
3458
- cm.indentLine(cm.getCursor().line, null, true);
3459
- })();
3460
- },
3461
- toggleOverwrite: function(cm) {cm.toggleOverwrite();}
3462
- };
3463
-
3464
- // STANDARD KEYMAPS
3465
-
3466
- var keyMap = CodeMirror.keyMap = {};
3467
- keyMap.basic = {
3468
- "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
3469
- "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
3470
- "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
3471
- "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
3472
- };
3473
- // Note that the save and find-related commands aren't defined by
3474
- // default. Unknown commands are simply ignored.
3475
- keyMap.pcDefault = {
3476
- "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
3477
- "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
3478
- "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
3479
- "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
3480
- "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
3481
- "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
3482
- fallthrough: "basic"
3483
- };
3484
- keyMap.macDefault = {
3485
- "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
3486
- "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
3487
- "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3488
- "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3489
- "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3490
- "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
3491
- fallthrough: ["basic", "emacsy"]
3492
- };
3493
- keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
3494
- keyMap.emacsy = {
3495
- "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
3496
- "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
3497
- "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
3498
- "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
3499
- };
3500
-
3501
- // KEYMAP DISPATCH
3502
-
3503
- function getKeyMap(val) {
3504
- if (typeof val == "string") return keyMap[val];
3505
- else return val;
3506
- }
3507
-
3508
- function lookupKey(name, maps, handle) {
3509
- function lookup(map) {
3510
- map = getKeyMap(map);
3511
- var found = map[name];
3512
- if (found === false) return "stop";
3513
- if (found != null && handle(found)) return true;
3514
- if (map.nofallthrough) return "stop";
3515
-
3516
- var fallthrough = map.fallthrough;
3517
- if (fallthrough == null) return false;
3518
- if (Object.prototype.toString.call(fallthrough) != "[object Array]")
3519
- return lookup(fallthrough);
3520
- for (var i = 0, e = fallthrough.length; i < e; ++i) {
3521
- var done = lookup(fallthrough[i]);
3522
- if (done) return done;
3523
- }
3524
- return false;
3525
- }
3526
-
3527
- for (var i = 0; i < maps.length; ++i) {
3528
- var done = lookup(maps[i]);
3529
- if (done) return done != "stop";
3530
- }
3531
- }
3532
- function isModifierKey(event) {
3533
- var name = keyNames[event.keyCode];
3534
- return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
3535
- }
3536
- function keyName(event, noShift) {
3537
- if (opera && event.keyCode == 34 && event["char"]) return false;
3538
- var name = keyNames[event.keyCode];
3539
- if (name == null || event.altGraphKey) return false;
3540
- if (event.altKey) name = "Alt-" + name;
3541
- if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
3542
- if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
3543
- if (!noShift && event.shiftKey) name = "Shift-" + name;
3544
- return name;
3545
- }
3546
- CodeMirror.lookupKey = lookupKey;
3547
- CodeMirror.isModifierKey = isModifierKey;
3548
- CodeMirror.keyName = keyName;
3549
-
3550
- // FROMTEXTAREA
3551
-
3552
- CodeMirror.fromTextArea = function(textarea, options) {
3553
- if (!options) options = {};
3554
- options.value = textarea.value;
3555
- if (!options.tabindex && textarea.tabindex)
3556
- options.tabindex = textarea.tabindex;
3557
- if (!options.placeholder && textarea.placeholder)
3558
- options.placeholder = textarea.placeholder;
3559
- // Set autofocus to true if this textarea is focused, or if it has
3560
- // autofocus and no other element is focused.
3561
- if (options.autofocus == null) {
3562
- var hasFocus = document.body;
3563
- // doc.activeElement occasionally throws on IE
3564
- try { hasFocus = document.activeElement; } catch(e) {}
3565
- options.autofocus = hasFocus == textarea ||
3566
- textarea.getAttribute("autofocus") != null && hasFocus == document.body;
3567
- }
3568
-
3569
- function save() {textarea.value = cm.getValue();}
3570
- if (textarea.form) {
3571
- on(textarea.form, "submit", save);
3572
- // Deplorable hack to make the submit method do the right thing.
3573
- if (!options.leaveSubmitMethodAlone) {
3574
- var form = textarea.form, realSubmit = form.submit;
3575
- try {
3576
- var wrappedSubmit = form.submit = function() {
3577
- save();
3578
- form.submit = realSubmit;
3579
- form.submit();
3580
- form.submit = wrappedSubmit;
3581
- };
3582
- } catch(e) {}
3583
- }
3584
- }
3585
-
3586
- textarea.style.display = "none";
3587
- var cm = CodeMirror(function(node) {
3588
- textarea.parentNode.insertBefore(node, textarea.nextSibling);
3589
- }, options);
3590
- cm.save = save;
3591
- cm.getTextArea = function() { return textarea; };
3592
- cm.toTextArea = function() {
3593
- save();
3594
- textarea.parentNode.removeChild(cm.getWrapperElement());
3595
- textarea.style.display = "";
3596
- if (textarea.form) {
3597
- off(textarea.form, "submit", save);
3598
- if (typeof textarea.form.submit == "function")
3599
- textarea.form.submit = realSubmit;
3600
- }
3601
- };
3602
- return cm;
3603
- };
3604
-
3605
- // STRING STREAM
3606
-
3607
- // Fed to the mode parsers, provides helper functions to make
3608
- // parsers more succinct.
3609
-
3610
- // The character stream used by a mode's parser.
3611
- function StringStream(string, tabSize) {
3612
- this.pos = this.start = 0;
3613
- this.string = string;
3614
- this.tabSize = tabSize || 8;
3615
- this.lastColumnPos = this.lastColumnValue = 0;
3616
- }
3617
-
3618
- StringStream.prototype = {
3619
- eol: function() {return this.pos >= this.string.length;},
3620
- sol: function() {return this.pos == 0;},
3621
- peek: function() {return this.string.charAt(this.pos) || undefined;},
3622
- next: function() {
3623
- if (this.pos < this.string.length)
3624
- return this.string.charAt(this.pos++);
3625
- },
3626
- eat: function(match) {
3627
- var ch = this.string.charAt(this.pos);
3628
- if (typeof match == "string") var ok = ch == match;
3629
- else var ok = ch && (match.test ? match.test(ch) : match(ch));
3630
- if (ok) {++this.pos; return ch;}
3631
- },
3632
- eatWhile: function(match) {
3633
- var start = this.pos;
3634
- while (this.eat(match)){}
3635
- return this.pos > start;
3636
- },
3637
- eatSpace: function() {
3638
- var start = this.pos;
3639
- while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
3640
- return this.pos > start;
3641
- },
3642
- skipToEnd: function() {this.pos = this.string.length;},
3643
- skipTo: function(ch) {
3644
- var found = this.string.indexOf(ch, this.pos);
3645
- if (found > -1) {this.pos = found; return true;}
3646
- },
3647
- backUp: function(n) {this.pos -= n;},
3648
- column: function() {
3649
- if (this.lastColumnPos < this.start) {
3650
- this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3651
- this.lastColumnPos = this.start;
3652
- }
3653
- return this.lastColumnValue;
3654
- },
3655
- indentation: function() {return countColumn(this.string, null, this.tabSize);},
3656
- match: function(pattern, consume, caseInsensitive) {
3657
- if (typeof pattern == "string") {
3658
- var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
3659
- var substr = this.string.substr(this.pos, pattern.length);
3660
- if (cased(substr) == cased(pattern)) {
3661
- if (consume !== false) this.pos += pattern.length;
3662
- return true;
3663
- }
3664
- } else {
3665
- var match = this.string.slice(this.pos).match(pattern);
3666
- if (match && match.index > 0) return null;
3667
- if (match && consume !== false) this.pos += match[0].length;
3668
- return match;
3669
- }
3670
- },
3671
- current: function(){return this.string.slice(this.start, this.pos);}
3672
- };
3673
- CodeMirror.StringStream = StringStream;
3674
-
3675
- // TEXTMARKERS
3676
-
3677
- function TextMarker(doc, type) {
3678
- this.lines = [];
3679
- this.type = type;
3680
- this.doc = doc;
3681
- }
3682
- CodeMirror.TextMarker = TextMarker;
3683
- eventMixin(TextMarker);
3684
-
3685
- TextMarker.prototype.clear = function() {
3686
- if (this.explicitlyCleared) return;
3687
- var cm = this.doc.cm, withOp = cm && !cm.curOp;
3688
- if (withOp) startOperation(cm);
3689
- if (hasHandler(this, "clear")) {
3690
- var found = this.find();
3691
- if (found) signalLater(this, "clear", found.from, found.to);
3692
- }
3693
- var min = null, max = null;
3694
- for (var i = 0; i < this.lines.length; ++i) {
3695
- var line = this.lines[i];
3696
- var span = getMarkedSpanFor(line.markedSpans, this);
3697
- if (span.to != null) max = lineNo(line);
3698
- line.markedSpans = removeMarkedSpan(line.markedSpans, span);
3699
- if (span.from != null)
3700
- min = lineNo(line);
3701
- else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
3702
- updateLineHeight(line, textHeight(cm.display));
3703
- }
3704
- if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
3705
- var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
3706
- if (len > cm.display.maxLineLength) {
3707
- cm.display.maxLine = visual;
3708
- cm.display.maxLineLength = len;
3709
- cm.display.maxLineChanged = true;
3710
- }
3711
- }
3712
-
3713
- if (min != null && cm) regChange(cm, min, max + 1);
3714
- this.lines.length = 0;
3715
- this.explicitlyCleared = true;
3716
- if (this.atomic && this.doc.cantEdit) {
3717
- this.doc.cantEdit = false;
3718
- if (cm) reCheckSelection(cm);
3719
- }
3720
- if (withOp) endOperation(cm);
3721
- };
3722
-
3723
- TextMarker.prototype.find = function() {
3724
- var from, to;
3725
- for (var i = 0; i < this.lines.length; ++i) {
3726
- var line = this.lines[i];
3727
- var span = getMarkedSpanFor(line.markedSpans, this);
3728
- if (span.from != null || span.to != null) {
3729
- var found = lineNo(line);
3730
- if (span.from != null) from = Pos(found, span.from);
3731
- if (span.to != null) to = Pos(found, span.to);
3732
- }
3733
- }
3734
- if (this.type == "bookmark") return from;
3735
- return from && {from: from, to: to};
3736
- };
3737
-
3738
- TextMarker.prototype.changed = function() {
3739
- var pos = this.find(), cm = this.doc.cm;
3740
- if (!pos || !cm) return;
3741
- var line = getLine(this.doc, pos.from.line);
3742
- clearCachedMeasurement(cm, line);
3743
- if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
3744
- for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3745
- if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3746
- break;
3747
- }
3748
- runInOp(cm, function() {
3749
- cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3750
- });
3751
- }
3752
- };
3753
-
3754
- TextMarker.prototype.attachLine = function(line) {
3755
- if (!this.lines.length && this.doc.cm) {
3756
- var op = this.doc.cm.curOp;
3757
- if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
3758
- (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
3759
- }
3760
- this.lines.push(line);
3761
- };
3762
- TextMarker.prototype.detachLine = function(line) {
3763
- this.lines.splice(indexOf(this.lines, line), 1);
3764
- if (!this.lines.length && this.doc.cm) {
3765
- var op = this.doc.cm.curOp;
3766
- (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
3767
- }
3768
- };
3769
-
3770
- function markText(doc, from, to, options, type) {
3771
- if (options && options.shared) return markTextShared(doc, from, to, options, type);
3772
- if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3773
-
3774
- var marker = new TextMarker(doc, type);
3775
- if (type == "range" && !posLess(from, to)) return marker;
3776
- if (options) copyObj(options, marker);
3777
- if (marker.replacedWith) {
3778
- marker.collapsed = true;
3779
- marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3780
- if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3781
- }
3782
- if (marker.collapsed) sawCollapsedSpans = true;
3783
-
3784
- if (marker.addToHistory)
3785
- addToHistory(doc, {from: from, to: to, origin: "markText"},
3786
- {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
3787
-
3788
- var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
3789
- doc.iter(curLine, to.line + 1, function(line) {
3790
- if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3791
- updateMaxLine = true;
3792
- var span = {from: null, to: null, marker: marker};
3793
- size += line.text.length;
3794
- if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
3795
- if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
3796
- if (marker.collapsed) {
3797
- if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
3798
- if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
3799
- else updateLineHeight(line, 0);
3800
- }
3801
- addMarkedSpan(line, span);
3802
- ++curLine;
3803
- });
3804
- if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
3805
- if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
3806
- });
3807
-
3808
- if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
3809
-
3810
- if (marker.readOnly) {
3811
- sawReadOnlySpans = true;
3812
- if (doc.history.done.length || doc.history.undone.length)
3813
- doc.clearHistory();
3814
- }
3815
- if (marker.collapsed) {
3816
- if (collapsedAtStart != collapsedAtEnd)
3817
- throw new Error("Inserting collapsed marker overlapping an existing one");
3818
- marker.size = size;
3819
- marker.atomic = true;
3820
- }
3821
- if (cm) {
3822
- if (updateMaxLine) cm.curOp.updateMaxLine = true;
3823
- if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3824
- regChange(cm, from.line, to.line + 1);
3825
- if (marker.atomic) reCheckSelection(cm);
3826
- }
3827
- return marker;
3828
- }
3829
-
3830
- // SHARED TEXTMARKERS
3831
-
3832
- function SharedTextMarker(markers, primary) {
3833
- this.markers = markers;
3834
- this.primary = primary;
3835
- for (var i = 0, me = this; i < markers.length; ++i) {
3836
- markers[i].parent = this;
3837
- on(markers[i], "clear", function(){me.clear();});
3838
- }
3839
- }
3840
- CodeMirror.SharedTextMarker = SharedTextMarker;
3841
- eventMixin(SharedTextMarker);
3842
-
3843
- SharedTextMarker.prototype.clear = function() {
3844
- if (this.explicitlyCleared) return;
3845
- this.explicitlyCleared = true;
3846
- for (var i = 0; i < this.markers.length; ++i)
3847
- this.markers[i].clear();
3848
- signalLater(this, "clear");
3849
- };
3850
- SharedTextMarker.prototype.find = function() {
3851
- return this.primary.find();
3852
- };
3853
-
3854
- function markTextShared(doc, from, to, options, type) {
3855
- options = copyObj(options);
3856
- options.shared = false;
3857
- var markers = [markText(doc, from, to, options, type)], primary = markers[0];
3858
- var widget = options.replacedWith;
3859
- linkedDocs(doc, function(doc) {
3860
- if (widget) options.replacedWith = widget.cloneNode(true);
3861
- markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
3862
- for (var i = 0; i < doc.linked.length; ++i)
3863
- if (doc.linked[i].isParent) return;
3864
- primary = lst(markers);
3865
- });
3866
- return new SharedTextMarker(markers, primary);
3867
- }
3868
-
3869
- // TEXTMARKER SPANS
3870
-
3871
- function getMarkedSpanFor(spans, marker) {
3872
- if (spans) for (var i = 0; i < spans.length; ++i) {
3873
- var span = spans[i];
3874
- if (span.marker == marker) return span;
3875
- }
3876
- }
3877
- function removeMarkedSpan(spans, span) {
3878
- for (var r, i = 0; i < spans.length; ++i)
3879
- if (spans[i] != span) (r || (r = [])).push(spans[i]);
3880
- return r;
3881
- }
3882
- function addMarkedSpan(line, span) {
3883
- line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
3884
- span.marker.attachLine(line);
3885
- }
3886
-
3887
- function markedSpansBefore(old, startCh, isInsert) {
3888
- if (old) for (var i = 0, nw; i < old.length; ++i) {
3889
- var span = old[i], marker = span.marker;
3890
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3891
- if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
3892
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
3893
- (nw || (nw = [])).push({from: span.from,
3894
- to: endsAfter ? null : span.to,
3895
- marker: marker});
3896
- }
3897
- }
3898
- return nw;
3899
- }
3900
-
3901
- function markedSpansAfter(old, endCh, isInsert) {
3902
- if (old) for (var i = 0, nw; i < old.length; ++i) {
3903
- var span = old[i], marker = span.marker;
3904
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3905
- if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
3906
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
3907
- (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
3908
- to: span.to == null ? null : span.to - endCh,
3909
- marker: marker});
3910
- }
3911
- }
3912
- return nw;
3913
- }
3914
-
3915
- function stretchSpansOverChange(doc, change) {
3916
- var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
3917
- var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
3918
- if (!oldFirst && !oldLast) return null;
3919
-
3920
- var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
3921
- // Get the spans that 'stick out' on both sides
3922
- var first = markedSpansBefore(oldFirst, startCh, isInsert);
3923
- var last = markedSpansAfter(oldLast, endCh, isInsert);
3924
-
3925
- // Next, merge those two ends
3926
- var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
3927
- if (first) {
3928
- // Fix up .to properties of first
3929
- for (var i = 0; i < first.length; ++i) {
3930
- var span = first[i];
3931
- if (span.to == null) {
3932
- var found = getMarkedSpanFor(last, span.marker);
3933
- if (!found) span.to = startCh;
3934
- else if (sameLine) span.to = found.to == null ? null : found.to + offset;
3935
- }
3936
- }
3937
- }
3938
- if (last) {
3939
- // Fix up .from in last (or move them into first in case of sameLine)
3940
- for (var i = 0; i < last.length; ++i) {
3941
- var span = last[i];
3942
- if (span.to != null) span.to += offset;
3943
- if (span.from == null) {
3944
- var found = getMarkedSpanFor(first, span.marker);
3945
- if (!found) {
3946
- span.from = offset;
3947
- if (sameLine) (first || (first = [])).push(span);
3948
- }
3949
- } else {
3950
- span.from += offset;
3951
- if (sameLine) (first || (first = [])).push(span);
3952
- }
3953
- }
3954
- }
3955
- if (sameLine && first) {
3956
- // Make sure we didn't create any zero-length spans
3957
- for (var i = 0; i < first.length; ++i)
3958
- if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
3959
- first.splice(i--, 1);
3960
- if (!first.length) first = null;
3961
- }
3962
-
3963
- var newMarkers = [first];
3964
- if (!sameLine) {
3965
- // Fill gap with whole-line-spans
3966
- var gap = change.text.length - 2, gapMarkers;
3967
- if (gap > 0 && first)
3968
- for (var i = 0; i < first.length; ++i)
3969
- if (first[i].to == null)
3970
- (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
3971
- for (var i = 0; i < gap; ++i)
3972
- newMarkers.push(gapMarkers);
3973
- newMarkers.push(last);
3974
- }
3975
- return newMarkers;
3976
- }
3977
-
3978
- function mergeOldSpans(doc, change) {
3979
- var old = getOldSpans(doc, change);
3980
- var stretched = stretchSpansOverChange(doc, change);
3981
- if (!old) return stretched;
3982
- if (!stretched) return old;
3983
-
3984
- for (var i = 0; i < old.length; ++i) {
3985
- var oldCur = old[i], stretchCur = stretched[i];
3986
- if (oldCur && stretchCur) {
3987
- spans: for (var j = 0; j < stretchCur.length; ++j) {
3988
- var span = stretchCur[j];
3989
- for (var k = 0; k < oldCur.length; ++k)
3990
- if (oldCur[k].marker == span.marker) continue spans;
3991
- oldCur.push(span);
3992
- }
3993
- } else if (stretchCur) {
3994
- old[i] = stretchCur;
3995
- }
3996
- }
3997
- return old;
3998
- }
3999
-
4000
- function removeReadOnlyRanges(doc, from, to) {
4001
- var markers = null;
4002
- doc.iter(from.line, to.line + 1, function(line) {
4003
- if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
4004
- var mark = line.markedSpans[i].marker;
4005
- if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
4006
- (markers || (markers = [])).push(mark);
4007
- }
4008
- });
4009
- if (!markers) return null;
4010
- var parts = [{from: from, to: to}];
4011
- for (var i = 0; i < markers.length; ++i) {
4012
- var mk = markers[i], m = mk.find();
4013
- for (var j = 0; j < parts.length; ++j) {
4014
- var p = parts[j];
4015
- if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
4016
- var newParts = [j, 1];
4017
- if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
4018
- newParts.push({from: p.from, to: m.from});
4019
- if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
4020
- newParts.push({from: m.to, to: p.to});
4021
- parts.splice.apply(parts, newParts);
4022
- j += newParts.length - 1;
4023
- }
4024
- }
4025
- return parts;
4026
- }
4027
-
4028
- function collapsedSpanAt(line, ch) {
4029
- var sps = sawCollapsedSpans && line.markedSpans, found;
4030
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4031
- sp = sps[i];
4032
- if (!sp.marker.collapsed) continue;
4033
- if ((sp.from == null || sp.from < ch) &&
4034
- (sp.to == null || sp.to > ch) &&
4035
- (!found || found.width < sp.marker.width))
4036
- found = sp.marker;
4037
- }
4038
- return found;
4039
- }
4040
- function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
4041
- function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
4042
-
4043
- function visualLine(doc, line) {
4044
- var merged;
4045
- while (merged = collapsedSpanAtStart(line))
4046
- line = getLine(doc, merged.find().from.line);
4047
- return line;
4048
- }
4049
-
4050
- function lineIsHidden(doc, line) {
4051
- var sps = sawCollapsedSpans && line.markedSpans;
4052
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4053
- sp = sps[i];
4054
- if (!sp.marker.collapsed) continue;
4055
- if (sp.from == null) return true;
4056
- if (sp.marker.replacedWith) continue;
4057
- if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
4058
- return true;
4059
- }
4060
- }
4061
- function lineIsHiddenInner(doc, line, span) {
4062
- if (span.to == null) {
4063
- var end = span.marker.find().to, endLine = getLine(doc, end.line);
4064
- return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
4065
- }
4066
- if (span.marker.inclusiveRight && span.to == line.text.length)
4067
- return true;
4068
- for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4069
- sp = line.markedSpans[i];
4070
- if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
4071
- (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4072
- lineIsHiddenInner(doc, line, sp)) return true;
4073
- }
4074
- }
4075
-
4076
- function detachMarkedSpans(line) {
4077
- var spans = line.markedSpans;
4078
- if (!spans) return;
4079
- for (var i = 0; i < spans.length; ++i)
4080
- spans[i].marker.detachLine(line);
4081
- line.markedSpans = null;
4082
- }
4083
-
4084
- function attachMarkedSpans(line, spans) {
4085
- if (!spans) return;
4086
- for (var i = 0; i < spans.length; ++i)
4087
- spans[i].marker.attachLine(line);
4088
- line.markedSpans = spans;
4089
- }
4090
-
4091
- // LINE WIDGETS
4092
-
4093
- var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4094
- if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4095
- this[opt] = options[opt];
4096
- this.cm = cm;
4097
- this.node = node;
4098
- };
4099
- eventMixin(LineWidget);
4100
- function widgetOperation(f) {
4101
- return function() {
4102
- var withOp = !this.cm.curOp;
4103
- if (withOp) startOperation(this.cm);
4104
- try {var result = f.apply(this, arguments);}
4105
- finally {if (withOp) endOperation(this.cm);}
4106
- return result;
4107
- };
4108
- }
4109
- LineWidget.prototype.clear = widgetOperation(function() {
4110
- var ws = this.line.widgets, no = lineNo(this.line);
4111
- if (no == null || !ws) return;
4112
- for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4113
- if (!ws.length) this.line.widgets = null;
4114
- var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4115
- updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4116
- if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4117
- regChange(this.cm, no, no + 1);
4118
- });
4119
- LineWidget.prototype.changed = widgetOperation(function() {
4120
- var oldH = this.height;
4121
- this.height = null;
4122
- var diff = widgetHeight(this) - oldH;
4123
- if (!diff) return;
4124
- updateLineHeight(this.line, this.line.height + diff);
4125
- var no = lineNo(this.line);
4126
- regChange(this.cm, no, no + 1);
4127
- });
4128
-
4129
- function widgetHeight(widget) {
4130
- if (widget.height != null) return widget.height;
4131
- if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
4132
- removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
4133
- return widget.height = widget.node.offsetHeight;
4134
- }
4135
-
4136
- function addLineWidget(cm, handle, node, options) {
4137
- var widget = new LineWidget(cm, node, options);
4138
- if (widget.noHScroll) cm.display.alignWidgets = true;
4139
- changeLine(cm, handle, function(line) {
4140
- var widgets = line.widgets || (line.widgets = []);
4141
- if (widget.insertAt == null) widgets.push(widget);
4142
- else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4143
- widget.line = line;
4144
- if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4145
- var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4146
- updateLineHeight(line, line.height + widgetHeight(widget));
4147
- if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4148
- }
4149
- return true;
4150
- });
4151
- return widget;
4152
- }
4153
-
4154
- // LINE DATA STRUCTURE
4155
-
4156
- // Line objects. These hold state related to a line, including
4157
- // highlighting info (the styles array).
4158
- var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4159
- this.text = text;
4160
- attachMarkedSpans(this, markedSpans);
4161
- this.height = estimateHeight ? estimateHeight(this) : 1;
4162
- };
4163
- eventMixin(Line);
4164
-
4165
- function updateLine(line, text, markedSpans, estimateHeight) {
4166
- line.text = text;
4167
- if (line.stateAfter) line.stateAfter = null;
4168
- if (line.styles) line.styles = null;
4169
- if (line.order != null) line.order = null;
4170
- detachMarkedSpans(line);
4171
- attachMarkedSpans(line, markedSpans);
4172
- var estHeight = estimateHeight ? estimateHeight(line) : 1;
4173
- if (estHeight != line.height) updateLineHeight(line, estHeight);
4174
- }
4175
-
4176
- function cleanUpLine(line) {
4177
- line.parent = null;
4178
- detachMarkedSpans(line);
4179
- }
4180
-
4181
- // Run the given mode's parser over a line, update the styles
4182
- // array, which contains alternating fragments of text and CSS
4183
- // classes.
4184
- function runMode(cm, text, mode, state, f) {
4185
- var flattenSpans = mode.flattenSpans;
4186
- if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4187
- var curStart = 0, curStyle = null;
4188
- var stream = new StringStream(text, cm.options.tabSize), style;
4189
- if (text == "" && mode.blankLine) mode.blankLine(state);
4190
- while (!stream.eol()) {
4191
- if (stream.pos > cm.options.maxHighlightLength) {
4192
- flattenSpans = false;
4193
- // Webkit seems to refuse to render text nodes longer than 57444 characters
4194
- stream.pos = Math.min(text.length, stream.start + 50000);
4195
- style = null;
4196
- } else {
4197
- style = mode.token(stream, state);
4198
- }
4199
- if (!flattenSpans || curStyle != style) {
4200
- if (curStart < stream.start) f(stream.start, curStyle);
4201
- curStart = stream.start; curStyle = style;
4202
- }
4203
- stream.start = stream.pos;
4204
- }
4205
- if (curStart < stream.pos) f(stream.pos, curStyle);
4206
- }
4207
-
4208
- function highlightLine(cm, line, state) {
4209
- // A styles array always starts with a number identifying the
4210
- // mode/overlays that it is based on (for easy invalidation).
4211
- var st = [cm.state.modeGen];
4212
- // Compute the base array of styles
4213
- runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4214
-
4215
- // Run overlays, adjust style array.
4216
- for (var o = 0; o < cm.state.overlays.length; ++o) {
4217
- var overlay = cm.state.overlays[o], i = 1, at = 0;
4218
- runMode(cm, line.text, overlay.mode, true, function(end, style) {
4219
- var start = i;
4220
- // Ensure there's a token end at the current position, and that i points at it
4221
- while (at < end) {
4222
- var i_end = st[i];
4223
- if (i_end > end)
4224
- st.splice(i, 1, end, st[i+1], i_end);
4225
- i += 2;
4226
- at = Math.min(end, i_end);
4227
- }
4228
- if (!style) return;
4229
- if (overlay.opaque) {
4230
- st.splice(start, i - start, end, style);
4231
- i = start + 2;
4232
- } else {
4233
- for (; start < i; start += 2) {
4234
- var cur = st[start+1];
4235
- st[start+1] = cur ? cur + " " + style : style;
4236
- }
4237
- }
4238
- });
4239
- }
4240
-
4241
- return st;
4242
- }
4243
-
4244
- function getLineStyles(cm, line) {
4245
- if (!line.styles || line.styles[0] != cm.state.modeGen)
4246
- line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
4247
- return line.styles;
4248
- }
4249
-
4250
- // Lightweight form of highlight -- proceed over this line and
4251
- // update state, but don't save a style array.
4252
- function processLine(cm, line, state) {
4253
- var mode = cm.doc.mode;
4254
- var stream = new StringStream(line.text, cm.options.tabSize);
4255
- if (line.text == "" && mode.blankLine) mode.blankLine(state);
4256
- while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
4257
- mode.token(stream, state);
4258
- stream.start = stream.pos;
4259
- }
4260
- }
4261
-
4262
- var styleToClassCache = {};
4263
- function styleToClass(style) {
4264
- if (!style) return null;
4265
- return styleToClassCache[style] ||
4266
- (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4267
- }
4268
-
4269
- function lineContent(cm, realLine, measure, copyWidgets) {
4270
- var merged, line = realLine, empty = true;
4271
- while (merged = collapsedSpanAtStart(line))
4272
- line = getLine(cm.doc, merged.find().from.line);
4273
-
4274
- var builder = {pre: elt("pre"), col: 0, pos: 0,
4275
- measure: null, measuredSomething: false, cm: cm,
4276
- copyWidgets: copyWidgets};
4277
- if (line.textClass) builder.pre.className = line.textClass;
4278
-
4279
- do {
4280
- if (line.text) empty = false;
4281
- builder.measure = line == realLine && measure;
4282
- builder.pos = 0;
4283
- builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4284
- if ((ie || webkit) && cm.getOption("lineWrapping"))
4285
- builder.addToken = buildTokenSplitSpaces(builder.addToken);
4286
- var next = insertLineContent(line, builder, getLineStyles(cm, line));
4287
- if (measure && line == realLine && !builder.measuredSomething) {
4288
- measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4289
- builder.measuredSomething = true;
4290
- }
4291
- if (next) line = getLine(cm.doc, next.to.line);
4292
- } while (next);
4293
-
4294
- if (measure && !builder.measuredSomething && !measure[0])
4295
- measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4296
- if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4297
- builder.pre.appendChild(document.createTextNode("\u00a0"));
4298
-
4299
- var order;
4300
- // Work around problem with the reported dimensions of single-char
4301
- // direction spans on IE (issue #1129). See also the comment in
4302
- // cursorCoords.
4303
- if (measure && ie && (order = getOrder(line))) {
4304
- var l = order.length - 1;
4305
- if (order[l].from == order[l].to) --l;
4306
- var last = order[l], prev = order[l - 1];
4307
- if (last.from + 1 == last.to && prev && last.level < prev.level) {
4308
- var span = measure[builder.pos - 1];
4309
- if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
4310
- span.nextSibling);
4311
- }
4312
- }
4313
-
4314
- signal(cm, "renderLine", cm, realLine, builder.pre);
4315
- return builder.pre;
4316
- }
4317
-
4318
- var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4319
- function buildToken(builder, text, style, startStyle, endStyle, title) {
4320
- if (!text) return;
4321
- if (!tokenSpecialChars.test(text)) {
4322
- builder.col += text.length;
4323
- var content = document.createTextNode(text);
4324
- } else {
4325
- var content = document.createDocumentFragment(), pos = 0;
4326
- while (true) {
4327
- tokenSpecialChars.lastIndex = pos;
4328
- var m = tokenSpecialChars.exec(text);
4329
- var skipped = m ? m.index - pos : text.length - pos;
4330
- if (skipped) {
4331
- content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
4332
- builder.col += skipped;
4333
- }
4334
- if (!m) break;
4335
- pos += skipped + 1;
4336
- if (m[0] == "\t") {
4337
- var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
4338
- content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
4339
- builder.col += tabWidth;
4340
- } else {
4341
- var token = elt("span", "\u2022", "cm-invalidchar");
4342
- token.title = "\\u" + m[0].charCodeAt(0).toString(16);
4343
- content.appendChild(token);
4344
- builder.col += 1;
4345
- }
4346
- }
4347
- }
4348
- if (style || startStyle || endStyle || builder.measure) {
4349
- var fullStyle = style || "";
4350
- if (startStyle) fullStyle += startStyle;
4351
- if (endStyle) fullStyle += endStyle;
4352
- var token = elt("span", [content], fullStyle);
4353
- if (title) token.title = title;
4354
- return builder.pre.appendChild(token);
4355
- }
4356
- builder.pre.appendChild(content);
4357
- }
4358
-
4359
- function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4360
- var wrapping = builder.cm.options.lineWrapping;
4361
- for (var i = 0; i < text.length; ++i) {
4362
- var ch = text.charAt(i), start = i == 0;
4363
- if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4364
- ch = text.slice(i, i + 2);
4365
- ++i;
4366
- } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4367
- builder.pre.appendChild(elt("wbr"));
4368
- }
4369
- var old = builder.measure[builder.pos];
4370
- var span = builder.measure[builder.pos] =
4371
- buildToken(builder, ch, style,
4372
- start && startStyle, i == text.length - 1 && endStyle);
4373
- if (old) span.leftSide = old.leftSide || old;
4374
- // In IE single-space nodes wrap differently than spaces
4375
- // embedded in larger text nodes, except when set to
4376
- // white-space: normal (issue #1268).
4377
- if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4378
- i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4379
- span.style.whiteSpace = "normal";
4380
- builder.pos += ch.length;
4381
- }
4382
- if (text.length) builder.measuredSomething = true;
4383
- }
4384
-
4385
- function buildTokenSplitSpaces(inner) {
4386
- function split(old) {
4387
- var out = " ";
4388
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
4389
- out += " ";
4390
- return out;
4391
- }
4392
- return function(builder, text, style, startStyle, endStyle, title) {
4393
- return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
4394
- };
4395
- }
4396
-
4397
- function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4398
- var widget = !ignoreWidget && marker.replacedWith;
4399
- if (widget) {
4400
- if (builder.copyWidgets) widget = widget.cloneNode(true);
4401
- builder.pre.appendChild(widget);
4402
- if (builder.measure) {
4403
- if (size) {
4404
- builder.measure[builder.pos] = widget;
4405
- } else {
4406
- var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
4407
- if (marker.type != "bookmark" || marker.insertLeft)
4408
- builder.pre.insertBefore(elt, widget);
4409
- else
4410
- builder.pre.appendChild(elt);
4411
- }
4412
- builder.measuredSomething = true;
4413
- }
4414
- }
4415
- builder.pos += size;
4416
- }
4417
-
4418
- // Outputs a number of spans to make up a line, taking highlighting
4419
- // and marked text into account.
4420
- function insertLineContent(line, builder, styles) {
4421
- var spans = line.markedSpans, allText = line.text, at = 0;
4422
- if (!spans) {
4423
- for (var i = 1; i < styles.length; i+=2)
4424
- builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
4425
- return;
4426
- }
4427
-
4428
- var len = allText.length, pos = 0, i = 1, text = "", style;
4429
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
4430
- for (;;) {
4431
- if (nextChange == pos) { // Update current marker set
4432
- spanStyle = spanEndStyle = spanStartStyle = title = "";
4433
- collapsed = null; nextChange = Infinity;
4434
- var foundBookmark = null;
4435
- for (var j = 0; j < spans.length; ++j) {
4436
- var sp = spans[j], m = sp.marker;
4437
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
4438
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
4439
- if (m.className) spanStyle += " " + m.className;
4440
- if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4441
- if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4442
- if (m.title && !title) title = m.title;
4443
- if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4444
- collapsed = sp;
4445
- } else if (sp.from > pos && nextChange > sp.from) {
4446
- nextChange = sp.from;
4447
- }
4448
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
4449
- }
4450
- if (collapsed && (collapsed.from || 0) == pos) {
4451
- buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4452
- collapsed.marker, collapsed.from == null);
4453
- if (collapsed.to == null) return collapsed.marker.find();
4454
- }
4455
- if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
4456
- }
4457
- if (pos >= len) break;
4458
-
4459
- var upto = Math.min(len, nextChange);
4460
- while (true) {
4461
- if (text) {
4462
- var end = pos + text.length;
4463
- if (!collapsed) {
4464
- var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4465
- builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4466
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4467
- }
4468
- if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
4469
- pos = end;
4470
- spanStartStyle = "";
4471
- }
4472
- text = allText.slice(at, at = styles[i++]);
4473
- style = styleToClass(styles[i++]);
4474
- }
4475
- }
4476
- }
4477
-
4478
- // DOCUMENT DATA STRUCTURE
4479
-
4480
- function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
4481
- function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
4482
- function update(line, text, spans) {
4483
- updateLine(line, text, spans, estimateHeight);
4484
- signalLater(line, "change", line, change);
4485
- }
4486
-
4487
- var from = change.from, to = change.to, text = change.text;
4488
- var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4489
- var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4490
-
4491
- // First adjust the line structure
4492
- if (from.ch == 0 && to.ch == 0 && lastText == "") {
4493
- // This is a whole-line replace. Treated specially to make
4494
- // sure line objects move the way they are supposed to.
4495
- for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4496
- added.push(new Line(text[i], spansFor(i), estimateHeight));
4497
- update(lastLine, lastLine.text, lastSpans);
4498
- if (nlines) doc.remove(from.line, nlines);
4499
- if (added.length) doc.insert(from.line, added);
4500
- } else if (firstLine == lastLine) {
4501
- if (text.length == 1) {
4502
- update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4503
- } else {
4504
- for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4505
- added.push(new Line(text[i], spansFor(i), estimateHeight));
4506
- added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4507
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4508
- doc.insert(from.line + 1, added);
4509
- }
4510
- } else if (text.length == 1) {
4511
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4512
- doc.remove(from.line + 1, nlines);
4513
- } else {
4514
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4515
- update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4516
- for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4517
- added.push(new Line(text[i], spansFor(i), estimateHeight));
4518
- if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4519
- doc.insert(from.line + 1, added);
4520
- }
4521
-
4522
- signalLater(doc, "change", doc, change);
4523
- setSelection(doc, selAfter.anchor, selAfter.head, null, true);
4524
- }
4525
-
4526
- function LeafChunk(lines) {
4527
- this.lines = lines;
4528
- this.parent = null;
4529
- for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
4530
- lines[i].parent = this;
4531
- height += lines[i].height;
4532
- }
4533
- this.height = height;
4534
- }
4535
-
4536
- LeafChunk.prototype = {
4537
- chunkSize: function() { return this.lines.length; },
4538
- removeInner: function(at, n) {
4539
- for (var i = at, e = at + n; i < e; ++i) {
4540
- var line = this.lines[i];
4541
- this.height -= line.height;
4542
- cleanUpLine(line);
4543
- signalLater(line, "delete");
4544
- }
4545
- this.lines.splice(at, n);
4546
- },
4547
- collapse: function(lines) {
4548
- lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
4549
- },
4550
- insertInner: function(at, lines, height) {
4551
- this.height += height;
4552
- this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
4553
- for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
4554
- },
4555
- iterN: function(at, n, op) {
4556
- for (var e = at + n; at < e; ++at)
4557
- if (op(this.lines[at])) return true;
4558
- }
4559
- };
4560
-
4561
- function BranchChunk(children) {
4562
- this.children = children;
4563
- var size = 0, height = 0;
4564
- for (var i = 0, e = children.length; i < e; ++i) {
4565
- var ch = children[i];
4566
- size += ch.chunkSize(); height += ch.height;
4567
- ch.parent = this;
4568
- }
4569
- this.size = size;
4570
- this.height = height;
4571
- this.parent = null;
4572
- }
4573
-
4574
- BranchChunk.prototype = {
4575
- chunkSize: function() { return this.size; },
4576
- removeInner: function(at, n) {
4577
- this.size -= n;
4578
- for (var i = 0; i < this.children.length; ++i) {
4579
- var child = this.children[i], sz = child.chunkSize();
4580
- if (at < sz) {
4581
- var rm = Math.min(n, sz - at), oldHeight = child.height;
4582
- child.removeInner(at, rm);
4583
- this.height -= oldHeight - child.height;
4584
- if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
4585
- if ((n -= rm) == 0) break;
4586
- at = 0;
4587
- } else at -= sz;
4588
- }
4589
- if (this.size - n < 25) {
4590
- var lines = [];
4591
- this.collapse(lines);
4592
- this.children = [new LeafChunk(lines)];
4593
- this.children[0].parent = this;
4594
- }
4595
- },
4596
- collapse: function(lines) {
4597
- for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
4598
- },
4599
- insertInner: function(at, lines, height) {
4600
- this.size += lines.length;
4601
- this.height += height;
4602
- for (var i = 0, e = this.children.length; i < e; ++i) {
4603
- var child = this.children[i], sz = child.chunkSize();
4604
- if (at <= sz) {
4605
- child.insertInner(at, lines, height);
4606
- if (child.lines && child.lines.length > 50) {
4607
- while (child.lines.length > 50) {
4608
- var spilled = child.lines.splice(child.lines.length - 25, 25);
4609
- var newleaf = new LeafChunk(spilled);
4610
- child.height -= newleaf.height;
4611
- this.children.splice(i + 1, 0, newleaf);
4612
- newleaf.parent = this;
4613
- }
4614
- this.maybeSpill();
4615
- }
4616
- break;
4617
- }
4618
- at -= sz;
4619
- }
4620
- },
4621
- maybeSpill: function() {
4622
- if (this.children.length <= 10) return;
4623
- var me = this;
4624
- do {
4625
- var spilled = me.children.splice(me.children.length - 5, 5);
4626
- var sibling = new BranchChunk(spilled);
4627
- if (!me.parent) { // Become the parent node
4628
- var copy = new BranchChunk(me.children);
4629
- copy.parent = me;
4630
- me.children = [copy, sibling];
4631
- me = copy;
4632
- } else {
4633
- me.size -= sibling.size;
4634
- me.height -= sibling.height;
4635
- var myIndex = indexOf(me.parent.children, me);
4636
- me.parent.children.splice(myIndex + 1, 0, sibling);
4637
- }
4638
- sibling.parent = me.parent;
4639
- } while (me.children.length > 10);
4640
- me.parent.maybeSpill();
4641
- },
4642
- iterN: function(at, n, op) {
4643
- for (var i = 0, e = this.children.length; i < e; ++i) {
4644
- var child = this.children[i], sz = child.chunkSize();
4645
- if (at < sz) {
4646
- var used = Math.min(n, sz - at);
4647
- if (child.iterN(at, used, op)) return true;
4648
- if ((n -= used) == 0) break;
4649
- at = 0;
4650
- } else at -= sz;
4651
- }
4652
- }
4653
- };
4654
-
4655
- var nextDocId = 0;
4656
- var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
4657
- if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4658
- if (firstLine == null) firstLine = 0;
4659
-
4660
- BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4661
- this.first = firstLine;
4662
- this.scrollTop = this.scrollLeft = 0;
4663
- this.cantEdit = false;
4664
- this.history = makeHistory();
4665
- this.cleanGeneration = 1;
4666
- this.frontier = firstLine;
4667
- var start = Pos(firstLine, 0);
4668
- this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4669
- this.id = ++nextDocId;
4670
- this.modeOption = mode;
4671
-
4672
- if (typeof text == "string") text = splitLines(text);
4673
- updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
4674
- };
4675
-
4676
- Doc.prototype = createObj(BranchChunk.prototype, {
4677
- constructor: Doc,
4678
- iter: function(from, to, op) {
4679
- if (op) this.iterN(from - this.first, to - from, op);
4680
- else this.iterN(this.first, this.first + this.size, from);
4681
- },
4682
-
4683
- insert: function(at, lines) {
4684
- var height = 0;
4685
- for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
4686
- this.insertInner(at - this.first, lines, height);
4687
- },
4688
- remove: function(at, n) { this.removeInner(at - this.first, n); },
4689
-
4690
- getValue: function(lineSep) {
4691
- var lines = getLines(this, this.first, this.first + this.size);
4692
- if (lineSep === false) return lines;
4693
- return lines.join(lineSep || "\n");
4694
- },
4695
- setValue: function(code) {
4696
- var top = Pos(this.first, 0), last = this.first + this.size - 1;
4697
- makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
4698
- text: splitLines(code), origin: "setValue"},
4699
- {head: top, anchor: top}, true);
4700
- },
4701
- replaceRange: function(code, from, to, origin) {
4702
- from = clipPos(this, from);
4703
- to = to ? clipPos(this, to) : from;
4704
- replaceRange(this, code, from, to, origin);
4705
- },
4706
- getRange: function(from, to, lineSep) {
4707
- var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
4708
- if (lineSep === false) return lines;
4709
- return lines.join(lineSep || "\n");
4710
- },
4711
-
4712
- getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
4713
- setLine: function(line, text) {
4714
- if (isLine(this, line))
4715
- replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
4716
- },
4717
- removeLine: function(line) {
4718
- if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
4719
- else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
4720
- },
4721
-
4722
- getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4723
- getLineNumber: function(line) {return lineNo(line);},
4724
-
4725
- getLineHandleVisualStart: function(line) {
4726
- if (typeof line == "number") line = getLine(this, line);
4727
- return visualLine(this, line);
4728
- },
4729
-
4730
- lineCount: function() {return this.size;},
4731
- firstLine: function() {return this.first;},
4732
- lastLine: function() {return this.first + this.size - 1;},
4733
-
4734
- clipPos: function(pos) {return clipPos(this, pos);},
4735
-
4736
- getCursor: function(start) {
4737
- var sel = this.sel, pos;
4738
- if (start == null || start == "head") pos = sel.head;
4739
- else if (start == "anchor") pos = sel.anchor;
4740
- else if (start == "end" || start === false) pos = sel.to;
4741
- else pos = sel.from;
4742
- return copyPos(pos);
4743
- },
4744
- somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
4745
-
4746
- setCursor: docOperation(function(line, ch, extend) {
4747
- var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
4748
- if (extend) extendSelection(this, pos);
4749
- else setSelection(this, pos, pos);
4750
- }),
4751
- setSelection: docOperation(function(anchor, head) {
4752
- setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
4753
- }),
4754
- extendSelection: docOperation(function(from, to) {
4755
- extendSelection(this, clipPos(this, from), to && clipPos(this, to));
4756
- }),
4757
-
4758
- getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
4759
- replaceSelection: function(code, collapse, origin) {
4760
- makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
4761
- },
4762
- undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
4763
- redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
4764
-
4765
- setExtending: function(val) {this.sel.extend = val;},
4766
-
4767
- historySize: function() {
4768
- var hist = this.history;
4769
- return {undo: hist.done.length, redo: hist.undone.length};
4770
- },
4771
- clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4772
-
4773
- markClean: function() {
4774
- this.cleanGeneration = this.changeGeneration();
4775
- },
4776
- changeGeneration: function() {
4777
- this.history.lastOp = this.history.lastOrigin = null;
4778
- return this.history.generation;
4779
- },
4780
- isClean: function (gen) {
4781
- return this.history.generation == (gen || this.cleanGeneration);
4782
- },
4783
-
4784
- getHistory: function() {
4785
- return {done: copyHistoryArray(this.history.done),
4786
- undone: copyHistoryArray(this.history.undone)};
4787
- },
4788
- setHistory: function(histData) {
4789
- var hist = this.history = makeHistory(this.history.maxGeneration);
4790
- hist.done = histData.done.slice(0);
4791
- hist.undone = histData.undone.slice(0);
4792
- },
4793
-
4794
- markText: function(from, to, options) {
4795
- return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
4796
- },
4797
- setBookmark: function(pos, options) {
4798
- var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4799
- insertLeft: options && options.insertLeft};
4800
- pos = clipPos(this, pos);
4801
- return markText(this, pos, pos, realOpts, "bookmark");
4802
- },
4803
- findMarksAt: function(pos) {
4804
- pos = clipPos(this, pos);
4805
- var markers = [], spans = getLine(this, pos.line).markedSpans;
4806
- if (spans) for (var i = 0; i < spans.length; ++i) {
4807
- var span = spans[i];
4808
- if ((span.from == null || span.from <= pos.ch) &&
4809
- (span.to == null || span.to >= pos.ch))
4810
- markers.push(span.marker.parent || span.marker);
4811
- }
4812
- return markers;
4813
- },
4814
- getAllMarks: function() {
4815
- var markers = [];
4816
- this.iter(function(line) {
4817
- var sps = line.markedSpans;
4818
- if (sps) for (var i = 0; i < sps.length; ++i)
4819
- if (sps[i].from != null) markers.push(sps[i].marker);
4820
- });
4821
- return markers;
4822
- },
4823
-
4824
- posFromIndex: function(off) {
4825
- var ch, lineNo = this.first;
4826
- this.iter(function(line) {
4827
- var sz = line.text.length + 1;
4828
- if (sz > off) { ch = off; return true; }
4829
- off -= sz;
4830
- ++lineNo;
4831
- });
4832
- return clipPos(this, Pos(lineNo, ch));
4833
- },
4834
- indexFromPos: function (coords) {
4835
- coords = clipPos(this, coords);
4836
- var index = coords.ch;
4837
- if (coords.line < this.first || coords.ch < 0) return 0;
4838
- this.iter(this.first, coords.line, function (line) {
4839
- index += line.text.length + 1;
4840
- });
4841
- return index;
4842
- },
4843
-
4844
- copy: function(copyHistory) {
4845
- var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
4846
- doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
4847
- doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
4848
- shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
4849
- if (copyHistory) {
4850
- doc.history.undoDepth = this.history.undoDepth;
4851
- doc.setHistory(this.getHistory());
4852
- }
4853
- return doc;
4854
- },
4855
-
4856
- linkedDoc: function(options) {
4857
- if (!options) options = {};
4858
- var from = this.first, to = this.first + this.size;
4859
- if (options.from != null && options.from > from) from = options.from;
4860
- if (options.to != null && options.to < to) to = options.to;
4861
- var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
4862
- if (options.sharedHist) copy.history = this.history;
4863
- (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
4864
- copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
4865
- return copy;
4866
- },
4867
- unlinkDoc: function(other) {
4868
- if (other instanceof CodeMirror) other = other.doc;
4869
- if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
4870
- var link = this.linked[i];
4871
- if (link.doc != other) continue;
4872
- this.linked.splice(i, 1);
4873
- other.unlinkDoc(this);
4874
- break;
4875
- }
4876
- // If the histories were shared, split them again
4877
- if (other.history == this.history) {
4878
- var splitIds = [other.id];
4879
- linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
4880
- other.history = makeHistory();
4881
- other.history.done = copyHistoryArray(this.history.done, splitIds);
4882
- other.history.undone = copyHistoryArray(this.history.undone, splitIds);
4883
- }
4884
- },
4885
- iterLinkedDocs: function(f) {linkedDocs(this, f);},
4886
-
4887
- getMode: function() {return this.mode;},
4888
- getEditor: function() {return this.cm;}
4889
- });
4890
-
4891
- Doc.prototype.eachLine = Doc.prototype.iter;
4892
-
4893
- // The Doc methods that should be available on CodeMirror instances
4894
- var dontDelegate = "iter insert remove copy getEditor".split(" ");
4895
- for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
4896
- CodeMirror.prototype[prop] = (function(method) {
4897
- return function() {return method.apply(this.doc, arguments);};
4898
- })(Doc.prototype[prop]);
4899
-
4900
- eventMixin(Doc);
4901
-
4902
- function linkedDocs(doc, f, sharedHistOnly) {
4903
- function propagate(doc, skip, sharedHist) {
4904
- if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
4905
- var rel = doc.linked[i];
4906
- if (rel.doc == skip) continue;
4907
- var shared = sharedHist && rel.sharedHist;
4908
- if (sharedHistOnly && !shared) continue;
4909
- f(rel.doc, shared);
4910
- propagate(rel.doc, doc, shared);
4911
- }
4912
- }
4913
- propagate(doc, null, true);
4914
- }
4915
-
4916
- function attachDoc(cm, doc) {
4917
- if (doc.cm) throw new Error("This document is already in use.");
4918
- cm.doc = doc;
4919
- doc.cm = cm;
4920
- estimateLineHeights(cm);
4921
- loadMode(cm);
4922
- if (!cm.options.lineWrapping) computeMaxLength(cm);
4923
- cm.options.mode = doc.modeOption;
4924
- regChange(cm);
4925
- }
4926
-
4927
- // LINE UTILITIES
4928
-
4929
- function getLine(chunk, n) {
4930
- n -= chunk.first;
4931
- while (!chunk.lines) {
4932
- for (var i = 0;; ++i) {
4933
- var child = chunk.children[i], sz = child.chunkSize();
4934
- if (n < sz) { chunk = child; break; }
4935
- n -= sz;
4936
- }
4937
- }
4938
- return chunk.lines[n];
4939
- }
4940
-
4941
- function getBetween(doc, start, end) {
4942
- var out = [], n = start.line;
4943
- doc.iter(start.line, end.line + 1, function(line) {
4944
- var text = line.text;
4945
- if (n == end.line) text = text.slice(0, end.ch);
4946
- if (n == start.line) text = text.slice(start.ch);
4947
- out.push(text);
4948
- ++n;
4949
- });
4950
- return out;
4951
- }
4952
- function getLines(doc, from, to) {
4953
- var out = [];
4954
- doc.iter(from, to, function(line) { out.push(line.text); });
4955
- return out;
4956
- }
4957
-
4958
- function updateLineHeight(line, height) {
4959
- var diff = height - line.height;
4960
- for (var n = line; n; n = n.parent) n.height += diff;
4961
- }
4962
-
4963
- function lineNo(line) {
4964
- if (line.parent == null) return null;
4965
- var cur = line.parent, no = indexOf(cur.lines, line);
4966
- for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
4967
- for (var i = 0;; ++i) {
4968
- if (chunk.children[i] == cur) break;
4969
- no += chunk.children[i].chunkSize();
4970
- }
4971
- }
4972
- return no + cur.first;
4973
- }
4974
-
4975
- function lineAtHeight(chunk, h) {
4976
- var n = chunk.first;
4977
- outer: do {
4978
- for (var i = 0, e = chunk.children.length; i < e; ++i) {
4979
- var child = chunk.children[i], ch = child.height;
4980
- if (h < ch) { chunk = child; continue outer; }
4981
- h -= ch;
4982
- n += child.chunkSize();
4983
- }
4984
- return n;
4985
- } while (!chunk.lines);
4986
- for (var i = 0, e = chunk.lines.length; i < e; ++i) {
4987
- var line = chunk.lines[i], lh = line.height;
4988
- if (h < lh) break;
4989
- h -= lh;
4990
- }
4991
- return n + i;
4992
- }
4993
-
4994
- function heightAtLine(cm, lineObj) {
4995
- lineObj = visualLine(cm.doc, lineObj);
4996
-
4997
- var h = 0, chunk = lineObj.parent;
4998
- for (var i = 0; i < chunk.lines.length; ++i) {
4999
- var line = chunk.lines[i];
5000
- if (line == lineObj) break;
5001
- else h += line.height;
5002
- }
5003
- for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
5004
- for (var i = 0; i < p.children.length; ++i) {
5005
- var cur = p.children[i];
5006
- if (cur == chunk) break;
5007
- else h += cur.height;
5008
- }
5009
- }
5010
- return h;
5011
- }
5012
-
5013
- function getOrder(line) {
5014
- var order = line.order;
5015
- if (order == null) order = line.order = bidiOrdering(line.text);
5016
- return order;
5017
- }
5018
-
5019
- // HISTORY
5020
-
5021
- function makeHistory(startGen) {
5022
- return {
5023
- // Arrays of history events. Doing something adds an event to
5024
- // done and clears undo. Undoing moves events from done to
5025
- // undone, redoing moves them in the other direction.
5026
- done: [], undone: [], undoDepth: Infinity,
5027
- // Used to track when changes can be merged into a single undo
5028
- // event
5029
- lastTime: 0, lastOp: null, lastOrigin: null,
5030
- // Used by the isClean() method
5031
- generation: startGen || 1, maxGeneration: startGen || 1
5032
- };
5033
- }
5034
-
5035
- function attachLocalSpans(doc, change, from, to) {
5036
- var existing = change["spans_" + doc.id], n = 0;
5037
- doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
5038
- if (line.markedSpans)
5039
- (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
5040
- ++n;
5041
- });
5042
- }
5043
-
5044
- function historyChangeFromChange(doc, change) {
5045
- var from = { line: change.from.line, ch: change.from.ch };
5046
- var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5047
- attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
5048
- linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
5049
- return histChange;
5050
- }
5051
-
5052
- function addToHistory(doc, change, selAfter, opId) {
5053
- var hist = doc.history;
5054
- hist.undone.length = 0;
5055
- var time = +new Date, cur = lst(hist.done);
5056
-
5057
- if (cur &&
5058
- (hist.lastOp == opId ||
5059
- hist.lastOrigin == change.origin && change.origin &&
5060
- ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
5061
- change.origin.charAt(0) == "*"))) {
5062
- // Merge this change into the last event
5063
- var last = lst(cur.changes);
5064
- if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
5065
- // Optimized case for simple insertion -- don't want to add
5066
- // new changesets for every character typed
5067
- last.to = changeEnd(change);
5068
- } else {
5069
- // Add new sub-event
5070
- cur.changes.push(historyChangeFromChange(doc, change));
5071
- }
5072
- cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
5073
- } else {
5074
- // Can not be merged, start a new event.
5075
- cur = {changes: [historyChangeFromChange(doc, change)],
5076
- generation: hist.generation,
5077
- anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5078
- anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5079
- hist.done.push(cur);
5080
- hist.generation = ++hist.maxGeneration;
5081
- while (hist.done.length > hist.undoDepth)
5082
- hist.done.shift();
5083
- }
5084
- hist.lastTime = time;
5085
- hist.lastOp = opId;
5086
- hist.lastOrigin = change.origin;
5087
- }
5088
-
5089
- function removeClearedSpans(spans) {
5090
- if (!spans) return null;
5091
- for (var i = 0, out; i < spans.length; ++i) {
5092
- if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
5093
- else if (out) out.push(spans[i]);
5094
- }
5095
- return !out ? spans : out.length ? out : null;
5096
- }
5097
-
5098
- function getOldSpans(doc, change) {
5099
- var found = change["spans_" + doc.id];
5100
- if (!found) return null;
5101
- for (var i = 0, nw = []; i < change.text.length; ++i)
5102
- nw.push(removeClearedSpans(found[i]));
5103
- return nw;
5104
- }
5105
-
5106
- // Used both to provide a JSON-safe object in .getHistory, and, when
5107
- // detaching a document, to split the history in two
5108
- function copyHistoryArray(events, newGroup) {
5109
- for (var i = 0, copy = []; i < events.length; ++i) {
5110
- var event = events[i], changes = event.changes, newChanges = [];
5111
- copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
5112
- anchorAfter: event.anchorAfter, headAfter: event.headAfter});
5113
- for (var j = 0; j < changes.length; ++j) {
5114
- var change = changes[j], m;
5115
- newChanges.push({from: change.from, to: change.to, text: change.text});
5116
- if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
5117
- if (indexOf(newGroup, Number(m[1])) > -1) {
5118
- lst(newChanges)[prop] = change[prop];
5119
- delete change[prop];
5120
- }
5121
- }
5122
- }
5123
- }
5124
- return copy;
5125
- }
5126
-
5127
- // Rebasing/resetting history to deal with externally-sourced changes
5128
-
5129
- function rebaseHistSel(pos, from, to, diff) {
5130
- if (to < pos.line) {
5131
- pos.line += diff;
5132
- } else if (from < pos.line) {
5133
- pos.line = from;
5134
- pos.ch = 0;
5135
- }
5136
- }
5137
-
5138
- // Tries to rebase an array of history events given a change in the
5139
- // document. If the change touches the same lines as the event, the
5140
- // event, and everything 'behind' it, is discarded. If the change is
5141
- // before the event, the event's positions are updated. Uses a
5142
- // copy-on-write scheme for the positions, to avoid having to
5143
- // reallocate them all on every rebase, but also avoid problems with
5144
- // shared position objects being unsafely updated.
5145
- function rebaseHistArray(array, from, to, diff) {
5146
- for (var i = 0; i < array.length; ++i) {
5147
- var sub = array[i], ok = true;
5148
- for (var j = 0; j < sub.changes.length; ++j) {
5149
- var cur = sub.changes[j];
5150
- if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
5151
- if (to < cur.from.line) {
5152
- cur.from.line += diff;
5153
- cur.to.line += diff;
5154
- } else if (from <= cur.to.line) {
5155
- ok = false;
5156
- break;
5157
- }
5158
- }
5159
- if (!sub.copied) {
5160
- sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
5161
- sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
5162
- sub.copied = true;
5163
- }
5164
- if (!ok) {
5165
- array.splice(0, i + 1);
5166
- i = 0;
5167
- } else {
5168
- rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
5169
- rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
5170
- }
5171
- }
5172
- }
5173
-
5174
- function rebaseHist(hist, change) {
5175
- var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5176
- rebaseHistArray(hist.done, from, to, diff);
5177
- rebaseHistArray(hist.undone, from, to, diff);
5178
- }
5179
-
5180
- // EVENT OPERATORS
5181
-
5182
- function stopMethod() {e_stop(this);}
5183
- // Ensure an event has a stop method.
5184
- function addStop(event) {
5185
- if (!event.stop) event.stop = stopMethod;
5186
- return event;
5187
- }
5188
-
5189
- function e_preventDefault(e) {
5190
- if (e.preventDefault) e.preventDefault();
5191
- else e.returnValue = false;
5192
- }
5193
- function e_stopPropagation(e) {
5194
- if (e.stopPropagation) e.stopPropagation();
5195
- else e.cancelBubble = true;
5196
- }
5197
- function e_defaultPrevented(e) {
5198
- return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5199
- }
5200
- function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5201
- CodeMirror.e_stop = e_stop;
5202
- CodeMirror.e_preventDefault = e_preventDefault;
5203
- CodeMirror.e_stopPropagation = e_stopPropagation;
5204
-
5205
- function e_target(e) {return e.target || e.srcElement;}
5206
- function e_button(e) {
5207
- var b = e.which;
5208
- if (b == null) {
5209
- if (e.button & 1) b = 1;
5210
- else if (e.button & 2) b = 3;
5211
- else if (e.button & 4) b = 2;
5212
- }
5213
- if (mac && e.ctrlKey && b == 1) b = 3;
5214
- return b;
5215
- }
5216
-
5217
- // EVENT HANDLING
5218
-
5219
- function on(emitter, type, f) {
5220
- if (emitter.addEventListener)
5221
- emitter.addEventListener(type, f, false);
5222
- else if (emitter.attachEvent)
5223
- emitter.attachEvent("on" + type, f);
5224
- else {
5225
- var map = emitter._handlers || (emitter._handlers = {});
5226
- var arr = map[type] || (map[type] = []);
5227
- arr.push(f);
5228
- }
5229
- }
5230
-
5231
- function off(emitter, type, f) {
5232
- if (emitter.removeEventListener)
5233
- emitter.removeEventListener(type, f, false);
5234
- else if (emitter.detachEvent)
5235
- emitter.detachEvent("on" + type, f);
5236
- else {
5237
- var arr = emitter._handlers && emitter._handlers[type];
5238
- if (!arr) return;
5239
- for (var i = 0; i < arr.length; ++i)
5240
- if (arr[i] == f) { arr.splice(i, 1); break; }
5241
- }
5242
- }
5243
-
5244
- function signal(emitter, type /*, values...*/) {
5245
- var arr = emitter._handlers && emitter._handlers[type];
5246
- if (!arr) return;
5247
- var args = Array.prototype.slice.call(arguments, 2);
5248
- for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
5249
- }
5250
-
5251
- var delayedCallbacks, delayedCallbackDepth = 0;
5252
- function signalLater(emitter, type /*, values...*/) {
5253
- var arr = emitter._handlers && emitter._handlers[type];
5254
- if (!arr) return;
5255
- var args = Array.prototype.slice.call(arguments, 2);
5256
- if (!delayedCallbacks) {
5257
- ++delayedCallbackDepth;
5258
- delayedCallbacks = [];
5259
- setTimeout(fireDelayed, 0);
5260
- }
5261
- function bnd(f) {return function(){f.apply(null, args);};};
5262
- for (var i = 0; i < arr.length; ++i)
5263
- delayedCallbacks.push(bnd(arr[i]));
5264
- }
5265
-
5266
- function signalDOMEvent(cm, e, override) {
5267
- signal(cm, override || e.type, cm, e);
5268
- return e_defaultPrevented(e) || e.codemirrorIgnore;
5269
- }
5270
-
5271
- function fireDelayed() {
5272
- --delayedCallbackDepth;
5273
- var delayed = delayedCallbacks;
5274
- delayedCallbacks = null;
5275
- for (var i = 0; i < delayed.length; ++i) delayed[i]();
5276
- }
5277
-
5278
- function hasHandler(emitter, type) {
5279
- var arr = emitter._handlers && emitter._handlers[type];
5280
- return arr && arr.length > 0;
5281
- }
5282
-
5283
- CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
5284
-
5285
- function eventMixin(ctor) {
5286
- ctor.prototype.on = function(type, f) {on(this, type, f);};
5287
- ctor.prototype.off = function(type, f) {off(this, type, f);};
5288
- }
5289
-
5290
- // MISC UTILITIES
5291
-
5292
- // Number of pixels added to scroller and sizer to hide scrollbar
5293
- var scrollerCutOff = 30;
5294
-
5295
- // Returned or thrown by various protocols to signal 'I'm not
5296
- // handling this'.
5297
- var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
5298
-
5299
- function Delayed() {this.id = null;}
5300
- Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
5301
-
5302
- // Counts the column offset in a string, taking tabs into account.
5303
- // Used mostly to find indentation.
5304
- function countColumn(string, end, tabSize, startIndex, startValue) {
5305
- if (end == null) {
5306
- end = string.search(/[^\s\u00a0]/);
5307
- if (end == -1) end = string.length;
5308
- }
5309
- for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
5310
- if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
5311
- else ++n;
5312
- }
5313
- return n;
5314
- }
5315
- CodeMirror.countColumn = countColumn;
5316
-
5317
- var spaceStrs = [""];
5318
- function spaceStr(n) {
5319
- while (spaceStrs.length <= n)
5320
- spaceStrs.push(lst(spaceStrs) + " ");
5321
- return spaceStrs[n];
5322
- }
5323
-
5324
- function lst(arr) { return arr[arr.length-1]; }
5325
-
5326
- function selectInput(node) {
5327
- if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5328
- node.selectionStart = 0;
5329
- node.selectionEnd = node.value.length;
5330
- } else {
5331
- // Suppress mysterious IE10 errors
5332
- try { node.select(); }
5333
- catch(_e) {}
5334
- }
5335
- }
5336
-
5337
- function indexOf(collection, elt) {
5338
- if (collection.indexOf) return collection.indexOf(elt);
5339
- for (var i = 0, e = collection.length; i < e; ++i)
5340
- if (collection[i] == elt) return i;
5341
- return -1;
5342
- }
5343
-
5344
- function createObj(base, props) {
5345
- function Obj() {}
5346
- Obj.prototype = base;
5347
- var inst = new Obj();
5348
- if (props) copyObj(props, inst);
5349
- return inst;
5350
- }
5351
-
5352
- function copyObj(obj, target) {
5353
- if (!target) target = {};
5354
- for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
5355
- return target;
5356
- }
5357
-
5358
- function emptyArray(size) {
5359
- for (var a = [], i = 0; i < size; ++i) a.push(undefined);
5360
- return a;
5361
- }
5362
-
5363
- function bind(f) {
5364
- var args = Array.prototype.slice.call(arguments, 1);
5365
- return function(){return f.apply(null, args);};
5366
- }
5367
-
5368
- var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
5369
- function isWordChar(ch) {
5370
- return /\w/.test(ch) || ch > "\x80" &&
5371
- (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
5372
- }
5373
-
5374
- function isEmpty(obj) {
5375
- for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
5376
- return true;
5377
- }
5378
-
5379
- 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]/;
5380
-
5381
- // DOM UTILITIES
5382
-
5383
- function elt(tag, content, className, style) {
5384
- var e = document.createElement(tag);
5385
- if (className) e.className = className;
5386
- if (style) e.style.cssText = style;
5387
- if (typeof content == "string") setTextContent(e, content);
5388
- else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
5389
- return e;
5390
- }
5391
-
5392
- function removeChildren(e) {
5393
- for (var count = e.childNodes.length; count > 0; --count)
5394
- e.removeChild(e.firstChild);
5395
- return e;
5396
- }
5397
-
5398
- function removeChildrenAndAdd(parent, e) {
5399
- return removeChildren(parent).appendChild(e);
5400
- }
5401
-
5402
- function setTextContent(e, str) {
5403
- if (ie_lt9) {
5404
- e.innerHTML = "";
5405
- e.appendChild(document.createTextNode(str));
5406
- } else e.textContent = str;
5407
- }
5408
-
5409
- function getRect(node) {
5410
- return node.getBoundingClientRect();
5411
- }
5412
- CodeMirror.replaceGetRect = function(f) { getRect = f; };
5413
-
5414
- // FEATURE DETECTION
5415
-
5416
- // Detect drag-and-drop
5417
- var dragAndDrop = function() {
5418
- // There is *some* kind of drag-and-drop support in IE6-8, but I
5419
- // couldn't get it to work yet.
5420
- if (ie_lt9) return false;
5421
- var div = elt('div');
5422
- return "draggable" in div || "dragDrop" in div;
5423
- }();
5424
-
5425
- // For a reason I have yet to figure out, some browsers disallow
5426
- // word wrapping between certain characters *only* if a new inline
5427
- // element is started between them. This makes it hard to reliably
5428
- // measure the position of things, since that requires inserting an
5429
- // extra span. This terribly fragile set of tests matches the
5430
- // character combinations that suffer from this phenomenon on the
5431
- // various browsers.
5432
- function spanAffectsWrapping() { return false; }
5433
- if (gecko) // Only for "$'"
5434
- spanAffectsWrapping = function(str, i) {
5435
- return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
5436
- };
5437
- else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
5438
- spanAffectsWrapping = function(str, i) {
5439
- return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5440
- };
5441
- else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
5442
- spanAffectsWrapping = function(str, i) {
5443
- if (i > 1 && str.charCodeAt(i - 1) == 45) {
5444
- if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5445
- if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5446
- }
5447
- return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5448
- };
5449
-
5450
- var knownScrollbarWidth;
5451
- function scrollbarWidth(measure) {
5452
- if (knownScrollbarWidth != null) return knownScrollbarWidth;
5453
- var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
5454
- removeChildrenAndAdd(measure, test);
5455
- if (test.offsetWidth)
5456
- knownScrollbarWidth = test.offsetHeight - test.clientHeight;
5457
- return knownScrollbarWidth || 0;
5458
- }
5459
-
5460
- var zwspSupported;
5461
- function zeroWidthElement(measure) {
5462
- if (zwspSupported == null) {
5463
- var test = elt("span", "\u200b");
5464
- removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
5465
- if (measure.firstChild.offsetHeight != 0)
5466
- zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
5467
- }
5468
- if (zwspSupported) return elt("span", "\u200b");
5469
- else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
5470
- }
5471
-
5472
- // See if "".split is the broken IE version, if so, provide an
5473
- // alternative way to split lines.
5474
- var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
5475
- var pos = 0, result = [], l = string.length;
5476
- while (pos <= l) {
5477
- var nl = string.indexOf("\n", pos);
5478
- if (nl == -1) nl = string.length;
5479
- var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
5480
- var rt = line.indexOf("\r");
5481
- if (rt != -1) {
5482
- result.push(line.slice(0, rt));
5483
- pos += rt + 1;
5484
- } else {
5485
- result.push(line);
5486
- pos = nl + 1;
5487
- }
5488
- }
5489
- return result;
5490
- } : function(string){return string.split(/\r\n?|\n/);};
5491
- CodeMirror.splitLines = splitLines;
5492
-
5493
- var hasSelection = window.getSelection ? function(te) {
5494
- try { return te.selectionStart != te.selectionEnd; }
5495
- catch(e) { return false; }
5496
- } : function(te) {
5497
- try {var range = te.ownerDocument.selection.createRange();}
5498
- catch(e) {}
5499
- if (!range || range.parentElement() != te) return false;
5500
- return range.compareEndPoints("StartToEnd", range) != 0;
5501
- };
5502
-
5503
- var hasCopyEvent = (function() {
5504
- var e = elt("div");
5505
- if ("oncopy" in e) return true;
5506
- e.setAttribute("oncopy", "return;");
5507
- return typeof e.oncopy == 'function';
5508
- })();
5509
-
5510
- // KEY NAMING
5511
-
5512
- var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
5513
- 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
5514
- 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
5515
- 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
5516
- 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5517
- 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
5518
- 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
5519
- CodeMirror.keyNames = keyNames;
5520
- (function() {
5521
- // Number keys
5522
- for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
5523
- // Alphabetic keys
5524
- for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
5525
- // Function keys
5526
- for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
5527
- })();
5528
-
5529
- // BIDI HELPERS
5530
-
5531
- function iterateBidiSections(order, from, to, f) {
5532
- if (!order) return f(from, to, "ltr");
5533
- var found = false;
5534
- for (var i = 0; i < order.length; ++i) {
5535
- var part = order[i];
5536
- if (part.from < to && part.to > from || from == to && part.to == from) {
5537
- f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5538
- found = true;
5539
- }
5540
- }
5541
- if (!found) f(from, to, "ltr");
5542
- }
5543
-
5544
- function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
5545
- function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
5546
-
5547
- function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
5548
- function lineRight(line) {
5549
- var order = getOrder(line);
5550
- if (!order) return line.text.length;
5551
- return bidiRight(lst(order));
5552
- }
5553
-
5554
- function lineStart(cm, lineN) {
5555
- var line = getLine(cm.doc, lineN);
5556
- var visual = visualLine(cm.doc, line);
5557
- if (visual != line) lineN = lineNo(visual);
5558
- var order = getOrder(visual);
5559
- var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
5560
- return Pos(lineN, ch);
5561
- }
5562
- function lineEnd(cm, lineN) {
5563
- var merged, line;
5564
- while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
5565
- lineN = merged.find().to.line;
5566
- var order = getOrder(line);
5567
- var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
5568
- return Pos(lineN, ch);
5569
- }
5570
-
5571
- function compareBidiLevel(order, a, b) {
5572
- var linedir = order[0].level;
5573
- if (a == linedir) return true;
5574
- if (b == linedir) return false;
5575
- return a < b;
5576
- }
5577
- var bidiOther;
5578
- function getBidiPartAt(order, pos) {
5579
- for (var i = 0, found; i < order.length; ++i) {
5580
- var cur = order[i];
5581
- if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5582
- if (cur.from == pos || cur.to == pos) {
5583
- if (found == null) {
5584
- found = i;
5585
- } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5586
- bidiOther = found;
5587
- return i;
5588
- } else {
5589
- bidiOther = i;
5590
- return found;
5591
- }
5592
- }
5593
- }
5594
- bidiOther = null;
5595
- return found;
5596
- }
5597
-
5598
- function moveInLine(line, pos, dir, byUnit) {
5599
- if (!byUnit) return pos + dir;
5600
- do pos += dir;
5601
- while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5602
- return pos;
5603
- }
5604
-
5605
- // This is somewhat involved. It is needed in order to move
5606
- // 'visually' through bi-directional text -- i.e., pressing left
5607
- // should make the cursor go left, even when in RTL text. The
5608
- // tricky part is the 'jumps', where RTL and LTR text touch each
5609
- // other. This often requires the cursor offset to move more than
5610
- // one unit, in order to visually move one unit.
5611
- function moveVisually(line, start, dir, byUnit) {
5612
- var bidi = getOrder(line);
5613
- if (!bidi) return moveLogically(line, start, dir, byUnit);
5614
- var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5615
- var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5616
-
5617
- for (;;) {
5618
- if (target > part.from && target < part.to) return target;
5619
- if (target == part.from || target == part.to) {
5620
- if (getBidiPartAt(bidi, target) == pos) return target;
5621
- part = bidi[pos += dir];
5622
- return (dir > 0) == part.level % 2 ? part.to : part.from;
5623
- } else {
5624
- part = bidi[pos += dir];
5625
- if (!part) return null;
5626
- if ((dir > 0) == part.level % 2)
5627
- target = moveInLine(line, part.to, -1, byUnit);
5628
- else
5629
- target = moveInLine(line, part.from, 1, byUnit);
5630
- }
5631
- }
5632
- }
5633
-
5634
- function moveLogically(line, start, dir, byUnit) {
5635
- var target = start + dir;
5636
- if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
5637
- return target < 0 || target > line.text.length ? null : target;
5638
- }
5639
-
5640
- // Bidirectional ordering algorithm
5641
- // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
5642
- // that this (partially) implements.
5643
-
5644
- // One-char codes used for character types:
5645
- // L (L): Left-to-Right
5646
- // R (R): Right-to-Left
5647
- // r (AL): Right-to-Left Arabic
5648
- // 1 (EN): European Number
5649
- // + (ES): European Number Separator
5650
- // % (ET): European Number Terminator
5651
- // n (AN): Arabic Number
5652
- // , (CS): Common Number Separator
5653
- // m (NSM): Non-Spacing Mark
5654
- // b (BN): Boundary Neutral
5655
- // s (B): Paragraph Separator
5656
- // t (S): Segment Separator
5657
- // w (WS): Whitespace
5658
- // N (ON): Other Neutrals
5659
-
5660
- // Returns null if characters are ordered as they appear
5661
- // (left-to-right), or an array of sections ({from, to, level}
5662
- // objects) in the order in which they occur visually.
5663
- var bidiOrdering = (function() {
5664
- // Character types for codepoints 0 to 0xff
5665
- var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
5666
- // Character types for codepoints 0x600 to 0x6ff
5667
- var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
5668
- function charType(code) {
5669
- if (code <= 0xff) return lowTypes.charAt(code);
5670
- else if (0x590 <= code && code <= 0x5f4) return "R";
5671
- else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
5672
- else if (0x700 <= code && code <= 0x8ac) return "r";
5673
- else return "L";
5674
- }
5675
-
5676
- var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
5677
- var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
5678
- // Browsers seem to always treat the boundaries of block elements as being L.
5679
- var outerType = "L";
5680
-
5681
- return function(str) {
5682
- if (!bidiRE.test(str)) return false;
5683
- var len = str.length, types = [];
5684
- for (var i = 0, type; i < len; ++i)
5685
- types.push(type = charType(str.charCodeAt(i)));
5686
-
5687
- // W1. Examine each non-spacing mark (NSM) in the level run, and
5688
- // change the type of the NSM to the type of the previous
5689
- // character. If the NSM is at the start of the level run, it will
5690
- // get the type of sor.
5691
- for (var i = 0, prev = outerType; i < len; ++i) {
5692
- var type = types[i];
5693
- if (type == "m") types[i] = prev;
5694
- else prev = type;
5695
- }
5696
-
5697
- // W2. Search backwards from each instance of a European number
5698
- // until the first strong type (R, L, AL, or sor) is found. If an
5699
- // AL is found, change the type of the European number to Arabic
5700
- // number.
5701
- // W3. Change all ALs to R.
5702
- for (var i = 0, cur = outerType; i < len; ++i) {
5703
- var type = types[i];
5704
- if (type == "1" && cur == "r") types[i] = "n";
5705
- else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
5706
- }
5707
-
5708
- // W4. A single European separator between two European numbers
5709
- // changes to a European number. A single common separator between
5710
- // two numbers of the same type changes to that type.
5711
- for (var i = 1, prev = types[0]; i < len - 1; ++i) {
5712
- var type = types[i];
5713
- if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
5714
- else if (type == "," && prev == types[i+1] &&
5715
- (prev == "1" || prev == "n")) types[i] = prev;
5716
- prev = type;
5717
- }
5718
-
5719
- // W5. A sequence of European terminators adjacent to European
5720
- // numbers changes to all European numbers.
5721
- // W6. Otherwise, separators and terminators change to Other
5722
- // Neutral.
5723
- for (var i = 0; i < len; ++i) {
5724
- var type = types[i];
5725
- if (type == ",") types[i] = "N";
5726
- else if (type == "%") {
5727
- for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
5728
- var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
5729
- for (var j = i; j < end; ++j) types[j] = replace;
5730
- i = end - 1;
5731
- }
5732
- }
5733
-
5734
- // W7. Search backwards from each instance of a European number
5735
- // until the first strong type (R, L, or sor) is found. If an L is
5736
- // found, then change the type of the European number to L.
5737
- for (var i = 0, cur = outerType; i < len; ++i) {
5738
- var type = types[i];
5739
- if (cur == "L" && type == "1") types[i] = "L";
5740
- else if (isStrong.test(type)) cur = type;
5741
- }
5742
-
5743
- // N1. A sequence of neutrals takes the direction of the
5744
- // surrounding strong text if the text on both sides has the same
5745
- // direction. European and Arabic numbers act as if they were R in
5746
- // terms of their influence on neutrals. Start-of-level-run (sor)
5747
- // and end-of-level-run (eor) are used at level run boundaries.
5748
- // N2. Any remaining neutrals take the embedding direction.
5749
- for (var i = 0; i < len; ++i) {
5750
- if (isNeutral.test(types[i])) {
5751
- for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5752
- var before = (i ? types[i-1] : outerType) == "L";
5753
- var after = (end < len - 1 ? types[end] : outerType) == "L";
5754
- var replace = before || after ? "L" : "R";
5755
- for (var j = i; j < end; ++j) types[j] = replace;
5756
- i = end - 1;
5757
- }
5758
- }
5759
-
5760
- // Here we depart from the documented algorithm, in order to avoid
5761
- // building up an actual levels array. Since there are only three
5762
- // levels (0, 1, 2) in an implementation that doesn't take
5763
- // explicit embedding into account, we can build up the order on
5764
- // the fly, without following the level-based algorithm.
5765
- var order = [], m;
5766
- for (var i = 0; i < len;) {
5767
- if (countsAsLeft.test(types[i])) {
5768
- var start = i;
5769
- for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
5770
- order.push({from: start, to: i, level: 0});
5771
- } else {
5772
- var pos = i, at = order.length;
5773
- for (++i; i < len && types[i] != "L"; ++i) {}
5774
- for (var j = pos; j < i;) {
5775
- if (countsAsNum.test(types[j])) {
5776
- if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
5777
- var nstart = j;
5778
- for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
5779
- order.splice(at, 0, {from: nstart, to: j, level: 2});
5780
- pos = j;
5781
- } else ++j;
5782
- }
5783
- if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
5784
- }
5785
- }
5786
- if (order[0].level == 1 && (m = str.match(/^\s+/))) {
5787
- order[0].from = m[0].length;
5788
- order.unshift({from: 0, to: m[0].length, level: 0});
5789
- }
5790
- if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
5791
- lst(order).to -= m[0].length;
5792
- order.push({from: len - m[0].length, to: len, level: 0});
5793
- }
5794
- if (order[0].level != lst(order).level)
5795
- order.push({from: len, to: len, level: order[0].level});
5796
-
5797
- return order;
5798
- };
5799
- })();
5800
-
5801
- // THE END
5802
-
5803
- CodeMirror.version = "3.15.0";
5804
-
5805
- return CodeMirror;
5806
- })();
1
+ /*
2
+ * CodeMirror version 3.15
3
+ * https://codemirror.net/
4
+ * Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
5
+ *
6
+ * Released under the MIT license
7
+ * https://codemirror.net/LICENSE
8
+ */
9
+
10
+ // CodeMirror is the only global var we claim
11
+ window.CodeMirror = (function() {
12
+ "use strict";
13
+
14
+ // BROWSER SNIFFING
15
+
16
+ // Crude, but necessary to handle a number of hard-to-feature-detect
17
+ // bugs and behavior differences.
18
+ var gecko = /gecko\/\d/i.test(navigator.userAgent);
19
+ var ie = /MSIE \d/.test(navigator.userAgent);
20
+ var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
21
+ var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
22
+ var webkit = /WebKit\//.test(navigator.userAgent);
23
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
24
+ var chrome = /Chrome\//.test(navigator.userAgent);
25
+ var opera = /Opera\//.test(navigator.userAgent);
26
+ var safari = /Apple Computer/.test(navigator.vendor);
27
+ var khtml = /KHTML\//.test(navigator.userAgent);
28
+ var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
29
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
30
+ var phantom = /PhantomJS/.test(navigator.userAgent);
31
+
32
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
33
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
34
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
35
+ var mac = ios || /Mac/.test(navigator.platform);
36
+ var windows = /windows/i.test(navigator.platform);
37
+
38
+ var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
39
+ if (opera_version) opera_version = Number(opera_version[1]);
40
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
41
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
42
+ var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
43
+ var captureMiddleClick = gecko || (ie && !ie_lt9);
44
+
45
+ // Optimize some code when these features are not used
46
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
47
+
48
+ // CONSTRUCTOR
49
+
50
+ function CodeMirror(place, options) {
51
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
52
+
53
+ this.options = options = options || {};
54
+ // Determine effective options based on given values and defaults.
55
+ for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
56
+ options[opt] = defaults[opt];
57
+ setGuttersForLineNumbers(options);
58
+
59
+ var docStart = typeof options.value == "string" ? 0 : options.value.first;
60
+ var display = this.display = makeDisplay(place, docStart);
61
+ display.wrapper.CodeMirror = this;
62
+ updateGutters(this);
63
+ if (options.autofocus && !mobile) focusInput(this);
64
+
65
+ this.state = {keyMaps: [],
66
+ overlays: [],
67
+ modeGen: 0,
68
+ overwrite: false, focused: false,
69
+ suppressEdits: false, pasteIncoming: false,
70
+ draggingText: false,
71
+ highlight: new Delayed()};
72
+
73
+ themeChanged(this);
74
+ if (options.lineWrapping)
75
+ this.display.wrapper.className += " CodeMirror-wrap";
76
+
77
+ var doc = options.value;
78
+ if (typeof doc == "string") doc = new Doc(options.value, options.mode);
79
+ operation(this, attachDoc)(this, doc);
80
+
81
+ // Override magic textarea content restore that IE sometimes does
82
+ // on our hidden textarea on reload
83
+ if (ie) setTimeout(bind(resetInput, this, true), 20);
84
+
85
+ registerEventHandlers(this);
86
+ // IE throws unspecified error in certain cases, when
87
+ // trying to access activeElement before onload
88
+ var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
89
+ if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
90
+ else onBlur(this);
91
+
92
+ operation(this, function() {
93
+ for (var opt in optionHandlers)
94
+ if (optionHandlers.propertyIsEnumerable(opt))
95
+ optionHandlers[opt](this, options[opt], Init);
96
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
97
+ })();
98
+ }
99
+
100
+ // DISPLAY CONSTRUCTOR
101
+
102
+ function makeDisplay(place, docStart) {
103
+ var d = {};
104
+
105
+ var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
106
+ if (webkit) input.style.width = "1000px";
107
+ else input.setAttribute("wrap", "off");
108
+ // if border: 0; -- iOS fails to open keyboard (issue #1287)
109
+ if (ios) input.style.border = "1px solid black";
110
+ input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
111
+
112
+ // Wraps and hides input textarea
113
+ d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
114
+ // The actual fake scrollbars.
115
+ d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
116
+ d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
117
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
118
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
119
+ // DIVs containing the selection and the actual code
120
+ d.lineDiv = elt("div", null, "CodeMirror-code");
121
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
122
+ // Blinky cursor, and element used to ensure cursor fits at the end of a line
123
+ d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
124
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
125
+ d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
126
+ // Used to measure text size
127
+ d.measure = elt("div", null, "CodeMirror-measure");
128
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
129
+ d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
130
+ null, "position: relative; outline: none");
131
+ // Moved around its parent to cover visible view
132
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
133
+ // Set to the height of the text, causes scrolling
134
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
135
+ // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
136
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
137
+ // Will contain the gutters, if any
138
+ d.gutters = elt("div", null, "CodeMirror-gutters");
139
+ d.lineGutter = null;
140
+ // Provides scrolling
141
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
142
+ d.scroller.setAttribute("tabIndex", "-1");
143
+ // The element in which the editor lives.
144
+ d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
145
+ d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
146
+ // Work around IE7 z-index bug
147
+ if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
148
+ if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
149
+
150
+ // Needed to hide big blue blinking cursor on Mobile Safari
151
+ if (ios) input.style.width = "0px";
152
+ if (!webkit) d.scroller.draggable = true;
153
+ // Needed to handle Tab key in KHTML
154
+ if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
155
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
156
+ else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
157
+
158
+ // Current visible range (may be bigger than the view window).
159
+ d.viewOffset = d.lastSizeC = 0;
160
+ d.showingFrom = d.showingTo = docStart;
161
+
162
+ // Used to only resize the line number gutter when necessary (when
163
+ // the amount of lines crosses a boundary that makes its width change)
164
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
165
+ // See readInput and resetInput
166
+ d.prevInput = "";
167
+ // Set to true when a non-horizontal-scrolling widget is added. As
168
+ // an optimization, widget aligning is skipped when d is false.
169
+ d.alignWidgets = false;
170
+ // Flag that indicates whether we currently expect input to appear
171
+ // (after some event like 'keypress' or 'input') and are polling
172
+ // intensively.
173
+ d.pollingFast = false;
174
+ // Self-resetting timeout for the poller
175
+ d.poll = new Delayed();
176
+
177
+ d.cachedCharWidth = d.cachedTextHeight = null;
178
+ d.measureLineCache = [];
179
+ d.measureLineCachePos = 0;
180
+
181
+ // Tracks when resetInput has punted to just putting a short
182
+ // string instead of the (large) selection.
183
+ d.inaccurateSelection = false;
184
+
185
+ // Tracks the maximum line length so that the horizontal scrollbar
186
+ // can be kept static when scrolling.
187
+ d.maxLine = null;
188
+ d.maxLineLength = 0;
189
+ d.maxLineChanged = false;
190
+
191
+ // Used for measuring wheel scrolling granularity
192
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
193
+
194
+ return d;
195
+ }
196
+
197
+ // STATE UPDATES
198
+
199
+ // Used to get the editor into a consistent state again when options change.
200
+
201
+ function loadMode(cm) {
202
+ cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
203
+ cm.doc.iter(function(line) {
204
+ if (line.stateAfter) line.stateAfter = null;
205
+ if (line.styles) line.styles = null;
206
+ });
207
+ cm.doc.frontier = cm.doc.first;
208
+ startWorker(cm, 100);
209
+ cm.state.modeGen++;
210
+ if (cm.curOp) regChange(cm);
211
+ }
212
+
213
+ function wrappingChanged(cm) {
214
+ if (cm.options.lineWrapping) {
215
+ cm.display.wrapper.className += " CodeMirror-wrap";
216
+ cm.display.sizer.style.minWidth = "";
217
+ } else {
218
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
219
+ computeMaxLength(cm);
220
+ }
221
+ estimateLineHeights(cm);
222
+ regChange(cm);
223
+ clearCaches(cm);
224
+ setTimeout(function(){updateScrollbars(cm);}, 100);
225
+ }
226
+
227
+ function estimateHeight(cm) {
228
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
229
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
230
+ return function(line) {
231
+ if (lineIsHidden(cm.doc, line))
232
+ return 0;
233
+ else if (wrapping)
234
+ return (Math.ceil(line.text.length / perLine) || 1) * th;
235
+ else
236
+ return th;
237
+ };
238
+ }
239
+
240
+ function estimateLineHeights(cm) {
241
+ var doc = cm.doc, est = estimateHeight(cm);
242
+ doc.iter(function(line) {
243
+ var estHeight = est(line);
244
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
245
+ });
246
+ }
247
+
248
+ function keyMapChanged(cm) {
249
+ var map = keyMap[cm.options.keyMap], style = map.style;
250
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
251
+ (style ? " cm-keymap-" + style : "");
252
+ cm.state.disableInput = map.disableInput;
253
+ }
254
+
255
+ function themeChanged(cm) {
256
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
257
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
258
+ clearCaches(cm);
259
+ }
260
+
261
+ function guttersChanged(cm) {
262
+ updateGutters(cm);
263
+ regChange(cm);
264
+ setTimeout(function(){alignHorizontally(cm);}, 20);
265
+ }
266
+
267
+ function updateGutters(cm) {
268
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
269
+ removeChildren(gutters);
270
+ for (var i = 0; i < specs.length; ++i) {
271
+ var gutterClass = specs[i];
272
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
273
+ if (gutterClass == "CodeMirror-linenumbers") {
274
+ cm.display.lineGutter = gElt;
275
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
276
+ }
277
+ }
278
+ gutters.style.display = i ? "" : "none";
279
+ }
280
+
281
+ function lineLength(doc, line) {
282
+ if (line.height == 0) return 0;
283
+ var len = line.text.length, merged, cur = line;
284
+ while (merged = collapsedSpanAtStart(cur)) {
285
+ var found = merged.find();
286
+ cur = getLine(doc, found.from.line);
287
+ len += found.from.ch - found.to.ch;
288
+ }
289
+ cur = line;
290
+ while (merged = collapsedSpanAtEnd(cur)) {
291
+ var found = merged.find();
292
+ len -= cur.text.length - found.from.ch;
293
+ cur = getLine(doc, found.to.line);
294
+ len += cur.text.length - found.to.ch;
295
+ }
296
+ return len;
297
+ }
298
+
299
+ function computeMaxLength(cm) {
300
+ var d = cm.display, doc = cm.doc;
301
+ d.maxLine = getLine(doc, doc.first);
302
+ d.maxLineLength = lineLength(doc, d.maxLine);
303
+ d.maxLineChanged = true;
304
+ doc.iter(function(line) {
305
+ var len = lineLength(doc, line);
306
+ if (len > d.maxLineLength) {
307
+ d.maxLineLength = len;
308
+ d.maxLine = line;
309
+ }
310
+ });
311
+ }
312
+
313
+ // Make sure the gutters options contains the element
314
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
315
+ function setGuttersForLineNumbers(options) {
316
+ var found = false;
317
+ for (var i = 0; i < options.gutters.length; ++i) {
318
+ if (options.gutters[i] == "CodeMirror-linenumbers") {
319
+ if (options.lineNumbers) found = true;
320
+ else options.gutters.splice(i--, 1);
321
+ }
322
+ }
323
+ if (!found && options.lineNumbers)
324
+ options.gutters.push("CodeMirror-linenumbers");
325
+ }
326
+
327
+ // SCROLLBARS
328
+
329
+ // Re-synchronize the fake scrollbars with the actual size of the
330
+ // content. Optionally force a scrollTop.
331
+ function updateScrollbars(cm) {
332
+ var d = cm.display, docHeight = cm.doc.height;
333
+ var totalHeight = docHeight + paddingVert(d);
334
+ d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
335
+ d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
336
+ var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
337
+ var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
338
+ var needsV = scrollHeight > (d.scroller.clientHeight + 1);
339
+ if (needsV) {
340
+ d.scrollbarV.style.display = "block";
341
+ d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
342
+ d.scrollbarV.firstChild.style.height =
343
+ (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
344
+ } else d.scrollbarV.style.display = "";
345
+ if (needsH) {
346
+ d.scrollbarH.style.display = "block";
347
+ d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
348
+ d.scrollbarH.firstChild.style.width =
349
+ (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
350
+ } else d.scrollbarH.style.display = "";
351
+ if (needsH && needsV) {
352
+ d.scrollbarFiller.style.display = "block";
353
+ d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
354
+ } else d.scrollbarFiller.style.display = "";
355
+ if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
356
+ d.gutterFiller.style.display = "block";
357
+ d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
358
+ d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
359
+ } else d.gutterFiller.style.display = "";
360
+
361
+ if (mac_geLion && scrollbarWidth(d.measure) === 0)
362
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
363
+ }
364
+
365
+ function visibleLines(display, doc, viewPort) {
366
+ var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
367
+ if (typeof viewPort == "number") top = viewPort;
368
+ else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
369
+ top = Math.floor(top - paddingTop(display));
370
+ var bottom = Math.ceil(top + height);
371
+ return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
372
+ }
373
+
374
+ // LINE NUMBERS
375
+
376
+ function alignHorizontally(cm) {
377
+ var display = cm.display;
378
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
379
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
380
+ var gutterW = display.gutters.offsetWidth, l = comp + "px";
381
+ for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
382
+ for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
383
+ }
384
+ if (cm.options.fixedGutter)
385
+ display.gutters.style.left = (comp + gutterW) + "px";
386
+ }
387
+
388
+ function maybeUpdateLineNumberWidth(cm) {
389
+ if (!cm.options.lineNumbers) return false;
390
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
391
+ if (last.length != display.lineNumChars) {
392
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
393
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
394
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
395
+ display.lineGutter.style.width = "";
396
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
397
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
398
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
399
+ display.lineGutter.style.width = display.lineNumWidth + "px";
400
+ return true;
401
+ }
402
+ return false;
403
+ }
404
+
405
+ function lineNumberFor(options, i) {
406
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
407
+ }
408
+ function compensateForHScroll(display) {
409
+ return getRect(display.scroller).left - getRect(display.sizer).left;
410
+ }
411
+
412
+ // DISPLAY DRAWING
413
+
414
+ function updateDisplay(cm, changes, viewPort, forced) {
415
+ var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
416
+ var visible = visibleLines(cm.display, cm.doc, viewPort);
417
+ for (;;) {
418
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
419
+ forced = false;
420
+ updated = true;
421
+ updateSelection(cm);
422
+ updateScrollbars(cm);
423
+
424
+ // Clip forced viewport to actual scrollable area
425
+ if (viewPort)
426
+ viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
427
+ typeof viewPort == "number" ? viewPort : viewPort.top);
428
+ visible = visibleLines(cm.display, cm.doc, viewPort);
429
+ if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
430
+ break;
431
+ changes = [];
432
+ }
433
+
434
+ if (updated) {
435
+ signalLater(cm, "update", cm);
436
+ if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
437
+ signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
438
+ }
439
+ return updated;
440
+ }
441
+
442
+ // Uses a set of changes plus the current scroll position to
443
+ // determine which DOM updates have to be made, and makes the
444
+ // updates.
445
+ function updateDisplayInner(cm, changes, visible, forced) {
446
+ var display = cm.display, doc = cm.doc;
447
+ if (!display.wrapper.clientWidth) {
448
+ display.showingFrom = display.showingTo = doc.first;
449
+ display.viewOffset = 0;
450
+ return;
451
+ }
452
+
453
+ // Bail out if the visible area is already rendered and nothing changed.
454
+ if (!forced && changes.length == 0 &&
455
+ visible.from > display.showingFrom && visible.to < display.showingTo)
456
+ return;
457
+
458
+ if (maybeUpdateLineNumberWidth(cm))
459
+ changes = [{from: doc.first, to: doc.first + doc.size}];
460
+ var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
461
+ display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
462
+
463
+ // Used to determine which lines need their line numbers updated
464
+ var positionsChangedFrom = Infinity;
465
+ if (cm.options.lineNumbers)
466
+ for (var i = 0; i < changes.length; ++i)
467
+ if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
468
+
469
+ var end = doc.first + doc.size;
470
+ var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
471
+ var to = Math.min(end, visible.to + cm.options.viewportMargin);
472
+ if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
473
+ if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
474
+ if (sawCollapsedSpans) {
475
+ from = lineNo(visualLine(doc, getLine(doc, from)));
476
+ while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
477
+ }
478
+
479
+ // Create a range of theoretically intact lines, and punch holes
480
+ // in that using the change info.
481
+ var intact = [{from: Math.max(display.showingFrom, doc.first),
482
+ to: Math.min(display.showingTo, end)}];
483
+ if (intact[0].from >= intact[0].to) intact = [];
484
+ else intact = computeIntact(intact, changes);
485
+ // When merged lines are present, we might have to reduce the
486
+ // intact ranges because changes in continued fragments of the
487
+ // intact lines do require the lines to be redrawn.
488
+ if (sawCollapsedSpans)
489
+ for (var i = 0; i < intact.length; ++i) {
490
+ var range = intact[i], merged;
491
+ while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
492
+ var newTo = merged.find().from.line;
493
+ if (newTo > range.from) range.to = newTo;
494
+ else { intact.splice(i--, 1); break; }
495
+ }
496
+ }
497
+
498
+ // Clip off the parts that won't be visible
499
+ var intactLines = 0;
500
+ for (var i = 0; i < intact.length; ++i) {
501
+ var range = intact[i];
502
+ if (range.from < from) range.from = from;
503
+ if (range.to > to) range.to = to;
504
+ if (range.from >= range.to) intact.splice(i--, 1);
505
+ else intactLines += range.to - range.from;
506
+ }
507
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
508
+ updateViewOffset(cm);
509
+ return;
510
+ }
511
+ intact.sort(function(a, b) {return a.from - b.from;});
512
+
513
+ // Avoid crashing on IE's "unspecified error" when in iframes
514
+ try {
515
+ var focused = document.activeElement;
516
+ } catch(e) {}
517
+ if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
518
+ patchDisplay(cm, from, to, intact, positionsChangedFrom);
519
+ display.lineDiv.style.display = "";
520
+ if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
521
+
522
+ var different = from != display.showingFrom || to != display.showingTo ||
523
+ display.lastSizeC != display.wrapper.clientHeight;
524
+ // This is just a bogus formula that detects when the editor is
525
+ // resized or the font size changes.
526
+ if (different) {
527
+ display.lastSizeC = display.wrapper.clientHeight;
528
+ startWorker(cm, 400);
529
+ }
530
+ display.showingFrom = from; display.showingTo = to;
531
+
532
+ updateHeightsInViewport(cm);
533
+ updateViewOffset(cm);
534
+
535
+ return true;
536
+ }
537
+
538
+ function updateHeightsInViewport(cm) {
539
+ var display = cm.display;
540
+ var prevBottom = display.lineDiv.offsetTop;
541
+ for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
542
+ if (ie_lt8) {
543
+ var bot = node.offsetTop + node.offsetHeight;
544
+ height = bot - prevBottom;
545
+ prevBottom = bot;
546
+ } else {
547
+ var box = getRect(node);
548
+ height = box.bottom - box.top;
549
+ }
550
+ var diff = node.lineObj.height - height;
551
+ if (height < 2) height = textHeight(display);
552
+ if (diff > .001 || diff < -.001) {
553
+ updateLineHeight(node.lineObj, height);
554
+ var widgets = node.lineObj.widgets;
555
+ if (widgets) for (var i = 0; i < widgets.length; ++i)
556
+ widgets[i].height = widgets[i].node.offsetHeight;
557
+ }
558
+ }
559
+ }
560
+
561
+ function updateViewOffset(cm) {
562
+ var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
563
+ // Position the mover div to align with the current virtual scroll position
564
+ cm.display.mover.style.top = off + "px";
565
+ }
566
+
567
+ function computeIntact(intact, changes) {
568
+ for (var i = 0, l = changes.length || 0; i < l; ++i) {
569
+ var change = changes[i], intact2 = [], diff = change.diff || 0;
570
+ for (var j = 0, l2 = intact.length; j < l2; ++j) {
571
+ var range = intact[j];
572
+ if (change.to <= range.from && change.diff) {
573
+ intact2.push({from: range.from + diff, to: range.to + diff});
574
+ } else if (change.to <= range.from || change.from >= range.to) {
575
+ intact2.push(range);
576
+ } else {
577
+ if (change.from > range.from)
578
+ intact2.push({from: range.from, to: change.from});
579
+ if (change.to < range.to)
580
+ intact2.push({from: change.to + diff, to: range.to + diff});
581
+ }
582
+ }
583
+ intact = intact2;
584
+ }
585
+ return intact;
586
+ }
587
+
588
+ function getDimensions(cm) {
589
+ var d = cm.display, left = {}, width = {};
590
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
591
+ left[cm.options.gutters[i]] = n.offsetLeft;
592
+ width[cm.options.gutters[i]] = n.offsetWidth;
593
+ }
594
+ return {fixedPos: compensateForHScroll(d),
595
+ gutterTotalWidth: d.gutters.offsetWidth,
596
+ gutterLeft: left,
597
+ gutterWidth: width,
598
+ wrapperWidth: d.wrapper.clientWidth};
599
+ }
600
+
601
+ function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
602
+ var dims = getDimensions(cm);
603
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
604
+ if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
605
+ removeChildren(display.lineDiv);
606
+ var container = display.lineDiv, cur = container.firstChild;
607
+
608
+ function rm(node) {
609
+ var next = node.nextSibling;
610
+ if (webkit && mac && cm.display.currentWheelTarget == node) {
611
+ node.style.display = "none";
612
+ node.lineObj = null;
613
+ } else {
614
+ node.parentNode.removeChild(node);
615
+ }
616
+ return next;
617
+ }
618
+
619
+ var nextIntact = intact.shift(), lineN = from;
620
+ cm.doc.iter(from, to, function(line) {
621
+ if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
622
+ if (lineIsHidden(cm.doc, line)) {
623
+ if (line.height != 0) updateLineHeight(line, 0);
624
+ if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
625
+ var w = line.widgets[i];
626
+ if (w.showIfHidden) {
627
+ var prev = cur.previousSibling;
628
+ if (/pre/i.test(prev.nodeName)) {
629
+ var wrap = elt("div", null, null, "position: relative");
630
+ prev.parentNode.replaceChild(wrap, prev);
631
+ wrap.appendChild(prev);
632
+ prev = wrap;
633
+ }
634
+ var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
635
+ if (!w.handleMouseEvents) wnode.ignoreEvents = true;
636
+ positionLineWidget(w, wnode, prev, dims);
637
+ }
638
+ }
639
+ } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
640
+ // This line is intact. Skip to the actual node. Update its
641
+ // line number if needed.
642
+ while (cur.lineObj != line) cur = rm(cur);
643
+ if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
644
+ setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
645
+ cur = cur.nextSibling;
646
+ } else {
647
+ // For lines with widgets, make an attempt to find and reuse
648
+ // the existing element, so that widgets aren't needlessly
649
+ // removed and re-inserted into the dom
650
+ if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
651
+ if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
652
+ // This line needs to be generated.
653
+ var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
654
+ if (lineNode != reuse) {
655
+ container.insertBefore(lineNode, cur);
656
+ } else {
657
+ while (cur != reuse) cur = rm(cur);
658
+ cur = cur.nextSibling;
659
+ }
660
+
661
+ lineNode.lineObj = line;
662
+ }
663
+ ++lineN;
664
+ });
665
+ while (cur) cur = rm(cur);
666
+ }
667
+
668
+ function buildLineElement(cm, line, lineNo, dims, reuse) {
669
+ var lineElement = lineContent(cm, line);
670
+ var markers = line.gutterMarkers, display = cm.display, wrap;
671
+
672
+ if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
673
+ return lineElement;
674
+
675
+ // Lines with gutter elements, widgets or a background class need
676
+ // to be wrapped again, and have the extra elements added to the
677
+ // wrapper div
678
+
679
+ if (reuse) {
680
+ reuse.alignable = null;
681
+ var isOk = true, widgetsSeen = 0, insertBefore = null;
682
+ for (var n = reuse.firstChild, next; n; n = next) {
683
+ next = n.nextSibling;
684
+ if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
685
+ reuse.removeChild(n);
686
+ } else {
687
+ for (var i = 0; i < line.widgets.length; ++i) {
688
+ var widget = line.widgets[i];
689
+ if (widget.node == n.firstChild) {
690
+ if (!widget.above && !insertBefore) insertBefore = n;
691
+ positionLineWidget(widget, n, reuse, dims);
692
+ ++widgetsSeen;
693
+ break;
694
+ }
695
+ }
696
+ if (i == line.widgets.length) { isOk = false; break; }
697
+ }
698
+ }
699
+ reuse.insertBefore(lineElement, insertBefore);
700
+ if (isOk && widgetsSeen == line.widgets.length) {
701
+ wrap = reuse;
702
+ reuse.className = line.wrapClass || "";
703
+ }
704
+ }
705
+ if (!wrap) {
706
+ wrap = elt("div", null, line.wrapClass, "position: relative");
707
+ wrap.appendChild(lineElement);
708
+ }
709
+ // Kludge to make sure the styled element lies behind the selection (by z-index)
710
+ if (line.bgClass)
711
+ wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
712
+ if (cm.options.lineNumbers || markers) {
713
+ var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
714
+ (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
715
+ wrap.firstChild);
716
+ if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
717
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
718
+ wrap.lineNumber = gutterWrap.appendChild(
719
+ elt("div", lineNumberFor(cm.options, lineNo),
720
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
721
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
722
+ + display.lineNumInnerWidth + "px"));
723
+ if (markers)
724
+ for (var k = 0; k < cm.options.gutters.length; ++k) {
725
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
726
+ if (found)
727
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
728
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
729
+ }
730
+ }
731
+ if (ie_lt8) wrap.style.zIndex = 2;
732
+ if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
733
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
734
+ if (!widget.handleMouseEvents) node.ignoreEvents = true;
735
+ positionLineWidget(widget, node, wrap, dims);
736
+ if (widget.above)
737
+ wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
738
+ else
739
+ wrap.appendChild(node);
740
+ signalLater(widget, "redraw");
741
+ }
742
+ return wrap;
743
+ }
744
+
745
+ function positionLineWidget(widget, node, wrap, dims) {
746
+ if (widget.noHScroll) {
747
+ (wrap.alignable || (wrap.alignable = [])).push(node);
748
+ var width = dims.wrapperWidth;
749
+ node.style.left = dims.fixedPos + "px";
750
+ if (!widget.coverGutter) {
751
+ width -= dims.gutterTotalWidth;
752
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
753
+ }
754
+ node.style.width = width + "px";
755
+ }
756
+ if (widget.coverGutter) {
757
+ node.style.zIndex = 5;
758
+ node.style.position = "relative";
759
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
760
+ }
761
+ }
762
+
763
+ // SELECTION / CURSOR
764
+
765
+ function updateSelection(cm) {
766
+ var display = cm.display;
767
+ var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
768
+ if (collapsed || cm.options.showCursorWhenSelecting)
769
+ updateSelectionCursor(cm);
770
+ else
771
+ display.cursor.style.display = display.otherCursor.style.display = "none";
772
+ if (!collapsed)
773
+ updateSelectionRange(cm);
774
+ else
775
+ display.selectionDiv.style.display = "none";
776
+
777
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
778
+ if (cm.options.moveInputWithCursor) {
779
+ var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
780
+ var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
781
+ display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
782
+ headPos.top + lineOff.top - wrapOff.top)) + "px";
783
+ display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
784
+ headPos.left + lineOff.left - wrapOff.left)) + "px";
785
+ }
786
+ }
787
+
788
+ // No selection, plain cursor
789
+ function updateSelectionCursor(cm) {
790
+ var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
791
+ display.cursor.style.left = pos.left + "px";
792
+ display.cursor.style.top = pos.top + "px";
793
+ display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
794
+ display.cursor.style.display = "";
795
+
796
+ if (pos.other) {
797
+ display.otherCursor.style.display = "";
798
+ display.otherCursor.style.left = pos.other.left + "px";
799
+ display.otherCursor.style.top = pos.other.top + "px";
800
+ display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
801
+ } else { display.otherCursor.style.display = "none"; }
802
+ }
803
+
804
+ // Highlight selection
805
+ function updateSelectionRange(cm) {
806
+ var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
807
+ var fragment = document.createDocumentFragment();
808
+ var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
809
+
810
+ function add(left, top, width, bottom) {
811
+ if (top < 0) top = 0;
812
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
813
+ "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
814
+ "px; height: " + (bottom - top) + "px"));
815
+ }
816
+
817
+ function drawForLine(line, fromArg, toArg) {
818
+ var lineObj = getLine(doc, line);
819
+ var lineLen = lineObj.text.length;
820
+ var start, end;
821
+ function coords(ch, bias) {
822
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
823
+ }
824
+
825
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
826
+ var leftPos = coords(from, "left"), rightPos, left, right;
827
+ if (from == to) {
828
+ rightPos = leftPos;
829
+ left = right = leftPos.left;
830
+ } else {
831
+ rightPos = coords(to - 1, "right");
832
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
833
+ left = leftPos.left;
834
+ right = rightPos.right;
835
+ }
836
+ if (fromArg == null && from == 0) left = pl;
837
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
838
+ add(left, leftPos.top, null, leftPos.bottom);
839
+ left = pl;
840
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
841
+ }
842
+ if (toArg == null && to == lineLen) right = clientWidth;
843
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
844
+ start = leftPos;
845
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
846
+ end = rightPos;
847
+ if (left < pl + 1) left = pl;
848
+ add(left, rightPos.top, right - left, rightPos.bottom);
849
+ });
850
+ return {start: start, end: end};
851
+ }
852
+
853
+ if (sel.from.line == sel.to.line) {
854
+ drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
855
+ } else {
856
+ var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
857
+ var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
858
+ var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
859
+ var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
860
+ if (singleVLine) {
861
+ if (leftEnd.top < rightStart.top - 2) {
862
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
863
+ add(pl, rightStart.top, rightStart.left, rightStart.bottom);
864
+ } else {
865
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
866
+ }
867
+ }
868
+ if (leftEnd.bottom < rightStart.top)
869
+ add(pl, leftEnd.bottom, null, rightStart.top);
870
+ }
871
+
872
+ removeChildrenAndAdd(display.selectionDiv, fragment);
873
+ display.selectionDiv.style.display = "";
874
+ }
875
+
876
+ // Cursor-blinking
877
+ function restartBlink(cm) {
878
+ if (!cm.state.focused) return;
879
+ var display = cm.display;
880
+ clearInterval(display.blinker);
881
+ var on = true;
882
+ display.cursor.style.visibility = display.otherCursor.style.visibility = "";
883
+ display.blinker = setInterval(function() {
884
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
885
+ }, cm.options.cursorBlinkRate);
886
+ }
887
+
888
+ // HIGHLIGHT WORKER
889
+
890
+ function startWorker(cm, time) {
891
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
892
+ cm.state.highlight.set(time, bind(highlightWorker, cm));
893
+ }
894
+
895
+ function highlightWorker(cm) {
896
+ var doc = cm.doc;
897
+ if (doc.frontier < doc.first) doc.frontier = doc.first;
898
+ if (doc.frontier >= cm.display.showingTo) return;
899
+ var end = +new Date + cm.options.workTime;
900
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
901
+ var changed = [], prevChange;
902
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
903
+ if (doc.frontier >= cm.display.showingFrom) { // Visible
904
+ var oldStyles = line.styles;
905
+ line.styles = highlightLine(cm, line, state);
906
+ var ischange = !oldStyles || oldStyles.length != line.styles.length;
907
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
908
+ if (ischange) {
909
+ if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
910
+ else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
911
+ }
912
+ line.stateAfter = copyState(doc.mode, state);
913
+ } else {
914
+ processLine(cm, line, state);
915
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
916
+ }
917
+ ++doc.frontier;
918
+ if (+new Date > end) {
919
+ startWorker(cm, cm.options.workDelay);
920
+ return true;
921
+ }
922
+ });
923
+ if (changed.length)
924
+ operation(cm, function() {
925
+ for (var i = 0; i < changed.length; ++i)
926
+ regChange(this, changed[i].start, changed[i].end);
927
+ })();
928
+ }
929
+
930
+ // Finds the line to start with when starting a parse. Tries to
931
+ // find a line with a stateAfter, so that it can start with a
932
+ // valid state. If that fails, it returns the line with the
933
+ // smallest indentation, which tends to need the least context to
934
+ // parse correctly.
935
+ function findStartLine(cm, n, precise) {
936
+ var minindent, minline, doc = cm.doc;
937
+ for (var search = n, lim = n - 100; search > lim; --search) {
938
+ if (search <= doc.first) return doc.first;
939
+ var line = getLine(doc, search - 1);
940
+ if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
941
+ var indented = countColumn(line.text, null, cm.options.tabSize);
942
+ if (minline == null || minindent > indented) {
943
+ minline = search - 1;
944
+ minindent = indented;
945
+ }
946
+ }
947
+ return minline;
948
+ }
949
+
950
+ function getStateBefore(cm, n, precise) {
951
+ var doc = cm.doc, display = cm.display;
952
+ if (!doc.mode.startState) return true;
953
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
954
+ if (!state) state = startState(doc.mode);
955
+ else state = copyState(doc.mode, state);
956
+ doc.iter(pos, n, function(line) {
957
+ processLine(cm, line, state);
958
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
959
+ line.stateAfter = save ? copyState(doc.mode, state) : null;
960
+ ++pos;
961
+ });
962
+ return state;
963
+ }
964
+
965
+ // POSITION MEASUREMENT
966
+
967
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
968
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
969
+ function paddingLeft(display) {
970
+ var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
971
+ return e.offsetLeft;
972
+ }
973
+
974
+ function measureChar(cm, line, ch, data, bias) {
975
+ var dir = -1;
976
+ data = data || measureLine(cm, line);
977
+
978
+ for (var pos = ch;; pos += dir) {
979
+ var r = data[pos];
980
+ if (r) break;
981
+ if (dir < 0 && pos == 0) dir = 1;
982
+ }
983
+ bias = pos > ch ? "left" : pos < ch ? "right" : bias;
984
+ if (bias == "left" && r.leftSide) r = r.leftSide;
985
+ else if (bias == "right" && r.rightSide) r = r.rightSide;
986
+ return {left: pos < ch ? r.right : r.left,
987
+ right: pos > ch ? r.left : r.right,
988
+ top: r.top,
989
+ bottom: r.bottom};
990
+ }
991
+
992
+ function findCachedMeasurement(cm, line) {
993
+ var cache = cm.display.measureLineCache;
994
+ for (var i = 0; i < cache.length; ++i) {
995
+ var memo = cache[i];
996
+ if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
997
+ cm.display.scroller.clientWidth == memo.width &&
998
+ memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
999
+ return memo;
1000
+ }
1001
+ }
1002
+
1003
+ function clearCachedMeasurement(cm, line) {
1004
+ var exists = findCachedMeasurement(cm, line);
1005
+ if (exists) exists.text = exists.measure = exists.markedSpans = null;
1006
+ }
1007
+
1008
+ function measureLine(cm, line) {
1009
+ // First look in the cache
1010
+ var cached = findCachedMeasurement(cm, line);
1011
+ if (cached) return cached.measure;
1012
+
1013
+ // Failing that, recompute and store result in cache
1014
+ var measure = measureLineInner(cm, line);
1015
+ var cache = cm.display.measureLineCache;
1016
+ var memo = {text: line.text, width: cm.display.scroller.clientWidth,
1017
+ markedSpans: line.markedSpans, measure: measure,
1018
+ classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
1019
+ if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1020
+ else cache.push(memo);
1021
+ return measure;
1022
+ }
1023
+
1024
+ function measureLineInner(cm, line) {
1025
+ var display = cm.display, measure = emptyArray(line.text.length);
1026
+ var pre = lineContent(cm, line, measure, true);
1027
+
1028
+ // IE does not cache element positions of inline elements between
1029
+ // calls to getBoundingClientRect. This makes the loop below,
1030
+ // which gathers the positions of all the characters on the line,
1031
+ // do an amount of layout work quadratic to the number of
1032
+ // characters. When line wrapping is off, we try to improve things
1033
+ // by first subdividing the line into a bunch of inline blocks, so
1034
+ // that IE can reuse most of the layout information from caches
1035
+ // for those blocks. This does interfere with line wrapping, so it
1036
+ // doesn't work when wrapping is on, but in that case the
1037
+ // situation is slightly better, since IE does cache line-wrapping
1038
+ // information and only recomputes per-line.
1039
+ if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1040
+ var fragment = document.createDocumentFragment();
1041
+ var chunk = 10, n = pre.childNodes.length;
1042
+ for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
1043
+ var wrap = elt("div", null, null, "display: inline-block");
1044
+ for (var j = 0; j < chunk && n; ++j) {
1045
+ wrap.appendChild(pre.firstChild);
1046
+ --n;
1047
+ }
1048
+ fragment.appendChild(wrap);
1049
+ }
1050
+ pre.appendChild(fragment);
1051
+ }
1052
+
1053
+ removeChildrenAndAdd(display.measure, pre);
1054
+
1055
+ var outer = getRect(display.lineDiv);
1056
+ var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
1057
+ // Work around an IE7/8 bug where it will sometimes have randomly
1058
+ // replaced our pre with a clone at this point.
1059
+ if (ie_lt9 && display.measure.first != pre)
1060
+ removeChildrenAndAdd(display.measure, pre);
1061
+
1062
+ function measureRect(rect) {
1063
+ var top = rect.top - outer.top, bot = rect.bottom - outer.top;
1064
+ if (bot > maxBot) bot = maxBot;
1065
+ if (top < 0) top = 0;
1066
+ for (var i = vranges.length - 2; i >= 0; i -= 2) {
1067
+ var rtop = vranges[i], rbot = vranges[i+1];
1068
+ if (rtop > bot || rbot < top) continue;
1069
+ if (rtop <= top && rbot >= bot ||
1070
+ top <= rtop && bot >= rbot ||
1071
+ Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1072
+ vranges[i] = Math.min(top, rtop);
1073
+ vranges[i+1] = Math.max(bot, rbot);
1074
+ break;
1075
+ }
1076
+ }
1077
+ if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1078
+ return {left: rect.left - outer.left,
1079
+ right: rect.right - outer.left,
1080
+ top: i, bottom: null};
1081
+ }
1082
+ function finishRect(rect) {
1083
+ rect.bottom = vranges[rect.top+1];
1084
+ rect.top = vranges[rect.top];
1085
+ }
1086
+
1087
+ for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1088
+ var node = cur, rect = null;
1089
+ // A widget might wrap, needs special care
1090
+ if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1091
+ if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1092
+ var rects = node.getClientRects();
1093
+ if (rects.length > 1) {
1094
+ rect = data[i] = measureRect(rects[0]);
1095
+ rect.rightSide = measureRect(rects[rects.length - 1]);
1096
+ }
1097
+ }
1098
+ if (!rect) rect = data[i] = measureRect(getRect(node));
1099
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1100
+ if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1101
+ }
1102
+ for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1103
+ finishRect(cur);
1104
+ if (cur.leftSide) finishRect(cur.leftSide);
1105
+ if (cur.rightSide) finishRect(cur.rightSide);
1106
+ }
1107
+ return data;
1108
+ }
1109
+
1110
+ function measureLineWidth(cm, line) {
1111
+ var hasBadSpan = false;
1112
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
1113
+ var sp = line.markedSpans[i];
1114
+ if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1115
+ }
1116
+ var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1117
+ if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1118
+
1119
+ var pre = lineContent(cm, line, null, true);
1120
+ var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1121
+ removeChildrenAndAdd(cm.display.measure, pre);
1122
+ return getRect(end).right - getRect(cm.display.lineDiv).left;
1123
+ }
1124
+
1125
+ function clearCaches(cm) {
1126
+ cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
1127
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
1128
+ if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
1129
+ cm.display.lineNumChars = null;
1130
+ }
1131
+
1132
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
1133
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
1134
+
1135
+ // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1136
+ function intoCoordSystem(cm, lineObj, rect, context) {
1137
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1138
+ var size = widgetHeight(lineObj.widgets[i]);
1139
+ rect.top += size; rect.bottom += size;
1140
+ }
1141
+ if (context == "line") return rect;
1142
+ if (!context) context = "local";
1143
+ var yOff = heightAtLine(cm, lineObj);
1144
+ if (context == "local") yOff += paddingTop(cm.display);
1145
+ else yOff -= cm.display.viewOffset;
1146
+ if (context == "page" || context == "window") {
1147
+ var lOff = getRect(cm.display.lineSpace);
1148
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1149
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1150
+ rect.left += xOff; rect.right += xOff;
1151
+ }
1152
+ rect.top += yOff; rect.bottom += yOff;
1153
+ return rect;
1154
+ }
1155
+
1156
+ // Context may be "window", "page", "div", or "local"/null
1157
+ // Result is in "div" coords
1158
+ function fromCoordSystem(cm, coords, context) {
1159
+ if (context == "div") return coords;
1160
+ var left = coords.left, top = coords.top;
1161
+ // First move into "page" coordinate system
1162
+ if (context == "page") {
1163
+ left -= pageScrollX();
1164
+ top -= pageScrollY();
1165
+ } else if (context == "local" || !context) {
1166
+ var localBox = getRect(cm.display.sizer);
1167
+ left += localBox.left;
1168
+ top += localBox.top;
1169
+ }
1170
+
1171
+ var lineSpaceBox = getRect(cm.display.lineSpace);
1172
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1173
+ }
1174
+
1175
+ function charCoords(cm, pos, context, lineObj, bias) {
1176
+ if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1177
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
1178
+ }
1179
+
1180
+ function cursorCoords(cm, pos, context, lineObj, measurement) {
1181
+ lineObj = lineObj || getLine(cm.doc, pos.line);
1182
+ if (!measurement) measurement = measureLine(cm, lineObj);
1183
+ function get(ch, right) {
1184
+ var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
1185
+ if (right) m.left = m.right; else m.right = m.left;
1186
+ return intoCoordSystem(cm, lineObj, m, context);
1187
+ }
1188
+ function getBidi(ch, partPos) {
1189
+ var part = order[partPos], right = part.level % 2;
1190
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
1191
+ part = order[--partPos];
1192
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
1193
+ right = true;
1194
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
1195
+ part = order[++partPos];
1196
+ ch = bidiLeft(part) - part.level % 2;
1197
+ right = false;
1198
+ }
1199
+ if (right && ch == part.to && ch > part.from) return get(ch - 1);
1200
+ return get(ch, right);
1201
+ }
1202
+ var order = getOrder(lineObj), ch = pos.ch;
1203
+ if (!order) return get(ch);
1204
+ var partPos = getBidiPartAt(order, ch);
1205
+ var val = getBidi(ch, partPos);
1206
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1207
+ return val;
1208
+ }
1209
+
1210
+ function PosWithInfo(line, ch, outside, xRel) {
1211
+ var pos = new Pos(line, ch);
1212
+ pos.xRel = xRel;
1213
+ if (outside) pos.outside = true;
1214
+ return pos;
1215
+ }
1216
+
1217
+ // Coords must be lineSpace-local
1218
+ function coordsChar(cm, x, y) {
1219
+ var doc = cm.doc;
1220
+ y += cm.display.viewOffset;
1221
+ if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1222
+ var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1223
+ if (lineNo > last)
1224
+ return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
1225
+ if (x < 0) x = 0;
1226
+
1227
+ for (;;) {
1228
+ var lineObj = getLine(doc, lineNo);
1229
+ var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1230
+ var merged = collapsedSpanAtEnd(lineObj);
1231
+ var mergedPos = merged && merged.find();
1232
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1233
+ lineNo = mergedPos.to.line;
1234
+ else
1235
+ return found;
1236
+ }
1237
+ }
1238
+
1239
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
1240
+ var innerOff = y - heightAtLine(cm, lineObj);
1241
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
1242
+ var measurement = measureLine(cm, lineObj);
1243
+
1244
+ function getX(ch) {
1245
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
1246
+ lineObj, measurement);
1247
+ wrongLine = true;
1248
+ if (innerOff > sp.bottom) return sp.left - adjust;
1249
+ else if (innerOff < sp.top) return sp.left + adjust;
1250
+ else wrongLine = false;
1251
+ return sp.left;
1252
+ }
1253
+
1254
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
1255
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
1256
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1257
+
1258
+ if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
1259
+ // Do a binary search between these bounds.
1260
+ for (;;) {
1261
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1262
+ var ch = x < fromX || x - fromX <= toX - x ? from : to;
1263
+ var xDiff = x - (ch == from ? fromX : toX);
1264
+ while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1265
+ var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1266
+ xDiff < 0 ? -1 : xDiff ? 1 : 0);
1267
+ return pos;
1268
+ }
1269
+ var step = Math.ceil(dist / 2), middle = from + step;
1270
+ if (bidi) {
1271
+ middle = from;
1272
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
1273
+ }
1274
+ var middleX = getX(middle);
1275
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
1276
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
1277
+ }
1278
+ }
1279
+
1280
+ var measureText;
1281
+ function textHeight(display) {
1282
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
1283
+ if (measureText == null) {
1284
+ measureText = elt("pre");
1285
+ // Measure a bunch of lines, for browsers that compute
1286
+ // fractional heights.
1287
+ for (var i = 0; i < 49; ++i) {
1288
+ measureText.appendChild(document.createTextNode("x"));
1289
+ measureText.appendChild(elt("br"));
1290
+ }
1291
+ measureText.appendChild(document.createTextNode("x"));
1292
+ }
1293
+ removeChildrenAndAdd(display.measure, measureText);
1294
+ var height = measureText.offsetHeight / 50;
1295
+ if (height > 3) display.cachedTextHeight = height;
1296
+ removeChildren(display.measure);
1297
+ return height || 1;
1298
+ }
1299
+
1300
+ function charWidth(display) {
1301
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
1302
+ var anchor = elt("span", "x");
1303
+ var pre = elt("pre", [anchor]);
1304
+ removeChildrenAndAdd(display.measure, pre);
1305
+ var width = anchor.offsetWidth;
1306
+ if (width > 2) display.cachedCharWidth = width;
1307
+ return width || 10;
1308
+ }
1309
+
1310
+ // OPERATIONS
1311
+
1312
+ // Operations are used to wrap changes in such a way that each
1313
+ // change won't have to update the cursor and display (which would
1314
+ // be awkward, slow, and error-prone), but instead updates are
1315
+ // batched and then all combined and executed at once.
1316
+
1317
+ var nextOpId = 0;
1318
+ function startOperation(cm) {
1319
+ cm.curOp = {
1320
+ // An array of ranges of lines that have to be updated. See
1321
+ // updateDisplay.
1322
+ changes: [],
1323
+ forceUpdate: false,
1324
+ updateInput: null,
1325
+ userSelChange: null,
1326
+ textChanged: null,
1327
+ selectionChanged: false,
1328
+ cursorActivity: false,
1329
+ updateMaxLine: false,
1330
+ updateScrollPos: false,
1331
+ id: ++nextOpId
1332
+ };
1333
+ if (!delayedCallbackDepth++) delayedCallbacks = [];
1334
+ }
1335
+
1336
+ function endOperation(cm) {
1337
+ var op = cm.curOp, doc = cm.doc, display = cm.display;
1338
+ cm.curOp = null;
1339
+
1340
+ if (op.updateMaxLine) computeMaxLength(cm);
1341
+ if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
1342
+ var width = measureLineWidth(cm, display.maxLine);
1343
+ display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
1344
+ display.maxLineChanged = false;
1345
+ var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
1346
+ if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
1347
+ setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
1348
+ }
1349
+ var newScrollPos, updated;
1350
+ if (op.updateScrollPos) {
1351
+ newScrollPos = op.updateScrollPos;
1352
+ } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
1353
+ var coords = cursorCoords(cm, doc.sel.head);
1354
+ newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
1355
+ }
1356
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1357
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1358
+ if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1359
+ }
1360
+ if (!updated && op.selectionChanged) updateSelection(cm);
1361
+ if (op.updateScrollPos) {
1362
+ display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
1363
+ display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
1364
+ alignHorizontally(cm);
1365
+ if (op.scrollToPos)
1366
+ scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
1367
+ } else if (newScrollPos) {
1368
+ scrollCursorIntoView(cm);
1369
+ }
1370
+ if (op.selectionChanged) restartBlink(cm);
1371
+
1372
+ if (cm.state.focused && op.updateInput)
1373
+ resetInput(cm, op.userSelChange);
1374
+
1375
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
1376
+ if (hidden) for (var i = 0; i < hidden.length; ++i)
1377
+ if (!hidden[i].lines.length) signal(hidden[i], "hide");
1378
+ if (unhidden) for (var i = 0; i < unhidden.length; ++i)
1379
+ if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
1380
+
1381
+ var delayed;
1382
+ if (!--delayedCallbackDepth) {
1383
+ delayed = delayedCallbacks;
1384
+ delayedCallbacks = null;
1385
+ }
1386
+ if (op.textChanged)
1387
+ signal(cm, "change", cm, op.textChanged);
1388
+ if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1389
+ if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
1390
+ }
1391
+
1392
+ // Wraps a function in an operation. Returns the wrapped function.
1393
+ function operation(cm1, f) {
1394
+ return function() {
1395
+ var cm = cm1 || this, withOp = !cm.curOp;
1396
+ if (withOp) startOperation(cm);
1397
+ try { var result = f.apply(cm, arguments); }
1398
+ finally { if (withOp) endOperation(cm); }
1399
+ return result;
1400
+ };
1401
+ }
1402
+ function docOperation(f) {
1403
+ return function() {
1404
+ var withOp = this.cm && !this.cm.curOp, result;
1405
+ if (withOp) startOperation(this.cm);
1406
+ try { result = f.apply(this, arguments); }
1407
+ finally { if (withOp) endOperation(this.cm); }
1408
+ return result;
1409
+ };
1410
+ }
1411
+ function runInOp(cm, f) {
1412
+ var withOp = !cm.curOp, result;
1413
+ if (withOp) startOperation(cm);
1414
+ try { result = f(); }
1415
+ finally { if (withOp) endOperation(cm); }
1416
+ return result;
1417
+ }
1418
+
1419
+ function regChange(cm, from, to, lendiff) {
1420
+ if (from == null) from = cm.doc.first;
1421
+ if (to == null) to = cm.doc.first + cm.doc.size;
1422
+ cm.curOp.changes.push({from: from, to: to, diff: lendiff});
1423
+ }
1424
+
1425
+ // INPUT HANDLING
1426
+
1427
+ function slowPoll(cm) {
1428
+ if (cm.display.pollingFast) return;
1429
+ cm.display.poll.set(cm.options.pollInterval, function() {
1430
+ readInput(cm);
1431
+ if (cm.state.focused) slowPoll(cm);
1432
+ });
1433
+ }
1434
+
1435
+ function fastPoll(cm) {
1436
+ var missed = false;
1437
+ cm.display.pollingFast = true;
1438
+ function p() {
1439
+ var changed = readInput(cm);
1440
+ if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
1441
+ else {cm.display.pollingFast = false; slowPoll(cm);}
1442
+ }
1443
+ cm.display.poll.set(20, p);
1444
+ }
1445
+
1446
+ // prevInput is a hack to work with IME. If we reset the textarea
1447
+ // on every change, that breaks IME. So we look for changes
1448
+ // compared to the previous content instead. (Modern browsers have
1449
+ // events that indicate IME taking place, but these are not widely
1450
+ // supported or compatible enough yet to rely on.)
1451
+ function readInput(cm) {
1452
+ var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1453
+ if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1454
+ var text = input.value;
1455
+ if (text == prevInput && posEq(sel.from, sel.to)) return false;
1456
+ if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1457
+ resetInput(cm, true);
1458
+ return false;
1459
+ }
1460
+
1461
+ var withOp = !cm.curOp;
1462
+ if (withOp) startOperation(cm);
1463
+ sel.shift = false;
1464
+ var same = 0, l = Math.min(prevInput.length, text.length);
1465
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1466
+ var from = sel.from, to = sel.to;
1467
+ if (same < prevInput.length)
1468
+ from = Pos(from.line, from.ch - (prevInput.length - same));
1469
+ else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1470
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1471
+
1472
+ var updateInput = cm.curOp.updateInput;
1473
+ var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1474
+ origin: cm.state.pasteIncoming ? "paste" : "+input"};
1475
+ makeChange(cm.doc, changeEvent, "end");
1476
+ cm.curOp.updateInput = updateInput;
1477
+ signalLater(cm, "inputRead", cm, changeEvent);
1478
+
1479
+ if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1480
+ else cm.display.prevInput = text;
1481
+ if (withOp) endOperation(cm);
1482
+ cm.state.pasteIncoming = false;
1483
+ return true;
1484
+ }
1485
+
1486
+ function resetInput(cm, user) {
1487
+ var minimal, selected, doc = cm.doc;
1488
+ if (!posEq(doc.sel.from, doc.sel.to)) {
1489
+ cm.display.prevInput = "";
1490
+ minimal = hasCopyEvent &&
1491
+ (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
1492
+ var content = minimal ? "-" : selected || cm.getSelection();
1493
+ cm.display.input.value = content;
1494
+ if (cm.state.focused) selectInput(cm.display.input);
1495
+ if (ie && !ie_lt9) cm.display.inputHasSelection = content;
1496
+ } else if (user) {
1497
+ cm.display.prevInput = cm.display.input.value = "";
1498
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
1499
+ }
1500
+ cm.display.inaccurateSelection = minimal;
1501
+ }
1502
+
1503
+ function focusInput(cm) {
1504
+ if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
1505
+ cm.display.input.focus();
1506
+ }
1507
+
1508
+ function isReadOnly(cm) {
1509
+ return cm.options.readOnly || cm.doc.cantEdit;
1510
+ }
1511
+
1512
+ // EVENT HANDLERS
1513
+
1514
+ function registerEventHandlers(cm) {
1515
+ var d = cm.display;
1516
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
1517
+ if (ie)
1518
+ on(d.scroller, "dblclick", operation(cm, function(e) {
1519
+ if (signalDOMEvent(cm, e)) return;
1520
+ var pos = posFromMouse(cm, e);
1521
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1522
+ e_preventDefault(e);
1523
+ var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
1524
+ extendSelection(cm.doc, word.from, word.to);
1525
+ }));
1526
+ else
1527
+ on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1528
+ on(d.lineSpace, "selectstart", function(e) {
1529
+ if (!eventInWidget(d, e)) e_preventDefault(e);
1530
+ });
1531
+ // Gecko browsers fire contextmenu *after* opening the menu, at
1532
+ // which point we can't mess with it anymore. Context menu is
1533
+ // handled in onMouseDown for Gecko.
1534
+ if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
1535
+
1536
+ on(d.scroller, "scroll", function() {
1537
+ if (d.scroller.clientHeight) {
1538
+ setScrollTop(cm, d.scroller.scrollTop);
1539
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
1540
+ signal(cm, "scroll", cm);
1541
+ }
1542
+ });
1543
+ on(d.scrollbarV, "scroll", function() {
1544
+ if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
1545
+ });
1546
+ on(d.scrollbarH, "scroll", function() {
1547
+ if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
1548
+ });
1549
+
1550
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
1551
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
1552
+
1553
+ function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
1554
+ on(d.scrollbarH, "mousedown", reFocus);
1555
+ on(d.scrollbarV, "mousedown", reFocus);
1556
+ // Prevent wrapper from ever scrolling
1557
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1558
+
1559
+ var resizeTimer;
1560
+ function onResize() {
1561
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
1562
+ resizeTimer = null;
1563
+ // Might be a text scaling operation, clear size caches.
1564
+ d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1565
+ clearCaches(cm);
1566
+ runInOp(cm, bind(regChange, cm));
1567
+ }, 100);
1568
+ }
1569
+ on(window, "resize", onResize);
1570
+ // Above handler holds on to the editor and its data structures.
1571
+ // Here we poll to unregister it when the editor is no longer in
1572
+ // the document, so that it can be garbage-collected.
1573
+ function unregister() {
1574
+ for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
1575
+ if (p) setTimeout(unregister, 5000);
1576
+ else off(window, "resize", onResize);
1577
+ }
1578
+ setTimeout(unregister, 5000);
1579
+
1580
+ on(d.input, "keyup", operation(cm, function(e) {
1581
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1582
+ if (e.keyCode == 16) cm.doc.sel.shift = false;
1583
+ }));
1584
+ on(d.input, "input", bind(fastPoll, cm));
1585
+ on(d.input, "keydown", operation(cm, onKeyDown));
1586
+ on(d.input, "keypress", operation(cm, onKeyPress));
1587
+ on(d.input, "focus", bind(onFocus, cm));
1588
+ on(d.input, "blur", bind(onBlur, cm));
1589
+
1590
+ function drag_(e) {
1591
+ if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1592
+ e_stop(e);
1593
+ }
1594
+ if (cm.options.dragDrop) {
1595
+ on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
1596
+ on(d.scroller, "dragenter", drag_);
1597
+ on(d.scroller, "dragover", drag_);
1598
+ on(d.scroller, "drop", operation(cm, onDrop));
1599
+ }
1600
+ on(d.scroller, "paste", function(e){
1601
+ if (eventInWidget(d, e)) return;
1602
+ focusInput(cm);
1603
+ fastPoll(cm);
1604
+ });
1605
+ on(d.input, "paste", function() {
1606
+ cm.state.pasteIncoming = true;
1607
+ fastPoll(cm);
1608
+ });
1609
+
1610
+ function prepareCopy() {
1611
+ if (d.inaccurateSelection) {
1612
+ d.prevInput = "";
1613
+ d.inaccurateSelection = false;
1614
+ d.input.value = cm.getSelection();
1615
+ selectInput(d.input);
1616
+ }
1617
+ }
1618
+ on(d.input, "cut", prepareCopy);
1619
+ on(d.input, "copy", prepareCopy);
1620
+
1621
+ // Needed to handle Tab key in KHTML
1622
+ if (khtml) on(d.sizer, "mouseup", function() {
1623
+ if (document.activeElement == d.input) d.input.blur();
1624
+ focusInput(cm);
1625
+ });
1626
+ }
1627
+
1628
+ function eventInWidget(display, e) {
1629
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1630
+ if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1631
+ }
1632
+ }
1633
+
1634
+ function posFromMouse(cm, e, liberal) {
1635
+ var display = cm.display;
1636
+ if (!liberal) {
1637
+ var target = e_target(e);
1638
+ if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1639
+ target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1640
+ target == display.scrollbarFiller || target == display.gutterFiller) return null;
1641
+ }
1642
+ var x, y, space = getRect(display.lineSpace);
1643
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1644
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1645
+ return coordsChar(cm, x - space.left, y - space.top);
1646
+ }
1647
+
1648
+ var lastClick, lastDoubleClick;
1649
+ function onMouseDown(e) {
1650
+ if (signalDOMEvent(this, e)) return;
1651
+ var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1652
+ sel.shift = e.shiftKey;
1653
+
1654
+ if (eventInWidget(display, e)) {
1655
+ if (!webkit) {
1656
+ display.scroller.draggable = false;
1657
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
1658
+ }
1659
+ return;
1660
+ }
1661
+ if (clickInGutter(cm, e)) return;
1662
+ var start = posFromMouse(cm, e);
1663
+
1664
+ switch (e_button(e)) {
1665
+ case 3:
1666
+ if (captureMiddleClick) onContextMenu.call(cm, cm, e);
1667
+ return;
1668
+ case 2:
1669
+ if (start) extendSelection(cm.doc, start);
1670
+ setTimeout(bind(focusInput, cm), 20);
1671
+ e_preventDefault(e);
1672
+ return;
1673
+ }
1674
+ // For button 1, if it was clicked inside the editor
1675
+ // (posFromMouse returning non-null), we have to adjust the
1676
+ // selection.
1677
+ if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
1678
+
1679
+ if (!cm.state.focused) onFocus(cm);
1680
+
1681
+ var now = +new Date, type = "single";
1682
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
1683
+ type = "triple";
1684
+ e_preventDefault(e);
1685
+ setTimeout(bind(focusInput, cm), 20);
1686
+ selectLine(cm, start.line);
1687
+ } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
1688
+ type = "double";
1689
+ lastDoubleClick = {time: now, pos: start};
1690
+ e_preventDefault(e);
1691
+ var word = findWordAt(getLine(doc, start.line).text, start);
1692
+ extendSelection(cm.doc, word.from, word.to);
1693
+ } else { lastClick = {time: now, pos: start}; }
1694
+
1695
+ var last = start;
1696
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
1697
+ !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
1698
+ var dragEnd = operation(cm, function(e2) {
1699
+ if (webkit) display.scroller.draggable = false;
1700
+ cm.state.draggingText = false;
1701
+ off(document, "mouseup", dragEnd);
1702
+ off(display.scroller, "drop", dragEnd);
1703
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
1704
+ e_preventDefault(e2);
1705
+ extendSelection(cm.doc, start);
1706
+ focusInput(cm);
1707
+ }
1708
+ });
1709
+ // Let the drag handler handle this.
1710
+ if (webkit) display.scroller.draggable = true;
1711
+ cm.state.draggingText = dragEnd;
1712
+ // IE's approach to draggable
1713
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
1714
+ on(document, "mouseup", dragEnd);
1715
+ on(display.scroller, "drop", dragEnd);
1716
+ return;
1717
+ }
1718
+ e_preventDefault(e);
1719
+ if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
1720
+
1721
+ var startstart = sel.from, startend = sel.to, lastPos = start;
1722
+
1723
+ function doSelect(cur) {
1724
+ if (posEq(lastPos, cur)) return;
1725
+ lastPos = cur;
1726
+
1727
+ if (type == "single") {
1728
+ extendSelection(cm.doc, clipPos(doc, start), cur);
1729
+ return;
1730
+ }
1731
+
1732
+ startstart = clipPos(doc, startstart);
1733
+ startend = clipPos(doc, startend);
1734
+ if (type == "double") {
1735
+ var word = findWordAt(getLine(doc, cur.line).text, cur);
1736
+ if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
1737
+ else extendSelection(cm.doc, startstart, word.to);
1738
+ } else if (type == "triple") {
1739
+ if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
1740
+ else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
1741
+ }
1742
+ }
1743
+
1744
+ var editorSize = getRect(display.wrapper);
1745
+ // Used to ensure timeout re-tries don't fire when another extend
1746
+ // happened in the meantime (clearTimeout isn't reliable -- at
1747
+ // least on Chrome, the timeouts still happen even when cleared,
1748
+ // if the clear happens after their scheduled firing time).
1749
+ var counter = 0;
1750
+
1751
+ function extend(e) {
1752
+ var curCount = ++counter;
1753
+ var cur = posFromMouse(cm, e, true);
1754
+ if (!cur) return;
1755
+ if (!posEq(cur, last)) {
1756
+ if (!cm.state.focused) onFocus(cm);
1757
+ last = cur;
1758
+ doSelect(cur);
1759
+ var visible = visibleLines(display, doc);
1760
+ if (cur.line >= visible.to || cur.line < visible.from)
1761
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
1762
+ } else {
1763
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
1764
+ if (outside) setTimeout(operation(cm, function() {
1765
+ if (counter != curCount) return;
1766
+ display.scroller.scrollTop += outside;
1767
+ extend(e);
1768
+ }), 50);
1769
+ }
1770
+ }
1771
+
1772
+ function done(e) {
1773
+ counter = Infinity;
1774
+ e_preventDefault(e);
1775
+ focusInput(cm);
1776
+ off(document, "mousemove", move);
1777
+ off(document, "mouseup", up);
1778
+ }
1779
+
1780
+ var move = operation(cm, function(e) {
1781
+ if (!ie && !e_button(e)) done(e);
1782
+ else extend(e);
1783
+ });
1784
+ var up = operation(cm, done);
1785
+ on(document, "mousemove", move);
1786
+ on(document, "mouseup", up);
1787
+ }
1788
+
1789
+ function clickInGutter(cm, e) {
1790
+ var display = cm.display;
1791
+ try { var mX = e.clientX, mY = e.clientY; }
1792
+ catch(e) { return false; }
1793
+
1794
+ if (mX >= Math.floor(getRect(display.gutters).right)) return false;
1795
+ e_preventDefault(e);
1796
+ if (!hasHandler(cm, "gutterClick")) return true;
1797
+
1798
+ var lineBox = getRect(display.lineDiv);
1799
+ if (mY > lineBox.bottom) return true;
1800
+ mY -= lineBox.top - display.viewOffset;
1801
+
1802
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
1803
+ var g = display.gutters.childNodes[i];
1804
+ if (g && getRect(g).right >= mX) {
1805
+ var line = lineAtHeight(cm.doc, mY);
1806
+ var gutter = cm.options.gutters[i];
1807
+ signalLater(cm, "gutterClick", cm, line, gutter, e);
1808
+ break;
1809
+ }
1810
+ }
1811
+ return true;
1812
+ }
1813
+
1814
+ // Kludge to work around strange IE behavior where it'll sometimes
1815
+ // re-fire a series of drag-related events right after the drop (#1551)
1816
+ var lastDrop = 0;
1817
+
1818
+ function onDrop(e) {
1819
+ var cm = this;
1820
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1821
+ return;
1822
+ e_preventDefault(e);
1823
+ if (ie) lastDrop = +new Date;
1824
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1825
+ if (!pos || isReadOnly(cm)) return;
1826
+ if (files && files.length && window.FileReader && window.File) {
1827
+ var n = files.length, text = Array(n), read = 0;
1828
+ var loadFile = function(file, i) {
1829
+ var reader = new FileReader;
1830
+ reader.onload = function() {
1831
+ text[i] = reader.result;
1832
+ if (++read == n) {
1833
+ pos = clipPos(cm.doc, pos);
1834
+ makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
1835
+ }
1836
+ };
1837
+ reader.readAsText(file);
1838
+ };
1839
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
1840
+ } else {
1841
+ // Don't do a replace if the drop happened inside of the selected text.
1842
+ if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
1843
+ cm.state.draggingText(e);
1844
+ // Ensure the editor is re-focused
1845
+ setTimeout(bind(focusInput, cm), 20);
1846
+ return;
1847
+ }
1848
+ try {
1849
+ var text = e.dataTransfer.getData("Text");
1850
+ if (text) {
1851
+ var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
1852
+ setSelection(cm.doc, pos, pos);
1853
+ if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
1854
+ cm.replaceSelection(text, null, "paste");
1855
+ focusInput(cm);
1856
+ onFocus(cm);
1857
+ }
1858
+ }
1859
+ catch(e){}
1860
+ }
1861
+ }
1862
+
1863
+ function onDragStart(cm, e) {
1864
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1865
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1866
+
1867
+ var txt = cm.getSelection();
1868
+ e.dataTransfer.setData("Text", txt);
1869
+
1870
+ // Use dummy image instead of default browsers image.
1871
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1872
+ if (e.dataTransfer.setDragImage && !safari) {
1873
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1874
+ if (opera) {
1875
+ img.width = img.height = 1;
1876
+ cm.display.wrapper.appendChild(img);
1877
+ // Force a relayout, or Opera won't use our image for some obscure reason
1878
+ img._top = img.offsetTop;
1879
+ }
1880
+ e.dataTransfer.setDragImage(img, 0, 0);
1881
+ if (opera) img.parentNode.removeChild(img);
1882
+ }
1883
+ }
1884
+
1885
+ function setScrollTop(cm, val) {
1886
+ if (Math.abs(cm.doc.scrollTop - val) < 2) return;
1887
+ cm.doc.scrollTop = val;
1888
+ if (!gecko) updateDisplay(cm, [], val);
1889
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1890
+ if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1891
+ if (gecko) updateDisplay(cm, []);
1892
+ startWorker(cm, 100);
1893
+ }
1894
+ function setScrollLeft(cm, val, isScroller) {
1895
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1896
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
1897
+ cm.doc.scrollLeft = val;
1898
+ alignHorizontally(cm);
1899
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
1900
+ if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
1901
+ }
1902
+
1903
+ // Since the delta values reported on mouse wheel events are
1904
+ // unstandardized between browsers and even browser versions, and
1905
+ // generally horribly unpredictable, this code starts by measuring
1906
+ // the scroll effect that the first few mouse wheel events have,
1907
+ // and, from that, detects the way it can convert deltas to pixel
1908
+ // offsets afterwards.
1909
+ //
1910
+ // The reason we want to know the amount a wheel event will scroll
1911
+ // is that it gives us a chance to update the display before the
1912
+ // actual scrolling happens, reducing flickering.
1913
+
1914
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
1915
+ // Fill in a browser-detected starting value on browsers where we
1916
+ // know one. These don't have to be accurate -- the result of them
1917
+ // being wrong would just be a slight flicker on the first wheel
1918
+ // scroll (if it is large enough).
1919
+ if (ie) wheelPixelsPerUnit = -.53;
1920
+ else if (gecko) wheelPixelsPerUnit = 15;
1921
+ else if (chrome) wheelPixelsPerUnit = -.7;
1922
+ else if (safari) wheelPixelsPerUnit = -1/3;
1923
+
1924
+ function onScrollWheel(cm, e) {
1925
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
1926
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
1927
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
1928
+ else if (dy == null) dy = e.wheelDelta;
1929
+
1930
+ var display = cm.display, scroll = display.scroller;
1931
+ // Quit if there's nothing to scroll here
1932
+ if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
1933
+ dy && scroll.scrollHeight > scroll.clientHeight)) return;
1934
+
1935
+ // Webkit browsers on OS X abort momentum scrolls when the target
1936
+ // of the scroll event is removed from the scrollable element.
1937
+ // This hack (see related code in patchDisplay) makes sure the
1938
+ // element is kept around.
1939
+ if (dy && mac && webkit) {
1940
+ for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
1941
+ if (cur.lineObj) {
1942
+ cm.display.currentWheelTarget = cur;
1943
+ break;
1944
+ }
1945
+ }
1946
+ }
1947
+
1948
+ // On some browsers, horizontal scrolling will cause redraws to
1949
+ // happen before the gutter has been realigned, causing it to
1950
+ // wriggle around in a most unseemly way. When we have an
1951
+ // estimated pixels/delta value, we just handle horizontal
1952
+ // scrolling entirely here. It'll be slightly off from native, but
1953
+ // better than glitching out.
1954
+ if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
1955
+ if (dy)
1956
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
1957
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
1958
+ e_preventDefault(e);
1959
+ display.wheelStartX = null; // Abort measurement, if in progress
1960
+ return;
1961
+ }
1962
+
1963
+ if (dy && wheelPixelsPerUnit != null) {
1964
+ var pixels = dy * wheelPixelsPerUnit;
1965
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
1966
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
1967
+ else bot = Math.min(cm.doc.height, bot + pixels + 50);
1968
+ updateDisplay(cm, [], {top: top, bottom: bot});
1969
+ }
1970
+
1971
+ if (wheelSamples < 20) {
1972
+ if (display.wheelStartX == null) {
1973
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
1974
+ display.wheelDX = dx; display.wheelDY = dy;
1975
+ setTimeout(function() {
1976
+ if (display.wheelStartX == null) return;
1977
+ var movedX = scroll.scrollLeft - display.wheelStartX;
1978
+ var movedY = scroll.scrollTop - display.wheelStartY;
1979
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
1980
+ (movedX && display.wheelDX && movedX / display.wheelDX);
1981
+ display.wheelStartX = display.wheelStartY = null;
1982
+ if (!sample) return;
1983
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
1984
+ ++wheelSamples;
1985
+ }, 200);
1986
+ } else {
1987
+ display.wheelDX += dx; display.wheelDY += dy;
1988
+ }
1989
+ }
1990
+ }
1991
+
1992
+ function doHandleBinding(cm, bound, dropShift) {
1993
+ if (typeof bound == "string") {
1994
+ bound = commands[bound];
1995
+ if (!bound) return false;
1996
+ }
1997
+ // Ensure previous input has been read, so that the handler sees a
1998
+ // consistent view of the document
1999
+ if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
2000
+ var doc = cm.doc, prevShift = doc.sel.shift, done = false;
2001
+ try {
2002
+ if (isReadOnly(cm)) cm.state.suppressEdits = true;
2003
+ if (dropShift) doc.sel.shift = false;
2004
+ done = bound(cm) != Pass;
2005
+ } finally {
2006
+ doc.sel.shift = prevShift;
2007
+ cm.state.suppressEdits = false;
2008
+ }
2009
+ return done;
2010
+ }
2011
+
2012
+ function allKeyMaps(cm) {
2013
+ var maps = cm.state.keyMaps.slice(0);
2014
+ if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
2015
+ maps.push(cm.options.keyMap);
2016
+ return maps;
2017
+ }
2018
+
2019
+ var maybeTransition;
2020
+ function handleKeyBinding(cm, e) {
2021
+ // Handle auto keymap transitions
2022
+ var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
2023
+ clearTimeout(maybeTransition);
2024
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
2025
+ if (getKeyMap(cm.options.keyMap) == startMap) {
2026
+ cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2027
+ keyMapChanged(cm);
2028
+ }
2029
+ }, 50);
2030
+
2031
+ var name = keyName(e, true), handled = false;
2032
+ if (!name) return false;
2033
+ var keymaps = allKeyMaps(cm);
2034
+
2035
+ if (e.shiftKey) {
2036
+ // First try to resolve full name (including 'Shift-'). Failing
2037
+ // that, see if there is a cursor-motion command (starting with
2038
+ // 'go') bound to the keyname without 'Shift-'.
2039
+ handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2040
+ || lookupKey(name, keymaps, function(b) {
2041
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
2042
+ return doHandleBinding(cm, b);
2043
+ });
2044
+ } else {
2045
+ handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
2046
+ }
2047
+
2048
+ if (handled) {
2049
+ e_preventDefault(e);
2050
+ restartBlink(cm);
2051
+ if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2052
+ signalLater(cm, "keyHandled", cm, name, e);
2053
+ }
2054
+ return handled;
2055
+ }
2056
+
2057
+ function handleCharBinding(cm, e, ch) {
2058
+ var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
2059
+ function(b) { return doHandleBinding(cm, b, true); });
2060
+ if (handled) {
2061
+ e_preventDefault(e);
2062
+ restartBlink(cm);
2063
+ signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2064
+ }
2065
+ return handled;
2066
+ }
2067
+
2068
+ var lastStoppedKey = null;
2069
+ function onKeyDown(e) {
2070
+ var cm = this;
2071
+ if (!cm.state.focused) onFocus(cm);
2072
+ if (ie && e.keyCode == 27) { e.returnValue = false; }
2073
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2074
+ var code = e.keyCode;
2075
+ // IE does strange things with escape.
2076
+ cm.doc.sel.shift = code == 16 || e.shiftKey;
2077
+ // First give onKeyEvent option a chance to handle this.
2078
+ var handled = handleKeyBinding(cm, e);
2079
+ if (opera) {
2080
+ lastStoppedKey = handled ? code : null;
2081
+ // Opera has no cut event... we try to at least catch the key combo
2082
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
2083
+ cm.replaceSelection("");
2084
+ }
2085
+ }
2086
+
2087
+ function onKeyPress(e) {
2088
+ var cm = this;
2089
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2090
+ var keyCode = e.keyCode, charCode = e.charCode;
2091
+ if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2092
+ if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2093
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2094
+ if (this.options.electricChars && this.doc.mode.electricChars &&
2095
+ this.options.smartIndent && !isReadOnly(this) &&
2096
+ this.doc.mode.electricChars.indexOf(ch) > -1)
2097
+ setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
2098
+ if (handleCharBinding(cm, e, ch)) return;
2099
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
2100
+ fastPoll(cm);
2101
+ }
2102
+
2103
+ function onFocus(cm) {
2104
+ if (cm.options.readOnly == "nocursor") return;
2105
+ if (!cm.state.focused) {
2106
+ signal(cm, "focus", cm);
2107
+ cm.state.focused = true;
2108
+ if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
2109
+ cm.display.wrapper.className += " CodeMirror-focused";
2110
+ resetInput(cm, true);
2111
+ }
2112
+ slowPoll(cm);
2113
+ restartBlink(cm);
2114
+ }
2115
+ function onBlur(cm) {
2116
+ if (cm.state.focused) {
2117
+ signal(cm, "blur", cm);
2118
+ cm.state.focused = false;
2119
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
2120
+ }
2121
+ clearInterval(cm.display.blinker);
2122
+ setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
2123
+ }
2124
+
2125
+ var detectingSelectAll;
2126
+ function onContextMenu(cm, e) {
2127
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
2128
+ var display = cm.display, sel = cm.doc.sel;
2129
+ if (eventInWidget(display, e)) return;
2130
+
2131
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
2132
+ if (!pos || opera) return; // Opera is difficult.
2133
+ if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
2134
+ operation(cm, setSelection)(cm.doc, pos, pos);
2135
+
2136
+ var oldCSS = display.input.style.cssText;
2137
+ display.inputDiv.style.position = "absolute";
2138
+ display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
2139
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2140
+ "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
2141
+ focusInput(cm);
2142
+ resetInput(cm, true);
2143
+ // Adds "Select all" to context menu in FF
2144
+ if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2145
+
2146
+ function prepareSelectAllHack() {
2147
+ if (display.input.selectionStart != null) {
2148
+ var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
2149
+ display.prevInput = " ";
2150
+ display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2151
+ }
2152
+ }
2153
+ function rehide() {
2154
+ display.inputDiv.style.position = "relative";
2155
+ display.input.style.cssText = oldCSS;
2156
+ if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
2157
+ slowPoll(cm);
2158
+
2159
+ // Try to detect the user choosing select-all
2160
+ if (display.input.selectionStart != null) {
2161
+ if (!ie || ie_lt9) prepareSelectAllHack();
2162
+ clearTimeout(detectingSelectAll);
2163
+ var i = 0, poll = function(){
2164
+ if (display.prevInput == " " && display.input.selectionStart == 0)
2165
+ operation(cm, commands.selectAll)(cm);
2166
+ else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2167
+ else resetInput(cm);
2168
+ };
2169
+ detectingSelectAll = setTimeout(poll, 200);
2170
+ }
2171
+ }
2172
+
2173
+ if (ie && !ie_lt9) prepareSelectAllHack();
2174
+ if (captureMiddleClick) {
2175
+ e_stop(e);
2176
+ var mouseup = function() {
2177
+ off(window, "mouseup", mouseup);
2178
+ setTimeout(rehide, 20);
2179
+ };
2180
+ on(window, "mouseup", mouseup);
2181
+ } else {
2182
+ setTimeout(rehide, 50);
2183
+ }
2184
+ }
2185
+
2186
+ // UPDATING
2187
+
2188
+ var changeEnd = CodeMirror.changeEnd = function(change) {
2189
+ if (!change.text) return change.to;
2190
+ return Pos(change.from.line + change.text.length - 1,
2191
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2192
+ };
2193
+
2194
+ // Make sure a position will be valid after the given change.
2195
+ function clipPostChange(doc, change, pos) {
2196
+ if (!posLess(change.from, pos)) return clipPos(doc, pos);
2197
+ var diff = (change.text.length - 1) - (change.to.line - change.from.line);
2198
+ if (pos.line > change.to.line + diff) {
2199
+ var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
2200
+ if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
2201
+ return clipToLen(pos, getLine(doc, preLine).text.length);
2202
+ }
2203
+ if (pos.line == change.to.line + diff)
2204
+ return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
2205
+ getLine(doc, change.to.line).text.length - change.to.ch);
2206
+ var inside = pos.line - change.from.line;
2207
+ return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
2208
+ }
2209
+
2210
+ // Hint can be null|"end"|"start"|"around"|{anchor,head}
2211
+ function computeSelAfterChange(doc, change, hint) {
2212
+ if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
2213
+ return {anchor: clipPostChange(doc, change, hint.anchor),
2214
+ head: clipPostChange(doc, change, hint.head)};
2215
+
2216
+ if (hint == "start") return {anchor: change.from, head: change.from};
2217
+
2218
+ var end = changeEnd(change);
2219
+ if (hint == "around") return {anchor: change.from, head: end};
2220
+ if (hint == "end") return {anchor: end, head: end};
2221
+
2222
+ // hint is null, leave the selection alone as much as possible
2223
+ var adjustPos = function(pos) {
2224
+ if (posLess(pos, change.from)) return pos;
2225
+ if (!posLess(change.to, pos)) return end;
2226
+
2227
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
2228
+ if (pos.line == change.to.line) ch += end.ch - change.to.ch;
2229
+ return Pos(line, ch);
2230
+ };
2231
+ return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2232
+ }
2233
+
2234
+ function filterChange(doc, change, update) {
2235
+ var obj = {
2236
+ canceled: false,
2237
+ from: change.from,
2238
+ to: change.to,
2239
+ text: change.text,
2240
+ origin: change.origin,
2241
+ cancel: function() { this.canceled = true; }
2242
+ };
2243
+ if (update) obj.update = function(from, to, text, origin) {
2244
+ if (from) this.from = clipPos(doc, from);
2245
+ if (to) this.to = clipPos(doc, to);
2246
+ if (text) this.text = text;
2247
+ if (origin !== undefined) this.origin = origin;
2248
+ };
2249
+ signal(doc, "beforeChange", doc, obj);
2250
+ if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2251
+
2252
+ if (obj.canceled) return null;
2253
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
2254
+ }
2255
+
2256
+ // Replace the range from from to to by the strings in replacement.
2257
+ // change is a {from, to, text [, origin]} object
2258
+ function makeChange(doc, change, selUpdate, ignoreReadOnly) {
2259
+ if (doc.cm) {
2260
+ if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
2261
+ if (doc.cm.state.suppressEdits) return;
2262
+ }
2263
+
2264
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2265
+ change = filterChange(doc, change, true);
2266
+ if (!change) return;
2267
+ }
2268
+
2269
+ // Possibly split or suppress the update based on the presence
2270
+ // of read-only spans in its range.
2271
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
2272
+ if (split) {
2273
+ for (var i = split.length - 1; i >= 1; --i)
2274
+ makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
2275
+ if (split.length)
2276
+ makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
2277
+ } else {
2278
+ makeChangeNoReadonly(doc, change, selUpdate);
2279
+ }
2280
+ }
2281
+
2282
+ function makeChangeNoReadonly(doc, change, selUpdate) {
2283
+ var selAfter = computeSelAfterChange(doc, change, selUpdate);
2284
+ addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
2285
+
2286
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
2287
+ var rebased = [];
2288
+
2289
+ linkedDocs(doc, function(doc, sharedHist) {
2290
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2291
+ rebaseHist(doc.history, change);
2292
+ rebased.push(doc.history);
2293
+ }
2294
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
2295
+ });
2296
+ }
2297
+
2298
+ function makeChangeFromHistory(doc, type) {
2299
+ if (doc.cm && doc.cm.state.suppressEdits) return;
2300
+
2301
+ var hist = doc.history;
2302
+ var event = (type == "undo" ? hist.done : hist.undone).pop();
2303
+ if (!event) return;
2304
+
2305
+ var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2306
+ anchorAfter: event.anchorBefore, headAfter: event.headBefore,
2307
+ generation: hist.generation};
2308
+ (type == "undo" ? hist.undone : hist.done).push(anti);
2309
+ hist.generation = event.generation || ++hist.maxGeneration;
2310
+
2311
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
2312
+
2313
+ for (var i = event.changes.length - 1; i >= 0; --i) {
2314
+ var change = event.changes[i];
2315
+ change.origin = type;
2316
+ if (filter && !filterChange(doc, change, false)) {
2317
+ (type == "undo" ? hist.done : hist.undone).length = 0;
2318
+ return;
2319
+ }
2320
+
2321
+ anti.changes.push(historyChangeFromChange(doc, change));
2322
+
2323
+ var after = i ? computeSelAfterChange(doc, change, null)
2324
+ : {anchor: event.anchorBefore, head: event.headBefore};
2325
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
2326
+ var rebased = [];
2327
+
2328
+ linkedDocs(doc, function(doc, sharedHist) {
2329
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2330
+ rebaseHist(doc.history, change);
2331
+ rebased.push(doc.history);
2332
+ }
2333
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
2334
+ });
2335
+ }
2336
+ }
2337
+
2338
+ function shiftDoc(doc, distance) {
2339
+ function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
2340
+ doc.first += distance;
2341
+ if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
2342
+ doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
2343
+ doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
2344
+ }
2345
+
2346
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
2347
+ if (doc.cm && !doc.cm.curOp)
2348
+ return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
2349
+
2350
+ if (change.to.line < doc.first) {
2351
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
2352
+ return;
2353
+ }
2354
+ if (change.from.line > doc.lastLine()) return;
2355
+
2356
+ // Clip the change to the size of this doc
2357
+ if (change.from.line < doc.first) {
2358
+ var shift = change.text.length - 1 - (doc.first - change.from.line);
2359
+ shiftDoc(doc, shift);
2360
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
2361
+ text: [lst(change.text)], origin: change.origin};
2362
+ }
2363
+ var last = doc.lastLine();
2364
+ if (change.to.line > last) {
2365
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
2366
+ text: [change.text[0]], origin: change.origin};
2367
+ }
2368
+
2369
+ change.removed = getBetween(doc, change.from, change.to);
2370
+
2371
+ if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
2372
+ if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
2373
+ else updateDoc(doc, change, spans, selAfter);
2374
+ }
2375
+
2376
+ function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
2377
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
2378
+
2379
+ var recomputeMaxLength = false, checkWidthStart = from.line;
2380
+ if (!cm.options.lineWrapping) {
2381
+ checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
2382
+ doc.iter(checkWidthStart, to.line + 1, function(line) {
2383
+ if (line == display.maxLine) {
2384
+ recomputeMaxLength = true;
2385
+ return true;
2386
+ }
2387
+ });
2388
+ }
2389
+
2390
+ if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
2391
+ cm.curOp.cursorActivity = true;
2392
+
2393
+ updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
2394
+
2395
+ if (!cm.options.lineWrapping) {
2396
+ doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
2397
+ var len = lineLength(doc, line);
2398
+ if (len > display.maxLineLength) {
2399
+ display.maxLine = line;
2400
+ display.maxLineLength = len;
2401
+ display.maxLineChanged = true;
2402
+ recomputeMaxLength = false;
2403
+ }
2404
+ });
2405
+ if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
2406
+ }
2407
+
2408
+ // Adjust frontier, schedule worker
2409
+ doc.frontier = Math.min(doc.frontier, from.line);
2410
+ startWorker(cm, 400);
2411
+
2412
+ var lendiff = change.text.length - (to.line - from.line) - 1;
2413
+ // Remember that these lines changed, for updating the display
2414
+ regChange(cm, from.line, to.line + 1, lendiff);
2415
+
2416
+ if (hasHandler(cm, "change")) {
2417
+ var changeObj = {from: from, to: to,
2418
+ text: change.text,
2419
+ removed: change.removed,
2420
+ origin: change.origin};
2421
+ if (cm.curOp.textChanged) {
2422
+ for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
2423
+ cur.next = changeObj;
2424
+ } else cm.curOp.textChanged = changeObj;
2425
+ }
2426
+ }
2427
+
2428
+ function replaceRange(doc, code, from, to, origin) {
2429
+ if (!to) to = from;
2430
+ if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
2431
+ if (typeof code == "string") code = splitLines(code);
2432
+ makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
2433
+ }
2434
+
2435
+ // POSITION OBJECT
2436
+
2437
+ function Pos(line, ch) {
2438
+ if (!(this instanceof Pos)) return new Pos(line, ch);
2439
+ this.line = line; this.ch = ch;
2440
+ }
2441
+ CodeMirror.Pos = Pos;
2442
+
2443
+ function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2444
+ function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2445
+ function copyPos(x) {return Pos(x.line, x.ch);}
2446
+
2447
+ // SELECTION
2448
+
2449
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2450
+ function clipPos(doc, pos) {
2451
+ if (pos.line < doc.first) return Pos(doc.first, 0);
2452
+ var last = doc.first + doc.size - 1;
2453
+ if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2454
+ return clipToLen(pos, getLine(doc, pos.line).text.length);
2455
+ }
2456
+ function clipToLen(pos, linelen) {
2457
+ var ch = pos.ch;
2458
+ if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2459
+ else if (ch < 0) return Pos(pos.line, 0);
2460
+ else return pos;
2461
+ }
2462
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2463
+
2464
+ // If shift is held, this will move the selection anchor. Otherwise,
2465
+ // it'll set the whole selection.
2466
+ function extendSelection(doc, pos, other, bias) {
2467
+ if (doc.sel.shift || doc.sel.extend) {
2468
+ var anchor = doc.sel.anchor;
2469
+ if (other) {
2470
+ var posBefore = posLess(pos, anchor);
2471
+ if (posBefore != posLess(other, anchor)) {
2472
+ anchor = pos;
2473
+ pos = other;
2474
+ } else if (posBefore != posLess(pos, other)) {
2475
+ pos = other;
2476
+ }
2477
+ }
2478
+ setSelection(doc, anchor, pos, bias);
2479
+ } else {
2480
+ setSelection(doc, pos, other || pos, bias);
2481
+ }
2482
+ if (doc.cm) doc.cm.curOp.userSelChange = true;
2483
+ }
2484
+
2485
+ function filterSelectionChange(doc, anchor, head) {
2486
+ var obj = {anchor: anchor, head: head};
2487
+ signal(doc, "beforeSelectionChange", doc, obj);
2488
+ if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2489
+ obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
2490
+ return obj;
2491
+ }
2492
+
2493
+ // Update the selection. Last two args are only used by
2494
+ // updateDoc, since they have to be expressed in the line
2495
+ // numbers before the update.
2496
+ function setSelection(doc, anchor, head, bias, checkAtomic) {
2497
+ if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
2498
+ var filtered = filterSelectionChange(doc, anchor, head);
2499
+ head = filtered.head;
2500
+ anchor = filtered.anchor;
2501
+ }
2502
+
2503
+ var sel = doc.sel;
2504
+ sel.goalColumn = null;
2505
+ // Skip over atomic spans.
2506
+ if (checkAtomic || !posEq(anchor, sel.anchor))
2507
+ anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
2508
+ if (checkAtomic || !posEq(head, sel.head))
2509
+ head = skipAtomic(doc, head, bias, checkAtomic != "push");
2510
+
2511
+ if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
2512
+
2513
+ sel.anchor = anchor; sel.head = head;
2514
+ var inv = posLess(head, anchor);
2515
+ sel.from = inv ? head : anchor;
2516
+ sel.to = inv ? anchor : head;
2517
+
2518
+ if (doc.cm)
2519
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
2520
+ doc.cm.curOp.cursorActivity = true;
2521
+
2522
+ signalLater(doc, "cursorActivity", doc);
2523
+ }
2524
+
2525
+ function reCheckSelection(cm) {
2526
+ setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
2527
+ }
2528
+
2529
+ function skipAtomic(doc, pos, bias, mayClear) {
2530
+ var flipped = false, curPos = pos;
2531
+ var dir = bias || 1;
2532
+ doc.cantEdit = false;
2533
+ search: for (;;) {
2534
+ var line = getLine(doc, curPos.line);
2535
+ if (line.markedSpans) {
2536
+ for (var i = 0; i < line.markedSpans.length; ++i) {
2537
+ var sp = line.markedSpans[i], m = sp.marker;
2538
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2539
+ (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2540
+ if (mayClear) {
2541
+ signal(m, "beforeCursorEnter");
2542
+ if (m.explicitlyCleared) {
2543
+ if (!line.markedSpans) break;
2544
+ else {--i; continue;}
2545
+ }
2546
+ }
2547
+ if (!m.atomic) continue;
2548
+ var newPos = m.find()[dir < 0 ? "from" : "to"];
2549
+ if (posEq(newPos, curPos)) {
2550
+ newPos.ch += dir;
2551
+ if (newPos.ch < 0) {
2552
+ if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2553
+ else newPos = null;
2554
+ } else if (newPos.ch > line.text.length) {
2555
+ if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2556
+ else newPos = null;
2557
+ }
2558
+ if (!newPos) {
2559
+ if (flipped) {
2560
+ // Driven in a corner -- no valid cursor position found at all
2561
+ // -- try again *with* clearing, if we didn't already
2562
+ if (!mayClear) return skipAtomic(doc, pos, bias, true);
2563
+ // Otherwise, turn off editing until further notice, and return the start of the doc
2564
+ doc.cantEdit = true;
2565
+ return Pos(doc.first, 0);
2566
+ }
2567
+ flipped = true; newPos = pos; dir = -dir;
2568
+ }
2569
+ }
2570
+ curPos = newPos;
2571
+ continue search;
2572
+ }
2573
+ }
2574
+ }
2575
+ return curPos;
2576
+ }
2577
+ }
2578
+
2579
+ // SCROLLING
2580
+
2581
+ function scrollCursorIntoView(cm) {
2582
+ var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
2583
+ if (!cm.state.focused) return;
2584
+ var display = cm.display, box = getRect(display.sizer), doScroll = null;
2585
+ if (coords.top + box.top < 0) doScroll = true;
2586
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2587
+ if (doScroll != null && !phantom) {
2588
+ var hidden = display.cursor.style.display == "none";
2589
+ if (hidden) {
2590
+ display.cursor.style.display = "";
2591
+ display.cursor.style.left = coords.left + "px";
2592
+ display.cursor.style.top = (coords.top - display.viewOffset) + "px";
2593
+ }
2594
+ display.cursor.scrollIntoView(doScroll);
2595
+ if (hidden) display.cursor.style.display = "none";
2596
+ }
2597
+ }
2598
+
2599
+ function scrollPosIntoView(cm, pos, margin) {
2600
+ if (margin == null) margin = 0;
2601
+ for (;;) {
2602
+ var changed = false, coords = cursorCoords(cm, pos);
2603
+ var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
2604
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
2605
+ if (scrollPos.scrollTop != null) {
2606
+ setScrollTop(cm, scrollPos.scrollTop);
2607
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
2608
+ }
2609
+ if (scrollPos.scrollLeft != null) {
2610
+ setScrollLeft(cm, scrollPos.scrollLeft);
2611
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
2612
+ }
2613
+ if (!changed) return coords;
2614
+ }
2615
+ }
2616
+
2617
+ function scrollIntoView(cm, x1, y1, x2, y2) {
2618
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
2619
+ if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
2620
+ if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
2621
+ }
2622
+
2623
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
2624
+ var display = cm.display, snapMargin = textHeight(cm.display);
2625
+ if (y1 < 0) y1 = 0;
2626
+ var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2627
+ var docBottom = cm.doc.height + paddingVert(display);
2628
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
2629
+ if (y1 < screentop) {
2630
+ result.scrollTop = atTop ? 0 : y1;
2631
+ } else if (y2 > screentop + screen) {
2632
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
2633
+ if (newTop != screentop) result.scrollTop = newTop;
2634
+ }
2635
+
2636
+ var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
2637
+ x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
2638
+ var gutterw = display.gutters.offsetWidth;
2639
+ var atLeft = x1 < gutterw + 10;
2640
+ if (x1 < screenleft + gutterw || atLeft) {
2641
+ if (atLeft) x1 = 0;
2642
+ result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
2643
+ } else if (x2 > screenw + screenleft - 3) {
2644
+ result.scrollLeft = x2 + 10 - screenw;
2645
+ }
2646
+ return result;
2647
+ }
2648
+
2649
+ function updateScrollPos(cm, left, top) {
2650
+ cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
2651
+ scrollTop: top == null ? cm.doc.scrollTop : top};
2652
+ }
2653
+
2654
+ function addToScrollPos(cm, left, top) {
2655
+ var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
2656
+ var scroll = cm.display.scroller;
2657
+ pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
2658
+ pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
2659
+ }
2660
+
2661
+ // API UTILITIES
2662
+
2663
+ function indentLine(cm, n, how, aggressive) {
2664
+ var doc = cm.doc;
2665
+ if (how == null) how = "add";
2666
+ if (how == "smart") {
2667
+ if (!cm.doc.mode.indent) how = "prev";
2668
+ else var state = getStateBefore(cm, n);
2669
+ }
2670
+
2671
+ var tabSize = cm.options.tabSize;
2672
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
2673
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
2674
+ if (how == "smart") {
2675
+ indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2676
+ if (indentation == Pass) {
2677
+ if (!aggressive) return;
2678
+ how = "prev";
2679
+ }
2680
+ }
2681
+ if (how == "prev") {
2682
+ if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
2683
+ else indentation = 0;
2684
+ } else if (how == "add") {
2685
+ indentation = curSpace + cm.options.indentUnit;
2686
+ } else if (how == "subtract") {
2687
+ indentation = curSpace - cm.options.indentUnit;
2688
+ } else if (typeof how == "number") {
2689
+ indentation = curSpace + how;
2690
+ }
2691
+ indentation = Math.max(0, indentation);
2692
+
2693
+ var indentString = "", pos = 0;
2694
+ if (cm.options.indentWithTabs)
2695
+ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
2696
+ if (pos < indentation) indentString += spaceStr(indentation - pos);
2697
+
2698
+ if (indentString != curSpaceString)
2699
+ replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
2700
+ line.stateAfter = null;
2701
+ }
2702
+
2703
+ function changeLine(cm, handle, op) {
2704
+ var no = handle, line = handle, doc = cm.doc;
2705
+ if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
2706
+ else no = lineNo(handle);
2707
+ if (no == null) return null;
2708
+ if (op(line, no)) regChange(cm, no, no + 1);
2709
+ else return null;
2710
+ return line;
2711
+ }
2712
+
2713
+ function findPosH(doc, pos, dir, unit, visually) {
2714
+ var line = pos.line, ch = pos.ch, origDir = dir;
2715
+ var lineObj = getLine(doc, line);
2716
+ var possible = true;
2717
+ function findNextLine() {
2718
+ var l = line + dir;
2719
+ if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
2720
+ line = l;
2721
+ return lineObj = getLine(doc, l);
2722
+ }
2723
+ function moveOnce(boundToLine) {
2724
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
2725
+ if (next == null) {
2726
+ if (!boundToLine && findNextLine()) {
2727
+ if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
2728
+ else ch = dir < 0 ? lineObj.text.length : 0;
2729
+ } else return (possible = false);
2730
+ } else ch = next;
2731
+ return true;
2732
+ }
2733
+
2734
+ if (unit == "char") moveOnce();
2735
+ else if (unit == "column") moveOnce(true);
2736
+ else if (unit == "word" || unit == "group") {
2737
+ var sawType = null, group = unit == "group";
2738
+ for (var first = true;; first = false) {
2739
+ if (dir < 0 && !moveOnce(!first)) break;
2740
+ var cur = lineObj.text.charAt(ch) || "\n";
2741
+ var type = isWordChar(cur) ? "w"
2742
+ : !group ? null
2743
+ : /\s/.test(cur) ? null
2744
+ : "p";
2745
+ if (sawType && sawType != type) {
2746
+ if (dir < 0) {dir = 1; moveOnce();}
2747
+ break;
2748
+ }
2749
+ if (type) sawType = type;
2750
+ if (dir > 0 && !moveOnce(!first)) break;
2751
+ }
2752
+ }
2753
+ var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2754
+ if (!possible) result.hitSide = true;
2755
+ return result;
2756
+ }
2757
+
2758
+ function findPosV(cm, pos, dir, unit) {
2759
+ var doc = cm.doc, x = pos.left, y;
2760
+ if (unit == "page") {
2761
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
2762
+ y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
2763
+ } else if (unit == "line") {
2764
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
2765
+ }
2766
+ for (;;) {
2767
+ var target = coordsChar(cm, x, y);
2768
+ if (!target.outside) break;
2769
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
2770
+ y += dir * 5;
2771
+ }
2772
+ return target;
2773
+ }
2774
+
2775
+ function findWordAt(line, pos) {
2776
+ var start = pos.ch, end = pos.ch;
2777
+ if (line) {
2778
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
2779
+ var startChar = line.charAt(start);
2780
+ var check = isWordChar(startChar) ? isWordChar
2781
+ : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2782
+ : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
2783
+ while (start > 0 && check(line.charAt(start - 1))) --start;
2784
+ while (end < line.length && check(line.charAt(end))) ++end;
2785
+ }
2786
+ return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
2787
+ }
2788
+
2789
+ function selectLine(cm, line) {
2790
+ extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
2791
+ }
2792
+
2793
+ // PROTOTYPE
2794
+
2795
+ // The publicly visible API. Note that operation(null, f) means
2796
+ // 'wrap f in an operation, performed on its `this` parameter'
2797
+
2798
+ CodeMirror.prototype = {
2799
+ constructor: CodeMirror,
2800
+ focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2801
+
2802
+ setOption: function(option, value) {
2803
+ var options = this.options, old = options[option];
2804
+ if (options[option] == value && option != "mode") return;
2805
+ options[option] = value;
2806
+ if (optionHandlers.hasOwnProperty(option))
2807
+ operation(this, optionHandlers[option])(this, value, old);
2808
+ },
2809
+
2810
+ getOption: function(option) {return this.options[option];},
2811
+ getDoc: function() {return this.doc;},
2812
+
2813
+ addKeyMap: function(map, bottom) {
2814
+ this.state.keyMaps[bottom ? "push" : "unshift"](map);
2815
+ },
2816
+ removeKeyMap: function(map) {
2817
+ var maps = this.state.keyMaps;
2818
+ for (var i = 0; i < maps.length; ++i)
2819
+ if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2820
+ maps.splice(i, 1);
2821
+ return true;
2822
+ }
2823
+ },
2824
+
2825
+ addOverlay: operation(null, function(spec, options) {
2826
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
2827
+ if (mode.startState) throw new Error("Overlays may not be stateful.");
2828
+ this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
2829
+ this.state.modeGen++;
2830
+ regChange(this);
2831
+ }),
2832
+ removeOverlay: operation(null, function(spec) {
2833
+ var overlays = this.state.overlays;
2834
+ for (var i = 0; i < overlays.length; ++i) {
2835
+ var cur = overlays[i].modeSpec;
2836
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
2837
+ overlays.splice(i, 1);
2838
+ this.state.modeGen++;
2839
+ regChange(this);
2840
+ return;
2841
+ }
2842
+ }
2843
+ }),
2844
+
2845
+ indentLine: operation(null, function(n, dir, aggressive) {
2846
+ if (typeof dir != "string" && typeof dir != "number") {
2847
+ if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2848
+ else dir = dir ? "add" : "subtract";
2849
+ }
2850
+ if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
2851
+ }),
2852
+ indentSelection: operation(null, function(how) {
2853
+ var sel = this.doc.sel;
2854
+ if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
2855
+ var e = sel.to.line - (sel.to.ch ? 0 : 1);
2856
+ for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
2857
+ }),
2858
+
2859
+ // Fetch the parser token for a given character. Useful for hacks
2860
+ // that want to inspect the mode state (say, for completion).
2861
+ getTokenAt: function(pos, precise) {
2862
+ var doc = this.doc;
2863
+ pos = clipPos(doc, pos);
2864
+ var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2865
+ var line = getLine(doc, pos.line);
2866
+ var stream = new StringStream(line.text, this.options.tabSize);
2867
+ while (stream.pos < pos.ch && !stream.eol()) {
2868
+ stream.start = stream.pos;
2869
+ var style = mode.token(stream, state);
2870
+ }
2871
+ return {start: stream.start,
2872
+ end: stream.pos,
2873
+ string: stream.current(),
2874
+ className: style || null, // Deprecated, use 'type' instead
2875
+ type: style || null,
2876
+ state: state};
2877
+ },
2878
+
2879
+ getTokenTypeAt: function(pos) {
2880
+ pos = clipPos(this.doc, pos);
2881
+ var styles = getLineStyles(this, getLine(this.doc, pos.line));
2882
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2883
+ if (ch == 0) return styles[2];
2884
+ for (;;) {
2885
+ var mid = (before + after) >> 1;
2886
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2887
+ else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2888
+ else return styles[mid * 2 + 2];
2889
+ }
2890
+ },
2891
+
2892
+ getModeAt: function(pos) {
2893
+ var mode = this.doc.mode;
2894
+ if (!mode.innerMode) return mode;
2895
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2896
+ },
2897
+
2898
+ getHelper: function(pos, type) {
2899
+ if (!helpers.hasOwnProperty(type)) return;
2900
+ var help = helpers[type], mode = this.getModeAt(pos);
2901
+ return mode[type] && help[mode[type]] ||
2902
+ mode.helperType && help[mode.helperType] ||
2903
+ help[mode.name];
2904
+ },
2905
+
2906
+ getStateAfter: function(line, precise) {
2907
+ var doc = this.doc;
2908
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2909
+ return getStateBefore(this, line + 1, precise);
2910
+ },
2911
+
2912
+ cursorCoords: function(start, mode) {
2913
+ var pos, sel = this.doc.sel;
2914
+ if (start == null) pos = sel.head;
2915
+ else if (typeof start == "object") pos = clipPos(this.doc, start);
2916
+ else pos = start ? sel.from : sel.to;
2917
+ return cursorCoords(this, pos, mode || "page");
2918
+ },
2919
+
2920
+ charCoords: function(pos, mode) {
2921
+ return charCoords(this, clipPos(this.doc, pos), mode || "page");
2922
+ },
2923
+
2924
+ coordsChar: function(coords, mode) {
2925
+ coords = fromCoordSystem(this, coords, mode || "page");
2926
+ return coordsChar(this, coords.left, coords.top);
2927
+ },
2928
+
2929
+ lineAtHeight: function(height, mode) {
2930
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
2931
+ return lineAtHeight(this.doc, height + this.display.viewOffset);
2932
+ },
2933
+ heightAtLine: function(line, mode) {
2934
+ var end = false, last = this.doc.first + this.doc.size - 1;
2935
+ if (line < this.doc.first) line = this.doc.first;
2936
+ else if (line > last) { line = last; end = true; }
2937
+ var lineObj = getLine(this.doc, line);
2938
+ return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
2939
+ (end ? lineObj.height : 0);
2940
+ },
2941
+
2942
+ defaultTextHeight: function() { return textHeight(this.display); },
2943
+ defaultCharWidth: function() { return charWidth(this.display); },
2944
+
2945
+ setGutterMarker: operation(null, function(line, gutterID, value) {
2946
+ return changeLine(this, line, function(line) {
2947
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
2948
+ markers[gutterID] = value;
2949
+ if (!value && isEmpty(markers)) line.gutterMarkers = null;
2950
+ return true;
2951
+ });
2952
+ }),
2953
+
2954
+ clearGutter: operation(null, function(gutterID) {
2955
+ var cm = this, doc = cm.doc, i = doc.first;
2956
+ doc.iter(function(line) {
2957
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
2958
+ line.gutterMarkers[gutterID] = null;
2959
+ regChange(cm, i, i + 1);
2960
+ if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
2961
+ }
2962
+ ++i;
2963
+ });
2964
+ }),
2965
+
2966
+ addLineClass: operation(null, function(handle, where, cls) {
2967
+ return changeLine(this, handle, function(line) {
2968
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2969
+ if (!line[prop]) line[prop] = cls;
2970
+ else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
2971
+ else line[prop] += " " + cls;
2972
+ return true;
2973
+ });
2974
+ }),
2975
+
2976
+ removeLineClass: operation(null, function(handle, where, cls) {
2977
+ return changeLine(this, handle, function(line) {
2978
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2979
+ var cur = line[prop];
2980
+ if (!cur) return false;
2981
+ else if (cls == null) line[prop] = null;
2982
+ else {
2983
+ var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2984
+ if (!found) return false;
2985
+ var end = found.index + found[0].length;
2986
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
2987
+ }
2988
+ return true;
2989
+ });
2990
+ }),
2991
+
2992
+ addLineWidget: operation(null, function(handle, node, options) {
2993
+ return addLineWidget(this, handle, node, options);
2994
+ }),
2995
+
2996
+ removeLineWidget: function(widget) { widget.clear(); },
2997
+
2998
+ lineInfo: function(line) {
2999
+ if (typeof line == "number") {
3000
+ if (!isLine(this.doc, line)) return null;
3001
+ var n = line;
3002
+ line = getLine(this.doc, line);
3003
+ if (!line) return null;
3004
+ } else {
3005
+ var n = lineNo(line);
3006
+ if (n == null) return null;
3007
+ }
3008
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
3009
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
3010
+ widgets: line.widgets};
3011
+ },
3012
+
3013
+ getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
3014
+
3015
+ addWidget: function(pos, node, scroll, vert, horiz) {
3016
+ var display = this.display;
3017
+ pos = cursorCoords(this, clipPos(this.doc, pos));
3018
+ var top = pos.bottom, left = pos.left;
3019
+ node.style.position = "absolute";
3020
+ display.sizer.appendChild(node);
3021
+ if (vert == "over") {
3022
+ top = pos.top;
3023
+ } else if (vert == "above" || vert == "near") {
3024
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
3025
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
3026
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
3027
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
3028
+ top = pos.top - node.offsetHeight;
3029
+ else if (pos.bottom + node.offsetHeight <= vspace)
3030
+ top = pos.bottom;
3031
+ if (left + node.offsetWidth > hspace)
3032
+ left = hspace - node.offsetWidth;
3033
+ }
3034
+ node.style.top = top + "px";
3035
+ node.style.left = node.style.right = "";
3036
+ if (horiz == "right") {
3037
+ left = display.sizer.clientWidth - node.offsetWidth;
3038
+ node.style.right = "0px";
3039
+ } else {
3040
+ if (horiz == "left") left = 0;
3041
+ else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
3042
+ node.style.left = left + "px";
3043
+ }
3044
+ if (scroll)
3045
+ scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
3046
+ },
3047
+
3048
+ triggerOnKeyDown: operation(null, onKeyDown),
3049
+
3050
+ execCommand: function(cmd) {return commands[cmd](this);},
3051
+
3052
+ findPosH: function(from, amount, unit, visually) {
3053
+ var dir = 1;
3054
+ if (amount < 0) { dir = -1; amount = -amount; }
3055
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3056
+ cur = findPosH(this.doc, cur, dir, unit, visually);
3057
+ if (cur.hitSide) break;
3058
+ }
3059
+ return cur;
3060
+ },
3061
+
3062
+ moveH: operation(null, function(dir, unit) {
3063
+ var sel = this.doc.sel, pos;
3064
+ if (sel.shift || sel.extend || posEq(sel.from, sel.to))
3065
+ pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
3066
+ else
3067
+ pos = dir < 0 ? sel.from : sel.to;
3068
+ extendSelection(this.doc, pos, pos, dir);
3069
+ }),
3070
+
3071
+ deleteH: operation(null, function(dir, unit) {
3072
+ var sel = this.doc.sel;
3073
+ if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
3074
+ else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
3075
+ this.curOp.userSelChange = true;
3076
+ }),
3077
+
3078
+ findPosV: function(from, amount, unit, goalColumn) {
3079
+ var dir = 1, x = goalColumn;
3080
+ if (amount < 0) { dir = -1; amount = -amount; }
3081
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3082
+ var coords = cursorCoords(this, cur, "div");
3083
+ if (x == null) x = coords.left;
3084
+ else coords.left = x;
3085
+ cur = findPosV(this, coords, dir, unit);
3086
+ if (cur.hitSide) break;
3087
+ }
3088
+ return cur;
3089
+ },
3090
+
3091
+ moveV: operation(null, function(dir, unit) {
3092
+ var sel = this.doc.sel;
3093
+ var pos = cursorCoords(this, sel.head, "div");
3094
+ if (sel.goalColumn != null) pos.left = sel.goalColumn;
3095
+ var target = findPosV(this, pos, dir, unit);
3096
+
3097
+ if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3098
+ extendSelection(this.doc, target, target, dir);
3099
+ sel.goalColumn = pos.left;
3100
+ }),
3101
+
3102
+ toggleOverwrite: function(value) {
3103
+ if (value != null && value == this.state.overwrite) return;
3104
+ if (this.state.overwrite = !this.state.overwrite)
3105
+ this.display.cursor.className += " CodeMirror-overwrite";
3106
+ else
3107
+ this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
3108
+ },
3109
+ hasFocus: function() { return this.state.focused; },
3110
+
3111
+ scrollTo: operation(null, function(x, y) {
3112
+ updateScrollPos(this, x, y);
3113
+ }),
3114
+ getScrollInfo: function() {
3115
+ var scroller = this.display.scroller, co = scrollerCutOff;
3116
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
3117
+ height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
3118
+ clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
3119
+ },
3120
+
3121
+ scrollIntoView: operation(null, function(pos, margin) {
3122
+ if (typeof pos == "number") pos = Pos(pos, 0);
3123
+ if (!margin) margin = 0;
3124
+ var coords = pos;
3125
+
3126
+ if (!pos || pos.line != null) {
3127
+ this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
3128
+ this.curOp.scrollToPosMargin = margin;
3129
+ coords = cursorCoords(this, this.curOp.scrollToPos);
3130
+ }
3131
+ var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
3132
+ updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
3133
+ }),
3134
+
3135
+ setSize: operation(null, function(width, height) {
3136
+ function interpret(val) {
3137
+ return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
3138
+ }
3139
+ if (width != null) this.display.wrapper.style.width = interpret(width);
3140
+ if (height != null) this.display.wrapper.style.height = interpret(height);
3141
+ if (this.options.lineWrapping)
3142
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3143
+ this.curOp.forceUpdate = true;
3144
+ }),
3145
+
3146
+ operation: function(f){return runInOp(this, f);},
3147
+
3148
+ refresh: operation(null, function() {
3149
+ clearCaches(this);
3150
+ updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
3151
+ regChange(this);
3152
+ }),
3153
+
3154
+ swapDoc: operation(null, function(doc) {
3155
+ var old = this.doc;
3156
+ old.cm = null;
3157
+ attachDoc(this, doc);
3158
+ clearCaches(this);
3159
+ resetInput(this, true);
3160
+ updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
3161
+ return old;
3162
+ }),
3163
+
3164
+ getInputField: function(){return this.display.input;},
3165
+ getWrapperElement: function(){return this.display.wrapper;},
3166
+ getScrollerElement: function(){return this.display.scroller;},
3167
+ getGutterElement: function(){return this.display.gutters;}
3168
+ };
3169
+ eventMixin(CodeMirror);
3170
+
3171
+ // OPTION DEFAULTS
3172
+
3173
+ var optionHandlers = CodeMirror.optionHandlers = {};
3174
+
3175
+ // The default configuration options.
3176
+ var defaults = CodeMirror.defaults = {};
3177
+
3178
+ function option(name, deflt, handle, notOnInit) {
3179
+ CodeMirror.defaults[name] = deflt;
3180
+ if (handle) optionHandlers[name] =
3181
+ notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
3182
+ }
3183
+
3184
+ var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
3185
+
3186
+ // These two are, on init, called from the constructor because they
3187
+ // have to be initialized before the editor can start at all.
3188
+ option("value", "", function(cm, val) {
3189
+ cm.setValue(val);
3190
+ }, true);
3191
+ option("mode", null, function(cm, val) {
3192
+ cm.doc.modeOption = val;
3193
+ loadMode(cm);
3194
+ }, true);
3195
+
3196
+ option("indentUnit", 2, loadMode, true);
3197
+ option("indentWithTabs", false);
3198
+ option("smartIndent", true);
3199
+ option("tabSize", 4, function(cm) {
3200
+ loadMode(cm);
3201
+ clearCaches(cm);
3202
+ regChange(cm);
3203
+ }, true);
3204
+ option("electricChars", true);
3205
+ option("rtlMoveVisually", !windows);
3206
+
3207
+ option("theme", "default", function(cm) {
3208
+ themeChanged(cm);
3209
+ guttersChanged(cm);
3210
+ }, true);
3211
+ option("keyMap", "default", keyMapChanged);
3212
+ option("extraKeys", null);
3213
+
3214
+ option("onKeyEvent", null);
3215
+ option("onDragEvent", null);
3216
+
3217
+ option("lineWrapping", false, wrappingChanged, true);
3218
+ option("gutters", [], function(cm) {
3219
+ setGuttersForLineNumbers(cm.options);
3220
+ guttersChanged(cm);
3221
+ }, true);
3222
+ option("fixedGutter", true, function(cm, val) {
3223
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3224
+ cm.refresh();
3225
+ }, true);
3226
+ option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3227
+ option("lineNumbers", false, function(cm) {
3228
+ setGuttersForLineNumbers(cm.options);
3229
+ guttersChanged(cm);
3230
+ }, true);
3231
+ option("firstLineNumber", 1, guttersChanged, true);
3232
+ option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
3233
+ option("showCursorWhenSelecting", false, updateSelection, true);
3234
+
3235
+ option("readOnly", false, function(cm, val) {
3236
+ if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
3237
+ else if (!val) resetInput(cm, true);
3238
+ });
3239
+ option("dragDrop", true);
3240
+
3241
+ option("cursorBlinkRate", 530);
3242
+ option("cursorScrollMargin", 0);
3243
+ option("cursorHeight", 1);
3244
+ option("workTime", 100);
3245
+ option("workDelay", 100);
3246
+ option("flattenSpans", true);
3247
+ option("pollInterval", 100);
3248
+ option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
3249
+ option("historyEventDelay", 500);
3250
+ option("viewportMargin", 10, function(cm){cm.refresh();}, true);
3251
+ option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
3252
+ option("moveInputWithCursor", true, function(cm, val) {
3253
+ if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
3254
+ });
3255
+
3256
+ option("tabindex", null, function(cm, val) {
3257
+ cm.display.input.tabIndex = val || "";
3258
+ });
3259
+ option("autofocus", null);
3260
+
3261
+ // MODE DEFINITION AND QUERYING
3262
+
3263
+ // Known modes, by name and by MIME
3264
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
3265
+
3266
+ CodeMirror.defineMode = function(name, mode) {
3267
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
3268
+ if (arguments.length > 2) {
3269
+ mode.dependencies = [];
3270
+ for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
3271
+ }
3272
+ modes[name] = mode;
3273
+ };
3274
+
3275
+ CodeMirror.defineMIME = function(mime, spec) {
3276
+ mimeModes[mime] = spec;
3277
+ };
3278
+
3279
+ CodeMirror.resolveMode = function(spec) {
3280
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3281
+ spec = mimeModes[spec];
3282
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
3283
+ var found = mimeModes[spec.name];
3284
+ spec = createObj(found, spec);
3285
+ spec.name = found.name;
3286
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
3287
+ return CodeMirror.resolveMode("application/xml");
3288
+ }
3289
+ if (typeof spec == "string") return {name: spec};
3290
+ else return spec || {name: "null"};
3291
+ };
3292
+
3293
+ CodeMirror.getMode = function(options, spec) {
3294
+ var spec = CodeMirror.resolveMode(spec);
3295
+ var mfactory = modes[spec.name];
3296
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
3297
+ var modeObj = mfactory(options, spec);
3298
+ if (modeExtensions.hasOwnProperty(spec.name)) {
3299
+ var exts = modeExtensions[spec.name];
3300
+ for (var prop in exts) {
3301
+ if (!exts.hasOwnProperty(prop)) continue;
3302
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
3303
+ modeObj[prop] = exts[prop];
3304
+ }
3305
+ }
3306
+ modeObj.name = spec.name;
3307
+
3308
+ return modeObj;
3309
+ };
3310
+
3311
+ CodeMirror.defineMode("null", function() {
3312
+ return {token: function(stream) {stream.skipToEnd();}};
3313
+ });
3314
+ CodeMirror.defineMIME("text/plain", "null");
3315
+
3316
+ var modeExtensions = CodeMirror.modeExtensions = {};
3317
+ CodeMirror.extendMode = function(mode, properties) {
3318
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
3319
+ copyObj(properties, exts);
3320
+ };
3321
+
3322
+ // EXTENSIONS
3323
+
3324
+ CodeMirror.defineExtension = function(name, func) {
3325
+ CodeMirror.prototype[name] = func;
3326
+ };
3327
+ CodeMirror.defineDocExtension = function(name, func) {
3328
+ Doc.prototype[name] = func;
3329
+ };
3330
+ CodeMirror.defineOption = option;
3331
+
3332
+ var initHooks = [];
3333
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
3334
+
3335
+ var helpers = CodeMirror.helpers = {};
3336
+ CodeMirror.registerHelper = function(type, name, value) {
3337
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3338
+ helpers[type][name] = value;
3339
+ };
3340
+
3341
+ // UTILITIES
3342
+
3343
+ CodeMirror.isWordChar = isWordChar;
3344
+
3345
+ // MODE STATE HANDLING
3346
+
3347
+ // Utility functions for working with state. Exported because modes
3348
+ // sometimes need to do this.
3349
+ function copyState(mode, state) {
3350
+ if (state === true) return state;
3351
+ if (mode.copyState) return mode.copyState(state);
3352
+ var nstate = {};
3353
+ for (var n in state) {
3354
+ var val = state[n];
3355
+ if (val instanceof Array) val = val.concat([]);
3356
+ nstate[n] = val;
3357
+ }
3358
+ return nstate;
3359
+ }
3360
+ CodeMirror.copyState = copyState;
3361
+
3362
+ function startState(mode, a1, a2) {
3363
+ return mode.startState ? mode.startState(a1, a2) : true;
3364
+ }
3365
+ CodeMirror.startState = startState;
3366
+
3367
+ CodeMirror.innerMode = function(mode, state) {
3368
+ while (mode.innerMode) {
3369
+ var info = mode.innerMode(state);
3370
+ if (!info || info.mode == mode) break;
3371
+ state = info.state;
3372
+ mode = info.mode;
3373
+ }
3374
+ return info || {mode: mode, state: state};
3375
+ };
3376
+
3377
+ // STANDARD COMMANDS
3378
+
3379
+ var commands = CodeMirror.commands = {
3380
+ selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
3381
+ killLine: function(cm) {
3382
+ var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
3383
+ if (!sel && cm.getLine(from.line).length == from.ch)
3384
+ cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
3385
+ else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
3386
+ },
3387
+ deleteLine: function(cm) {
3388
+ var l = cm.getCursor().line;
3389
+ cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3390
+ },
3391
+ delLineLeft: function(cm) {
3392
+ var cur = cm.getCursor();
3393
+ cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3394
+ },
3395
+ undo: function(cm) {cm.undo();},
3396
+ redo: function(cm) {cm.redo();},
3397
+ goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3398
+ goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
3399
+ goLineStart: function(cm) {
3400
+ cm.extendSelection(lineStart(cm, cm.getCursor().line));
3401
+ },
3402
+ goLineStartSmart: function(cm) {
3403
+ var cur = cm.getCursor(), start = lineStart(cm, cur.line);
3404
+ var line = cm.getLineHandle(start.line);
3405
+ var order = getOrder(line);
3406
+ if (!order || order[0].level == 0) {
3407
+ var firstNonWS = Math.max(0, line.text.search(/\S/));
3408
+ var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
3409
+ cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
3410
+ } else cm.extendSelection(start);
3411
+ },
3412
+ goLineEnd: function(cm) {
3413
+ cm.extendSelection(lineEnd(cm, cm.getCursor().line));
3414
+ },
3415
+ goLineRight: function(cm) {
3416
+ var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3417
+ cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
3418
+ },
3419
+ goLineLeft: function(cm) {
3420
+ var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3421
+ cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
3422
+ },
3423
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
3424
+ goLineDown: function(cm) {cm.moveV(1, "line");},
3425
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
3426
+ goPageDown: function(cm) {cm.moveV(1, "page");},
3427
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
3428
+ goCharRight: function(cm) {cm.moveH(1, "char");},
3429
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
3430
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
3431
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
3432
+ goGroupRight: function(cm) {cm.moveH(1, "group");},
3433
+ goGroupLeft: function(cm) {cm.moveH(-1, "group");},
3434
+ goWordRight: function(cm) {cm.moveH(1, "word");},
3435
+ delCharBefore: function(cm) {cm.deleteH(-1, "char");},
3436
+ delCharAfter: function(cm) {cm.deleteH(1, "char");},
3437
+ delWordBefore: function(cm) {cm.deleteH(-1, "word");},
3438
+ delWordAfter: function(cm) {cm.deleteH(1, "word");},
3439
+ delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
3440
+ delGroupAfter: function(cm) {cm.deleteH(1, "group");},
3441
+ indentAuto: function(cm) {cm.indentSelection("smart");},
3442
+ indentMore: function(cm) {cm.indentSelection("add");},
3443
+ indentLess: function(cm) {cm.indentSelection("subtract");},
3444
+ insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
3445
+ defaultTab: function(cm) {
3446
+ if (cm.somethingSelected()) cm.indentSelection("add");
3447
+ else cm.replaceSelection("\t", "end", "+input");
3448
+ },
3449
+ transposeChars: function(cm) {
3450
+ var cur = cm.getCursor(), line = cm.getLine(cur.line);
3451
+ if (cur.ch > 0 && cur.ch < line.length - 1)
3452
+ cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
3453
+ Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
3454
+ },
3455
+ newlineAndIndent: function(cm) {
3456
+ operation(cm, function() {
3457
+ cm.replaceSelection("\n", "end", "+input");
3458
+ cm.indentLine(cm.getCursor().line, null, true);
3459
+ })();
3460
+ },
3461
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
3462
+ };
3463
+
3464
+ // STANDARD KEYMAPS
3465
+
3466
+ var keyMap = CodeMirror.keyMap = {};
3467
+ keyMap.basic = {
3468
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
3469
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
3470
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
3471
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
3472
+ };
3473
+ // Note that the save and find-related commands aren't defined by
3474
+ // default. Unknown commands are simply ignored.
3475
+ keyMap.pcDefault = {
3476
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
3477
+ "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
3478
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
3479
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
3480
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
3481
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
3482
+ fallthrough: "basic"
3483
+ };
3484
+ keyMap.macDefault = {
3485
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
3486
+ "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
3487
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3488
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3489
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3490
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
3491
+ fallthrough: ["basic", "emacsy"]
3492
+ };
3493
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
3494
+ keyMap.emacsy = {
3495
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
3496
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
3497
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
3498
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
3499
+ };
3500
+
3501
+ // KEYMAP DISPATCH
3502
+
3503
+ function getKeyMap(val) {
3504
+ if (typeof val == "string") return keyMap[val];
3505
+ else return val;
3506
+ }
3507
+
3508
+ function lookupKey(name, maps, handle) {
3509
+ function lookup(map) {
3510
+ map = getKeyMap(map);
3511
+ var found = map[name];
3512
+ if (found === false) return "stop";
3513
+ if (found != null && handle(found)) return true;
3514
+ if (map.nofallthrough) return "stop";
3515
+
3516
+ var fallthrough = map.fallthrough;
3517
+ if (fallthrough == null) return false;
3518
+ if (Object.prototype.toString.call(fallthrough) != "[object Array]")
3519
+ return lookup(fallthrough);
3520
+ for (var i = 0, e = fallthrough.length; i < e; ++i) {
3521
+ var done = lookup(fallthrough[i]);
3522
+ if (done) return done;
3523
+ }
3524
+ return false;
3525
+ }
3526
+
3527
+ for (var i = 0; i < maps.length; ++i) {
3528
+ var done = lookup(maps[i]);
3529
+ if (done) return done != "stop";
3530
+ }
3531
+ }
3532
+ function isModifierKey(event) {
3533
+ var name = keyNames[event.keyCode];
3534
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
3535
+ }
3536
+ function keyName(event, noShift) {
3537
+ if (opera && event.keyCode == 34 && event["char"]) return false;
3538
+ var name = keyNames[event.keyCode];
3539
+ if (name == null || event.altGraphKey) return false;
3540
+ if (event.altKey) name = "Alt-" + name;
3541
+ if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
3542
+ if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
3543
+ if (!noShift && event.shiftKey) name = "Shift-" + name;
3544
+ return name;
3545
+ }
3546
+ CodeMirror.lookupKey = lookupKey;
3547
+ CodeMirror.isModifierKey = isModifierKey;
3548
+ CodeMirror.keyName = keyName;
3549
+
3550
+ // FROMTEXTAREA
3551
+
3552
+ CodeMirror.fromTextArea = function(textarea, options) {
3553
+ if (!options) options = {};
3554
+ options.value = textarea.value;
3555
+ if (!options.tabindex && textarea.tabindex)
3556
+ options.tabindex = textarea.tabindex;
3557
+ if (!options.placeholder && textarea.placeholder)
3558
+ options.placeholder = textarea.placeholder;
3559
+ // Set autofocus to true if this textarea is focused, or if it has
3560
+ // autofocus and no other element is focused.
3561
+ if (options.autofocus == null) {
3562
+ var hasFocus = document.body;
3563
+ // doc.activeElement occasionally throws on IE
3564
+ try { hasFocus = document.activeElement; } catch(e) {}
3565
+ options.autofocus = hasFocus == textarea ||
3566
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
3567
+ }
3568
+
3569
+ function save() {textarea.value = cm.getValue();}
3570
+ if (textarea.form) {
3571
+ on(textarea.form, "submit", save);
3572
+ // Deplorable hack to make the submit method do the right thing.
3573
+ if (!options.leaveSubmitMethodAlone) {
3574
+ var form = textarea.form, realSubmit = form.submit;
3575
+ try {
3576
+ var wrappedSubmit = form.submit = function() {
3577
+ save();
3578
+ form.submit = realSubmit;
3579
+ form.submit();
3580
+ form.submit = wrappedSubmit;
3581
+ };
3582
+ } catch(e) {}
3583
+ }
3584
+ }
3585
+
3586
+ textarea.style.display = "none";
3587
+ var cm = CodeMirror(function(node) {
3588
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
3589
+ }, options);
3590
+ cm.save = save;
3591
+ cm.getTextArea = function() { return textarea; };
3592
+ cm.toTextArea = function() {
3593
+ save();
3594
+ textarea.parentNode.removeChild(cm.getWrapperElement());
3595
+ textarea.style.display = "";
3596
+ if (textarea.form) {
3597
+ off(textarea.form, "submit", save);
3598
+ if (typeof textarea.form.submit == "function")
3599
+ textarea.form.submit = realSubmit;
3600
+ }
3601
+ };
3602
+ return cm;
3603
+ };
3604
+
3605
+ // STRING STREAM
3606
+
3607
+ // Fed to the mode parsers, provides helper functions to make
3608
+ // parsers more succinct.
3609
+
3610
+ // The character stream used by a mode's parser.
3611
+ function StringStream(string, tabSize) {
3612
+ this.pos = this.start = 0;
3613
+ this.string = string;
3614
+ this.tabSize = tabSize || 8;
3615
+ this.lastColumnPos = this.lastColumnValue = 0;
3616
+ }
3617
+
3618
+ StringStream.prototype = {
3619
+ eol: function() {return this.pos >= this.string.length;},
3620
+ sol: function() {return this.pos == 0;},
3621
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
3622
+ next: function() {
3623
+ if (this.pos < this.string.length)
3624
+ return this.string.charAt(this.pos++);
3625
+ },
3626
+ eat: function(match) {
3627
+ var ch = this.string.charAt(this.pos);
3628
+ if (typeof match == "string") var ok = ch == match;
3629
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
3630
+ if (ok) {++this.pos; return ch;}
3631
+ },
3632
+ eatWhile: function(match) {
3633
+ var start = this.pos;
3634
+ while (this.eat(match)){}
3635
+ return this.pos > start;
3636
+ },
3637
+ eatSpace: function() {
3638
+ var start = this.pos;
3639
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
3640
+ return this.pos > start;
3641
+ },
3642
+ skipToEnd: function() {this.pos = this.string.length;},
3643
+ skipTo: function(ch) {
3644
+ var found = this.string.indexOf(ch, this.pos);
3645
+ if (found > -1) {this.pos = found; return true;}
3646
+ },
3647
+ backUp: function(n) {this.pos -= n;},
3648
+ column: function() {
3649
+ if (this.lastColumnPos < this.start) {
3650
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3651
+ this.lastColumnPos = this.start;
3652
+ }
3653
+ return this.lastColumnValue;
3654
+ },
3655
+ indentation: function() {return countColumn(this.string, null, this.tabSize);},
3656
+ match: function(pattern, consume, caseInsensitive) {
3657
+ if (typeof pattern == "string") {
3658
+ var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
3659
+ var substr = this.string.substr(this.pos, pattern.length);
3660
+ if (cased(substr) == cased(pattern)) {
3661
+ if (consume !== false) this.pos += pattern.length;
3662
+ return true;
3663
+ }
3664
+ } else {
3665
+ var match = this.string.slice(this.pos).match(pattern);
3666
+ if (match && match.index > 0) return null;
3667
+ if (match && consume !== false) this.pos += match[0].length;
3668
+ return match;
3669
+ }
3670
+ },
3671
+ current: function(){return this.string.slice(this.start, this.pos);}
3672
+ };
3673
+ CodeMirror.StringStream = StringStream;
3674
+
3675
+ // TEXTMARKERS
3676
+
3677
+ function TextMarker(doc, type) {
3678
+ this.lines = [];
3679
+ this.type = type;
3680
+ this.doc = doc;
3681
+ }
3682
+ CodeMirror.TextMarker = TextMarker;
3683
+ eventMixin(TextMarker);
3684
+
3685
+ TextMarker.prototype.clear = function() {
3686
+ if (this.explicitlyCleared) return;
3687
+ var cm = this.doc.cm, withOp = cm && !cm.curOp;
3688
+ if (withOp) startOperation(cm);
3689
+ if (hasHandler(this, "clear")) {
3690
+ var found = this.find();
3691
+ if (found) signalLater(this, "clear", found.from, found.to);
3692
+ }
3693
+ var min = null, max = null;
3694
+ for (var i = 0; i < this.lines.length; ++i) {
3695
+ var line = this.lines[i];
3696
+ var span = getMarkedSpanFor(line.markedSpans, this);
3697
+ if (span.to != null) max = lineNo(line);
3698
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
3699
+ if (span.from != null)
3700
+ min = lineNo(line);
3701
+ else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
3702
+ updateLineHeight(line, textHeight(cm.display));
3703
+ }
3704
+ if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
3705
+ var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
3706
+ if (len > cm.display.maxLineLength) {
3707
+ cm.display.maxLine = visual;
3708
+ cm.display.maxLineLength = len;
3709
+ cm.display.maxLineChanged = true;
3710
+ }
3711
+ }
3712
+
3713
+ if (min != null && cm) regChange(cm, min, max + 1);
3714
+ this.lines.length = 0;
3715
+ this.explicitlyCleared = true;
3716
+ if (this.atomic && this.doc.cantEdit) {
3717
+ this.doc.cantEdit = false;
3718
+ if (cm) reCheckSelection(cm);
3719
+ }
3720
+ if (withOp) endOperation(cm);
3721
+ };
3722
+
3723
+ TextMarker.prototype.find = function() {
3724
+ var from, to;
3725
+ for (var i = 0; i < this.lines.length; ++i) {
3726
+ var line = this.lines[i];
3727
+ var span = getMarkedSpanFor(line.markedSpans, this);
3728
+ if (span.from != null || span.to != null) {
3729
+ var found = lineNo(line);
3730
+ if (span.from != null) from = Pos(found, span.from);
3731
+ if (span.to != null) to = Pos(found, span.to);
3732
+ }
3733
+ }
3734
+ if (this.type == "bookmark") return from;
3735
+ return from && {from: from, to: to};
3736
+ };
3737
+
3738
+ TextMarker.prototype.changed = function() {
3739
+ var pos = this.find(), cm = this.doc.cm;
3740
+ if (!pos || !cm) return;
3741
+ var line = getLine(this.doc, pos.from.line);
3742
+ clearCachedMeasurement(cm, line);
3743
+ if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
3744
+ for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3745
+ if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3746
+ break;
3747
+ }
3748
+ runInOp(cm, function() {
3749
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3750
+ });
3751
+ }
3752
+ };
3753
+
3754
+ TextMarker.prototype.attachLine = function(line) {
3755
+ if (!this.lines.length && this.doc.cm) {
3756
+ var op = this.doc.cm.curOp;
3757
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
3758
+ (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
3759
+ }
3760
+ this.lines.push(line);
3761
+ };
3762
+ TextMarker.prototype.detachLine = function(line) {
3763
+ this.lines.splice(indexOf(this.lines, line), 1);
3764
+ if (!this.lines.length && this.doc.cm) {
3765
+ var op = this.doc.cm.curOp;
3766
+ (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
3767
+ }
3768
+ };
3769
+
3770
+ function markText(doc, from, to, options, type) {
3771
+ if (options && options.shared) return markTextShared(doc, from, to, options, type);
3772
+ if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3773
+
3774
+ var marker = new TextMarker(doc, type);
3775
+ if (type == "range" && !posLess(from, to)) return marker;
3776
+ if (options) copyObj(options, marker);
3777
+ if (marker.replacedWith) {
3778
+ marker.collapsed = true;
3779
+ marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3780
+ if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3781
+ }
3782
+ if (marker.collapsed) sawCollapsedSpans = true;
3783
+
3784
+ if (marker.addToHistory)
3785
+ addToHistory(doc, {from: from, to: to, origin: "markText"},
3786
+ {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
3787
+
3788
+ var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
3789
+ doc.iter(curLine, to.line + 1, function(line) {
3790
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3791
+ updateMaxLine = true;
3792
+ var span = {from: null, to: null, marker: marker};
3793
+ size += line.text.length;
3794
+ if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
3795
+ if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
3796
+ if (marker.collapsed) {
3797
+ if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
3798
+ if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
3799
+ else updateLineHeight(line, 0);
3800
+ }
3801
+ addMarkedSpan(line, span);
3802
+ ++curLine;
3803
+ });
3804
+ if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
3805
+ if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
3806
+ });
3807
+
3808
+ if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
3809
+
3810
+ if (marker.readOnly) {
3811
+ sawReadOnlySpans = true;
3812
+ if (doc.history.done.length || doc.history.undone.length)
3813
+ doc.clearHistory();
3814
+ }
3815
+ if (marker.collapsed) {
3816
+ if (collapsedAtStart != collapsedAtEnd)
3817
+ throw new Error("Inserting collapsed marker overlapping an existing one");
3818
+ marker.size = size;
3819
+ marker.atomic = true;
3820
+ }
3821
+ if (cm) {
3822
+ if (updateMaxLine) cm.curOp.updateMaxLine = true;
3823
+ if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3824
+ regChange(cm, from.line, to.line + 1);
3825
+ if (marker.atomic) reCheckSelection(cm);
3826
+ }
3827
+ return marker;
3828
+ }
3829
+
3830
+ // SHARED TEXTMARKERS
3831
+
3832
+ function SharedTextMarker(markers, primary) {
3833
+ this.markers = markers;
3834
+ this.primary = primary;
3835
+ for (var i = 0, me = this; i < markers.length; ++i) {
3836
+ markers[i].parent = this;
3837
+ on(markers[i], "clear", function(){me.clear();});
3838
+ }
3839
+ }
3840
+ CodeMirror.SharedTextMarker = SharedTextMarker;
3841
+ eventMixin(SharedTextMarker);
3842
+
3843
+ SharedTextMarker.prototype.clear = function() {
3844
+ if (this.explicitlyCleared) return;
3845
+ this.explicitlyCleared = true;
3846
+ for (var i = 0; i < this.markers.length; ++i)
3847
+ this.markers[i].clear();
3848
+ signalLater(this, "clear");
3849
+ };
3850
+ SharedTextMarker.prototype.find = function() {
3851
+ return this.primary.find();
3852
+ };
3853
+
3854
+ function markTextShared(doc, from, to, options, type) {
3855
+ options = copyObj(options);
3856
+ options.shared = false;
3857
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0];
3858
+ var widget = options.replacedWith;
3859
+ linkedDocs(doc, function(doc) {
3860
+ if (widget) options.replacedWith = widget.cloneNode(true);
3861
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
3862
+ for (var i = 0; i < doc.linked.length; ++i)
3863
+ if (doc.linked[i].isParent) return;
3864
+ primary = lst(markers);
3865
+ });
3866
+ return new SharedTextMarker(markers, primary);
3867
+ }
3868
+
3869
+ // TEXTMARKER SPANS
3870
+
3871
+ function getMarkedSpanFor(spans, marker) {
3872
+ if (spans) for (var i = 0; i < spans.length; ++i) {
3873
+ var span = spans[i];
3874
+ if (span.marker == marker) return span;
3875
+ }
3876
+ }
3877
+ function removeMarkedSpan(spans, span) {
3878
+ for (var r, i = 0; i < spans.length; ++i)
3879
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
3880
+ return r;
3881
+ }
3882
+ function addMarkedSpan(line, span) {
3883
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
3884
+ span.marker.attachLine(line);
3885
+ }
3886
+
3887
+ function markedSpansBefore(old, startCh, isInsert) {
3888
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
3889
+ var span = old[i], marker = span.marker;
3890
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3891
+ if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
3892
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
3893
+ (nw || (nw = [])).push({from: span.from,
3894
+ to: endsAfter ? null : span.to,
3895
+ marker: marker});
3896
+ }
3897
+ }
3898
+ return nw;
3899
+ }
3900
+
3901
+ function markedSpansAfter(old, endCh, isInsert) {
3902
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
3903
+ var span = old[i], marker = span.marker;
3904
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3905
+ if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
3906
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
3907
+ (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
3908
+ to: span.to == null ? null : span.to - endCh,
3909
+ marker: marker});
3910
+ }
3911
+ }
3912
+ return nw;
3913
+ }
3914
+
3915
+ function stretchSpansOverChange(doc, change) {
3916
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
3917
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
3918
+ if (!oldFirst && !oldLast) return null;
3919
+
3920
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
3921
+ // Get the spans that 'stick out' on both sides
3922
+ var first = markedSpansBefore(oldFirst, startCh, isInsert);
3923
+ var last = markedSpansAfter(oldLast, endCh, isInsert);
3924
+
3925
+ // Next, merge those two ends
3926
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
3927
+ if (first) {
3928
+ // Fix up .to properties of first
3929
+ for (var i = 0; i < first.length; ++i) {
3930
+ var span = first[i];
3931
+ if (span.to == null) {
3932
+ var found = getMarkedSpanFor(last, span.marker);
3933
+ if (!found) span.to = startCh;
3934
+ else if (sameLine) span.to = found.to == null ? null : found.to + offset;
3935
+ }
3936
+ }
3937
+ }
3938
+ if (last) {
3939
+ // Fix up .from in last (or move them into first in case of sameLine)
3940
+ for (var i = 0; i < last.length; ++i) {
3941
+ var span = last[i];
3942
+ if (span.to != null) span.to += offset;
3943
+ if (span.from == null) {
3944
+ var found = getMarkedSpanFor(first, span.marker);
3945
+ if (!found) {
3946
+ span.from = offset;
3947
+ if (sameLine) (first || (first = [])).push(span);
3948
+ }
3949
+ } else {
3950
+ span.from += offset;
3951
+ if (sameLine) (first || (first = [])).push(span);
3952
+ }
3953
+ }
3954
+ }
3955
+ if (sameLine && first) {
3956
+ // Make sure we didn't create any zero-length spans
3957
+ for (var i = 0; i < first.length; ++i)
3958
+ if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
3959
+ first.splice(i--, 1);
3960
+ if (!first.length) first = null;
3961
+ }
3962
+
3963
+ var newMarkers = [first];
3964
+ if (!sameLine) {
3965
+ // Fill gap with whole-line-spans
3966
+ var gap = change.text.length - 2, gapMarkers;
3967
+ if (gap > 0 && first)
3968
+ for (var i = 0; i < first.length; ++i)
3969
+ if (first[i].to == null)
3970
+ (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
3971
+ for (var i = 0; i < gap; ++i)
3972
+ newMarkers.push(gapMarkers);
3973
+ newMarkers.push(last);
3974
+ }
3975
+ return newMarkers;
3976
+ }
3977
+
3978
+ function mergeOldSpans(doc, change) {
3979
+ var old = getOldSpans(doc, change);
3980
+ var stretched = stretchSpansOverChange(doc, change);
3981
+ if (!old) return stretched;
3982
+ if (!stretched) return old;
3983
+
3984
+ for (var i = 0; i < old.length; ++i) {
3985
+ var oldCur = old[i], stretchCur = stretched[i];
3986
+ if (oldCur && stretchCur) {
3987
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
3988
+ var span = stretchCur[j];
3989
+ for (var k = 0; k < oldCur.length; ++k)
3990
+ if (oldCur[k].marker == span.marker) continue spans;
3991
+ oldCur.push(span);
3992
+ }
3993
+ } else if (stretchCur) {
3994
+ old[i] = stretchCur;
3995
+ }
3996
+ }
3997
+ return old;
3998
+ }
3999
+
4000
+ function removeReadOnlyRanges(doc, from, to) {
4001
+ var markers = null;
4002
+ doc.iter(from.line, to.line + 1, function(line) {
4003
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
4004
+ var mark = line.markedSpans[i].marker;
4005
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
4006
+ (markers || (markers = [])).push(mark);
4007
+ }
4008
+ });
4009
+ if (!markers) return null;
4010
+ var parts = [{from: from, to: to}];
4011
+ for (var i = 0; i < markers.length; ++i) {
4012
+ var mk = markers[i], m = mk.find();
4013
+ for (var j = 0; j < parts.length; ++j) {
4014
+ var p = parts[j];
4015
+ if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
4016
+ var newParts = [j, 1];
4017
+ if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
4018
+ newParts.push({from: p.from, to: m.from});
4019
+ if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
4020
+ newParts.push({from: m.to, to: p.to});
4021
+ parts.splice.apply(parts, newParts);
4022
+ j += newParts.length - 1;
4023
+ }
4024
+ }
4025
+ return parts;
4026
+ }
4027
+
4028
+ function collapsedSpanAt(line, ch) {
4029
+ var sps = sawCollapsedSpans && line.markedSpans, found;
4030
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4031
+ sp = sps[i];
4032
+ if (!sp.marker.collapsed) continue;
4033
+ if ((sp.from == null || sp.from < ch) &&
4034
+ (sp.to == null || sp.to > ch) &&
4035
+ (!found || found.width < sp.marker.width))
4036
+ found = sp.marker;
4037
+ }
4038
+ return found;
4039
+ }
4040
+ function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
4041
+ function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
4042
+
4043
+ function visualLine(doc, line) {
4044
+ var merged;
4045
+ while (merged = collapsedSpanAtStart(line))
4046
+ line = getLine(doc, merged.find().from.line);
4047
+ return line;
4048
+ }
4049
+
4050
+ function lineIsHidden(doc, line) {
4051
+ var sps = sawCollapsedSpans && line.markedSpans;
4052
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4053
+ sp = sps[i];
4054
+ if (!sp.marker.collapsed) continue;
4055
+ if (sp.from == null) return true;
4056
+ if (sp.marker.replacedWith) continue;
4057
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
4058
+ return true;
4059
+ }
4060
+ }
4061
+ function lineIsHiddenInner(doc, line, span) {
4062
+ if (span.to == null) {
4063
+ var end = span.marker.find().to, endLine = getLine(doc, end.line);
4064
+ return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
4065
+ }
4066
+ if (span.marker.inclusiveRight && span.to == line.text.length)
4067
+ return true;
4068
+ for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4069
+ sp = line.markedSpans[i];
4070
+ if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
4071
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4072
+ lineIsHiddenInner(doc, line, sp)) return true;
4073
+ }
4074
+ }
4075
+
4076
+ function detachMarkedSpans(line) {
4077
+ var spans = line.markedSpans;
4078
+ if (!spans) return;
4079
+ for (var i = 0; i < spans.length; ++i)
4080
+ spans[i].marker.detachLine(line);
4081
+ line.markedSpans = null;
4082
+ }
4083
+
4084
+ function attachMarkedSpans(line, spans) {
4085
+ if (!spans) return;
4086
+ for (var i = 0; i < spans.length; ++i)
4087
+ spans[i].marker.attachLine(line);
4088
+ line.markedSpans = spans;
4089
+ }
4090
+
4091
+ // LINE WIDGETS
4092
+
4093
+ var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4094
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4095
+ this[opt] = options[opt];
4096
+ this.cm = cm;
4097
+ this.node = node;
4098
+ };
4099
+ eventMixin(LineWidget);
4100
+ function widgetOperation(f) {
4101
+ return function() {
4102
+ var withOp = !this.cm.curOp;
4103
+ if (withOp) startOperation(this.cm);
4104
+ try {var result = f.apply(this, arguments);}
4105
+ finally {if (withOp) endOperation(this.cm);}
4106
+ return result;
4107
+ };
4108
+ }
4109
+ LineWidget.prototype.clear = widgetOperation(function() {
4110
+ var ws = this.line.widgets, no = lineNo(this.line);
4111
+ if (no == null || !ws) return;
4112
+ for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4113
+ if (!ws.length) this.line.widgets = null;
4114
+ var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4115
+ updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4116
+ if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4117
+ regChange(this.cm, no, no + 1);
4118
+ });
4119
+ LineWidget.prototype.changed = widgetOperation(function() {
4120
+ var oldH = this.height;
4121
+ this.height = null;
4122
+ var diff = widgetHeight(this) - oldH;
4123
+ if (!diff) return;
4124
+ updateLineHeight(this.line, this.line.height + diff);
4125
+ var no = lineNo(this.line);
4126
+ regChange(this.cm, no, no + 1);
4127
+ });
4128
+
4129
+ function widgetHeight(widget) {
4130
+ if (widget.height != null) return widget.height;
4131
+ if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
4132
+ removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
4133
+ return widget.height = widget.node.offsetHeight;
4134
+ }
4135
+
4136
+ function addLineWidget(cm, handle, node, options) {
4137
+ var widget = new LineWidget(cm, node, options);
4138
+ if (widget.noHScroll) cm.display.alignWidgets = true;
4139
+ changeLine(cm, handle, function(line) {
4140
+ var widgets = line.widgets || (line.widgets = []);
4141
+ if (widget.insertAt == null) widgets.push(widget);
4142
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4143
+ widget.line = line;
4144
+ if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4145
+ var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4146
+ updateLineHeight(line, line.height + widgetHeight(widget));
4147
+ if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4148
+ }
4149
+ return true;
4150
+ });
4151
+ return widget;
4152
+ }
4153
+
4154
+ // LINE DATA STRUCTURE
4155
+
4156
+ // Line objects. These hold state related to a line, including
4157
+ // highlighting info (the styles array).
4158
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4159
+ this.text = text;
4160
+ attachMarkedSpans(this, markedSpans);
4161
+ this.height = estimateHeight ? estimateHeight(this) : 1;
4162
+ };
4163
+ eventMixin(Line);
4164
+
4165
+ function updateLine(line, text, markedSpans, estimateHeight) {
4166
+ line.text = text;
4167
+ if (line.stateAfter) line.stateAfter = null;
4168
+ if (line.styles) line.styles = null;
4169
+ if (line.order != null) line.order = null;
4170
+ detachMarkedSpans(line);
4171
+ attachMarkedSpans(line, markedSpans);
4172
+ var estHeight = estimateHeight ? estimateHeight(line) : 1;
4173
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
4174
+ }
4175
+
4176
+ function cleanUpLine(line) {
4177
+ line.parent = null;
4178
+ detachMarkedSpans(line);
4179
+ }
4180
+
4181
+ // Run the given mode's parser over a line, update the styles
4182
+ // array, which contains alternating fragments of text and CSS
4183
+ // classes.
4184
+ function runMode(cm, text, mode, state, f) {
4185
+ var flattenSpans = mode.flattenSpans;
4186
+ if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4187
+ var curStart = 0, curStyle = null;
4188
+ var stream = new StringStream(text, cm.options.tabSize), style;
4189
+ if (text == "" && mode.blankLine) mode.blankLine(state);
4190
+ while (!stream.eol()) {
4191
+ if (stream.pos > cm.options.maxHighlightLength) {
4192
+ flattenSpans = false;
4193
+ // Webkit seems to refuse to render text nodes longer than 57444 characters
4194
+ stream.pos = Math.min(text.length, stream.start + 50000);
4195
+ style = null;
4196
+ } else {
4197
+ style = mode.token(stream, state);
4198
+ }
4199
+ if (!flattenSpans || curStyle != style) {
4200
+ if (curStart < stream.start) f(stream.start, curStyle);
4201
+ curStart = stream.start; curStyle = style;
4202
+ }
4203
+ stream.start = stream.pos;
4204
+ }
4205
+ if (curStart < stream.pos) f(stream.pos, curStyle);
4206
+ }
4207
+
4208
+ function highlightLine(cm, line, state) {
4209
+ // A styles array always starts with a number identifying the
4210
+ // mode/overlays that it is based on (for easy invalidation).
4211
+ var st = [cm.state.modeGen];
4212
+ // Compute the base array of styles
4213
+ runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4214
+
4215
+ // Run overlays, adjust style array.
4216
+ for (var o = 0; o < cm.state.overlays.length; ++o) {
4217
+ var overlay = cm.state.overlays[o], i = 1, at = 0;
4218
+ runMode(cm, line.text, overlay.mode, true, function(end, style) {
4219
+ var start = i;
4220
+ // Ensure there's a token end at the current position, and that i points at it
4221
+ while (at < end) {
4222
+ var i_end = st[i];
4223
+ if (i_end > end)
4224
+ st.splice(i, 1, end, st[i+1], i_end);
4225
+ i += 2;
4226
+ at = Math.min(end, i_end);
4227
+ }
4228
+ if (!style) return;
4229
+ if (overlay.opaque) {
4230
+ st.splice(start, i - start, end, style);
4231
+ i = start + 2;
4232
+ } else {
4233
+ for (; start < i; start += 2) {
4234
+ var cur = st[start+1];
4235
+ st[start+1] = cur ? cur + " " + style : style;
4236
+ }
4237
+ }
4238
+ });
4239
+ }
4240
+
4241
+ return st;
4242
+ }
4243
+
4244
+ function getLineStyles(cm, line) {
4245
+ if (!line.styles || line.styles[0] != cm.state.modeGen)
4246
+ line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
4247
+ return line.styles;
4248
+ }
4249
+
4250
+ // Lightweight form of highlight -- proceed over this line and
4251
+ // update state, but don't save a style array.
4252
+ function processLine(cm, line, state) {
4253
+ var mode = cm.doc.mode;
4254
+ var stream = new StringStream(line.text, cm.options.tabSize);
4255
+ if (line.text == "" && mode.blankLine) mode.blankLine(state);
4256
+ while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
4257
+ mode.token(stream, state);
4258
+ stream.start = stream.pos;
4259
+ }
4260
+ }
4261
+
4262
+ var styleToClassCache = {};
4263
+ function styleToClass(style) {
4264
+ if (!style) return null;
4265
+ return styleToClassCache[style] ||
4266
+ (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4267
+ }
4268
+
4269
+ function lineContent(cm, realLine, measure, copyWidgets) {
4270
+ var merged, line = realLine, empty = true;
4271
+ while (merged = collapsedSpanAtStart(line))
4272
+ line = getLine(cm.doc, merged.find().from.line);
4273
+
4274
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
4275
+ measure: null, measuredSomething: false, cm: cm,
4276
+ copyWidgets: copyWidgets};
4277
+ if (line.textClass) builder.pre.className = line.textClass;
4278
+
4279
+ do {
4280
+ if (line.text) empty = false;
4281
+ builder.measure = line == realLine && measure;
4282
+ builder.pos = 0;
4283
+ builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4284
+ if ((ie || webkit) && cm.getOption("lineWrapping"))
4285
+ builder.addToken = buildTokenSplitSpaces(builder.addToken);
4286
+ var next = insertLineContent(line, builder, getLineStyles(cm, line));
4287
+ if (measure && line == realLine && !builder.measuredSomething) {
4288
+ measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4289
+ builder.measuredSomething = true;
4290
+ }
4291
+ if (next) line = getLine(cm.doc, next.to.line);
4292
+ } while (next);
4293
+
4294
+ if (measure && !builder.measuredSomething && !measure[0])
4295
+ measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4296
+ if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4297
+ builder.pre.appendChild(document.createTextNode("\u00a0"));
4298
+
4299
+ var order;
4300
+ // Work around problem with the reported dimensions of single-char
4301
+ // direction spans on IE (issue #1129). See also the comment in
4302
+ // cursorCoords.
4303
+ if (measure && ie && (order = getOrder(line))) {
4304
+ var l = order.length - 1;
4305
+ if (order[l].from == order[l].to) --l;
4306
+ var last = order[l], prev = order[l - 1];
4307
+ if (last.from + 1 == last.to && prev && last.level < prev.level) {
4308
+ var span = measure[builder.pos - 1];
4309
+ if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
4310
+ span.nextSibling);
4311
+ }
4312
+ }
4313
+
4314
+ signal(cm, "renderLine", cm, realLine, builder.pre);
4315
+ return builder.pre;
4316
+ }
4317
+
4318
+ var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4319
+ function buildToken(builder, text, style, startStyle, endStyle, title) {
4320
+ if (!text) return;
4321
+ if (!tokenSpecialChars.test(text)) {
4322
+ builder.col += text.length;
4323
+ var content = document.createTextNode(text);
4324
+ } else {
4325
+ var content = document.createDocumentFragment(), pos = 0;
4326
+ while (true) {
4327
+ tokenSpecialChars.lastIndex = pos;
4328
+ var m = tokenSpecialChars.exec(text);
4329
+ var skipped = m ? m.index - pos : text.length - pos;
4330
+ if (skipped) {
4331
+ content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
4332
+ builder.col += skipped;
4333
+ }
4334
+ if (!m) break;
4335
+ pos += skipped + 1;
4336
+ if (m[0] == "\t") {
4337
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
4338
+ content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
4339
+ builder.col += tabWidth;
4340
+ } else {
4341
+ var token = elt("span", "\u2022", "cm-invalidchar");
4342
+ token.title = "\\u" + m[0].charCodeAt(0).toString(16);
4343
+ content.appendChild(token);
4344
+ builder.col += 1;
4345
+ }
4346
+ }
4347
+ }
4348
+ if (style || startStyle || endStyle || builder.measure) {
4349
+ var fullStyle = style || "";
4350
+ if (startStyle) fullStyle += startStyle;
4351
+ if (endStyle) fullStyle += endStyle;
4352
+ var token = elt("span", [content], fullStyle);
4353
+ if (title) token.title = title;
4354
+ return builder.pre.appendChild(token);
4355
+ }
4356
+ builder.pre.appendChild(content);
4357
+ }
4358
+
4359
+ function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4360
+ var wrapping = builder.cm.options.lineWrapping;
4361
+ for (var i = 0; i < text.length; ++i) {
4362
+ var ch = text.charAt(i), start = i == 0;
4363
+ if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4364
+ ch = text.slice(i, i + 2);
4365
+ ++i;
4366
+ } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4367
+ builder.pre.appendChild(elt("wbr"));
4368
+ }
4369
+ var old = builder.measure[builder.pos];
4370
+ var span = builder.measure[builder.pos] =
4371
+ buildToken(builder, ch, style,
4372
+ start && startStyle, i == text.length - 1 && endStyle);
4373
+ if (old) span.leftSide = old.leftSide || old;
4374
+ // In IE single-space nodes wrap differently than spaces
4375
+ // embedded in larger text nodes, except when set to
4376
+ // white-space: normal (issue #1268).
4377
+ if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4378
+ i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4379
+ span.style.whiteSpace = "normal";
4380
+ builder.pos += ch.length;
4381
+ }
4382
+ if (text.length) builder.measuredSomething = true;
4383
+ }
4384
+
4385
+ function buildTokenSplitSpaces(inner) {
4386
+ function split(old) {
4387
+ var out = " ";
4388
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
4389
+ out += " ";
4390
+ return out;
4391
+ }
4392
+ return function(builder, text, style, startStyle, endStyle, title) {
4393
+ return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
4394
+ };
4395
+ }
4396
+
4397
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4398
+ var widget = !ignoreWidget && marker.replacedWith;
4399
+ if (widget) {
4400
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
4401
+ builder.pre.appendChild(widget);
4402
+ if (builder.measure) {
4403
+ if (size) {
4404
+ builder.measure[builder.pos] = widget;
4405
+ } else {
4406
+ var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
4407
+ if (marker.type != "bookmark" || marker.insertLeft)
4408
+ builder.pre.insertBefore(elt, widget);
4409
+ else
4410
+ builder.pre.appendChild(elt);
4411
+ }
4412
+ builder.measuredSomething = true;
4413
+ }
4414
+ }
4415
+ builder.pos += size;
4416
+ }
4417
+
4418
+ // Outputs a number of spans to make up a line, taking highlighting
4419
+ // and marked text into account.
4420
+ function insertLineContent(line, builder, styles) {
4421
+ var spans = line.markedSpans, allText = line.text, at = 0;
4422
+ if (!spans) {
4423
+ for (var i = 1; i < styles.length; i+=2)
4424
+ builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
4425
+ return;
4426
+ }
4427
+
4428
+ var len = allText.length, pos = 0, i = 1, text = "", style;
4429
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
4430
+ for (;;) {
4431
+ if (nextChange == pos) { // Update current marker set
4432
+ spanStyle = spanEndStyle = spanStartStyle = title = "";
4433
+ collapsed = null; nextChange = Infinity;
4434
+ var foundBookmark = null;
4435
+ for (var j = 0; j < spans.length; ++j) {
4436
+ var sp = spans[j], m = sp.marker;
4437
+ if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
4438
+ if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
4439
+ if (m.className) spanStyle += " " + m.className;
4440
+ if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4441
+ if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4442
+ if (m.title && !title) title = m.title;
4443
+ if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4444
+ collapsed = sp;
4445
+ } else if (sp.from > pos && nextChange > sp.from) {
4446
+ nextChange = sp.from;
4447
+ }
4448
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
4449
+ }
4450
+ if (collapsed && (collapsed.from || 0) == pos) {
4451
+ buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4452
+ collapsed.marker, collapsed.from == null);
4453
+ if (collapsed.to == null) return collapsed.marker.find();
4454
+ }
4455
+ if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
4456
+ }
4457
+ if (pos >= len) break;
4458
+
4459
+ var upto = Math.min(len, nextChange);
4460
+ while (true) {
4461
+ if (text) {
4462
+ var end = pos + text.length;
4463
+ if (!collapsed) {
4464
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4465
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4466
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4467
+ }
4468
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
4469
+ pos = end;
4470
+ spanStartStyle = "";
4471
+ }
4472
+ text = allText.slice(at, at = styles[i++]);
4473
+ style = styleToClass(styles[i++]);
4474
+ }
4475
+ }
4476
+ }
4477
+
4478
+ // DOCUMENT DATA STRUCTURE
4479
+
4480
+ function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
4481
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
4482
+ function update(line, text, spans) {
4483
+ updateLine(line, text, spans, estimateHeight);
4484
+ signalLater(line, "change", line, change);
4485
+ }
4486
+
4487
+ var from = change.from, to = change.to, text = change.text;
4488
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4489
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4490
+
4491
+ // First adjust the line structure
4492
+ if (from.ch == 0 && to.ch == 0 && lastText == "") {
4493
+ // This is a whole-line replace. Treated specially to make
4494
+ // sure line objects move the way they are supposed to.
4495
+ for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4496
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4497
+ update(lastLine, lastLine.text, lastSpans);
4498
+ if (nlines) doc.remove(from.line, nlines);
4499
+ if (added.length) doc.insert(from.line, added);
4500
+ } else if (firstLine == lastLine) {
4501
+ if (text.length == 1) {
4502
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4503
+ } else {
4504
+ for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4505
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4506
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4507
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4508
+ doc.insert(from.line + 1, added);
4509
+ }
4510
+ } else if (text.length == 1) {
4511
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4512
+ doc.remove(from.line + 1, nlines);
4513
+ } else {
4514
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4515
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4516
+ for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4517
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4518
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4519
+ doc.insert(from.line + 1, added);
4520
+ }
4521
+
4522
+ signalLater(doc, "change", doc, change);
4523
+ setSelection(doc, selAfter.anchor, selAfter.head, null, true);
4524
+ }
4525
+
4526
+ function LeafChunk(lines) {
4527
+ this.lines = lines;
4528
+ this.parent = null;
4529
+ for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
4530
+ lines[i].parent = this;
4531
+ height += lines[i].height;
4532
+ }
4533
+ this.height = height;
4534
+ }
4535
+
4536
+ LeafChunk.prototype = {
4537
+ chunkSize: function() { return this.lines.length; },
4538
+ removeInner: function(at, n) {
4539
+ for (var i = at, e = at + n; i < e; ++i) {
4540
+ var line = this.lines[i];
4541
+ this.height -= line.height;
4542
+ cleanUpLine(line);
4543
+ signalLater(line, "delete");
4544
+ }
4545
+ this.lines.splice(at, n);
4546
+ },
4547
+ collapse: function(lines) {
4548
+ lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
4549
+ },
4550
+ insertInner: function(at, lines, height) {
4551
+ this.height += height;
4552
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
4553
+ for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
4554
+ },
4555
+ iterN: function(at, n, op) {
4556
+ for (var e = at + n; at < e; ++at)
4557
+ if (op(this.lines[at])) return true;
4558
+ }
4559
+ };
4560
+
4561
+ function BranchChunk(children) {
4562
+ this.children = children;
4563
+ var size = 0, height = 0;
4564
+ for (var i = 0, e = children.length; i < e; ++i) {
4565
+ var ch = children[i];
4566
+ size += ch.chunkSize(); height += ch.height;
4567
+ ch.parent = this;
4568
+ }
4569
+ this.size = size;
4570
+ this.height = height;
4571
+ this.parent = null;
4572
+ }
4573
+
4574
+ BranchChunk.prototype = {
4575
+ chunkSize: function() { return this.size; },
4576
+ removeInner: function(at, n) {
4577
+ this.size -= n;
4578
+ for (var i = 0; i < this.children.length; ++i) {
4579
+ var child = this.children[i], sz = child.chunkSize();
4580
+ if (at < sz) {
4581
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
4582
+ child.removeInner(at, rm);
4583
+ this.height -= oldHeight - child.height;
4584
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
4585
+ if ((n -= rm) == 0) break;
4586
+ at = 0;
4587
+ } else at -= sz;
4588
+ }
4589
+ if (this.size - n < 25) {
4590
+ var lines = [];
4591
+ this.collapse(lines);
4592
+ this.children = [new LeafChunk(lines)];
4593
+ this.children[0].parent = this;
4594
+ }
4595
+ },
4596
+ collapse: function(lines) {
4597
+ for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
4598
+ },
4599
+ insertInner: function(at, lines, height) {
4600
+ this.size += lines.length;
4601
+ this.height += height;
4602
+ for (var i = 0, e = this.children.length; i < e; ++i) {
4603
+ var child = this.children[i], sz = child.chunkSize();
4604
+ if (at <= sz) {
4605
+ child.insertInner(at, lines, height);
4606
+ if (child.lines && child.lines.length > 50) {
4607
+ while (child.lines.length > 50) {
4608
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
4609
+ var newleaf = new LeafChunk(spilled);
4610
+ child.height -= newleaf.height;
4611
+ this.children.splice(i + 1, 0, newleaf);
4612
+ newleaf.parent = this;
4613
+ }
4614
+ this.maybeSpill();
4615
+ }
4616
+ break;
4617
+ }
4618
+ at -= sz;
4619
+ }
4620
+ },
4621
+ maybeSpill: function() {
4622
+ if (this.children.length <= 10) return;
4623
+ var me = this;
4624
+ do {
4625
+ var spilled = me.children.splice(me.children.length - 5, 5);
4626
+ var sibling = new BranchChunk(spilled);
4627
+ if (!me.parent) { // Become the parent node
4628
+ var copy = new BranchChunk(me.children);
4629
+ copy.parent = me;
4630
+ me.children = [copy, sibling];
4631
+ me = copy;
4632
+ } else {
4633
+ me.size -= sibling.size;
4634
+ me.height -= sibling.height;
4635
+ var myIndex = indexOf(me.parent.children, me);
4636
+ me.parent.children.splice(myIndex + 1, 0, sibling);
4637
+ }
4638
+ sibling.parent = me.parent;
4639
+ } while (me.children.length > 10);
4640
+ me.parent.maybeSpill();
4641
+ },
4642
+ iterN: function(at, n, op) {
4643
+ for (var i = 0, e = this.children.length; i < e; ++i) {
4644
+ var child = this.children[i], sz = child.chunkSize();
4645
+ if (at < sz) {
4646
+ var used = Math.min(n, sz - at);
4647
+ if (child.iterN(at, used, op)) return true;
4648
+ if ((n -= used) == 0) break;
4649
+ at = 0;
4650
+ } else at -= sz;
4651
+ }
4652
+ }
4653
+ };
4654
+
4655
+ var nextDocId = 0;
4656
+ var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
4657
+ if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4658
+ if (firstLine == null) firstLine = 0;
4659
+
4660
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4661
+ this.first = firstLine;
4662
+ this.scrollTop = this.scrollLeft = 0;
4663
+ this.cantEdit = false;
4664
+ this.history = makeHistory();
4665
+ this.cleanGeneration = 1;
4666
+ this.frontier = firstLine;
4667
+ var start = Pos(firstLine, 0);
4668
+ this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4669
+ this.id = ++nextDocId;
4670
+ this.modeOption = mode;
4671
+
4672
+ if (typeof text == "string") text = splitLines(text);
4673
+ updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
4674
+ };
4675
+
4676
+ Doc.prototype = createObj(BranchChunk.prototype, {
4677
+ constructor: Doc,
4678
+ iter: function(from, to, op) {
4679
+ if (op) this.iterN(from - this.first, to - from, op);
4680
+ else this.iterN(this.first, this.first + this.size, from);
4681
+ },
4682
+
4683
+ insert: function(at, lines) {
4684
+ var height = 0;
4685
+ for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
4686
+ this.insertInner(at - this.first, lines, height);
4687
+ },
4688
+ remove: function(at, n) { this.removeInner(at - this.first, n); },
4689
+
4690
+ getValue: function(lineSep) {
4691
+ var lines = getLines(this, this.first, this.first + this.size);
4692
+ if (lineSep === false) return lines;
4693
+ return lines.join(lineSep || "\n");
4694
+ },
4695
+ setValue: function(code) {
4696
+ var top = Pos(this.first, 0), last = this.first + this.size - 1;
4697
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
4698
+ text: splitLines(code), origin: "setValue"},
4699
+ {head: top, anchor: top}, true);
4700
+ },
4701
+ replaceRange: function(code, from, to, origin) {
4702
+ from = clipPos(this, from);
4703
+ to = to ? clipPos(this, to) : from;
4704
+ replaceRange(this, code, from, to, origin);
4705
+ },
4706
+ getRange: function(from, to, lineSep) {
4707
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
4708
+ if (lineSep === false) return lines;
4709
+ return lines.join(lineSep || "\n");
4710
+ },
4711
+
4712
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
4713
+ setLine: function(line, text) {
4714
+ if (isLine(this, line))
4715
+ replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
4716
+ },
4717
+ removeLine: function(line) {
4718
+ if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
4719
+ else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
4720
+ },
4721
+
4722
+ getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4723
+ getLineNumber: function(line) {return lineNo(line);},
4724
+
4725
+ getLineHandleVisualStart: function(line) {
4726
+ if (typeof line == "number") line = getLine(this, line);
4727
+ return visualLine(this, line);
4728
+ },
4729
+
4730
+ lineCount: function() {return this.size;},
4731
+ firstLine: function() {return this.first;},
4732
+ lastLine: function() {return this.first + this.size - 1;},
4733
+
4734
+ clipPos: function(pos) {return clipPos(this, pos);},
4735
+
4736
+ getCursor: function(start) {
4737
+ var sel = this.sel, pos;
4738
+ if (start == null || start == "head") pos = sel.head;
4739
+ else if (start == "anchor") pos = sel.anchor;
4740
+ else if (start == "end" || start === false) pos = sel.to;
4741
+ else pos = sel.from;
4742
+ return copyPos(pos);
4743
+ },
4744
+ somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
4745
+
4746
+ setCursor: docOperation(function(line, ch, extend) {
4747
+ var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
4748
+ if (extend) extendSelection(this, pos);
4749
+ else setSelection(this, pos, pos);
4750
+ }),
4751
+ setSelection: docOperation(function(anchor, head) {
4752
+ setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
4753
+ }),
4754
+ extendSelection: docOperation(function(from, to) {
4755
+ extendSelection(this, clipPos(this, from), to && clipPos(this, to));
4756
+ }),
4757
+
4758
+ getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
4759
+ replaceSelection: function(code, collapse, origin) {
4760
+ makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
4761
+ },
4762
+ undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
4763
+ redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
4764
+
4765
+ setExtending: function(val) {this.sel.extend = val;},
4766
+
4767
+ historySize: function() {
4768
+ var hist = this.history;
4769
+ return {undo: hist.done.length, redo: hist.undone.length};
4770
+ },
4771
+ clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4772
+
4773
+ markClean: function() {
4774
+ this.cleanGeneration = this.changeGeneration();
4775
+ },
4776
+ changeGeneration: function() {
4777
+ this.history.lastOp = this.history.lastOrigin = null;
4778
+ return this.history.generation;
4779
+ },
4780
+ isClean: function (gen) {
4781
+ return this.history.generation == (gen || this.cleanGeneration);
4782
+ },
4783
+
4784
+ getHistory: function() {
4785
+ return {done: copyHistoryArray(this.history.done),
4786
+ undone: copyHistoryArray(this.history.undone)};
4787
+ },
4788
+ setHistory: function(histData) {
4789
+ var hist = this.history = makeHistory(this.history.maxGeneration);
4790
+ hist.done = histData.done.slice(0);
4791
+ hist.undone = histData.undone.slice(0);
4792
+ },
4793
+
4794
+ markText: function(from, to, options) {
4795
+ return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
4796
+ },
4797
+ setBookmark: function(pos, options) {
4798
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4799
+ insertLeft: options && options.insertLeft};
4800
+ pos = clipPos(this, pos);
4801
+ return markText(this, pos, pos, realOpts, "bookmark");
4802
+ },
4803
+ findMarksAt: function(pos) {
4804
+ pos = clipPos(this, pos);
4805
+ var markers = [], spans = getLine(this, pos.line).markedSpans;
4806
+ if (spans) for (var i = 0; i < spans.length; ++i) {
4807
+ var span = spans[i];
4808
+ if ((span.from == null || span.from <= pos.ch) &&
4809
+ (span.to == null || span.to >= pos.ch))
4810
+ markers.push(span.marker.parent || span.marker);
4811
+ }
4812
+ return markers;
4813
+ },
4814
+ getAllMarks: function() {
4815
+ var markers = [];
4816
+ this.iter(function(line) {
4817
+ var sps = line.markedSpans;
4818
+ if (sps) for (var i = 0; i < sps.length; ++i)
4819
+ if (sps[i].from != null) markers.push(sps[i].marker);
4820
+ });
4821
+ return markers;
4822
+ },
4823
+
4824
+ posFromIndex: function(off) {
4825
+ var ch, lineNo = this.first;
4826
+ this.iter(function(line) {
4827
+ var sz = line.text.length + 1;
4828
+ if (sz > off) { ch = off; return true; }
4829
+ off -= sz;
4830
+ ++lineNo;
4831
+ });
4832
+ return clipPos(this, Pos(lineNo, ch));
4833
+ },
4834
+ indexFromPos: function (coords) {
4835
+ coords = clipPos(this, coords);
4836
+ var index = coords.ch;
4837
+ if (coords.line < this.first || coords.ch < 0) return 0;
4838
+ this.iter(this.first, coords.line, function (line) {
4839
+ index += line.text.length + 1;
4840
+ });
4841
+ return index;
4842
+ },
4843
+
4844
+ copy: function(copyHistory) {
4845
+ var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
4846
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
4847
+ doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
4848
+ shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
4849
+ if (copyHistory) {
4850
+ doc.history.undoDepth = this.history.undoDepth;
4851
+ doc.setHistory(this.getHistory());
4852
+ }
4853
+ return doc;
4854
+ },
4855
+
4856
+ linkedDoc: function(options) {
4857
+ if (!options) options = {};
4858
+ var from = this.first, to = this.first + this.size;
4859
+ if (options.from != null && options.from > from) from = options.from;
4860
+ if (options.to != null && options.to < to) to = options.to;
4861
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
4862
+ if (options.sharedHist) copy.history = this.history;
4863
+ (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
4864
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
4865
+ return copy;
4866
+ },
4867
+ unlinkDoc: function(other) {
4868
+ if (other instanceof CodeMirror) other = other.doc;
4869
+ if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
4870
+ var link = this.linked[i];
4871
+ if (link.doc != other) continue;
4872
+ this.linked.splice(i, 1);
4873
+ other.unlinkDoc(this);
4874
+ break;
4875
+ }
4876
+ // If the histories were shared, split them again
4877
+ if (other.history == this.history) {
4878
+ var splitIds = [other.id];
4879
+ linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
4880
+ other.history = makeHistory();
4881
+ other.history.done = copyHistoryArray(this.history.done, splitIds);
4882
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds);
4883
+ }
4884
+ },
4885
+ iterLinkedDocs: function(f) {linkedDocs(this, f);},
4886
+
4887
+ getMode: function() {return this.mode;},
4888
+ getEditor: function() {return this.cm;}
4889
+ });
4890
+
4891
+ Doc.prototype.eachLine = Doc.prototype.iter;
4892
+
4893
+ // The Doc methods that should be available on CodeMirror instances
4894
+ var dontDelegate = "iter insert remove copy getEditor".split(" ");
4895
+ for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
4896
+ CodeMirror.prototype[prop] = (function(method) {
4897
+ return function() {return method.apply(this.doc, arguments);};
4898
+ })(Doc.prototype[prop]);
4899
+
4900
+ eventMixin(Doc);
4901
+
4902
+ function linkedDocs(doc, f, sharedHistOnly) {
4903
+ function propagate(doc, skip, sharedHist) {
4904
+ if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
4905
+ var rel = doc.linked[i];
4906
+ if (rel.doc == skip) continue;
4907
+ var shared = sharedHist && rel.sharedHist;
4908
+ if (sharedHistOnly && !shared) continue;
4909
+ f(rel.doc, shared);
4910
+ propagate(rel.doc, doc, shared);
4911
+ }
4912
+ }
4913
+ propagate(doc, null, true);
4914
+ }
4915
+
4916
+ function attachDoc(cm, doc) {
4917
+ if (doc.cm) throw new Error("This document is already in use.");
4918
+ cm.doc = doc;
4919
+ doc.cm = cm;
4920
+ estimateLineHeights(cm);
4921
+ loadMode(cm);
4922
+ if (!cm.options.lineWrapping) computeMaxLength(cm);
4923
+ cm.options.mode = doc.modeOption;
4924
+ regChange(cm);
4925
+ }
4926
+
4927
+ // LINE UTILITIES
4928
+
4929
+ function getLine(chunk, n) {
4930
+ n -= chunk.first;
4931
+ while (!chunk.lines) {
4932
+ for (var i = 0;; ++i) {
4933
+ var child = chunk.children[i], sz = child.chunkSize();
4934
+ if (n < sz) { chunk = child; break; }
4935
+ n -= sz;
4936
+ }
4937
+ }
4938
+ return chunk.lines[n];
4939
+ }
4940
+
4941
+ function getBetween(doc, start, end) {
4942
+ var out = [], n = start.line;
4943
+ doc.iter(start.line, end.line + 1, function(line) {
4944
+ var text = line.text;
4945
+ if (n == end.line) text = text.slice(0, end.ch);
4946
+ if (n == start.line) text = text.slice(start.ch);
4947
+ out.push(text);
4948
+ ++n;
4949
+ });
4950
+ return out;
4951
+ }
4952
+ function getLines(doc, from, to) {
4953
+ var out = [];
4954
+ doc.iter(from, to, function(line) { out.push(line.text); });
4955
+ return out;
4956
+ }
4957
+
4958
+ function updateLineHeight(line, height) {
4959
+ var diff = height - line.height;
4960
+ for (var n = line; n; n = n.parent) n.height += diff;
4961
+ }
4962
+
4963
+ function lineNo(line) {
4964
+ if (line.parent == null) return null;
4965
+ var cur = line.parent, no = indexOf(cur.lines, line);
4966
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
4967
+ for (var i = 0;; ++i) {
4968
+ if (chunk.children[i] == cur) break;
4969
+ no += chunk.children[i].chunkSize();
4970
+ }
4971
+ }
4972
+ return no + cur.first;
4973
+ }
4974
+
4975
+ function lineAtHeight(chunk, h) {
4976
+ var n = chunk.first;
4977
+ outer: do {
4978
+ for (var i = 0, e = chunk.children.length; i < e; ++i) {
4979
+ var child = chunk.children[i], ch = child.height;
4980
+ if (h < ch) { chunk = child; continue outer; }
4981
+ h -= ch;
4982
+ n += child.chunkSize();
4983
+ }
4984
+ return n;
4985
+ } while (!chunk.lines);
4986
+ for (var i = 0, e = chunk.lines.length; i < e; ++i) {
4987
+ var line = chunk.lines[i], lh = line.height;
4988
+ if (h < lh) break;
4989
+ h -= lh;
4990
+ }
4991
+ return n + i;
4992
+ }
4993
+
4994
+ function heightAtLine(cm, lineObj) {
4995
+ lineObj = visualLine(cm.doc, lineObj);
4996
+
4997
+ var h = 0, chunk = lineObj.parent;
4998
+ for (var i = 0; i < chunk.lines.length; ++i) {
4999
+ var line = chunk.lines[i];
5000
+ if (line == lineObj) break;
5001
+ else h += line.height;
5002
+ }
5003
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
5004
+ for (var i = 0; i < p.children.length; ++i) {
5005
+ var cur = p.children[i];
5006
+ if (cur == chunk) break;
5007
+ else h += cur.height;
5008
+ }
5009
+ }
5010
+ return h;
5011
+ }
5012
+
5013
+ function getOrder(line) {
5014
+ var order = line.order;
5015
+ if (order == null) order = line.order = bidiOrdering(line.text);
5016
+ return order;
5017
+ }
5018
+
5019
+ // HISTORY
5020
+
5021
+ function makeHistory(startGen) {
5022
+ return {
5023
+ // Arrays of history events. Doing something adds an event to
5024
+ // done and clears undo. Undoing moves events from done to
5025
+ // undone, redoing moves them in the other direction.
5026
+ done: [], undone: [], undoDepth: Infinity,
5027
+ // Used to track when changes can be merged into a single undo
5028
+ // event
5029
+ lastTime: 0, lastOp: null, lastOrigin: null,
5030
+ // Used by the isClean() method
5031
+ generation: startGen || 1, maxGeneration: startGen || 1
5032
+ };
5033
+ }
5034
+
5035
+ function attachLocalSpans(doc, change, from, to) {
5036
+ var existing = change["spans_" + doc.id], n = 0;
5037
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
5038
+ if (line.markedSpans)
5039
+ (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
5040
+ ++n;
5041
+ });
5042
+ }
5043
+
5044
+ function historyChangeFromChange(doc, change) {
5045
+ var from = { line: change.from.line, ch: change.from.ch };
5046
+ var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5047
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
5048
+ linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
5049
+ return histChange;
5050
+ }
5051
+
5052
+ function addToHistory(doc, change, selAfter, opId) {
5053
+ var hist = doc.history;
5054
+ hist.undone.length = 0;
5055
+ var time = +new Date, cur = lst(hist.done);
5056
+
5057
+ if (cur &&
5058
+ (hist.lastOp == opId ||
5059
+ hist.lastOrigin == change.origin && change.origin &&
5060
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
5061
+ change.origin.charAt(0) == "*"))) {
5062
+ // Merge this change into the last event
5063
+ var last = lst(cur.changes);
5064
+ if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
5065
+ // Optimized case for simple insertion -- don't want to add
5066
+ // new changesets for every character typed
5067
+ last.to = changeEnd(change);
5068
+ } else {
5069
+ // Add new sub-event
5070
+ cur.changes.push(historyChangeFromChange(doc, change));
5071
+ }
5072
+ cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
5073
+ } else {
5074
+ // Can not be merged, start a new event.
5075
+ cur = {changes: [historyChangeFromChange(doc, change)],
5076
+ generation: hist.generation,
5077
+ anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5078
+ anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5079
+ hist.done.push(cur);
5080
+ hist.generation = ++hist.maxGeneration;
5081
+ while (hist.done.length > hist.undoDepth)
5082
+ hist.done.shift();
5083
+ }
5084
+ hist.lastTime = time;
5085
+ hist.lastOp = opId;
5086
+ hist.lastOrigin = change.origin;
5087
+ }
5088
+
5089
+ function removeClearedSpans(spans) {
5090
+ if (!spans) return null;
5091
+ for (var i = 0, out; i < spans.length; ++i) {
5092
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
5093
+ else if (out) out.push(spans[i]);
5094
+ }
5095
+ return !out ? spans : out.length ? out : null;
5096
+ }
5097
+
5098
+ function getOldSpans(doc, change) {
5099
+ var found = change["spans_" + doc.id];
5100
+ if (!found) return null;
5101
+ for (var i = 0, nw = []; i < change.text.length; ++i)
5102
+ nw.push(removeClearedSpans(found[i]));
5103
+ return nw;
5104
+ }
5105
+
5106
+ // Used both to provide a JSON-safe object in .getHistory, and, when
5107
+ // detaching a document, to split the history in two
5108
+ function copyHistoryArray(events, newGroup) {
5109
+ for (var i = 0, copy = []; i < events.length; ++i) {
5110
+ var event = events[i], changes = event.changes, newChanges = [];
5111
+ copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
5112
+ anchorAfter: event.anchorAfter, headAfter: event.headAfter});
5113
+ for (var j = 0; j < changes.length; ++j) {
5114
+ var change = changes[j], m;
5115
+ newChanges.push({from: change.from, to: change.to, text: change.text});
5116
+ if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
5117
+ if (indexOf(newGroup, Number(m[1])) > -1) {
5118
+ lst(newChanges)[prop] = change[prop];
5119
+ delete change[prop];
5120
+ }
5121
+ }
5122
+ }
5123
+ }
5124
+ return copy;
5125
+ }
5126
+
5127
+ // Rebasing/resetting history to deal with externally-sourced changes
5128
+
5129
+ function rebaseHistSel(pos, from, to, diff) {
5130
+ if (to < pos.line) {
5131
+ pos.line += diff;
5132
+ } else if (from < pos.line) {
5133
+ pos.line = from;
5134
+ pos.ch = 0;
5135
+ }
5136
+ }
5137
+
5138
+ // Tries to rebase an array of history events given a change in the
5139
+ // document. If the change touches the same lines as the event, the
5140
+ // event, and everything 'behind' it, is discarded. If the change is
5141
+ // before the event, the event's positions are updated. Uses a
5142
+ // copy-on-write scheme for the positions, to avoid having to
5143
+ // reallocate them all on every rebase, but also avoid problems with
5144
+ // shared position objects being unsafely updated.
5145
+ function rebaseHistArray(array, from, to, diff) {
5146
+ for (var i = 0; i < array.length; ++i) {
5147
+ var sub = array[i], ok = true;
5148
+ for (var j = 0; j < sub.changes.length; ++j) {
5149
+ var cur = sub.changes[j];
5150
+ if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
5151
+ if (to < cur.from.line) {
5152
+ cur.from.line += diff;
5153
+ cur.to.line += diff;
5154
+ } else if (from <= cur.to.line) {
5155
+ ok = false;
5156
+ break;
5157
+ }
5158
+ }
5159
+ if (!sub.copied) {
5160
+ sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
5161
+ sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
5162
+ sub.copied = true;
5163
+ }
5164
+ if (!ok) {
5165
+ array.splice(0, i + 1);
5166
+ i = 0;
5167
+ } else {
5168
+ rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
5169
+ rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
5170
+ }
5171
+ }
5172
+ }
5173
+
5174
+ function rebaseHist(hist, change) {
5175
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5176
+ rebaseHistArray(hist.done, from, to, diff);
5177
+ rebaseHistArray(hist.undone, from, to, diff);
5178
+ }
5179
+
5180
+ // EVENT OPERATORS
5181
+
5182
+ function stopMethod() {e_stop(this);}
5183
+ // Ensure an event has a stop method.
5184
+ function addStop(event) {
5185
+ if (!event.stop) event.stop = stopMethod;
5186
+ return event;
5187
+ }
5188
+
5189
+ function e_preventDefault(e) {
5190
+ if (e.preventDefault) e.preventDefault();
5191
+ else e.returnValue = false;
5192
+ }
5193
+ function e_stopPropagation(e) {
5194
+ if (e.stopPropagation) e.stopPropagation();
5195
+ else e.cancelBubble = true;
5196
+ }
5197
+ function e_defaultPrevented(e) {
5198
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5199
+ }
5200
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5201
+ CodeMirror.e_stop = e_stop;
5202
+ CodeMirror.e_preventDefault = e_preventDefault;
5203
+ CodeMirror.e_stopPropagation = e_stopPropagation;
5204
+
5205
+ function e_target(e) {return e.target || e.srcElement;}
5206
+ function e_button(e) {
5207
+ var b = e.which;
5208
+ if (b == null) {
5209
+ if (e.button & 1) b = 1;
5210
+ else if (e.button & 2) b = 3;
5211
+ else if (e.button & 4) b = 2;
5212
+ }
5213
+ if (mac && e.ctrlKey && b == 1) b = 3;
5214
+ return b;
5215
+ }
5216
+
5217
+ // EVENT HANDLING
5218
+
5219
+ function on(emitter, type, f) {
5220
+ if (emitter.addEventListener)
5221
+ emitter.addEventListener(type, f, false);
5222
+ else if (emitter.attachEvent)
5223
+ emitter.attachEvent("on" + type, f);
5224
+ else {
5225
+ var map = emitter._handlers || (emitter._handlers = {});
5226
+ var arr = map[type] || (map[type] = []);
5227
+ arr.push(f);
5228
+ }
5229
+ }
5230
+
5231
+ function off(emitter, type, f) {
5232
+ if (emitter.removeEventListener)
5233
+ emitter.removeEventListener(type, f, false);
5234
+ else if (emitter.detachEvent)
5235
+ emitter.detachEvent("on" + type, f);
5236
+ else {
5237
+ var arr = emitter._handlers && emitter._handlers[type];
5238
+ if (!arr) return;
5239
+ for (var i = 0; i < arr.length; ++i)
5240
+ if (arr[i] == f) { arr.splice(i, 1); break; }
5241
+ }
5242
+ }
5243
+
5244
+ function signal(emitter, type /*, values...*/) {
5245
+ var arr = emitter._handlers && emitter._handlers[type];
5246
+ if (!arr) return;
5247
+ var args = Array.prototype.slice.call(arguments, 2);
5248
+ for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
5249
+ }
5250
+
5251
+ var delayedCallbacks, delayedCallbackDepth = 0;
5252
+ function signalLater(emitter, type /*, values...*/) {
5253
+ var arr = emitter._handlers && emitter._handlers[type];
5254
+ if (!arr) return;
5255
+ var args = Array.prototype.slice.call(arguments, 2);
5256
+ if (!delayedCallbacks) {
5257
+ ++delayedCallbackDepth;
5258
+ delayedCallbacks = [];
5259
+ setTimeout(fireDelayed, 0);
5260
+ }
5261
+ function bnd(f) {return function(){f.apply(null, args);};};
5262
+ for (var i = 0; i < arr.length; ++i)
5263
+ delayedCallbacks.push(bnd(arr[i]));
5264
+ }
5265
+
5266
+ function signalDOMEvent(cm, e, override) {
5267
+ signal(cm, override || e.type, cm, e);
5268
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
5269
+ }
5270
+
5271
+ function fireDelayed() {
5272
+ --delayedCallbackDepth;
5273
+ var delayed = delayedCallbacks;
5274
+ delayedCallbacks = null;
5275
+ for (var i = 0; i < delayed.length; ++i) delayed[i]();
5276
+ }
5277
+
5278
+ function hasHandler(emitter, type) {
5279
+ var arr = emitter._handlers && emitter._handlers[type];
5280
+ return arr && arr.length > 0;
5281
+ }
5282
+
5283
+ CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
5284
+
5285
+ function eventMixin(ctor) {
5286
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
5287
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
5288
+ }
5289
+
5290
+ // MISC UTILITIES
5291
+
5292
+ // Number of pixels added to scroller and sizer to hide scrollbar
5293
+ var scrollerCutOff = 30;
5294
+
5295
+ // Returned or thrown by various protocols to signal 'I'm not
5296
+ // handling this'.
5297
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
5298
+
5299
+ function Delayed() {this.id = null;}
5300
+ Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
5301
+
5302
+ // Counts the column offset in a string, taking tabs into account.
5303
+ // Used mostly to find indentation.
5304
+ function countColumn(string, end, tabSize, startIndex, startValue) {
5305
+ if (end == null) {
5306
+ end = string.search(/[^\s\u00a0]/);
5307
+ if (end == -1) end = string.length;
5308
+ }
5309
+ for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
5310
+ if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
5311
+ else ++n;
5312
+ }
5313
+ return n;
5314
+ }
5315
+ CodeMirror.countColumn = countColumn;
5316
+
5317
+ var spaceStrs = [""];
5318
+ function spaceStr(n) {
5319
+ while (spaceStrs.length <= n)
5320
+ spaceStrs.push(lst(spaceStrs) + " ");
5321
+ return spaceStrs[n];
5322
+ }
5323
+
5324
+ function lst(arr) { return arr[arr.length-1]; }
5325
+
5326
+ function selectInput(node) {
5327
+ if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5328
+ node.selectionStart = 0;
5329
+ node.selectionEnd = node.value.length;
5330
+ } else {
5331
+ // Suppress mysterious IE10 errors
5332
+ try { node.select(); }
5333
+ catch(_e) {}
5334
+ }
5335
+ }
5336
+
5337
+ function indexOf(collection, elt) {
5338
+ if (collection.indexOf) return collection.indexOf(elt);
5339
+ for (var i = 0, e = collection.length; i < e; ++i)
5340
+ if (collection[i] == elt) return i;
5341
+ return -1;
5342
+ }
5343
+
5344
+ function createObj(base, props) {
5345
+ function Obj() {}
5346
+ Obj.prototype = base;
5347
+ var inst = new Obj();
5348
+ if (props) copyObj(props, inst);
5349
+ return inst;
5350
+ }
5351
+
5352
+ function copyObj(obj, target) {
5353
+ if (!target) target = {};
5354
+ for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
5355
+ return target;
5356
+ }
5357
+
5358
+ function emptyArray(size) {
5359
+ for (var a = [], i = 0; i < size; ++i) a.push(undefined);
5360
+ return a;
5361
+ }
5362
+
5363
+ function bind(f) {
5364
+ var args = Array.prototype.slice.call(arguments, 1);
5365
+ return function(){return f.apply(null, args);};
5366
+ }
5367
+
5368
+ var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
5369
+ function isWordChar(ch) {
5370
+ return /\w/.test(ch) || ch > "\x80" &&
5371
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
5372
+ }
5373
+
5374
+ function isEmpty(obj) {
5375
+ for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
5376
+ return true;
5377
+ }
5378
+
5379
+ 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]/;
5380
+
5381
+ // DOM UTILITIES
5382
+
5383
+ function elt(tag, content, className, style) {
5384
+ var e = document.createElement(tag);
5385
+ if (className) e.className = className;
5386
+ if (style) e.style.cssText = style;
5387
+ if (typeof content == "string") setTextContent(e, content);
5388
+ else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
5389
+ return e;
5390
+ }
5391
+
5392
+ function removeChildren(e) {
5393
+ for (var count = e.childNodes.length; count > 0; --count)
5394
+ e.removeChild(e.firstChild);
5395
+ return e;
5396
+ }
5397
+
5398
+ function removeChildrenAndAdd(parent, e) {
5399
+ return removeChildren(parent).appendChild(e);
5400
+ }
5401
+
5402
+ function setTextContent(e, str) {
5403
+ if (ie_lt9) {
5404
+ e.innerHTML = "";
5405
+ e.appendChild(document.createTextNode(str));
5406
+ } else e.textContent = str;
5407
+ }
5408
+
5409
+ function getRect(node) {
5410
+ return node.getBoundingClientRect();
5411
+ }
5412
+ CodeMirror.replaceGetRect = function(f) { getRect = f; };
5413
+
5414
+ // FEATURE DETECTION
5415
+
5416
+ // Detect drag-and-drop
5417
+ var dragAndDrop = function() {
5418
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
5419
+ // couldn't get it to work yet.
5420
+ if (ie_lt9) return false;
5421
+ var div = elt('div');
5422
+ return "draggable" in div || "dragDrop" in div;
5423
+ }();
5424
+
5425
+ // For a reason I have yet to figure out, some browsers disallow
5426
+ // word wrapping between certain characters *only* if a new inline
5427
+ // element is started between them. This makes it hard to reliably
5428
+ // measure the position of things, since that requires inserting an
5429
+ // extra span. This terribly fragile set of tests matches the
5430
+ // character combinations that suffer from this phenomenon on the
5431
+ // various browsers.
5432
+ function spanAffectsWrapping() { return false; }
5433
+ if (gecko) // Only for "$'"
5434
+ spanAffectsWrapping = function(str, i) {
5435
+ return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
5436
+ };
5437
+ else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
5438
+ spanAffectsWrapping = function(str, i) {
5439
+ return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5440
+ };
5441
+ else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
5442
+ spanAffectsWrapping = function(str, i) {
5443
+ if (i > 1 && str.charCodeAt(i - 1) == 45) {
5444
+ if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5445
+ if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5446
+ }
5447
+ return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5448
+ };
5449
+
5450
+ var knownScrollbarWidth;
5451
+ function scrollbarWidth(measure) {
5452
+ if (knownScrollbarWidth != null) return knownScrollbarWidth;
5453
+ var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
5454
+ removeChildrenAndAdd(measure, test);
5455
+ if (test.offsetWidth)
5456
+ knownScrollbarWidth = test.offsetHeight - test.clientHeight;
5457
+ return knownScrollbarWidth || 0;
5458
+ }
5459
+
5460
+ var zwspSupported;
5461
+ function zeroWidthElement(measure) {
5462
+ if (zwspSupported == null) {
5463
+ var test = elt("span", "\u200b");
5464
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
5465
+ if (measure.firstChild.offsetHeight != 0)
5466
+ zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
5467
+ }
5468
+ if (zwspSupported) return elt("span", "\u200b");
5469
+ else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
5470
+ }
5471
+
5472
+ // See if "".split is the broken IE version, if so, provide an
5473
+ // alternative way to split lines.
5474
+ var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
5475
+ var pos = 0, result = [], l = string.length;
5476
+ while (pos <= l) {
5477
+ var nl = string.indexOf("\n", pos);
5478
+ if (nl == -1) nl = string.length;
5479
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
5480
+ var rt = line.indexOf("\r");
5481
+ if (rt != -1) {
5482
+ result.push(line.slice(0, rt));
5483
+ pos += rt + 1;
5484
+ } else {
5485
+ result.push(line);
5486
+ pos = nl + 1;
5487
+ }
5488
+ }
5489
+ return result;
5490
+ } : function(string){return string.split(/\r\n?|\n/);};
5491
+ CodeMirror.splitLines = splitLines;
5492
+
5493
+ var hasSelection = window.getSelection ? function(te) {
5494
+ try { return te.selectionStart != te.selectionEnd; }
5495
+ catch(e) { return false; }
5496
+ } : function(te) {
5497
+ try {var range = te.ownerDocument.selection.createRange();}
5498
+ catch(e) {}
5499
+ if (!range || range.parentElement() != te) return false;
5500
+ return range.compareEndPoints("StartToEnd", range) != 0;
5501
+ };
5502
+
5503
+ var hasCopyEvent = (function() {
5504
+ var e = elt("div");
5505
+ if ("oncopy" in e) return true;
5506
+ e.setAttribute("oncopy", "return;");
5507
+ return typeof e.oncopy == 'function';
5508
+ })();
5509
+
5510
+ // KEY NAMING
5511
+
5512
+ var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
5513
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
5514
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
5515
+ 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
5516
+ 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5517
+ 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
5518
+ 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
5519
+ CodeMirror.keyNames = keyNames;
5520
+ (function() {
5521
+ // Number keys
5522
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
5523
+ // Alphabetic keys
5524
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
5525
+ // Function keys
5526
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
5527
+ })();
5528
+
5529
+ // BIDI HELPERS
5530
+
5531
+ function iterateBidiSections(order, from, to, f) {
5532
+ if (!order) return f(from, to, "ltr");
5533
+ var found = false;
5534
+ for (var i = 0; i < order.length; ++i) {
5535
+ var part = order[i];
5536
+ if (part.from < to && part.to > from || from == to && part.to == from) {
5537
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5538
+ found = true;
5539
+ }
5540
+ }
5541
+ if (!found) f(from, to, "ltr");
5542
+ }
5543
+
5544
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
5545
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
5546
+
5547
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
5548
+ function lineRight(line) {
5549
+ var order = getOrder(line);
5550
+ if (!order) return line.text.length;
5551
+ return bidiRight(lst(order));
5552
+ }
5553
+
5554
+ function lineStart(cm, lineN) {
5555
+ var line = getLine(cm.doc, lineN);
5556
+ var visual = visualLine(cm.doc, line);
5557
+ if (visual != line) lineN = lineNo(visual);
5558
+ var order = getOrder(visual);
5559
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
5560
+ return Pos(lineN, ch);
5561
+ }
5562
+ function lineEnd(cm, lineN) {
5563
+ var merged, line;
5564
+ while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
5565
+ lineN = merged.find().to.line;
5566
+ var order = getOrder(line);
5567
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
5568
+ return Pos(lineN, ch);
5569
+ }
5570
+
5571
+ function compareBidiLevel(order, a, b) {
5572
+ var linedir = order[0].level;
5573
+ if (a == linedir) return true;
5574
+ if (b == linedir) return false;
5575
+ return a < b;
5576
+ }
5577
+ var bidiOther;
5578
+ function getBidiPartAt(order, pos) {
5579
+ for (var i = 0, found; i < order.length; ++i) {
5580
+ var cur = order[i];
5581
+ if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5582
+ if (cur.from == pos || cur.to == pos) {
5583
+ if (found == null) {
5584
+ found = i;
5585
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5586
+ bidiOther = found;
5587
+ return i;
5588
+ } else {
5589
+ bidiOther = i;
5590
+ return found;
5591
+ }
5592
+ }
5593
+ }
5594
+ bidiOther = null;
5595
+ return found;
5596
+ }
5597
+
5598
+ function moveInLine(line, pos, dir, byUnit) {
5599
+ if (!byUnit) return pos + dir;
5600
+ do pos += dir;
5601
+ while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5602
+ return pos;
5603
+ }
5604
+
5605
+ // This is somewhat involved. It is needed in order to move
5606
+ // 'visually' through bi-directional text -- i.e., pressing left
5607
+ // should make the cursor go left, even when in RTL text. The
5608
+ // tricky part is the 'jumps', where RTL and LTR text touch each
5609
+ // other. This often requires the cursor offset to move more than
5610
+ // one unit, in order to visually move one unit.
5611
+ function moveVisually(line, start, dir, byUnit) {
5612
+ var bidi = getOrder(line);
5613
+ if (!bidi) return moveLogically(line, start, dir, byUnit);
5614
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5615
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5616
+
5617
+ for (;;) {
5618
+ if (target > part.from && target < part.to) return target;
5619
+ if (target == part.from || target == part.to) {
5620
+ if (getBidiPartAt(bidi, target) == pos) return target;
5621
+ part = bidi[pos += dir];
5622
+ return (dir > 0) == part.level % 2 ? part.to : part.from;
5623
+ } else {
5624
+ part = bidi[pos += dir];
5625
+ if (!part) return null;
5626
+ if ((dir > 0) == part.level % 2)
5627
+ target = moveInLine(line, part.to, -1, byUnit);
5628
+ else
5629
+ target = moveInLine(line, part.from, 1, byUnit);
5630
+ }
5631
+ }
5632
+ }
5633
+
5634
+ function moveLogically(line, start, dir, byUnit) {
5635
+ var target = start + dir;
5636
+ if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
5637
+ return target < 0 || target > line.text.length ? null : target;
5638
+ }
5639
+
5640
+ // Bidirectional ordering algorithm
5641
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
5642
+ // that this (partially) implements.
5643
+
5644
+ // One-char codes used for character types:
5645
+ // L (L): Left-to-Right
5646
+ // R (R): Right-to-Left
5647
+ // r (AL): Right-to-Left Arabic
5648
+ // 1 (EN): European Number
5649
+ // + (ES): European Number Separator
5650
+ // % (ET): European Number Terminator
5651
+ // n (AN): Arabic Number
5652
+ // , (CS): Common Number Separator
5653
+ // m (NSM): Non-Spacing Mark
5654
+ // b (BN): Boundary Neutral
5655
+ // s (B): Paragraph Separator
5656
+ // t (S): Segment Separator
5657
+ // w (WS): Whitespace
5658
+ // N (ON): Other Neutrals
5659
+
5660
+ // Returns null if characters are ordered as they appear
5661
+ // (left-to-right), or an array of sections ({from, to, level}
5662
+ // objects) in the order in which they occur visually.
5663
+ var bidiOrdering = (function() {
5664
+ // Character types for codepoints 0 to 0xff
5665
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
5666
+ // Character types for codepoints 0x600 to 0x6ff
5667
+ var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
5668
+ function charType(code) {
5669
+ if (code <= 0xff) return lowTypes.charAt(code);
5670
+ else if (0x590 <= code && code <= 0x5f4) return "R";
5671
+ else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
5672
+ else if (0x700 <= code && code <= 0x8ac) return "r";
5673
+ else return "L";
5674
+ }
5675
+
5676
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
5677
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
5678
+ // Browsers seem to always treat the boundaries of block elements as being L.
5679
+ var outerType = "L";
5680
+
5681
+ return function(str) {
5682
+ if (!bidiRE.test(str)) return false;
5683
+ var len = str.length, types = [];
5684
+ for (var i = 0, type; i < len; ++i)
5685
+ types.push(type = charType(str.charCodeAt(i)));
5686
+
5687
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
5688
+ // change the type of the NSM to the type of the previous
5689
+ // character. If the NSM is at the start of the level run, it will
5690
+ // get the type of sor.
5691
+ for (var i = 0, prev = outerType; i < len; ++i) {
5692
+ var type = types[i];
5693
+ if (type == "m") types[i] = prev;
5694
+ else prev = type;
5695
+ }
5696
+
5697
+ // W2. Search backwards from each instance of a European number
5698
+ // until the first strong type (R, L, AL, or sor) is found. If an
5699
+ // AL is found, change the type of the European number to Arabic
5700
+ // number.
5701
+ // W3. Change all ALs to R.
5702
+ for (var i = 0, cur = outerType; i < len; ++i) {
5703
+ var type = types[i];
5704
+ if (type == "1" && cur == "r") types[i] = "n";
5705
+ else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
5706
+ }
5707
+
5708
+ // W4. A single European separator between two European numbers
5709
+ // changes to a European number. A single common separator between
5710
+ // two numbers of the same type changes to that type.
5711
+ for (var i = 1, prev = types[0]; i < len - 1; ++i) {
5712
+ var type = types[i];
5713
+ if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
5714
+ else if (type == "," && prev == types[i+1] &&
5715
+ (prev == "1" || prev == "n")) types[i] = prev;
5716
+ prev = type;
5717
+ }
5718
+
5719
+ // W5. A sequence of European terminators adjacent to European
5720
+ // numbers changes to all European numbers.
5721
+ // W6. Otherwise, separators and terminators change to Other
5722
+ // Neutral.
5723
+ for (var i = 0; i < len; ++i) {
5724
+ var type = types[i];
5725
+ if (type == ",") types[i] = "N";
5726
+ else if (type == "%") {
5727
+ for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
5728
+ var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
5729
+ for (var j = i; j < end; ++j) types[j] = replace;
5730
+ i = end - 1;
5731
+ }
5732
+ }
5733
+
5734
+ // W7. Search backwards from each instance of a European number
5735
+ // until the first strong type (R, L, or sor) is found. If an L is
5736
+ // found, then change the type of the European number to L.
5737
+ for (var i = 0, cur = outerType; i < len; ++i) {
5738
+ var type = types[i];
5739
+ if (cur == "L" && type == "1") types[i] = "L";
5740
+ else if (isStrong.test(type)) cur = type;
5741
+ }
5742
+
5743
+ // N1. A sequence of neutrals takes the direction of the
5744
+ // surrounding strong text if the text on both sides has the same
5745
+ // direction. European and Arabic numbers act as if they were R in
5746
+ // terms of their influence on neutrals. Start-of-level-run (sor)
5747
+ // and end-of-level-run (eor) are used at level run boundaries.
5748
+ // N2. Any remaining neutrals take the embedding direction.
5749
+ for (var i = 0; i < len; ++i) {
5750
+ if (isNeutral.test(types[i])) {
5751
+ for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5752
+ var before = (i ? types[i-1] : outerType) == "L";
5753
+ var after = (end < len - 1 ? types[end] : outerType) == "L";
5754
+ var replace = before || after ? "L" : "R";
5755
+ for (var j = i; j < end; ++j) types[j] = replace;
5756
+ i = end - 1;
5757
+ }
5758
+ }
5759
+
5760
+ // Here we depart from the documented algorithm, in order to avoid
5761
+ // building up an actual levels array. Since there are only three
5762
+ // levels (0, 1, 2) in an implementation that doesn't take
5763
+ // explicit embedding into account, we can build up the order on
5764
+ // the fly, without following the level-based algorithm.
5765
+ var order = [], m;
5766
+ for (var i = 0; i < len;) {
5767
+ if (countsAsLeft.test(types[i])) {
5768
+ var start = i;
5769
+ for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
5770
+ order.push({from: start, to: i, level: 0});
5771
+ } else {
5772
+ var pos = i, at = order.length;
5773
+ for (++i; i < len && types[i] != "L"; ++i) {}
5774
+ for (var j = pos; j < i;) {
5775
+ if (countsAsNum.test(types[j])) {
5776
+ if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
5777
+ var nstart = j;
5778
+ for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
5779
+ order.splice(at, 0, {from: nstart, to: j, level: 2});
5780
+ pos = j;
5781
+ } else ++j;
5782
+ }
5783
+ if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
5784
+ }
5785
+ }
5786
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
5787
+ order[0].from = m[0].length;
5788
+ order.unshift({from: 0, to: m[0].length, level: 0});
5789
+ }
5790
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
5791
+ lst(order).to -= m[0].length;
5792
+ order.push({from: len - m[0].length, to: len, level: 0});
5793
+ }
5794
+ if (order[0].level != lst(order).level)
5795
+ order.push({from: len, to: len, level: order[0].level});
5796
+
5797
+ return order;
5798
+ };
5799
+ })();
5800
+
5801
+ // THE END
5802
+
5803
+ CodeMirror.version = "3.15.0";
5804
+
5805
+ return CodeMirror;
5806
+ })();
plugin-fw/assets/js/codemirror/javascript.js CHANGED
@@ -1,630 +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 });
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/how-to.js CHANGED
@@ -1,6 +1,6 @@
1
- (function ( $ ) {
2
- var how_to_link = $( '#yith-how-to-premium' ).parent();
3
- if ( typeof how_to_link != 'undefined' ) {
4
- how_to_link.prop( 'target', '_blank' );
5
- }
6
- })( jQuery );
1
+ (function ( $ ) {
2
+ var how_to_link = $( '#yith-how-to-premium' ).parent();
3
+ if ( typeof how_to_link != 'undefined' ) {
4
+ how_to_link.prop( 'target', '_blank' );
5
+ }
6
+ })( jQuery );
plugin-fw/assets/js/jquery-tiptip/jquery.tipTip.js CHANGED
@@ -1,191 +1,191 @@
1
- /*
2
- * TipTip
3
- * Copyright 2010 Drew Wilson
4
- * www.drewwilson.com
5
- * code.drewwilson.com/entry/tiptip-jquery-plugin
6
- *
7
- * Version 1.3 - Updated: Mar. 23, 2010
8
- *
9
- * This Plug-In will create a custom tooltip to replace the default
10
- * browser tooltip. It is extremely lightweight and very smart in
11
- * that it detects the edges of the browser window and will make sure
12
- * the tooltip stays within the current window size. As a result the
13
- * tooltip will adjust itself to be displayed above, below, to the left
14
- * or to the right depending on what is necessary to stay within the
15
- * browser window. It is completely customizable as well via CSS.
16
- *
17
- * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
18
- * http://www.opensource.org/licenses/mit-license.php
19
- * http://www.gnu.org/licenses/gpl.html
20
- */
21
-
22
- (function($){
23
- $.fn.tipTip = function(options) {
24
- var defaults = {
25
- activation: "hover",
26
- keepAlive: false,
27
- maxWidth: "200px",
28
- edgeOffset: 3,
29
- defaultPosition: "bottom",
30
- delay: 400,
31
- fadeIn: 200,
32
- fadeOut: 200,
33
- attribute: "title",
34
- content: false, // HTML or String to fill TipTIp with
35
- enter: function(){},
36
- exit: function(){}
37
- };
38
- var opts = $.extend(defaults, options);
39
-
40
- // Setup tip tip elements and render them to the DOM
41
- if($("#tiptip_holder").length <= 0){
42
- var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
43
- var tiptip_content = $('<div id="tiptip_content"></div>');
44
- var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
45
- $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
46
- } else {
47
- var tiptip_holder = $("#tiptip_holder");
48
- var tiptip_content = $("#tiptip_content");
49
- var tiptip_arrow = $("#tiptip_arrow");
50
- }
51
-
52
- return this.each(function(){
53
- var org_elem = $(this);
54
- if(opts.content){
55
- var org_title = opts.content;
56
- } else {
57
- var org_title = org_elem.attr(opts.attribute);
58
- }
59
- if(org_title != ""){
60
- if(!opts.content){
61
- org_elem.removeAttr(opts.attribute); //remove original Attribute
62
- }
63
- var timeout = false;
64
-
65
- if(opts.activation == "hover"){
66
- org_elem.hover(function(){
67
- active_tiptip();
68
- }, function(){
69
- if(!opts.keepAlive || !tiptip_holder.is(':hover')){
70
- deactive_tiptip();
71
- }
72
- });
73
- if(opts.keepAlive){
74
- tiptip_holder.hover(function(){}, function(){
75
- deactive_tiptip();
76
- });
77
- }
78
- } else if(opts.activation == "focus"){
79
- org_elem.focus(function(){
80
- active_tiptip();
81
- }).blur(function(){
82
- deactive_tiptip();
83
- });
84
- } else if(opts.activation == "click"){
85
- org_elem.click(function(){
86
- active_tiptip();
87
- return false;
88
- }).hover(function(){},function(){
89
- if(!opts.keepAlive){
90
- deactive_tiptip();
91
- }
92
- });
93
- if(opts.keepAlive){
94
- tiptip_holder.hover(function(){}, function(){
95
- deactive_tiptip();
96
- });
97
- }
98
- }
99
-
100
- function active_tiptip(){
101
- opts.enter.call(this);
102
- tiptip_content.html(org_title);
103
- tiptip_holder.hide().removeAttr("class").css("margin","0");
104
- tiptip_arrow.removeAttr("style");
105
-
106
- var top = parseInt(org_elem.offset()['top']);
107
- var left = parseInt(org_elem.offset()['left']);
108
- var org_width = parseInt(org_elem.outerWidth());
109
- var org_height = parseInt(org_elem.outerHeight());
110
- var tip_w = tiptip_holder.outerWidth();
111
- var tip_h = tiptip_holder.outerHeight();
112
- var w_compare = Math.round((org_width - tip_w) / 2);
113
- var h_compare = Math.round((org_height - tip_h) / 2);
114
- var marg_left = Math.round(left + w_compare);
115
- var marg_top = Math.round(top + org_height + opts.edgeOffset);
116
- var t_class = "";
117
- var arrow_top = "";
118
- var arrow_left = Math.round(tip_w - 12) / 2;
119
-
120
- if(opts.defaultPosition == "bottom"){
121
- t_class = "_bottom";
122
- } else if(opts.defaultPosition == "top"){
123
- t_class = "_top";
124
- } else if(opts.defaultPosition == "left"){
125
- t_class = "_left";
126
- } else if(opts.defaultPosition == "right"){
127
- t_class = "_right";
128
- }
129
-
130
- var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
131
- var left_compare = (tip_w + left) > parseInt($(window).width());
132
-
133
- if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
134
- t_class = "_right";
135
- arrow_top = Math.round(tip_h - 13) / 2;
136
- arrow_left = -12;
137
- marg_left = Math.round(left + org_width + opts.edgeOffset);
138
- marg_top = Math.round(top + h_compare);
139
- } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
140
- t_class = "_left";
141
- arrow_top = Math.round(tip_h - 13) / 2;
142
- arrow_left = Math.round(tip_w);
143
- marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
144
- marg_top = Math.round(top + h_compare);
145
- }
146
-
147
- var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
148
- var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
149
-
150
- if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
151
- if(t_class == "_top" || t_class == "_bottom"){
152
- t_class = "_top";
153
- } else {
154
- t_class = t_class+"_top";
155
- }
156
- arrow_top = tip_h;
157
- marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
158
- } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
159
- if(t_class == "_top" || t_class == "_bottom"){
160
- t_class = "_bottom";
161
- } else {
162
- t_class = t_class+"_bottom";
163
- }
164
- arrow_top = -12;
165
- marg_top = Math.round(top + org_height + opts.edgeOffset);
166
- }
167
-
168
- if(t_class == "_right_top" || t_class == "_left_top"){
169
- marg_top = marg_top + 5;
170
- } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
171
- marg_top = marg_top - 5;
172
- }
173
- if(t_class == "_left_top" || t_class == "_left_bottom"){
174
- marg_left = marg_left + 5;
175
- }
176
- tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
177
- tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
178
-
179
- if (timeout){ clearTimeout(timeout); }
180
- timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
181
- }
182
-
183
- function deactive_tiptip(){
184
- opts.exit.call(this);
185
- if (timeout){ clearTimeout(timeout); }
186
- tiptip_holder.fadeOut(opts.fadeOut);
187
- }
188
- }
189
- });
190
- }
191
- })(jQuery);
1
+ /*
2
+ * TipTip
3
+ * Copyright 2010 Drew Wilson
4
+ * www.drewwilson.com
5
+ * code.drewwilson.com/entry/tiptip-jquery-plugin
6
+ *
7
+ * Version 1.3 - Updated: Mar. 23, 2010
8
+ *
9
+ * This Plug-In will create a custom tooltip to replace the default
10
+ * browser tooltip. It is extremely lightweight and very smart in
11
+ * that it detects the edges of the browser window and will make sure
12
+ * the tooltip stays within the current window size. As a result the
13
+ * tooltip will adjust itself to be displayed above, below, to the left
14
+ * or to the right depending on what is necessary to stay within the
15
+ * browser window. It is completely customizable as well via CSS.
16
+ *
17
+ * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
18
+ * http://www.opensource.org/licenses/mit-license.php
19
+ * http://www.gnu.org/licenses/gpl.html
20
+ */
21
+
22
+ (function($){
23
+ $.fn.tipTip = function(options) {
24
+ var defaults = {
25
+ activation: "hover",
26
+ keepAlive: false,
27
+ maxWidth: "200px",
28
+ edgeOffset: 3,
29
+ defaultPosition: "bottom",
30
+ delay: 400,
31
+ fadeIn: 200,
32
+ fadeOut: 200,
33
+ attribute: "title",
34
+ content: false, // HTML or String to fill TipTIp with
35
+ enter: function(){},
36
+ exit: function(){}
37
+ };
38
+ var opts = $.extend(defaults, options);
39
+
40
+ // Setup tip tip elements and render them to the DOM
41
+ if($("#tiptip_holder").length <= 0){
42
+ var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
43
+ var tiptip_content = $('<div id="tiptip_content"></div>');
44
+ var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
45
+ $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
46
+ } else {
47
+ var tiptip_holder = $("#tiptip_holder");
48
+ var tiptip_content = $("#tiptip_content");
49
+ var tiptip_arrow = $("#tiptip_arrow");
50
+ }
51
+
52
+ return this.each(function(){
53
+ var org_elem = $(this);
54
+ if(opts.content){
55
+ var org_title = opts.content;
56
+ } else {
57
+ var org_title = org_elem.attr(opts.attribute);
58
+ }
59
+ if(org_title != ""){
60
+ if(!opts.content){
61
+ org_elem.removeAttr(opts.attribute); //remove original Attribute
62
+ }
63
+ var timeout = false;
64
+
65
+ if(opts.activation == "hover"){
66
+ org_elem.hover(function(){
67
+ active_tiptip();
68
+ }, function(){
69
+ if(!opts.keepAlive || !tiptip_holder.is(':hover')){
70
+ deactive_tiptip();
71
+ }
72
+ });
73
+ if(opts.keepAlive){
74
+ tiptip_holder.hover(function(){}, function(){
75
+ deactive_tiptip();
76
+ });
77
+ }
78
+ } else if(opts.activation == "focus"){
79
+ org_elem.focus(function(){
80
+ active_tiptip();
81
+ }).blur(function(){
82
+ deactive_tiptip();
83
+ });
84
+ } else if(opts.activation == "click"){
85
+ org_elem.click(function(){
86
+ active_tiptip();
87
+ return false;
88
+ }).hover(function(){},function(){
89
+ if(!opts.keepAlive){
90
+ deactive_tiptip();
91
+ }
92
+ });
93
+ if(opts.keepAlive){
94
+ tiptip_holder.hover(function(){}, function(){
95
+ deactive_tiptip();
96
+ });
97
+ }
98
+ }
99
+
100
+ function active_tiptip(){
101
+ opts.enter.call(this);
102
+ tiptip_content.html(org_title);
103
+ tiptip_holder.hide().removeAttr("class").css("margin","0");
104
+ tiptip_arrow.removeAttr("style");
105
+
106
+ var top = parseInt(org_elem.offset()['top']);
107
+ var left = parseInt(org_elem.offset()['left']);
108
+ var org_width = parseInt(org_elem.outerWidth());
109
+ var org_height = parseInt(org_elem.outerHeight());
110
+ var tip_w = tiptip_holder.outerWidth();
111
+ var tip_h = tiptip_holder.outerHeight();
112
+ var w_compare = Math.round((org_width - tip_w) / 2);
113
+ var h_compare = Math.round((org_height - tip_h) / 2);
114
+ var marg_left = Math.round(left + w_compare);
115
+ var marg_top = Math.round(top + org_height + opts.edgeOffset);
116
+ var t_class = "";
117
+ var arrow_top = "";
118
+ var arrow_left = Math.round(tip_w - 12) / 2;
119
+
120
+ if(opts.defaultPosition == "bottom"){
121
+ t_class = "_bottom";
122
+ } else if(opts.defaultPosition == "top"){
123
+ t_class = "_top";
124
+ } else if(opts.defaultPosition == "left"){
125
+ t_class = "_left";
126
+ } else if(opts.defaultPosition == "right"){
127
+ t_class = "_right";
128
+ }
129
+
130
+ var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
131
+ var left_compare = (tip_w + left) > parseInt($(window).width());
132
+
133
+ if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
134
+ t_class = "_right";
135
+ arrow_top = Math.round(tip_h - 13) / 2;
136
+ arrow_left = -12;
137
+ marg_left = Math.round(left + org_width + opts.edgeOffset);
138
+ marg_top = Math.round(top + h_compare);
139
+ } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
140
+ t_class = "_left";
141
+ arrow_top = Math.round(tip_h - 13) / 2;
142
+ arrow_left = Math.round(tip_w);
143
+ marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
144
+ marg_top = Math.round(top + h_compare);
145
+ }
146
+
147
+ var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
148
+ var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
149
+
150
+ if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
151
+ if(t_class == "_top" || t_class == "_bottom"){
152
+ t_class = "_top";
153
+ } else {
154
+ t_class = t_class+"_top";
155
+ }
156
+ arrow_top = tip_h;
157
+ marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
158
+ } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
159
+ if(t_class == "_top" || t_class == "_bottom"){
160
+ t_class = "_bottom";
161
+ } else {
162
+ t_class = t_class+"_bottom";
163
+ }
164
+ arrow_top = -12;
165
+ marg_top = Math.round(top + org_height + opts.edgeOffset);
166
+ }
167
+
168
+ if(t_class == "_right_top" || t_class == "_left_top"){
169
+ marg_top = marg_top + 5;
170
+ } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
171
+ marg_top = marg_top - 5;
172
+ }
173
+ if(t_class == "_left_top" || t_class == "_left_bottom"){
174
+ marg_left = marg_left + 5;
175
+ }
176
+ tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
177
+ tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
178
+
179
+ if (timeout){ clearTimeout(timeout); }
180
+ timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
181
+ }
182
+
183
+ function deactive_tiptip(){
184
+ opts.exit.call(this);
185
+ if (timeout){ clearTimeout(timeout); }
186
+ tiptip_holder.fadeOut(opts.fadeOut);
187
+ }
188
+ }
189
+ });
190
+ }
191
+ })(jQuery);
plugin-fw/assets/js/jquery.colorbox.js CHANGED
@@ -1,1105 +1,1105 @@
1
- /*!
2
- Colorbox 1.6.3
3
- license: MIT
4
- http://www.jacklmoore.com/colorbox
5
- */
6
- (function ($, document, window) {
7
- var
8
- // Default settings object.
9
- // See http://jacklmoore.com/colorbox for details.
10
- defaults = {
11
- // data sources
12
- html: false,
13
- photo: false,
14
- iframe: false,
15
- inline: false,
16
-
17
- // behavior and appearance
18
- transition: "elastic",
19
- speed: 300,
20
- fadeOut: 300,
21
- width: false,
22
- initialWidth: "600",
23
- innerWidth: false,
24
- maxWidth: false,
25
- height: false,
26
- initialHeight: "450",
27
- innerHeight: false,
28
- maxHeight: false,
29
- scalePhotos: true,
30
- scrolling: true,
31
- opacity: 0.9,
32
- preloading: true,
33
- className: false,
34
- overlayClose: true,
35
- escKey: true,
36
- arrowKey: true,
37
- top: false,
38
- bottom: false,
39
- left: false,
40
- right: false,
41
- fixed: false,
42
- data: undefined,
43
- closeButton: true,
44
- fastIframe: true,
45
- open: false,
46
- reposition: true,
47
- loop: true,
48
- slideshow: false,
49
- slideshowAuto: true,
50
- slideshowSpeed: 2500,
51
- slideshowStart: "start slideshow",
52
- slideshowStop: "stop slideshow",
53
- photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,
54
-
55
- // alternate image paths for high-res displays
56
- retinaImage: false,
57
- retinaUrl: false,
58
- retinaSuffix: '@2x.$1',
59
-
60
- // internationalization
61
- current: "image {current} of {total}",
62
- previous: "previous",
63
- next: "next",
64
- close: "close",
65
- xhrError: "This content failed to load.",
66
- imgError: "This image failed to load.",
67
-
68
- // accessbility
69
- returnFocus: true,
70
- trapFocus: true,
71
-
72
- // callbacks
73
- onOpen: false,
74
- onLoad: false,
75
- onComplete: false,
76
- onCleanup: false,
77
- onClosed: false,
78
-
79
- rel: function() {
80
- return this.rel;
81
- },
82
- href: function() {
83
- // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container')
84
- return $(this).attr('href');
85
- },
86
- title: function() {
87
- return this.title;
88
- },
89
- createImg: function() {
90
- var img = new Image();
91
- var attrs = $(this).data('cbox-img-attrs');
92
-
93
- if (typeof attrs === 'object') {
94
- $.each(attrs, function(key, val){
95
- img[key] = val;
96
- });
97
- }
98
-
99
- return img;
100
- },
101
- createIframe: function() {
102
- var iframe = document.createElement('iframe');
103
- var attrs = $(this).data('cbox-iframe-attrs');
104
-
105
- if (typeof attrs === 'object') {
106
- $.each(attrs, function(key, val){
107
- iframe[key] = val;
108
- });
109
- }
110
-
111
- if ('frameBorder' in iframe) {
112
- iframe.frameBorder = 0;
113
- }
114
- if ('allowTransparency' in iframe) {
115
- iframe.allowTransparency = "true";
116
- }
117
- iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching
118
- iframe.allowFullscreen = true;
119
-
120
- return iframe;
121
- }
122
- },
123
-
124
- // Abstracting the HTML and event identifiers for easy rebranding
125
- colorbox = 'colorbox',
126
- prefix = 'cbox',
127
- boxElement = prefix + 'Element',
128
-
129
- // Events
130
- event_open = prefix + '_open',
131
- event_load = prefix + '_load',
132
- event_complete = prefix + '_complete',
133
- event_cleanup = prefix + '_cleanup',
134
- event_closed = prefix + '_closed',
135
- event_purge = prefix + '_purge',
136
-
137
- // Cached jQuery Object Variables
138
- $overlay,
139
- $box,
140
- $wrap,
141
- $content,
142
- $topBorder,
143
- $leftBorder,
144
- $rightBorder,
145
- $bottomBorder,
146
- $related,
147
- $window,
148
- $loaded,
149
- $loadingBay,
150
- $loadingOverlay,
151
- $title,
152
- $current,
153
- $slideshow,
154
- $next,
155
- $prev,
156
- $close,
157
- $groupControls,
158
- $events = $('<a/>'), // $({}) would be prefered, but there is an issue with jQuery 1.4.2
159
-
160
- // Variables for cached values or use across multiple functions
161
- settings,
162
- interfaceHeight,
163
- interfaceWidth,
164
- loadedHeight,
165
- loadedWidth,
166
- index,
167
- photo,
168
- open,
169
- active,
170
- closing,
171
- loadingTimer,
172
- publicMethod,
173
- div = "div",
174
- requests = 0,
175
- previousCSS = {},
176
- init;
177
-
178
- // ****************
179
- // HELPER FUNCTIONS
180
- // ****************
181
-
182
- // Convenience function for creating new jQuery objects
183
- function $tag(tag, id, css) {
184
- var element = document.createElement(tag);
185
-
186
- if (id) {
187
- element.id = prefix + id;
188
- }
189
-
190
- if (css) {
191
- element.style.cssText = css;
192
- }
193
-
194
- return $(element);
195
- }
196
-
197
- // Get the window height using innerHeight when available to avoid an issue with iOS
198
- // http://bugs.jquery.com/ticket/6724
199
- function winheight() {
200
- return window.innerHeight ? window.innerHeight : $(window).height();
201
- }
202
-
203
- function Settings(element, options) {
204
- if (options !== Object(options)) {
205
- options = {};
206
- }
207
-
208
- this.cache = {};
209
- this.el = element;
210
-
211
- this.value = function(key) {
212
- var dataAttr;
213
-
214
- if (this.cache[key] === undefined) {
215
- dataAttr = $(this.el).attr('data-cbox-'+key);
216
-
217
- if (dataAttr !== undefined) {
218
- this.cache[key] = dataAttr;
219
- } else if (options[key] !== undefined) {
220
- this.cache[key] = options[key];
221
- } else if (defaults[key] !== undefined) {
222
- this.cache[key] = defaults[key];
223
- }
224
- }
225
-
226
- return this.cache[key];
227
- };
228
-
229
- this.get = function(key) {
230
- var value = this.value(key);
231
- return $.isFunction(value) ? value.call(this.el, this) : value;
232
- };
233
- }
234
-
235
- // Determine the next and previous members in a group.
236
- function getIndex(increment) {
237
- var
238
- max = $related.length,
239
- newIndex = (index + increment) % max;
240
-
241
- return (newIndex < 0) ? max + newIndex : newIndex;
242
- }
243
-
244
- // Convert '%' and 'px' values to integers
245
- function setSize(size, dimension) {
246
- return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10));
247
- }
248
-
249
- // Checks an href to see if it is a photo.
250
- // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex.
251
- function isImage(settings, url) {
252
- return settings.get('photo') || settings.get('photoRegex').test(url);
253
- }
254
-
255
- function retinaUrl(settings, url) {
256
- return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url;
257
- }
258
-
259
- function trapFocus(e) {
260
- if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) {
261
- e.stopPropagation();
262
- $box.focus();
263
- }
264
- }
265
-
266
- function setClass(str) {
267
- if (setClass.str !== str) {
268
- $box.add($overlay).removeClass(setClass.str).addClass(str);
269
- setClass.str = str;
270
- }
271
- }
272
-
273
- function getRelated(rel) {
274
- index = 0;
275
-
276
- if (rel && rel !== false && rel !== 'nofollow') {
277
- $related = $('.' + boxElement).filter(function () {
278
- var options = $.data(this, colorbox);
279
- var settings = new Settings(this, options);
280
- return (settings.get('rel') === rel);
281
- });
282
- index = $related.index(settings.el);
283
-
284
- // Check direct calls to Colorbox.
285
- if (index === -1) {
286
- $related = $related.add(settings.el);
287
- index = $related.length - 1;
288
- }
289
- } else {
290
- $related = $(settings.el);
291
- }
292
- }
293
-
294
- function trigger(event) {
295
- // for external use
296
- $(document).trigger(event);
297
- // for internal use
298
- $events.triggerHandler(event);
299
- }
300
-
301
- var slideshow = (function(){
302
- var active,
303
- className = prefix + "Slideshow_",
304
- click = "click." + prefix,
305
- timeOut;
306
-
307
- function clear () {
308
- clearTimeout(timeOut);
309
- }
310
-
311
- function set() {
312
- if (settings.get('loop') || $related[index + 1]) {
313
- clear();
314
- timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed'));
315
- }
316
- }
317
-
318
- function start() {
319
- $slideshow
320
- .html(settings.get('slideshowStop'))
321
- .unbind(click)
322
- .one(click, stop);
323
-
324
- $events
325
- .bind(event_complete, set)
326
- .bind(event_load, clear);
327
-
328
- $box.removeClass(className + "off").addClass(className + "on");
329
- }
330
-
331
- function stop() {
332
- clear();
333
-
334
- $events
335
- .unbind(event_complete, set)
336
- .unbind(event_load, clear);
337
-
338
- $slideshow
339
- .html(settings.get('slideshowStart'))
340
- .unbind(click)
341
- .one(click, function () {
342
- publicMethod.next();
343
- start();
344
- });
345
-
346
- $box.removeClass(className + "on").addClass(className + "off");
347
- }
348
-
349
- function reset() {
350
- active = false;
351
- $slideshow.hide();
352
- clear();
353
- $events
354
- .unbind(event_complete, set)
355
- .unbind(event_load, clear);
356
- $box.removeClass(className + "off " + className + "on");
357
- }
358
-
359
- return function(){
360
- if (active) {
361
- if (!settings.get('slideshow')) {
362
- $events.unbind(event_cleanup, reset);
363
- reset();
364
- }
365
- } else {
366
- if (settings.get('slideshow') && $related[1]) {
367
- active = true;
368
- $events.one(event_cleanup, reset);
369
- if (settings.get('slideshowAuto')) {
370
- start();
371
- } else {
372
- stop();
373
- }
374
- $slideshow.show();
375
- }
376
- }
377
- };
378
-
379
- }());
380
-
381
-
382
- function launch(element) {
383
- var options;
384
-
385
- if (!closing) {
386
-
387
- options = $(element).data(colorbox);
388
-
389
- settings = new Settings(element, options);
390
-
391
- getRelated(settings.get('rel'));
392
-
393
- if (!open) {
394
- open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
395
-
396
- setClass(settings.get('className'));
397
-
398
- // Show colorbox so the sizes can be calculated in older versions of jQuery
399
- $box.css({visibility:'hidden', display:'block', opacity:''});
400
-
401
- $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden');
402
- $content.css({width:'', height:''}).append($loaded);
403
-
404
- // Cache values needed for size calculations
405
- interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();
406
- interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
407
- loadedHeight = $loaded.outerHeight(true);
408
- loadedWidth = $loaded.outerWidth(true);
409
-
410
- // Opens inital empty Colorbox prior to content being loaded.
411
- var initialWidth = setSize(settings.get('initialWidth'), 'x');
412
- var initialHeight = setSize(settings.get('initialHeight'), 'y');
413
- var maxWidth = settings.get('maxWidth');
414
- var maxHeight = settings.get('maxHeight');
415
-
416
- settings.w = Math.max((maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth, 0);
417
- settings.h = Math.max((maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight, 0);
418
-
419
- $loaded.css({width:'', height:settings.h});
420
- publicMethod.position();
421
-
422
- trigger(event_open);
423
- settings.get('onOpen');
424
-
425
- $groupControls.add($title).hide();
426
-
427
- $box.focus();
428
-
429
- if (settings.get('trapFocus')) {
430
- // Confine focus to the modal
431
- // Uses event capturing that is not supported in IE8-
432
- if (document.addEventListener) {
433
-
434
- document.addEventListener('focus', trapFocus, true);
435
-
436
- $events.one(event_closed, function () {
437
- document.removeEventListener('focus', trapFocus, true);
438
- });
439
- }
440
- }
441
-
442
- // Return focus on closing
443
- if (settings.get('returnFocus')) {
444
- $events.one(event_closed, function () {
445
- $(settings.el).focus();
446
- });
447
- }
448
- }
449
-
450
- var opacity = parseFloat(settings.get('opacity'));
451
- $overlay.css({
452
- opacity: opacity === opacity ? opacity : '',
453
- cursor: settings.get('overlayClose') ? 'pointer' : '',
454
- visibility: 'visible'
455
- }).show();
456
-
457
- if (settings.get('closeButton')) {
458
- $close.html(settings.get('close')).appendTo($content);
459
- } else {
460
- $close.appendTo('<div/>'); // replace with .detach() when dropping jQuery < 1.4
461
- }
462
-
463
- load();
464
- }
465
- }
466
-
467
- // Colorbox's markup needs to be added to the DOM prior to being called
468
- // so that the browser will go ahead and load the CSS background images.
469
- function appendHTML() {
470
- if (!$box) {
471
- init = false;
472
- $window = $(window);
473
- $box = $tag(div).attr({
474
- id: colorbox,
475
- 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS.
476
- role: 'dialog',
477
- tabindex: '-1'
478
- }).hide();
479
- $overlay = $tag(div, "Overlay").hide();
480
- $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]);
481
- $wrap = $tag(div, "Wrapper");
482
- $content = $tag(div, "Content").append(
483
- $title = $tag(div, "Title"),
484
- $current = $tag(div, "Current"),
485
- $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}),
486
- $next = $('<button type="button"/>').attr({id:prefix+'Next'}),
487
- $slideshow = $tag('button', "Slideshow"),
488
- $loadingOverlay
489
- );
490
-
491
- $close = $('<button type="button"/>').attr({id:prefix+'Close'});
492
-
493
- $wrap.append( // The 3x3 Grid that makes up Colorbox
494
- $tag(div).append(
495
- $tag(div, "TopLeft"),
496
- $topBorder = $tag(div, "TopCenter"),
497
- $tag(div, "TopRight")
498
- ),
499
- $tag(div, false, 'clear:left').append(
500
- $leftBorder = $tag(div, "MiddleLeft"),
501
- $content,
502
- $rightBorder = $tag(div, "MiddleRight")
503
- ),
504
- $tag(div, false, 'clear:left').append(
505
- $tag(div, "BottomLeft"),
506
- $bottomBorder = $tag(div, "BottomCenter"),
507
- $tag(div, "BottomRight")
508
- )
509
- ).find('div div').css({'float': 'left'});
510
-
511
- $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;');
512
-
513
- $groupControls = $next.add($prev).add($current).add($slideshow);
514
- }
515
- if (document.body && !$box.parent().length) {
516
- $(document.body).append($overlay, $box.append($wrap, $loadingBay));
517
- }
518
- }
519
-
520
- // Add Colorbox's event bindings
521
- function addBindings() {
522
- function clickHandler(e) {
523
- // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt.
524
- // See: http://jacklmoore.com/notes/click-events/
525
- if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) {
526
- e.preventDefault();
527
- launch(this);
528
- }
529
- }
530
-
531
- if ($box) {
532
- if (!init) {
533
- init = true;
534
-
535
- // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly.
536
- $next.click(function () {
537
- publicMethod.next();
538
- });
539
- $prev.click(function () {
540
- publicMethod.prev();
541
- });
542
- $close.click(function () {
543
- publicMethod.close();
544
- });
545
- $overlay.click(function () {
546
- if (settings.get('overlayClose')) {
547
- publicMethod.close();
548
- }
549
- });
550
-
551
- // Key Bindings
552
- $(document).bind('keydown.' + prefix, function (e) {
553
- var key = e.keyCode;
554
- if (open && settings.get('escKey') && key === 27) {
555
- e.preventDefault();
556
- publicMethod.close();
557
- }
558
- if (open && settings.get('arrowKey') && $related[1] && !e.altKey) {
559
- if (key === 37) {
560
- e.preventDefault();
561
- $prev.click();
562
- } else if (key === 39) {
563
- e.preventDefault();
564
- $next.click();
565
- }
566
- }
567
- });
568
-
569
- if ($.isFunction($.fn.on)) {
570
- // For jQuery 1.7+
571
- $(document).on('click.'+prefix, '.'+boxElement, clickHandler);
572
- } else {
573
- // For jQuery 1.3.x -> 1.6.x
574
- // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed.
575
- // This is not here for jQuery 1.9, it's here for legacy users.
576
- $('.'+boxElement).live('click.'+prefix, clickHandler);
577
- }
578
- }
579
- return true;
580
- }
581
- return false;
582
- }
583
-
584
- // Don't do anything if Colorbox already exists.
585
- if ($[colorbox]) {
586
- return;
587
- }
588
-
589
- // Append the HTML when the DOM loads
590
- $(appendHTML);
591
-
592
-
593
- // ****************
594
- // PUBLIC FUNCTIONS
595
- // Usage format: $.colorbox.close();
596
- // Usage from within an iframe: parent.jQuery.colorbox.close();
597
- // ****************
598
-
599
- publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
600
- var settings;
601
- var $obj = this;
602
-
603
- options = options || {};
604
-
605
- if ($.isFunction($obj)) { // assume a call to $.colorbox
606
- $obj = $('<a/>');
607
- options.open = true;
608
- }
609
-
610
- if (!$obj[0]) { // colorbox being applied to empty collection
611
- return $obj;
612
- }
613
-
614
- appendHTML();
615
-
616
- if (addBindings()) {
617
-
618
- if (callback) {
619
- options.onComplete = callback;
620
- }
621
-
622
- $obj.each(function () {
623
- var old = $.data(this, colorbox) || {};
624
- $.data(this, colorbox, $.extend(old, options));
625
- }).addClass(boxElement);
626
-
627
- settings = new Settings($obj[0], options);
628
-
629
- if (settings.get('open')) {
630
- launch($obj[0]);
631
- }
632
- }
633
-
634
- return $obj;
635
- };
636
-
637
- publicMethod.position = function (speed, loadedCallback) {
638
- var
639
- css,
640
- top = 0,
641
- left = 0,
642
- offset = $box.offset(),
643
- scrollTop,
644
- scrollLeft;
645
-
646
- $window.unbind('resize.' + prefix);
647
-
648
- // remove the modal so that it doesn't influence the document width/height
649
- $box.css({top: -9e4, left: -9e4});
650
-
651
- scrollTop = $window.scrollTop();
652
- scrollLeft = $window.scrollLeft();
653
-
654
- if (settings.get('fixed')) {
655
- offset.top -= scrollTop;
656
- offset.left -= scrollLeft;
657
- $box.css({position: 'fixed'});
658
- } else {
659
- top = scrollTop;
660
- left = scrollLeft;
661
- $box.css({position: 'absolute'});
662
- }
663
-
664
- // keeps the top and left positions within the browser's viewport.
665
- if (settings.get('right') !== false) {
666
- left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.get('right'), 'x'), 0);
667
- } else if (settings.get('left') !== false) {
668
- left += setSize(settings.get('left'), 'x');
669
- } else {
670
- left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2);
671
- }
672
-
673
- if (settings.get('bottom') !== false) {
674
- top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.get('bottom'), 'y'), 0);
675
- } else if (settings.get('top') !== false) {
676
- top += setSize(settings.get('top'), 'y');
677
- } else {
678
- top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2);
679
- }
680
-
681
- $box.css({top: offset.top, left: offset.left, visibility:'visible'});
682
-
683
- // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
684
- // but it has to be shrank down around the size of div#colorbox when it's done. If not,
685
- // it can invoke an obscure IE bug when using iframes.
686
- $wrap[0].style.width = $wrap[0].style.height = "9999px";
687
-
688
- function modalDimensions() {
689
- $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px';
690
- $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px';
691
- }
692
-
693
- css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left};
694
-
695
- // setting the speed to 0 if the content hasn't changed size or position
696
- if (speed) {
697
- var tempSpeed = 0;
698
- $.each(css, function(i){
699
- if (css[i] !== previousCSS[i]) {
700
- tempSpeed = speed;
701
- return;
702
- }
703
- });
704
- speed = tempSpeed;
705
- }
706
-
707
- previousCSS = css;
708
-
709
- if (!speed) {
710
- $box.css(css);
711
- }
712
-
713
- $box.dequeue().animate(css, {
714
- duration: speed || 0,
715
- complete: function () {
716
- modalDimensions();
717
-
718
- active = false;
719
-
720
- // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
721
- $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
722
- $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
723
-
724
- if (settings.get('reposition')) {
725
- setTimeout(function () { // small delay before binding onresize due to an IE8 bug.
726
- $window.bind('resize.' + prefix, publicMethod.position);
727
- }, 1);
728
- }
729
-
730
- if ($.isFunction(loadedCallback)) {
731
- loadedCallback();
732
- }
733
- },
734
- step: modalDimensions
735
- });
736
- };
737
-
738
- publicMethod.resize = function (options) {
739
- var scrolltop;
740
-
741
- if (open) {
742
- options = options || {};
743
-
744
- if (options.width) {
745
- settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
746
- }
747
-
748
- if (options.innerWidth) {
749
- settings.w = setSize(options.innerWidth, 'x');
750
- }
751
-
752
- $loaded.css({width: settings.w});
753
-
754
- if (options.height) {
755
- settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
756
- }
757
-
758
- if (options.innerHeight) {
759
- settings.h = setSize(options.innerHeight, 'y');
760
- }
761
-
762
- if (!options.innerHeight && !options.height) {
763
- scrolltop = $loaded.scrollTop();
764
- $loaded.css({height: "auto"});
765
- settings.h = $loaded.height();
766
- }
767
-
768
- $loaded.css({height: settings.h});
769
-
770
- if(scrolltop) {
771
- $loaded.scrollTop(scrolltop);
772
- }
773
-
774
- publicMethod.position(settings.get('transition') === "none" ? 0 : settings.get('speed'));
775
- }
776
- };
777
-
778
- publicMethod.prep = function (object) {
779
- if (!open) {
780
- return;
781
- }
782
-
783
- var callback, speed = settings.get('transition') === "none" ? 0 : settings.get('speed');
784
-
785
- $loaded.remove();
786
-
787
- $loaded = $tag(div, 'LoadedContent').append(object);
788
-
789
- function getWidth() {
790
- settings.w = settings.w || $loaded.width();
791
- settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
792
- return settings.w;
793
- }
794
- function getHeight() {
795
- settings.h = settings.h || $loaded.height();
796
- settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
797
- return settings.h;
798
- }
799
-
800
- $loaded.hide()
801
- .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
802
- .css({width: getWidth(), overflow: settings.get('scrolling') ? 'auto' : 'hidden'})
803
- .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
804
- .prependTo($content);
805
-
806
- $loadingBay.hide();
807
-
808
- // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
809
-
810
- $(photo).css({'float': 'none'});
811
-
812
- setClass(settings.get('className'));
813
-
814
- callback = function () {
815
- var total = $related.length,
816
- iframe,
817
- complete;
818
-
819
- if (!open) {
820
- return;
821
- }
822
-
823
- function removeFilter() { // Needed for IE8 in versions of jQuery prior to 1.7.2
824
- if ($.support.opacity === false) {
825
- $box[0].style.removeAttribute('filter');
826
- }
827
- }
828
-
829
- complete = function () {
830
- clearTimeout(loadingTimer);
831
- $loadingOverlay.hide();
832
- trigger(event_complete);
833
- settings.get('onComplete');
834
- };
835
-
836
-
837
- $title.html(settings.get('title')).show();
838
- $loaded.show();
839
-
840
- if (total > 1) { // handle grouping
841
- if (typeof settings.get('current') === "string") {
842
- $current.html(settings.get('current').replace('{current}', index + 1).replace('{total}', total)).show();
843
- }
844
-
845
- $next[(settings.get('loop') || index < total - 1) ? "show" : "hide"]().html(settings.get('next'));
846
- $prev[(settings.get('loop') || index) ? "show" : "hide"]().html(settings.get('previous'));
847
-
848
- slideshow();
849
-
850
- // Preloads images within a rel group
851
- if (settings.get('preloading')) {
852
- $.each([getIndex(-1), getIndex(1)], function(){
853
- var img,
854
- i = $related[this],
855
- settings = new Settings(i, $.data(i, colorbox)),
856
- src = settings.get('href');
857
-
858
- if (src && isImage(settings, src)) {
859
- src = retinaUrl(settings, src);
860
- img = document.createElement('img');
861
- img.src = src;
862
- }
863
- });
864
- }
865
- } else {
866
- $groupControls.hide();
867
- }
868
-
869
- if (settings.get('iframe')) {
870
-
871
- iframe = settings.get('createIframe');
872
-
873
- if (!settings.get('scrolling')) {
874
- iframe.scrolling = "no";
875
- }
876
-
877
- $(iframe)
878
- .attr({
879
- src: settings.get('href'),
880
- 'class': prefix + 'Iframe'
881
- })
882
- .one('load', complete)
883
- .appendTo($loaded);
884
-
885
- $events.one(event_purge, function () {
886
- iframe.src = "//about:blank";
887
- });
888
-
889
- if (settings.get('fastIframe')) {
890
- $(iframe).trigger('load');
891
- }
892
- } else {
893
- complete();
894
- }
895
-
896
- if (settings.get('transition') === 'fade') {
897
- $box.fadeTo(speed, 1, removeFilter);
898
- } else {
899
- removeFilter();
900
- }
901
- };
902
-
903
- if (settings.get('transition') === 'fade') {
904
- $box.fadeTo(speed, 0, function () {
905
- publicMethod.position(0, callback);
906
- });
907
- } else {
908
- publicMethod.position(speed, callback);
909
- }
910
- };
911
-
912
- function load () {
913
- var href, setResize, prep = publicMethod.prep, $inline, request = ++requests;
914
-
915
- active = true;
916
-
917
- photo = false;
918
-
919
- trigger(event_purge);
920
- trigger(event_load);
921
- settings.get('onLoad');
922
-
923
- settings.h = settings.get('height') ?
924
- setSize(settings.get('height'), 'y') - loadedHeight - interfaceHeight :
925
- settings.get('innerHeight') && setSize(settings.get('innerHeight'), 'y');
926
-
927
- settings.w = settings.get('width') ?
928
- setSize(settings.get('width'), 'x') - loadedWidth - interfaceWidth :
929
- settings.get('innerWidth') && setSize(settings.get('innerWidth'), 'x');
930
-
931
- // Sets the minimum dimensions for use in image scaling
932
- settings.mw = settings.w;
933
- settings.mh = settings.h;
934
-
935
- // Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
936
- // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
937
- if (settings.get('maxWidth')) {
938
- settings.mw = setSize(settings.get('maxWidth'), 'x') - loadedWidth - interfaceWidth;
939
- settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
940
- }
941
- if (settings.get('maxHeight')) {
942
- settings.mh = setSize(settings.get('maxHeight'), 'y') - loadedHeight - interfaceHeight;
943
- settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
944
- }
945
-
946
- href = settings.get('href');
947
-
948
- loadingTimer = setTimeout(function () {
949
- $loadingOverlay.show();
950
- }, 100);
951
-
952
- if (settings.get('inline')) {
953
- var $target = $(href);
954
- // Inserts an empty placeholder where inline content is being pulled from.
955
- // An event is bound to put inline content back when Colorbox closes or loads new content.
956
- $inline = $('<div>').hide().insertBefore($target);
957
-
958
- $events.one(event_purge, function () {
959
- $inline.replaceWith($target);
960
- });
961
-
962
- prep($target);
963
- } else if (settings.get('iframe')) {
964
- // IFrame element won't be added to the DOM until it is ready to be displayed,
965
- // to avoid problems with DOM-ready JS that might be trying to run in that iframe.
966
- prep(" ");
967
- } else if (settings.get('html')) {
968
- prep(settings.get('html'));
969
- } else if (isImage(settings, href)) {
970
-
971
- href = retinaUrl(settings, href);
972
-
973
- photo = settings.get('createImg');
974
-
975
- $(photo)
976
- .addClass(prefix + 'Photo')
977
- .bind('error.'+prefix,function () {
978
- prep($tag(div, 'Error').html(settings.get('imgError')));
979
- })
980
- .one('load', function () {
981
- if (request !== requests) {
982
- return;
983
- }
984
-
985
- // A small pause because some browsers will occassionaly report a
986
- // img.width and img.height of zero immediately after the img.onload fires
987
- setTimeout(function(){
988
- var percent;
989
-
990
- if (settings.get('retinaImage') && window.devicePixelRatio > 1) {
991
- photo.height = photo.height / window.devicePixelRatio;
992
- photo.width = photo.width / window.devicePixelRatio;
993
- }
994
-
995
- if (settings.get('scalePhotos')) {
996
- setResize = function () {
997
- photo.height -= photo.height * percent;
998
- photo.width -= photo.width * percent;
999
- };
1000
- if (settings.mw && photo.width > settings.mw) {
1001
- percent = (photo.width - settings.mw) / photo.width;
1002
- setResize();
1003
- }
1004
- if (settings.mh && photo.height > settings.mh) {
1005
- percent = (photo.height - settings.mh) / photo.height;
1006
- setResize();
1007
- }
1008
- }
1009
-
1010
- if (settings.h) {
1011
- photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px';
1012
- }
1013
-
1014
- if ($related[1] && (settings.get('loop') || $related[index + 1])) {
1015
- photo.style.cursor = 'pointer';
1016
-
1017
- $(photo).bind('click.'+prefix, function () {
1018
- publicMethod.next();
1019
- });
1020
- }
1021
-
1022
- photo.style.width = photo.width + 'px';
1023
- photo.style.height = photo.height + 'px';
1024
- prep(photo);
1025
- }, 1);
1026
- });
1027
-
1028
- photo.src = href;
1029
-
1030
- } else if (href) {
1031
- $loadingBay.load(href, settings.get('data'), function (data, status) {
1032
- if (request === requests) {
1033
- prep(status === 'error' ? $tag(div, 'Error').html(settings.get('xhrError')) : $(this).contents());
1034
- }
1035
- });
1036
- }
1037
- }
1038
-
1039
- // Navigates to the next page/image in a set.
1040
- publicMethod.next = function () {
1041
- if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) {
1042
- index = getIndex(1);
1043
- launch($related[index]);
1044
- }
1045
- };
1046
-
1047
- publicMethod.prev = function () {
1048
- if (!active && $related[1] && (settings.get('loop') || index)) {
1049
- index = getIndex(-1);
1050
- launch($related[index]);
1051
- }
1052
- };
1053
-
1054
- // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close();
1055
- publicMethod.close = function () {
1056
- if (open && !closing) {
1057
-
1058
- closing = true;
1059
- open = false;
1060
- trigger(event_cleanup);
1061
- settings.get('onCleanup');
1062
- $window.unbind('.' + prefix);
1063
- $overlay.fadeTo(settings.get('fadeOut') || 0, 0);
1064
-
1065
- $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () {
1066
- $box.hide();
1067
- $overlay.hide();
1068
- trigger(event_purge);
1069
- $loaded.remove();
1070
-
1071
- setTimeout(function () {
1072
- closing = false;
1073
- trigger(event_closed);
1074
- settings.get('onClosed');
1075
- }, 1);
1076
- });
1077
- }
1078
- };
1079
-
1080
- // Removes changes Colorbox made to the document, but does not remove the plugin.
1081
- publicMethod.remove = function () {
1082
- if (!$box) { return; }
1083
-
1084
- $box.stop();
1085
- $[colorbox].close();
1086
- $box.stop(false, true).remove();
1087
- $overlay.remove();
1088
- closing = false;
1089
- $box = null;
1090
- $('.' + boxElement)
1091
- .removeData(colorbox)
1092
- .removeClass(boxElement);
1093
-
1094
- $(document).unbind('click.'+prefix).unbind('keydown.'+prefix);
1095
- };
1096
-
1097
- // A method for fetching the current element Colorbox is referencing.
1098
- // returns a jQuery object.
1099
- publicMethod.element = function () {
1100
- return $(settings.el);
1101
- };
1102
-
1103
- publicMethod.settings = defaults;
1104
-
1105
  }(jQuery, document, window));
1
+ /*!
2
+ Colorbox 1.6.3
3
+ license: MIT
4
+ http://www.jacklmoore.com/colorbox
5
+ */
6
+ (function ($, document, window) {
7
+ var
8
+ // Default settings object.
9
+ // See http://jacklmoore.com/colorbox for details.
10
+ defaults = {
11
+ // data sources
12
+ html: false,
13
+ photo: false,
14
+ iframe: false,
15
+ inline: false,
16
+
17
+ // behavior and appearance
18
+ transition: "elastic",
19
+ speed: 300,
20
+ fadeOut: 300,
21
+ width: false,
22
+ initialWidth: "600",
23
+ innerWidth: false,
24
+ maxWidth: false,
25
+ height: false,
26
+ initialHeight: "450",
27
+ innerHeight: false,
28
+ maxHeight: false,
29
+ scalePhotos: true,
30
+ scrolling: true,
31
+ opacity: 0.9,
32
+ preloading: true,
33
+ className: false,
34
+ overlayClose: true,
35
+ escKey: true,
36
+ arrowKey: true,
37
+ top: false,
38
+ bottom: false,
39
+ left: false,
40
+ right: false,
41
+ fixed: false,
42
+ data: undefined,
43
+ closeButton: true,
44
+ fastIframe: true,
45
+ open: false,
46
+ reposition: true,
47
+ loop: true,
48
+ slideshow: false,
49
+ slideshowAuto: true,
50
+ slideshowSpeed: 2500,
51
+ slideshowStart: "start slideshow",
52
+ slideshowStop: "stop slideshow",
53
+ photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,
54
+
55
+ // alternate image paths for high-res displays
56
+ retinaImage: false,
57
+ retinaUrl: false,
58
+ retinaSuffix: '@2x.$1',
59
+
60
+ // internationalization
61
+ current: "image {current} of {total}",
62
+ previous: "previous",
63
+ next: "next",
64
+ close: "close",
65
+ xhrError: "This content failed to load.",
66
+ imgError: "This image failed to load.",
67
+
68
+ // accessbility
69
+ returnFocus: true,
70
+ trapFocus: true,
71
+
72
+ // callbacks
73
+ onOpen: false,
74
+ onLoad: false,
75
+ onComplete: false,
76
+ onCleanup: false,
77
+ onClosed: false,
78
+
79
+ rel: function() {
80
+ return this.rel;
81
+ },
82
+ href: function() {
83
+ // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container')
84
+ return $(this).attr('href');
85
+ },
86
+ title: function() {
87
+ return this.title;
88
+ },
89
+ createImg: function() {
90
+ var img = new Image();
91
+ var attrs = $(this).data('cbox-img-attrs');
92
+
93
+ if (typeof attrs === 'object') {
94
+ $.each(attrs, function(key, val){
95
+ img[key] = val;
96
+ });
97
+ }
98
+
99
+ return img;
100
+ },
101
+ createIframe: function() {
102
+ var iframe = document.createElement('iframe');
103
+ var attrs = $(this).data('cbox-iframe-attrs');
104
+
105
+ if (typeof attrs === 'object') {
106
+ $.each(attrs, function(key, val){
107
+ iframe[key] = val;
108
+ });
109
+ }
110
+
111
+ if ('frameBorder' in iframe) {
112
+ iframe.frameBorder = 0;
113
+ }
114
+ if ('allowTransparency' in iframe) {
115
+ iframe.allowTransparency = "true";
116
+ }
117
+ iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching
118
+ iframe.allowFullscreen = true;
119
+
120
+ return iframe;
121
+ }
122
+ },
123
+
124
+ // Abstracting the HTML and event identifiers for easy rebranding
125
+ colorbox = 'colorbox',
126
+ prefix = 'cbox',
127
+ boxElement = prefix + 'Element',
128
+
129
+ // Events
130
+ event_open = prefix + '_open',
131
+ event_load = prefix + '_load',
132
+ event_complete = prefix + '_complete',
133
+ event_cleanup = prefix + '_cleanup',
134
+ event_closed = prefix + '_closed',
135
+ event_purge = prefix + '_purge',
136
+
137
+ // Cached jQuery Object Variables
138
+ $overlay,
139
+ $box,
140
+ $wrap,
141
+ $content,
142
+ $topBorder,
143
+ $leftBorder,
144
+ $rightBorder,
145
+ $bottomBorder,
146
+ $related,
147
+ $window,
148
+ $loaded,
149
+ $loadingBay,
150
+ $loadingOverlay,
151
+ $title,
152
+ $current,
153
+ $slideshow,
154
+ $next,
155
+ $prev,
156
+ $close,
157
+ $groupControls,
158
+ $events = $('<a/>'), // $({}) would be prefered, but there is an issue with jQuery 1.4.2
159
+
160
+ // Variables for cached values or use across multiple functions
161
+ settings,
162
+ interfaceHeight,
163
+ interfaceWidth,
164
+ loadedHeight,
165
+ loadedWidth,
166
+ index,
167
+ photo,
168
+ open,
169
+ active,
170
+ closing,
171
+ loadingTimer,
172
+ publicMethod,
173
+ div = "div",
174
+ requests = 0,
175
+ previousCSS = {},
176
+ init;
177
+
178
+ // ****************
179
+ // HELPER FUNCTIONS
180
+ // ****************
181
+
182
+ // Convenience function for creating new jQuery objects
183
+ function $tag(tag, id, css) {
184
+ var element = document.createElement(tag);
185
+
186
+ if (id) {
187
+ element.id = prefix + id;
188
+ }
189
+
190
+ if (css) {
191
+ element.style.cssText = css;
192
+ }
193
+
194
+ return $(element);
195
+ }
196
+
197
+ // Get the window height using innerHeight when available to avoid an issue with iOS
198
+ // http://bugs.jquery.com/ticket/6724
199
+ function winheight() {
200
+ return window.innerHeight ? window.innerHeight : $(window).height();
201
+ }
202
+
203
+ function Settings(element, options) {
204
+ if (options !== Object(options)) {
205
+ options = {};
206
+ }
207
+
208
+ this.cache = {};
209
+ this.el = element;
210
+
211
+ this.value = function(key) {
212
+ var dataAttr;
213
+
214
+ if (this.cache[key] === undefined) {
215
+ dataAttr = $(this.el).attr('data-cbox-'+key);
216
+
217
+ if (dataAttr !== undefined) {
218
+ this.cache[key] = dataAttr;
219
+ } else if (options[key] !== undefined) {
220
+ this.cache[key] = options[key];
221
+ } else if (defaults[key] !== undefined) {
222
+ this.cache[key] = defaults[key];
223
+ }
224
+ }
225
+
226
+ return this.cache[key];
227
+ };
228
+
229
+ this.get = function(key) {
230
+ var value = this.value(key);
231
+ return $.isFunction(value) ? value.call(this.el, this) : value;
232
+ };
233
+ }
234
+
235
+ // Determine the next and previous members in a group.
236
+ function getIndex(increment) {
237
+ var
238
+ max = $related.length,
239
+ newIndex = (index + increment) % max;
240
+
241
+ return (newIndex < 0) ? max + newIndex : newIndex;
242
+ }
243
+
244
+ // Convert '%' and 'px' values to integers
245
+ function setSize(size, dimension) {
246
+ return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10));
247
+ }
248
+
249
+ // Checks an href to see if it is a photo.
250
+ // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex.
251
+ function isImage(settings, url) {
252
+ return settings.get('photo') || settings.get('photoRegex').test(url);
253
+ }
254
+
255
+ function retinaUrl(settings, url) {
256
+ return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url;
257
+ }
258
+
259
+ function trapFocus(e) {
260
+ if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) {
261
+ e.stopPropagation();
262
+ $box.focus();
263
+ }
264
+ }
265
+
266
+ function setClass(str) {
267
+ if (setClass.str !== str) {
268
+ $box.add($overlay).removeClass(setClass.str).addClass(str);
269
+ setClass.str = str;
270
+ }
271
+ }
272
+
273
+ function getRelated(rel) {
274
+ index = 0;
275
+
276
+ if (rel && rel !== false && rel !== 'nofollow') {
277
+ $related = $('.' + boxElement).filter(function () {
278
+ var options = $.data(this, colorbox);
279
+ var settings = new Settings(this, options);
280
+ return (settings.get('rel') === rel);
281
+ });
282
+ index = $related.index(settings.el);
283
+
284
+ // Check direct calls to Colorbox.
285
+ if (index === -1) {
286
+ $related = $related.add(settings.el);
287
+ index = $related.length - 1;
288
+ }
289
+ } else {
290
+ $related = $(settings.el);
291
+ }
292
+ }
293
+
294
+ function trigger(event) {
295
+ // for external use
296
+ $(document).trigger(event);
297
+ // for internal use
298
+ $events.triggerHandler(event);
299
+ }
300
+
301
+ var slideshow = (function(){
302
+ var active,
303
+ className = prefix + "Slideshow_",
304
+ click = "click." + prefix,
305
+ timeOut;
306
+
307
+ function clear () {
308
+ clearTimeout(timeOut);
309
+ }
310
+
311
+ function set() {
312
+ if (settings.get('loop') || $related[index + 1]) {
313
+ clear();
314
+ timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed'));
315
+ }
316
+ }
317
+
318
+ function start() {
319
+ $slideshow
320
+ .html(settings.get('slideshowStop'))
321
+ .unbind(click)
322
+ .one(click, stop);
323
+
324
+ $events
325
+ .bind(event_complete, set)
326
+ .bind(event_load, clear);
327
+
328
+ $box.removeClass(className + "off").addClass(className + "on");
329
+ }
330
+
331
+ function stop() {
332
+ clear();
333
+
334
+ $events
335
+ .unbind(event_complete, set)
336
+ .unbind(event_load, clear);
337
+
338
+ $slideshow
339
+ .html(settings.get('slideshowStart'))
340
+ .unbind(click)
341
+ .one(click, function () {
342
+ publicMethod.next();
343
+ start();
344
+ });
345
+
346
+ $box.removeClass(className + "on").addClass(className + "off");
347
+ }
348
+
349
+ function reset() {
350
+ active = false;
351
+ $slideshow.hide();
352
+ clear();
353
+ $events
354
+ .unbind(event_complete, set)
355
+ .unbind(event_load, clear);
356
+ $box.removeClass(className + "off " + className + "on");
357
+ }
358
+
359
+ return function(){
360
+ if (active) {
361
+ if (!settings.get('slideshow')) {
362
+ $events.unbind(event_cleanup, reset);
363
+ reset();
364
+ }
365
+ } else {
366
+ if (settings.get('slideshow') && $related[1]) {
367
+ active = true;
368
+ $events.one(event_cleanup, reset);
369
+ if (settings.get('slideshowAuto')) {
370
+ start();
371
+ } else {
372
+ stop();
373
+ }
374
+ $slideshow.show();
375
+ }
376
+ }
377
+ };
378
+
379
+ }());
380
+
381
+
382
+ function launch(element) {
383
+ var options;
384
+
385
+ if (!closing) {
386
+
387
+ options = $(element).data(colorbox);
388
+
389
+ settings = new Settings(element, options);
390
+
391
+ getRelated(settings.get('rel'));
392
+
393
+ if (!open) {
394
+ open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
395
+
396
+ setClass(settings.get('className'));
397
+
398
+ // Show colorbox so the sizes can be calculated in older versions of jQuery
399
+ $box.css({visibility:'hidden', display:'block', opacity:''});
400
+
401
+ $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden');
402
+ $content.css({width:'', height:''}).append($loaded);
403
+
404
+ // Cache values needed for size calculations
405
+ interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();
406
+ interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
407
+ loadedHeight = $loaded.outerHeight(true);
408
+ loadedWidth = $loaded.outerWidth(true);
409
+
410
+ // Opens inital empty Colorbox prior to content being loaded.
411
+ var initialWidth = setSize(settings.get('initialWidth'), 'x');
412
+ var initialHeight = setSize(settings.get('initialHeight'), 'y');
413
+ var maxWidth = settings.get('maxWidth');
414
+ var maxHeight = settings.get('maxHeight');
415
+
416
+ settings.w = Math.max((maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth, 0);
417
+ settings.h = Math.max((maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight, 0);
418
+
419
+ $loaded.css({width:'', height:settings.h});
420
+ publicMethod.position();
421
+
422
+ trigger(event_open);
423
+ settings.get('onOpen');
424
+
425
+ $groupControls.add($title).hide();
426
+
427
+ $box.focus();
428
+
429
+ if (settings.get('trapFocus')) {
430
+ // Confine focus to the modal
431
+ // Uses event capturing that is not supported in IE8-
432
+ if (document.addEventListener) {
433
+
434
+ document.addEventListener('focus', trapFocus, true);
435
+
436
+ $events.one(event_closed, function () {
437
+ document.removeEventListener('focus', trapFocus, true);
438
+ });
439
+ }
440
+ }
441
+
442
+ // Return focus on closing
443
+ if (settings.get('returnFocus')) {
444
+ $events.one(event_closed, function () {
445
+ $(settings.el).focus();
446
+ });
447
+ }
448
+ }
449
+
450
+ var opacity = parseFloat(settings.get('opacity'));
451
+ $overlay.css({
452
+ opacity: opacity === opacity ? opacity : '',
453
+ cursor: settings.get('overlayClose') ? 'pointer' : '',
454
+ visibility: 'visible'
455
+ }).show();
456
+
457
+ if (settings.get('closeButton')) {
458
+ $close.html(settings.get('close')).appendTo($content);
459
+ } else {
460
+ $close.appendTo('<div/>'); // replace with .detach() when dropping jQuery < 1.4
461
+ }
462
+
463
+ load();
464
+ }
465
+ }
466
+
467
+ // Colorbox's markup needs to be added to the DOM prior to being called
468
+ // so that the browser will go ahead and load the CSS background images.
469
+ function appendHTML() {
470
+ if (!$box) {
471
+ init = false;
472
+ $window = $(window);
473
+ $box = $tag(div).attr({
474
+ id: colorbox,
475
+ 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS.
476
+ role: 'dialog',
477
+ tabindex: '-1'
478
+ }).hide();
479
+ $overlay = $tag(div, "Overlay").hide();
480
+ $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]);
481
+ $wrap = $tag(div, "Wrapper");
482
+ $content = $tag(div, "Content").append(
483
+ $title = $tag(div, "Title"),
484
+ $current = $tag(div, "Current"),
485
+ $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}),
486
+ $next = $('<button type="button"/>').attr({id:prefix+'Next'}),
487
+ $slideshow = $tag('button', "Slideshow"),
488
+ $loadingOverlay
489
+ );
490
+
491
+ $close = $('<button type="button"/>').attr({id:prefix+'Close'});
492
+
493
+ $wrap.append( // The 3x3 Grid that makes up Colorbox
494
+ $tag(div).append(
495
+ $tag(div, "TopLeft"),
496
+ $topBorder = $tag(div, "TopCenter"),
497
+ $tag(div, "TopRight")
498
+ ),
499
+ $tag(div, false, 'clear:left').append(
500
+ $leftBorder = $tag(div, "MiddleLeft"),
501
+ $content,
502
+ $rightBorder = $tag(div, "MiddleRight")
503
+ ),
504
+ $tag(div, false, 'clear:left').append(
505
+ $tag(div, "BottomLeft"),
506
+ $bottomBorder = $tag(div, "BottomCenter"),
507
+ $tag(div, "BottomRight")
508
+ )
509
+ ).find('div div').css({'float': 'left'});
510
+
511
+ $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;');
512
+
513
+ $groupControls = $next.add($prev).add($current).add($slideshow);
514
+ }
515
+ if (document.body && !$box.parent().length) {
516
+ $(document.body).append($overlay, $box.append($wrap, $loadingBay));
517
+ }
518
+ }
519
+
520
+ // Add Colorbox's event bindings
521
+ function addBindings() {
522
+ function clickHandler(e) {
523
+ // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt.
524
+ // See: http://jacklmoore.com/notes/click-events/
525
+ if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) {
526
+ e.preventDefault();
527
+ launch(this);
528
+ }
529
+ }
530
+
531
+ if ($box) {
532
+ if (!init) {
533
+ init = true;
534
+
535
+ // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly.
536
+ $next.click(function () {
537
+ publicMethod.next();
538
+ });
539
+ $prev.click(function () {
540
+ publicMethod.prev();
541
+ });
542
+ $close.click(function () {
543
+ publicMethod.close();
544
+ });
545
+ $overlay.click(function () {
546
+ if (settings.get('overlayClose')) {
547
+ publicMethod.close();
548
+ }
549
+ });
550
+
551
+ // Key Bindings
552
+ $(document).bind('keydown.' + prefix, function (e) {
553
+ var key = e.keyCode;
554
+ if (open && settings.get('escKey') && key === 27) {
555
+ e.preventDefault();
556
+ publicMethod.close();
557
+ }
558
+ if (open && settings.get('arrowKey') && $related[1] && !e.altKey) {
559
+ if (key === 37) {
560
+ e.preventDefault();
561
+ $prev.click();
562
+ } else if (key === 39) {
563
+ e.preventDefault();
564
+ $next.click();
565
+ }
566
+ }
567
+ });
568
+
569
+ if ($.isFunction($.fn.on)) {
570
+ // For jQuery 1.7+
571
+ $(document).on('click.'+prefix, '.'+boxElement, clickHandler);
572
+ } else {
573
+ // For jQuery 1.3.x -> 1.6.x
574
+ // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed.
575
+ // This is not here for jQuery 1.9, it's here for legacy users.
576
+ $('.'+boxElement).live('click.'+prefix, clickHandler);
577
+ }
578
+ }
579
+ return true;
580
+ }
581
+ return false;
582
+ }
583
+
584
+ // Don't do anything if Colorbox already exists.
585
+ if ($[colorbox]) {
586
+ return;
587
+ }
588
+
589
+ // Append the HTML when the DOM loads
590
+ $(appendHTML);
591
+
592
+
593
+ // ****************
594
+ // PUBLIC FUNCTIONS
595
+ // Usage format: $.colorbox.close();
596
+ // Usage from within an iframe: parent.jQuery.colorbox.close();
597
+ // ****************
598
+
599
+ publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
600
+ var settings;
601
+ var $obj = this;
602
+
603
+ options = options || {};
604
+
605
+ if ($.isFunction($obj)) { // assume a call to $.colorbox
606
+ $obj = $('<a/>');
607
+ options.open = true;
608
+ }
609
+
610
+ if (!$obj[0]) { // colorbox being applied to empty collection
611
+ return $obj;
612
+ }
613
+
614
+ appendHTML();
615
+
616
+ if (addBindings()) {
617
+
618
+ if (callback) {
619
+ options.onComplete = callback;
620
+ }
621
+
622
+ $obj.each(function () {
623
+ var old = $.data(this, colorbox) || {};
624
+ $.data(this, colorbox, $.extend(old, options));
625
+ }).addClass(boxElement);
626
+
627
+ settings = new Settings($obj[0], options);
628
+
629
+ if (settings.get('open')) {
630
+ launch($obj[0]);
631
+ }
632
+ }
633
+
634
+ return $obj;
635
+ };
636
+
637
+ publicMethod.position = function (speed, loadedCallback) {
638
+ var
639
+ css,
640
+ top = 0,
641
+ left = 0,
642
+ offset = $box.offset(),
643
+ scrollTop,
644
+ scrollLeft;
645
+
646
+ $window.unbind('resize.' + prefix);
647
+
648
+ // remove the modal so that it doesn't influence the document width/height
649
+ $box.css({top: -9e4, left: -9e4});
650
+
651
+ scrollTop = $window.scrollTop();
652
+ scrollLeft = $window.scrollLeft();
653
+
654
+ if (settings.get('fixed')) {
655
+ offset.top -= scrollTop;
656
+ offset.left -= scrollLeft;
657
+ $box.css({position: 'fixed'});
658
+ } else {
659
+ top = scrollTop;
660
+ left = scrollLeft;
661
+ $box.css({position: 'absolute'});
662
+ }
663
+
664
+ // keeps the top and left positions within the browser's viewport.
665
+ if (settings.get('right') !== false) {
666
+ left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.get('right'), 'x'), 0);
667
+ } else if (settings.get('left') !== false) {
668
+ left += setSize(settings.get('left'), 'x');
669
+ } else {
670
+ left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2);
671
+ }
672
+
673
+ if (settings.get('bottom') !== false) {
674
+ top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.get('bottom'), 'y'), 0);
675
+ } else if (settings.get('top') !== false) {
676
+ top += setSize(settings.get('top'), 'y');
677
+ } else {
678
+ top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2);
679
+ }
680
+
681
+ $box.css({top: offset.top, left: offset.left, visibility:'visible'});
682
+
683
+ // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
684
+ // but it has to be shrank down around the size of div#colorbox when it's done. If not,
685
+ // it can invoke an obscure IE bug when using iframes.
686
+ $wrap[0].style.width = $wrap[0].style.height = "9999px";
687
+
688
+ function modalDimensions() {
689
+ $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px';
690
+ $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px';
691
+ }
692
+
693
+ css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left};
694
+
695
+ // setting the speed to 0 if the content hasn't changed size or position
696
+ if (speed) {
697
+ var tempSpeed = 0;
698
+ $.each(css, function(i){
699
+ if (css[i] !== previousCSS[i]) {
700
+ tempSpeed = speed;
701
+ return;
702
+ }
703
+ });
704
+ speed = tempSpeed;
705
+ }
706
+
707
+ previousCSS = css;
708
+
709
+ if (!speed) {
710
+ $box.css(css);
711
+ }
712
+
713
+ $box.dequeue().animate(css, {
714
+ duration: speed || 0,
715
+ complete: function () {
716
+ modalDimensions();
717
+
718
+ active = false;
719
+
720
+ // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
721
+ $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
722
+ $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
723
+
724
+ if (settings.get('reposition')) {
725
+ setTimeout(function () { // small delay before binding onresize due to an IE8 bug.
726
+ $window.bind('resize.' + prefix, publicMethod.position);
727
+ }, 1);
728
+ }
729
+
730
+ if ($.isFunction(loadedCallback)) {
731
+ loadedCallback();
732
+ }
733
+ },
734
+ step: modalDimensions
735
+ });
736
+ };
737
+
738
+ publicMethod.resize = function (options) {
739
+ var scrolltop;
740
+
741
+ if (open) {
742
+ options = options || {};
743
+
744
+ if (options.width) {
745
+ settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
746
+ }
747
+
748
+ if (options.innerWidth) {
749
+ settings.w = setSize(options.innerWidth, 'x');
750
+ }
751
+
752
+ $loaded.css({width: settings.w});
753
+
754
+ if (options.height) {
755
+ settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
756
+ }
757
+
758
+ if (options.innerHeight) {
759
+ settings.h = setSize(options.innerHeight, 'y');
760
+ }
761
+
762
+ if (!options.innerHeight && !options.height) {
763
+ scrolltop = $loaded.scrollTop();
764
+ $loaded.css({height: "auto"});
765
+ settings.h = $loaded.height();
766
+ }
767
+
768
+ $loaded.css({height: settings.h});
769
+
770
+ if(scrolltop) {
771
+ $loaded.scrollTop(scrolltop);
772
+ }
773
+
774
+ publicMethod.position(settings.get('transition') === "none" ? 0 : settings.get('speed'));
775
+ }
776
+ };
777
+
778
+ publicMethod.prep = function (object) {
779
+ if (!open) {
780
+ return;
781
+ }
782
+
783
+ var callback, speed = settings.get('transition') === "none" ? 0 : settings.get('speed');
784
+
785
+ $loaded.remove();
786
+
787
+ $loaded = $tag(div, 'LoadedContent').append(object);
788
+
789
+ function getWidth() {
790
+ settings.w = settings.w || $loaded.width();
791
+ settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
792
+ return settings.w;
793
+ }
794
+ function getHeight() {
795
+ settings.h = settings.h || $loaded.height();
796
+ settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
797
+ return settings.h;
798
+ }
799
+
800
+ $loaded.hide()
801
+ .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
802
+ .css({width: getWidth(), overflow: settings.get('scrolling') ? 'auto' : 'hidden'})
803
+ .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
804
+ .prependTo($content);
805
+
806
+ $loadingBay.hide();
807
+
808
+ // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
809
+
810
+ $(photo).css({'float': 'none'});
811
+
812
+ setClass(settings.get('className'));
813
+
814
+ callback = function () {
815
+ var total = $related.length,
816
+ iframe,
817
+ complete;
818
+
819
+ if (!open) {
820
+ return;
821
+ }
822
+
823
+ function removeFilter() { // Needed for IE8 in versions of jQuery prior to 1.7.2
824
+ if ($.support.opacity === false) {
825
+ $box[0].style.removeAttribute('filter');
826
+ }
827
+ }
828
+
829
+ complete = function () {
830
+ clearTimeout(loadingTimer);
831
+ $loadingOverlay.hide();
832
+ trigger(event_complete);
833
+ settings.get('onComplete');
834
+ };
835
+
836
+
837
+ $title.html(settings.get('title')).show();
838
+ $loaded.show();
839
+
840
+ if (total > 1) { // handle grouping
841
+ if (typeof settings.get('current') === "string") {
842
+ $current.html(settings.get('current').replace('{current}', index + 1).replace('{total}', total)).show();
843
+ }
844
+
845
+ $next[(settings.get('loop') || index < total - 1) ? "show" : "hide"]().html(settings.get('next'));
846
+ $prev[(settings.get('loop') || index) ? "show" : "hide"]().html(settings.get('previous'));
847
+
848
+ slideshow();
849
+
850
+ // Preloads images within a rel group
851
+ if (settings.get('preloading')) {
852
+ $.each([getIndex(-1), getIndex(1)], function(){
853
+ var img,
854
+ i = $related[this],
855
+ settings = new Settings(i, $.data(i, colorbox)),
856
+ src = settings.get('href');
857
+
858
+ if (src && isImage(settings, src)) {
859
+ src = retinaUrl(settings, src);
860
+ img = document.createElement('img');
861
+ img.src = src;
862
+ }
863
+ });
864
+ }
865
+ } else {
866
+ $groupControls.hide();
867
+ }
868
+
869
+ if (settings.get('iframe')) {
870
+
871
+ iframe = settings.get('createIframe');
872
+
873
+ if (!settings.get('scrolling')) {
874
+ iframe.scrolling = "no";
875
+ }
876
+
877
+ $(iframe)
878
+ .attr({
879
+ src: settings.get('href'),
880
+ 'class': prefix + 'Iframe'
881
+ })
882
+ .one('load', complete)
883
+ .appendTo($loaded);
884
+
885
+ $events.one(event_purge, function () {
886
+ iframe.src = "//about:blank";
887
+ });
888
+
889
+ if (settings.get('fastIframe')) {
890
+ $(iframe).trigger('load');
891
+ }
892
+ } else {
893
+ complete();
894
+ }
895
+
896
+ if (settings.get('transition') === 'fade') {
897
+ $box.fadeTo(speed, 1, removeFilter);
898
+ } else {
899
+ removeFilter();
900
+ }
901
+ };
902
+
903
+ if (settings.get('transition') === 'fade') {
904
+ $box.fadeTo(speed, 0, function () {
905
+ publicMethod.position(0, callback);
906
+ });
907
+ } else {
908
+ publicMethod.position(speed, callback);
909
+ }
910
+ };
911
+
912
+ function load () {
913
+ var href, setResize, prep = publicMethod.prep, $inline, request = ++requests;
914
+
915
+ active = true;
916
+
917
+ photo = false;
918
+
919
+ trigger(event_purge);
920
+ trigger(event_load);
921
+ settings.get('onLoad');
922
+
923
+ settings.h = settings.get('height') ?
924
+ setSize(settings.get('height'), 'y') - loadedHeight - interfaceHeight :
925
+ settings.get('innerHeight') && setSize(settings.get('innerHeight'), 'y');
926
+
927
+ settings.w = settings.get('width') ?
928
+ setSize(settings.get('width'), 'x') - loadedWidth - interfaceWidth :
929
+ settings.get('innerWidth') && setSize(settings.get('innerWidth'), 'x');
930
+
931
+ // Sets the minimum dimensions for use in image scaling
932
+ settings.mw = settings.w;
933
+ settings.mh = settings.h;
934
+
935
+ // Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
936
+ // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
937
+ if (settings.get('maxWidth')) {
938
+ settings.mw = setSize(settings.get('maxWidth'), 'x') - loadedWidth - interfaceWidth;
939
+ settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
940
+ }
941
+ if (settings.get('maxHeight')) {
942
+ settings.mh = setSize(settings.get('maxHeight'), 'y') - loadedHeight - interfaceHeight;
943
+ settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
944
+ }
945
+
946
+ href = settings.get('href');
947
+
948
+ loadingTimer = setTimeout(function () {
949
+ $loadingOverlay.show();
950
+ }, 100);
951
+
952
+ if (settings.get('inline')) {
953
+ var $target = $(href);
954
+ // Inserts an empty placeholder where inline content is being pulled from.
955
+ // An event is bound to put inline content back when Colorbox closes or loads new content.
956
+ $inline = $('<div>').hide().insertBefore($target);
957
+
958
+ $events.one(event_purge, function () {
959
+ $inline.replaceWith($target);
960
+ });
961
+
962
+ prep($target);
963
+ } else if (settings.get('iframe')) {
964
+ // IFrame element won't be added to the DOM until it is ready to be displayed,
965
+ // to avoid problems with DOM-ready JS that might be trying to run in that iframe.
966
+ prep(" ");
967
+ } else if (settings.get('html')) {
968
+ prep(settings.get('html'));
969
+ } else if (isImage(settings, href)) {
970
+
971
+ href = retinaUrl(settings, href);
972
+
973
+ photo = settings.get('createImg');
974
+
975
+ $(photo)
976
+ .addClass(prefix + 'Photo')
977
+ .bind('error.'+prefix,function () {
978
+ prep($tag(div, 'Error').html(settings.get('imgError')));
979
+ })
980
+ .one('load', function () {
981
+ if (request !== requests) {
982
+ return;
983
+ }
984
+
985
+ // A small pause because some browsers will occassionaly report a
986
+ // img.width and img.height of zero immediately after the img.onload fires
987
+ setTimeout(function(){
988
+ var percent;
989
+
990
+ if (settings.get('retinaImage') && window.devicePixelRatio > 1) {
991
+ photo.height = photo.height / window.devicePixelRatio;
992
+ photo.width = photo.width / window.devicePixelRatio;
993
+ }
994
+
995
+ if (settings.get('scalePhotos')) {
996
+ setResize = function () {
997
+ photo.height -= photo.height * percent;
998
+ photo.width -= photo.width * percent;
999
+ };
1000
+ if (settings.mw && photo.width > settings.mw) {
1001
+ percent = (photo.width - settings.mw) / photo.width;
1002
+ setResize();
1003
+ }
1004
+ if (settings.mh && photo.height > settings.mh) {
1005
+ percent = (photo.height - settings.mh) / photo.height;
1006
+ setResize();
1007
+ }
1008
+ }
1009
+
1010
+ if (settings.h) {
1011
+ photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px';
1012
+ }
1013
+
1014
+ if ($related[1] && (settings.get('loop') || $related[index + 1])) {
1015
+ photo.style.cursor = 'pointer';
1016
+
1017
+ $(photo).bind('click.'+prefix, function () {
1018
+ publicMethod.next();
1019
+ });
1020
+ }
1021
+
1022
+ photo.style.width = photo.width + 'px';
1023
+ photo.style.height = photo.height + 'px';
1024
+ prep(photo);
1025
+ }, 1);
1026
+ });
1027
+
1028
+ photo.src = href;
1029
+
1030
+ } else if (href) {
1031
+ $loadingBay.load(href, settings.get('data'), function (data, status) {
1032
+ if (request === requests) {
1033
+ prep(status === 'error' ? $tag(div, 'Error').html(settings.get('xhrError')) : $(this).contents());
1034
+ }
1035
+ });
1036
+ }
1037
+ }
1038
+
1039
+ // Navigates to the next page/image in a set.
1040
+ publicMethod.next = function () {
1041
+ if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) {
1042
+ index = getIndex(1);
1043
+ launch($related[index]);
1044
+ }
1045
+ };
1046
+
1047
+ publicMethod.prev = function () {
1048
+ if (!active && $related[1] && (settings.get('loop') || index)) {
1049
+ index = getIndex(-1);
1050
+ launch($related[index]);
1051
+ }
1052
+ };
1053
+
1054
+ // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close();
1055
+ publicMethod.close = function () {
1056
+ if (open && !closing) {
1057
+
1058
+ closing = true;
1059
+ open = false;
1060
+ trigger(event_cleanup);
1061
+ settings.get('onCleanup');
1062
+ $window.unbind('.' + prefix);
1063
+ $overlay.fadeTo(settings.get('fadeOut') || 0, 0);
1064
+
1065
+ $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () {
1066
+ $box.hide();
1067
+ $overlay.hide();
1068
+ trigger(event_purge);
1069
+ $loaded.remove();
1070
+
1071
+ setTimeout(function () {
1072
+ closing = false;
1073
+ trigger(event_closed);
1074
+ settings.get('onClosed');
1075
+ }, 1);
1076
+ });
1077
+ }
1078
+ };
1079
+
1080
+ // Removes changes Colorbox made to the document, but does not remove the plugin.
1081
+ publicMethod.remove = function () {
1082
+ if (!$box) { return; }
1083
+
1084
+ $box.stop();
1085
+ $[colorbox].close();
1086
+ $box.stop(false, true).remove();
1087
+ $overlay.remove();
1088
+ closing = false;
1089
+ $box = null;
1090
+ $('.' + boxElement)
1091
+ .removeData(colorbox)
1092
+ .removeClass(boxElement);
1093
+
1094
+ $(document).unbind('click.'+prefix).unbind('keydown.'+prefix);
1095
+ };
1096
+
1097
+ // A method for fetching the current element Colorbox is referencing.
1098
+ // returns a jQuery object.
1099
+ publicMethod.element = function () {
1100
+ return $(settings.el);
1101
+ };
1102
+
1103
+ publicMethod.settings = defaults;
1104
+
1105
  }(jQuery, document, window));
plugin-fw/assets/js/jquery.colorbox.min.js CHANGED
@@ -1,6 +1,6 @@
1
- /*!
2
- Colorbox 1.6.3
3
- license: MIT
4
- http://www.jacklmoore.com/colorbox
5
- */
6
  !function(t,e,i){var n,o,h,r,a,s,l,d,c,g,u,f,p,m,w,v,x,y,b,T,C,H,k,W,E,I,M,L,F,R,S,K,P,B={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:undefined,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return t(this).attr("href")},title:function(){return this.title},createImg:function(){var e=new Image,i=t(this).data("cbox-img-attrs");return"object"==typeof i&&t.each(i,function(t,i){e[t]=i}),e},createIframe:function(){var i=e.createElement("iframe"),n=t(this).data("cbox-iframe-attrs");return"object"==typeof n&&t.each(n,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},O="colorbox",_="cbox",j=_+"Element",D=_+"_open",N=_+"_load",z=_+"_complete",A=_+"_cleanup",U=_+"_closed",$=_+"_purge",q=t("<a/>"),G="div",Q=0,J={};function V(i,n,o){var h=e.createElement(i);return n&&(h.id=_+n),o&&(h.style.cssText=o),t(h)}function X(){return i.innerHeight?i.innerHeight:t(i).height()}function Y(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return this.cache[e]===undefined&&((n=t(this.el).attr("data-cbox-"+e))!==undefined?this.cache[e]=n:i[e]!==undefined?this.cache[e]=i[e]:B[e]!==undefined&&(this.cache[e]=B[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function Z(t){var e=c.length,i=(I+t)%e;return i<0?e+i:i}function tt(t,e){return Math.round((/%/.test(t)?("x"===e?g.width():X())/100:1)*parseInt(t,10))}function et(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function it(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function nt(t){"contains"in o[0]&&!o[0].contains(t.target)&&t.target!==n[0]&&(t.stopPropagation(),o.focus())}function ot(t){ot.str!==t&&(o.add(n).removeClass(ot.str).addClass(t),ot.str=t)}function ht(i){t(e).trigger(i),q.triggerHandler(i)}var rt=function(){var t,e,i=_+"Slideshow_",n="click."+_;function h(){clearTimeout(e)}function r(){(C.get("loop")||c[I+1])&&(h(),e=setTimeout(K.next,C.get("slideshowSpeed")))}function a(){v.html(C.get("slideshowStop")).unbind(n).one(n,s),q.bind(z,r).bind(N,h),o.removeClass(i+"off").addClass(i+"on")}function s(){h(),q.unbind(z,r).unbind(N,h),v.html(C.get("slideshowStart")).unbind(n).one(n,function(){K.next(),a()}),o.removeClass(i+"on").addClass(i+"off")}function l(){t=!1,v.hide(),h(),q.unbind(z,r).unbind(N,h),o.removeClass(i+"off "+i+"on")}return function(){t?C.get("slideshow")||(q.unbind(A,l),l()):C.get("slideshow")&&c[1]&&(t=!0,q.one(A,l),C.get("slideshowAuto")?a():s(),v.show())}}();function at(h){var g,w;if(!R){if(g=t(h).data(O),C=new Y(h,g),w=C.get("rel"),I=0,w&&!1!==w&&"nofollow"!==w?(c=t("."+j).filter(function(){return new Y(this,t.data(this,O)).get("rel")===w}),-1===(I=c.index(C.el))&&(c=c.add(C.el),I=c.length-1)):c=t(C.el),!L){L=F=!0,ot(C.get("className")),o.css({visibility:"hidden",display:"block",opacity:""}),u=V(G,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),r.css({width:"",height:""}).append(u),H=a.height()+d.height()+r.outerHeight(!0)-r.height(),k=s.width()+l.width()+r.outerWidth(!0)-r.width(),W=u.outerHeight(!0),E=u.outerWidth(!0);var v=tt(C.get("initialWidth"),"x"),x=tt(C.get("initialHeight"),"y"),y=C.get("maxWidth"),P=C.get("maxHeight");C.w=Math.max((!1!==y?Math.min(v,tt(y,"x")):v)-E-k,0),C.h=Math.max((!1!==P?Math.min(x,tt(P,"y")):x)-W-H,0),u.css({width:"",height:C.h}),K.position(),ht(D),C.get("onOpen"),T.add(m).hide(),o.focus(),C.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",nt,!0),q.one(U,function(){e.removeEventListener("focus",nt,!0)})),C.get("returnFocus")&&q.one(U,function(){t(C.el).focus()})}var B=parseFloat(C.get("opacity"));n.css({opacity:B==B?B:"",cursor:C.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),C.get("closeButton")?b.html(C.get("close")).appendTo(r):b.appendTo("<div/>"),function(){var e,n,o,h=K.prep,r=++Q;F=!0,M=!1,ht($),ht(N),C.get("onLoad"),C.h=C.get("height")?tt(C.get("height"),"y")-W-H:C.get("innerHeight")&&tt(C.get("innerHeight"),"y"),C.w=C.get("width")?tt(C.get("width"),"x")-E-k:C.get("innerWidth")&&tt(C.get("innerWidth"),"x"),C.mw=C.w,C.mh=C.h,C.get("maxWidth")&&(C.mw=tt(C.get("maxWidth"),"x")-E-k,C.mw=C.w&&C.w<C.mw?C.w:C.mw);C.get("maxHeight")&&(C.mh=tt(C.get("maxHeight"),"y")-W-H,C.mh=C.h&&C.h<C.mh?C.h:C.mh);if(e=C.get("href"),S=setTimeout(function(){p.show()},100),C.get("inline")){var a=t(e);o=t("<div>").hide().insertBefore(a),q.one($,function(){o.replaceWith(a)}),h(a)}else C.get("iframe")?h(" "):C.get("html")?h(C.get("html")):et(C,e)?(e=it(C,e),M=C.get("createImg"),t(M).addClass(_+"Photo").bind("error."+_,function(){h(V(G,"Error").html(C.get("imgError")))}).one("load",function(){r===Q&&setTimeout(function(){var e;C.get("retinaImage")&&i.devicePixelRatio>1&&(M.height=M.height/i.devicePixelRatio,M.width=M.width/i.devicePixelRatio),C.get("scalePhotos")&&(n=function(){M.height-=M.height*e,M.width-=M.width*e},C.mw&&M.width>C.mw&&(e=(M.width-C.mw)/M.width,n()),C.mh&&M.height>C.mh&&(e=(M.height-C.mh)/M.height,n())),C.h&&(M.style.marginTop=Math.max(C.mh-M.height,0)/2+"px"),c[1]&&(C.get("loop")||c[I+1])&&(M.style.cursor="pointer",t(M).bind("click."+_,function(){K.next()})),M.style.width=M.width+"px",M.style.height=M.height+"px",h(M)},1)}),M.src=e):e&&f.load(e,C.get("data"),function(e,i){r===Q&&h("error"===i?V(G,"Error").html(C.get("xhrError")):t(this).contents())})}()}}function st(){o||(P=!1,g=t(i),o=V(G).attr({id:O,"class":!1===t.support.opacity?_+"IE":"",role:"dialog",tabindex:"-1"}).hide(),n=V(G,"Overlay").hide(),p=t([V(G,"LoadingOverlay")[0],V(G,"LoadingGraphic")[0]]),h=V(G,"Wrapper"),r=V(G,"Content").append(m=V(G,"Title"),w=V(G,"Current"),y=t('<button type="button"/>').attr({id:_+"Previous"}),x=t('<button type="button"/>').attr({id:_+"Next"}),v=V("button","Slideshow"),p),b=t('<button type="button"/>').attr({id:_+"Close"}),h.append(V(G).append(V(G,"TopLeft"),a=V(G,"TopCenter"),V(G,"TopRight")),V(G,!1,"clear:left").append(s=V(G,"MiddleLeft"),r,l=V(G,"MiddleRight")),V(G,!1,"clear:left").append(V(G,"BottomLeft"),d=V(G,"BottomCenter"),V(G,"BottomRight"))).find("div div").css({float:"left"}),f=V(G,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),T=x.add(y).add(w).add(v)),e.body&&!o.parent().length&&t(e.body).append(n,o.append(h,f))}function lt(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),at(this))}return!!o&&(P||(P=!0,x.click(function(){K.next()}),y.click(function(){K.prev()}),b.click(function(){K.close()}),n.click(function(){C.get("overlayClose")&&K.close()}),t(e).bind("keydown."+_,function(t){var e=t.keyCode;L&&C.get("escKey")&&27===e&&(t.preventDefault(),K.close()),L&&C.get("arrowKey")&&c[1]&&!t.altKey&&(37===e?(t.preventDefault(),y.click()):39===e&&(t.preventDefault(),x.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+_,"."+j,i):t("."+j).live("click."+_,i)),!0)}t[O]||(t(st),(K=t.fn[O]=t[O]=function(e,i){var n=this;return e=e||{},t.isFunction(n)&&(n=t("<a/>"),e.open=!0),n[0]?(st(),lt()&&(i&&(e.onComplete=i),n.each(function(){var i=t.data(this,O)||{};t.data(this,O,t.extend(i,e))}).addClass(j),new Y(n[0],e).get("open")&&at(n[0])),n):n}).position=function(e,i){var n,c,u,f=0,p=0,m=o.offset();function w(){a[0].style.width=d[0].style.width=r[0].style.width=parseInt(o[0].style.width,10)-k+"px",r[0].style.height=s[0].style.height=l[0].style.height=parseInt(o[0].style.height,10)-H+"px"}if(g.unbind("resize."+_),o.css({top:-9e4,left:-9e4}),c=g.scrollTop(),u=g.scrollLeft(),C.get("fixed")?(m.top-=c,m.left-=u,o.css({position:"fixed"})):(f=c,p=u,o.css({position:"absolute"})),!1!==C.get("right")?p+=Math.max(g.width()-C.w-E-k-tt(C.get("right"),"x"),0):!1!==C.get("left")?p+=tt(C.get("left"),"x"):p+=Math.round(Math.max(g.width()-C.w-E-k,0)/2),!1!==C.get("bottom")?f+=Math.max(X()-C.h-W-H-tt(C.get("bottom"),"y"),0):!1!==C.get("top")?f+=tt(C.get("top"),"y"):f+=Math.round(Math.max(X()-C.h-W-H,0)/2),o.css({top:m.top,left:m.left,visibility:"visible"}),h[0].style.width=h[0].style.height="9999px",n={width:C.w+E+k,height:C.h+W+H,top:f,left:p},e){var v=0;t.each(n,function(t){n[t]===J[t]||(v=e)}),e=v}J=n,e||o.css(n),o.dequeue().animate(n,{duration:e||0,complete:function(){w(),F=!1,h[0].style.width=C.w+E+k+"px",h[0].style.height=C.h+W+H+"px",C.get("reposition")&&setTimeout(function(){g.bind("resize."+_,K.position)},1),t.isFunction(i)&&i()},step:w})},K.resize=function(t){var e;L&&((t=t||{}).width&&(C.w=tt(t.width,"x")-E-k),t.innerWidth&&(C.w=tt(t.innerWidth,"x")),u.css({width:C.w}),t.height&&(C.h=tt(t.height,"y")-W-H),t.innerHeight&&(C.h=tt(t.innerHeight,"y")),t.innerHeight||t.height||(e=u.scrollTop(),u.css({height:"auto"}),C.h=u.height()),u.css({height:C.h}),e&&u.scrollTop(e),K.position("none"===C.get("transition")?0:C.get("speed")))},K.prep=function(i){if(L){var n,h="none"===C.get("transition")?0:C.get("speed");u.remove(),(u=V(G,"LoadedContent").append(i)).hide().appendTo(f.show()).css({width:(C.w=C.w||u.width(),C.w=C.mw&&C.mw<C.w?C.mw:C.w,C.w),overflow:C.get("scrolling")?"auto":"hidden"}).css({height:(C.h=C.h||u.height(),C.h=C.mh&&C.mh<C.h?C.mh:C.h,C.h)}).prependTo(r),f.hide(),t(M).css({float:"none"}),ot(C.get("className")),n=function(){var i,n,r=c.length;function a(){!1===t.support.opacity&&o[0].style.removeAttribute("filter")}L&&(n=function(){clearTimeout(S),p.hide(),ht(z),C.get("onComplete")},m.html(C.get("title")).show(),u.show(),r>1?("string"==typeof C.get("current")&&w.html(C.get("current").replace("{current}",I+1).replace("{total}",r)).show(),x[C.get("loop")||I<r-1?"show":"hide"]().html(C.get("next")),y[C.get("loop")||I?"show":"hide"]().html(C.get("previous")),rt(),C.get("preloading")&&t.each([Z(-1),Z(1)],function(){var i=c[this],n=new Y(i,t.data(i,O)),o=n.get("href");o&&et(n,o)&&(o=it(n,o),e.createElement("img").src=o)})):T.hide(),C.get("iframe")?(i=C.get("createIframe"),C.get("scrolling")||(i.scrolling="no"),t(i).attr({src:C.get("href"),"class":_+"Iframe"}).one("load",n).appendTo(u),q.one($,function(){i.src="//about:blank"}),C.get("fastIframe")&&t(i).trigger("load")):n(),"fade"===C.get("transition")?o.fadeTo(h,1,a):a())},"fade"===C.get("transition")?o.fadeTo(h,0,function(){K.position(0,n)}):K.position(h,n)}},K.next=function(){!F&&c[1]&&(C.get("loop")||c[I+1])&&(I=Z(1),at(c[I]))},K.prev=function(){!F&&c[1]&&(C.get("loop")||I)&&(I=Z(-1),at(c[I]))},K.close=function(){L&&!R&&(R=!0,L=!1,ht(A),C.get("onCleanup"),g.unbind("."+_),n.fadeTo(C.get("fadeOut")||0,0),o.stop().fadeTo(C.get("fadeOut")||0,0,function(){o.hide(),n.hide(),ht($),u.remove(),setTimeout(function(){R=!1,ht(U),C.get("onClosed")},1)}))},K.remove=function(){o&&(o.stop(),t[O].close(),o.stop(!1,!0).remove(),n.remove(),R=!1,o=null,t("."+j).removeData(O).removeClass(j),t(e).unbind("click."+_).unbind("keydown."+_))},K.element=function(){return t(C.el)},K.settings=B)}(jQuery,document,window);
1
+ /*!
2
+ Colorbox 1.6.3
3
+ license: MIT
4
+ http://www.jacklmoore.com/colorbox
5
+ */
6
  !function(t,e,i){var n,o,h,r,a,s,l,d,c,g,u,f,p,m,w,v,x,y,b,T,C,H,k,W,E,I,M,L,F,R,S,K,P,B={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:undefined,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return t(this).attr("href")},title:function(){return this.title},createImg:function(){var e=new Image,i=t(this).data("cbox-img-attrs");return"object"==typeof i&&t.each(i,function(t,i){e[t]=i}),e},createIframe:function(){var i=e.createElement("iframe"),n=t(this).data("cbox-iframe-attrs");return"object"==typeof n&&t.each(n,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},O="colorbox",_="cbox",j=_+"Element",D=_+"_open",N=_+"_load",z=_+"_complete",A=_+"_cleanup",U=_+"_closed",$=_+"_purge",q=t("<a/>"),G="div",Q=0,J={};function V(i,n,o){var h=e.createElement(i);return n&&(h.id=_+n),o&&(h.style.cssText=o),t(h)}function X(){return i.innerHeight?i.innerHeight:t(i).height()}function Y(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return this.cache[e]===undefined&&((n=t(this.el).attr("data-cbox-"+e))!==undefined?this.cache[e]=n:i[e]!==undefined?this.cache[e]=i[e]:B[e]!==undefined&&(this.cache[e]=B[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function Z(t){var e=c.length,i=(I+t)%e;return i<0?e+i:i}function tt(t,e){return Math.round((/%/.test(t)?("x"===e?g.width():X())/100:1)*parseInt(t,10))}function et(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function it(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function nt(t){"contains"in o[0]&&!o[0].contains(t.target)&&t.target!==n[0]&&(t.stopPropagation(),o.focus())}function ot(t){ot.str!==t&&(o.add(n).removeClass(ot.str).addClass(t),ot.str=t)}function ht(i){t(e).trigger(i),q.triggerHandler(i)}var rt=function(){var t,e,i=_+"Slideshow_",n="click."+_;function h(){clearTimeout(e)}function r(){(C.get("loop")||c[I+1])&&(h(),e=setTimeout(K.next,C.get("slideshowSpeed")))}function a(){v.html(C.get("slideshowStop")).unbind(n).one(n,s),q.bind(z,r).bind(N,h),o.removeClass(i+"off").addClass(i+"on")}function s(){h(),q.unbind(z,r).unbind(N,h),v.html(C.get("slideshowStart")).unbind(n).one(n,function(){K.next(),a()}),o.removeClass(i+"on").addClass(i+"off")}function l(){t=!1,v.hide(),h(),q.unbind(z,r).unbind(N,h),o.removeClass(i+"off "+i+"on")}return function(){t?C.get("slideshow")||(q.unbind(A,l),l()):C.get("slideshow")&&c[1]&&(t=!0,q.one(A,l),C.get("slideshowAuto")?a():s(),v.show())}}();function at(h){var g,w;if(!R){if(g=t(h).data(O),C=new Y(h,g),w=C.get("rel"),I=0,w&&!1!==w&&"nofollow"!==w?(c=t("."+j).filter(function(){return new Y(this,t.data(this,O)).get("rel")===w}),-1===(I=c.index(C.el))&&(c=c.add(C.el),I=c.length-1)):c=t(C.el),!L){L=F=!0,ot(C.get("className")),o.css({visibility:"hidden",display:"block",opacity:""}),u=V(G,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),r.css({width:"",height:""}).append(u),H=a.height()+d.height()+r.outerHeight(!0)-r.height(),k=s.width()+l.width()+r.outerWidth(!0)-r.width(),W=u.outerHeight(!0),E=u.outerWidth(!0);var v=tt(C.get("initialWidth"),"x"),x=tt(C.get("initialHeight"),"y"),y=C.get("maxWidth"),P=C.get("maxHeight");C.w=Math.max((!1!==y?Math.min(v,tt(y,"x")):v)-E-k,0),C.h=Math.max((!1!==P?Math.min(x,tt(P,"y")):x)-W-H,0),u.css({width:"",height:C.h}),K.position(),ht(D),C.get("onOpen"),T.add(m).hide(),o.focus(),C.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",nt,!0),q.one(U,function(){e.removeEventListener("focus",nt,!0)})),C.get("returnFocus")&&q.one(U,function(){t(C.el).focus()})}var B=parseFloat(C.get("opacity"));n.css({opacity:B==B?B:"",cursor:C.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),C.get("closeButton")?b.html(C.get("close")).appendTo(r):b.appendTo("<div/>"),function(){var e,n,o,h=K.prep,r=++Q;F=!0,M=!1,ht($),ht(N),C.get("onLoad"),C.h=C.get("height")?tt(C.get("height"),"y")-W-H:C.get("innerHeight")&&tt(C.get("innerHeight"),"y"),C.w=C.get("width")?tt(C.get("width"),"x")-E-k:C.get("innerWidth")&&tt(C.get("innerWidth"),"x"),C.mw=C.w,C.mh=C.h,C.get("maxWidth")&&(C.mw=tt(C.get("maxWidth"),"x")-E-k,C.mw=C.w&&C.w<C.mw?C.w:C.mw);C.get("maxHeight")&&(C.mh=tt(C.get("maxHeight"),"y")-W-H,C.mh=C.h&&C.h<C.mh?C.h:C.mh);if(e=C.get("href"),S=setTimeout(function(){p.show()},100),C.get("inline")){var a=t(e);o=t("<div>").hide().insertBefore(a),q.one($,function(){o.replaceWith(a)}),h(a)}else C.get("iframe")?h(" "):C.get("html")?h(C.get("html")):et(C,e)?(e=it(C,e),M=C.get("createImg"),t(M).addClass(_+"Photo").bind("error."+_,function(){h(V(G,"Error").html(C.get("imgError")))}).one("load",function(){r===Q&&setTimeout(function(){var e;C.get("retinaImage")&&i.devicePixelRatio>1&&(M.height=M.height/i.devicePixelRatio,M.width=M.width/i.devicePixelRatio),C.get("scalePhotos")&&(n=function(){M.height-=M.height*e,M.width-=M.width*e},C.mw&&M.width>C.mw&&(e=(M.width-C.mw)/M.width,n()),C.mh&&M.height>C.mh&&(e=(M.height-C.mh)/M.height,n())),C.h&&(M.style.marginTop=Math.max(C.mh-M.height,0)/2+"px"),c[1]&&(C.get("loop")||c[I+1])&&(M.style.cursor="pointer",t(M).bind("click."+_,function(){K.next()})),M.style.width=M.width+"px",M.style.height=M.height+"px",h(M)},1)}),M.src=e):e&&f.load(e,C.get("data"),function(e,i){r===Q&&h("error"===i?V(G,"Error").html(C.get("xhrError")):t(this).contents())})}()}}function st(){o||(P=!1,g=t(i),o=V(G).attr({id:O,"class":!1===t.support.opacity?_+"IE":"",role:"dialog",tabindex:"-1"}).hide(),n=V(G,"Overlay").hide(),p=t([V(G,"LoadingOverlay")[0],V(G,"LoadingGraphic")[0]]),h=V(G,"Wrapper"),r=V(G,"Content").append(m=V(G,"Title"),w=V(G,"Current"),y=t('<button type="button"/>').attr({id:_+"Previous"}),x=t('<button type="button"/>').attr({id:_+"Next"}),v=V("button","Slideshow"),p),b=t('<button type="button"/>').attr({id:_+"Close"}),h.append(V(G).append(V(G,"TopLeft"),a=V(G,"TopCenter"),V(G,"TopRight")),V(G,!1,"clear:left").append(s=V(G,"MiddleLeft"),r,l=V(G,"MiddleRight")),V(G,!1,"clear:left").append(V(G,"BottomLeft"),d=V(G,"BottomCenter"),V(G,"BottomRight"))).find("div div").css({float:"left"}),f=V(G,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),T=x.add(y).add(w).add(v)),e.body&&!o.parent().length&&t(e.body).append(n,o.append(h,f))}function lt(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),at(this))}return!!o&&(P||(P=!0,x.click(function(){K.next()}),y.click(function(){K.prev()}),b.click(function(){K.close()}),n.click(function(){C.get("overlayClose")&&K.close()}),t(e).bind("keydown."+_,function(t){var e=t.keyCode;L&&C.get("escKey")&&27===e&&(t.preventDefault(),K.close()),L&&C.get("arrowKey")&&c[1]&&!t.altKey&&(37===e?(t.preventDefault(),y.click()):39===e&&(t.preventDefault(),x.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+_,"."+j,i):t("."+j).live("click."+_,i)),!0)}t[O]||(t(st),(K=t.fn[O]=t[O]=function(e,i){var n=this;return e=e||{},t.isFunction(n)&&(n=t("<a/>"),e.open=!0),n[0]?(st(),lt()&&(i&&(e.onComplete=i),n.each(function(){var i=t.data(this,O)||{};t.data(this,O,t.extend(i,e))}).addClass(j),new Y(n[0],e).get("open")&&at(n[0])),n):n}).position=function(e,i){var n,c,u,f=0,p=0,m=o.offset();function w(){a[0].style.width=d[0].style.width=r[0].style.width=parseInt(o[0].style.width,10)-k+"px",r[0].style.height=s[0].style.height=l[0].style.height=parseInt(o[0].style.height,10)-H+"px"}if(g.unbind("resize."+_),o.css({top:-9e4,left:-9e4}),c=g.scrollTop(),u=g.scrollLeft(),C.get("fixed")?(m.top-=c,m.left-=u,o.css({position:"fixed"})):(f=c,p=u,o.css({position:"absolute"})),!1!==C.get("right")?p+=Math.max(g.width()-C.w-E-k-tt(C.get("right"),"x"),0):!1!==C.get("left")?p+=tt(C.get("left"),"x"):p+=Math.round(Math.max(g.width()-C.w-E-k,0)/2),!1!==C.get("bottom")?f+=Math.max(X()-C.h-W-H-tt(C.get("bottom"),"y"),0):!1!==C.get("top")?f+=tt(C.get("top"),"y"):f+=Math.round(Math.max(X()-C.h-W-H,0)/2),o.css({top:m.top,left:m.left,visibility:"visible"}),h[0].style.width=h[0].style.height="9999px",n={width:C.w+E+k,height:C.h+W+H,top:f,left:p},e){var v=0;t.each(n,function(t){n[t]===J[t]||(v=e)}),e=v}J=n,e||o.css(n),o.dequeue().animate(n,{duration:e||0,complete:function(){w(),F=!1,h[0].style.width=C.w+E+k+"px",h[0].style.height=C.h+W+H+"px",C.get("reposition")&&setTimeout(function(){g.bind("resize."+_,K.position)},1),t.isFunction(i)&&i()},step:w})},K.resize=function(t){var e;L&&((t=t||{}).width&&(C.w=tt(t.width,"x")-E-k),t.innerWidth&&(C.w=tt(t.innerWidth,"x")),u.css({width:C.w}),t.height&&(C.h=tt(t.height,"y")-W-H),t.innerHeight&&(C.h=tt(t.innerHeight,"y")),t.innerHeight||t.height||(e=u.scrollTop(),u.css({height:"auto"}),C.h=u.height()),u.css({height:C.h}),e&&u.scrollTop(e),K.position("none"===C.get("transition")?0:C.get("speed")))},K.prep=function(i){if(L){var n,h="none"===C.get("transition")?0:C.get("speed");u.remove(),(u=V(G,"LoadedContent").append(i)).hide().appendTo(f.show()).css({width:(C.w=C.w||u.width(),C.w=C.mw&&C.mw<C.w?C.mw:C.w,C.w),overflow:C.get("scrolling")?"auto":"hidden"}).css({height:(C.h=C.h||u.height(),C.h=C.mh&&C.mh<C.h?C.mh:C.h,C.h)}).prependTo(r),f.hide(),t(M).css({float:"none"}),ot(C.get("className")),n=function(){var i,n,r=c.length;function a(){!1===t.support.opacity&&o[0].style.removeAttribute("filter")}L&&(n=function(){clearTimeout(S),p.hide(),ht(z),C.get("onComplete")},m.html(C.get("title")).show(),u.show(),r>1?("string"==typeof C.get("current")&&w.html(C.get("current").replace("{current}",I+1).replace("{total}",r)).show(),x[C.get("loop")||I<r-1?"show":"hide"]().html(C.get("next")),y[C.get("loop")||I?"show":"hide"]().html(C.get("previous")),rt(),C.get("preloading")&&t.each([Z(-1),Z(1)],function(){var i=c[this],n=new Y(i,t.data(i,O)),o=n.get("href");o&&et(n,o)&&(o=it(n,o),e.createElement("img").src=o)})):T.hide(),C.get("iframe")?(i=C.get("createIframe"),C.get("scrolling")||(i.scrolling="no"),t(i).attr({src:C.get("href"),"class":_+"Iframe"}).one("load",n).appendTo(u),q.one($,function(){i.src="//about:blank"}),C.get("fastIframe")&&t(i).trigger("load")):n(),"fade"===C.get("transition")?o.fadeTo(h,1,a):a())},"fade"===C.get("transition")?o.fadeTo(h,0,function(){K.position(0,n)}):K.position(h,n)}},K.next=function(){!F&&c[1]&&(C.get("loop")||c[I+1])&&(I=Z(1),at(c[I]))},K.prev=function(){!F&&c[1]&&(C.get("loop")||I)&&(I=Z(-1),at(c[I]))},K.close=function(){L&&!R&&(R=!0,L=!1,ht(A),C.get("onCleanup"),g.unbind("."+_),n.fadeTo(C.get("fadeOut")||0,0),o.stop().fadeTo(C.get("fadeOut")||0,0,function(){o.hide(),n.hide(),ht($),u.remove(),setTimeout(function(){R=!1,ht(U),C.get("onClosed")},1)}))},K.remove=function(){o&&(o.stop(),t[O].close(),o.stop(!1,!0).remove(),n.remove(),R=!1,o=null,t("."+j).removeData(O).removeClass(j),t(e).unbind("click."+_).unbind("keydown."+_))},K.element=function(){return t(C.el)},K.settings=B)}(jQuery,document,window);
plugin-fw/assets/js/multisite-updater.js CHANGED
@@ -1,222 +1,222 @@
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( ".plugin-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 = '*[data-slug="' + 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 notice inline notice-warning notice-alt">' + localize.strings.new_version.replace( '%plugin_name%', name ) +
64
- '<a class="thickbox open-plugin-details-modal" 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( version_compare( plugin[ headers ].Version, plugin[ headers ].Latest, '>' ) ){
77
- html = html + localize.strings.version_issue.replace( '%plugin_name%', name )
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
- // fix ThickBox issue (width-height) when opening a changelog
217
- $( 'body' ).on( 'click', '.yit-changelog-button', function () {
218
- $( '#TB_window' ).remove();
219
- } );
220
-
221
-
222
- })( jQuery );
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( ".plugin-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 = '*[data-slug="' + 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 notice inline notice-warning notice-alt">' + localize.strings.new_version.replace( '%plugin_name%', name ) +
64
+ '<a class="thickbox open-plugin-details-modal" 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( version_compare( plugin[ headers ].Version, plugin[ headers ].Latest, '>' ) ){
77
+ html = html + localize.strings.version_issue.replace( '%plugin_name%', name )
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
+ // fix ThickBox issue (width-height) when opening a changelog
217
+ $( 'body' ).on( 'click', '.yit-changelog-button', function () {
218
+ $( '#TB_window' ).remove();
219
+ } );
220
+
221
+
222
+ })( jQuery );
plugin-fw/assets/js/wp-pages.js CHANGED
@@ -1,76 +1,76 @@
1
- /* global yith_plugin_fw_wp_pages */
2
- jQuery( function ( $ ) {
3
- var wrap = $( '.yith-plugin-fw-wp-page-wrapper' ),
4
- notices = $( 'div.updated, div.error, div.notice' ).not( '#message' ),
5
- message = $( 'div#message.updated' );
6
-
7
- // prevents the WC message for changes when leaving the panel page
8
- $( '.yith-plugin-fw-wp-page-wrapper .woo-nav-tab-wrapper' ).removeClass( 'woo-nav-tab-wrapper' ).addClass( 'yith-nav-tab-wrapper' );
9
-
10
- // prevent moving notices withing the tab in WP Pages and move them into the wrapper
11
- notices.addClass( 'inline' );
12
- if ( wrap.length ) {
13
- wrap.prepend( notices );
14
- }
15
-
16
- // Update message animation.
17
- if ( message.length ) {
18
- message.addClass( 'yith-plugin-fw-animate__appear-from-top' ).show();
19
- message.on( 'click', '.notice-dismiss', function ( e ) {
20
- e.stopPropagation();
21
- message.removeClass( 'yith-plugin-fw-animate__appear-from-top' ).slideUp( 200 );
22
- } )
23
- }
24
-
25
- // Confirmation window when deleting custom post types and custom terms through Bulk Actions.
26
- if ( yith_plugin_fw_wp_pages.bulk_delete_confirmation_enabled ) {
27
- var bulkDeleteConfirmed = false;
28
-
29
- $( document ).on( 'click', '#doaction, #doaction2', function ( e ) {
30
- var doActionButton = $( this ),
31
- bulkActionSelector = doActionButton.siblings( '#bulk-action-selector-top, #bulk-action-selector-bottom' );
32
-
33
- if ( 'yith' in window && 'ui' in yith ) {
34
- if ( bulkDeleteConfirmed ) {
35
- bulkDeleteConfirmed = false;
36
- } else {
37
- var confirmOptions = {},
38
- selectedItems = $( '#the-list .check-column input[type=checkbox]:checked' );
39
-
40
- if ( selectedItems.length ) {
41
- switch ( bulkActionSelector.val() ) {
42
- case 'trash':
43
- confirmOptions.title = yith_plugin_fw_wp_pages.i18n.bulk_trash_confirm_title;
44
- confirmOptions.message = yith_plugin_fw_wp_pages.i18n.bulk_trash_confirm_message;
45
- confirmOptions.cancelButton = yith_plugin_fw_wp_pages.i18n.bulk_trash_cancel_button;
46
- confirmOptions.confirmButton = yith_plugin_fw_wp_pages.i18n.bulk_trash_confirm_button;
47
- confirmOptions.confirmButtonType = 'delete';
48
- break;
49
- case 'delete':
50
- confirmOptions.title = yith_plugin_fw_wp_pages.i18n.bulk_delete_confirm_title;
51
- confirmOptions.message = yith_plugin_fw_wp_pages.i18n.bulk_delete_confirm_message;
52
- confirmOptions.cancelButton = yith_plugin_fw_wp_pages.i18n.bulk_delete_cancel_button;
53
- confirmOptions.confirmButton = yith_plugin_fw_wp_pages.i18n.bulk_delete_confirm_button;
54
- confirmOptions.confirmButtonType = 'delete';
55
- break;
56
- }
57
-
58
- if ( !$.isEmptyObject( confirmOptions ) ) {
59
- e.preventDefault();
60
-
61
- confirmOptions.closeAfterConfirm = false;
62
- confirmOptions.onConfirm = function () {
63
- bulkDeleteConfirmed = true;
64
- doActionButton.trigger( 'click' );
65
- };
66
-
67
- yith.ui.confirm( confirmOptions );
68
- }
69
- }
70
- }
71
-
72
- }
73
- } );
74
- }
75
-
76
  } );
1
+ /* global yith_plugin_fw_wp_pages */
2
+ jQuery( function ( $ ) {
3
+ var wrap = $( '.yith-plugin-fw-wp-page-wrapper' ),
4
+ notices = $( 'div.updated, div.error, div.notice' ).not( '#message' ),
5
+ message = $( 'div#message.updated' );
6
+
7
+ // prevents the WC message for changes when leaving the panel page
8
+ $( '.yith-plugin-fw-wp-page-wrapper .woo-nav-tab-wrapper' ).removeClass( 'woo-nav-tab-wrapper' ).addClass( 'yith-nav-tab-wrapper' );
9
+
10
+ // prevent moving notices withing the tab in WP Pages and move them into the wrapper
11
+ notices.addClass( 'inline' );
12
+ if ( wrap.length ) {
13
+ wrap.prepend( notices );
14
+ }
15
+
16
+ // Update message animation.
17
+ if ( message.length ) {
18
+ message.addClass( 'yith-plugin-fw-animate__appear-from-top' ).show();
19
+ message.on( 'click', '.notice-dismiss', function ( e ) {
20
+ e.stopPropagation();
21
+ message.removeClass( 'yith-plugin-fw-animate__appear-from-top' ).slideUp( 200 );
22
+ } )
23
+ }
24
+
25
+ // Confirmation window when deleting custom post types and custom terms through Bulk Actions.
26
+ if ( yith_plugin_fw_wp_pages.bulk_delete_confirmation_enabled ) {
27
+ var bulkDeleteConfirmed = false;
28
+
29
+ $( document ).on( 'click', '#doaction, #doaction2', function ( e ) {
30
+ var doActionButton = $( this ),
31
+ bulkActionSelector = doActionButton.siblings( '#bulk-action-selector-top, #bulk-action-selector-bottom' );
32
+
33
+ if ( 'yith' in window && 'ui' in yith ) {
34
+ if ( bulkDeleteConfirmed ) {
35
+ bulkDeleteConfirmed = false;
36
+ } else {
37
+ var confirmOptions = {},
38
+ selectedItems = $( '#the-list .check-column input[type=checkbox]:checked' );
39
+
40
+ if ( selectedItems.length ) {
41
+ switch ( bulkActionSelector.val() ) {
42
+ case 'trash':
43
+ confirmOptions.title = yith_plugin_fw_wp_pages.i18n.bulk_trash_confirm_title;
44
+ confirmOptions.message = yith_plugin_fw_wp_pages.i18n.bulk_trash_confirm_message;
45
+ confirmOptions.cancelButton = yith_plugin_fw_wp_pages.i18n.bulk_trash_cancel_button;
46
+ confirmOptions.confirmButton = yith_plugin_fw_wp_pages.i18n.bulk_trash_confirm_button;
47
+ confirmOptions.confirmButtonType = 'delete';
48
+ break;
49
+ case 'delete':
50
+ confirmOptions.title = yith_plugin_fw_wp_pages.i18n.bulk_delete_confirm_title;
51
+ confirmOptions.message = yith_plugin_fw_wp_pages.i18n.bulk_delete_confirm_message;
52
+ confirmOptions.cancelButton = yith_plugin_fw_wp_pages.i18n.bulk_delete_cancel_button;
53
+ confirmOptions.confirmButton = yith_plugin_fw_wp_pages.i18n.bulk_delete_confirm_button;
54
+ confirmOptions.confirmButtonType = 'delete';
55
+ break;
56
+ }
57
+
58
+ if ( !$.isEmptyObject( confirmOptions ) ) {
59
+ e.preventDefault();
60
+
61
+ confirmOptions.closeAfterConfirm = false;
62
+ confirmOptions.onConfirm = function () {
63
+ bulkDeleteConfirmed = true;
64
+ doActionButton.trigger( 'click' );
65
+ };
66
+
67
+ yith.ui.confirm( confirmOptions );
68
+ }
69
+ }
70
+ }
71
+
72
+ }
73
+ } );
74
+ }
75
+
76
  } );
plugin-fw/assets/js/yit-cpt-unlimited.js CHANGED
@@ -1,80 +1,80 @@
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 h1, .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
- console.log( button.data('nonce') );
55
- // make AJAX request
56
- $.post( ajaxurl, {
57
- images: images,
58
- post_type: typenow,
59
- action: 'yit_cptu_multiuploader',
60
- _ajax_nonce: button.data('nonce')
61
- }, function( data ){
62
- location.reload();
63
- });
64
-
65
- button.next('span.spinner').css( 'display', 'inline-block' );
66
-
67
- // flag
68
- selected = true;
69
- });
70
-
71
- // when close
72
- file_frame.on( 'close', function() {
73
- if ( ! selected ) button.next('span.spinner').hide();
74
- });
75
-
76
- // Finally, open the modal
77
- file_frame.open();
78
- });
79
-
80
  })(jQuery);
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 h1, .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
+ console.log( button.data('nonce') );
55
+ // make AJAX request
56
+ $.post( ajaxurl, {
57
+ images: images,
58
+ post_type: typenow,
59
+ action: 'yit_cptu_multiuploader',
60
+ _ajax_nonce: button.data('nonce')
61
+ }, function( data ){
62
+ location.reload();
63
+ });
64
+
65
+ button.next('span.spinner').css( 'display', 'inline-block' );
66
+
67
+ // flag
68
+ selected = true;
69
+ });
70
+
71
+ // when close
72
+ file_frame.on( 'close', function() {
73
+ if ( ! selected ) button.next('span.spinner').hide();
74
+ });
75
+
76
+ // Finally, open the modal
77
+ file_frame.open();
78
+ });
79
+
80
  })(jQuery);
plugin-fw/assets/js/yit-plugin-panel.js CHANGED
@@ -1,302 +1,302 @@
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
- jQuery( function ( $ ) {
11
- // Handle dependencies.
12
- function dependencies_handler( id, deps, values, type ) {
13
- var result = true;
14
- if ( typeof ( deps ) == 'string' ) {
15
- if ( deps.substr( 0, 6 ) === ':radio' ) {
16
- deps = deps + ':checked';
17
- }
18
-
19
- var depsOn = $( deps ),
20
- depsOnType = depsOn.attr( 'type' ),
21
- val = depsOn.val();
22
-
23
- switch ( depsOnType ) {
24
- case 'checkbox':
25
- val = depsOn.is( ':checked' ) ? 'yes' : 'no';
26
- break;
27
- case 'radio':
28
- val = depsOn.find( 'input[type="radio"]' ).filter( ':checked' ).val();
29
- break;
30
- }
31
-
32
- values = values.split( ',' );
33
-
34
- for ( var i = 0; i < values.length; i++ ) {
35
- if ( val != values[ i ] ) {
36
- result = false;
37
- } else {
38
- result = true;
39
- break;
40
- }
41
- }
42
- }
43
-
44
- var $current_field = $( id ),
45
- $current_container = $( id + '-container' ).closest( 'tr' ); // container for YIT Plugin Panel
46
-
47
- if ( $current_container.length < 1 ) {
48
- // container for YIT Plugin Panel WooCommerce
49
- $current_container = $current_field.closest( '.yith-plugin-fw-panel-wc-row, .yith-toggle-content-row' );
50
- }
51
-
52
- var types = type.split( '-' ), j;
53
- for ( j in types ) {
54
- var current_type = types[ j ];
55
-
56
- if ( !result ) {
57
- switch ( current_type ) {
58
- case 'disable':
59
- $current_container.addClass( 'yith-disabled' );
60
- $current_field.attr( 'disabled', true );
61
- break;
62
- case 'hide':
63
- case 'hideNow':
64
- $current_container.hide();
65
- break;
66
- case 'hideme':
67
- $current_field.hide();
68
- break;
69
- case 'fadeInOut':
70
- case 'fadeOut':
71
- $current_container.hide( 500 );
72
- break;
73
- case 'fadeIn':
74
- default:
75
- $current_container.hide();
76
- }
77
- } else {
78
- switch ( current_type ) {
79
- case 'disable':
80
- $current_container.removeClass( 'yith-disabled' );
81
- $current_field.attr( 'disabled', false );
82
- break;
83
- case 'hide':
84
- case 'hideNow':
85
- $current_container.show();
86
- break;
87
- case 'hideme':
88
- $current_field.show();
89
- break;
90
- case 'fadeOut':
91
- $current_container.show();
92
- break;
93
- case 'fadeInOut':
94
- case 'fadeIn':
95
- default:
96
- $current_container.show( 500 );
97
- }
98
- }
99
- }
100
- }
101
-
102
- function init_dependencies() {
103
- $( '[data-dep-target]:not( .deps-initialized )' ).each( function () {
104
- var t = $( this );
105
-
106
- if ( t.closest( '.metaboxes-tab' ).length ) {
107
- // Let meta-boxes handle their own deps.
108
- return;
109
- }
110
-
111
- // init field deps
112
- t.addClass( 'deps-initialized' );
113
-
114
- var field = '#' + t.data( 'dep-target' ),
115
- dep = '#' + t.data( 'dep-id' ),
116
- value = t.data( 'dep-value' ),
117
- type = t.data( 'dep-type' );
118
-
119
- $( dep ).on( 'change', function () {
120
- dependencies_handler( field, dep, value.toString(), type );
121
- } ).trigger( 'change' );
122
- } );
123
- }
124
-
125
- init_dependencies();
126
- // re-init deps after an add toggle action
127
- $( document ).on( 'yith-add-box-button-toggle', init_dependencies );
128
-
129
- //connected list
130
- $( '.rm_connectedlist' ).each( function () {
131
- var ul = $( this ).find( 'ul' );
132
- var input = $( this ).find( ':hidden' );
133
- var sortable = ul.sortable( {
134
- connectWith: ul,
135
- update : function ( event, ui ) {
136
- var value = {};
137
-
138
- ul.each( function () {
139
- var options = {};
140
-
141
- $( this ).children().each( function () {
142
- options[ $( this ).data( 'option' ) ] = $( this ).text();
143
- } );
144
-
145
- value[ $( this ).data( 'list' ) ] = options;
146
- } );
147
-
148
- input.val( ( JSON.stringify( value ) ).replace( /[\\"']/g, '\\$&' ).replace( /\u0000/g, '\\0' ) );
149
- }
150
- } ).disableSelection();
151
- } );
152
-
153
- //google analytics generation
154
- $( function () {
155
- $( '.google-analytic-generate' ).click( function () {
156
- var editor = $( '#' + $( this ).data( 'textarea' ) ).data( 'codemirrorInstance' );
157
- var gatc = $( '#' + $( this ).data( 'input' ) ).val();
158
- var basename = $( this ).data( 'basename' );
159
-
160
- var text = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n";
161
- text += "(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement( o ),\n";
162
- text += "m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n";
163
- text += "})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n";
164
- text += "ga('create', '" + gatc + "', '" + basename + "');\n";
165
- text += "ga('send', 'pageview');\n";
166
- editor.replaceRange(
167
- text,
168
- editor.getCursor( 'start' ),
169
- editor.getCursor( 'end' )
170
- );
171
- } );
172
- } );
173
-
174
-
175
- // Prevent the WC message for changes when leaving the panel page
176
- $( '.yith-plugin-fw-panel .woo-nav-tab-wrapper' ).removeClass( 'woo-nav-tab-wrapper' ).addClass( 'yith-nav-tab-wrapper' );
177
-
178
- var wrap = $( '.wrap.yith-plugin-ui' ).first(),
179
- notices = $( 'div.updated, div.error, div.notice' );
180
-
181
- // Prevent moving notices into the wrapper
182
- notices.addClass( 'inline' );
183
- if ( wrap.length ) {
184
- wrap.prepend( notices );
185
- }
186
-
187
-
188
- // Additional wrapping just in case 'wrap' div is placed within a sub-tab and it's not already wrapped twice.
189
- // TODO: Deprecated usage, it'll be removed, since also custom panels should use the automatic-wrapping through 'show_container' param.
190
- ( function () {
191
- var active_subnav = $( '.yith-nav-sub-tab.nav-tab-active' ),
192
- subnav_wrap = $( '.yith-plugin-fw-wp-page__sub-tab-wrap' );
193
-
194
- if ( active_subnav.length && !subnav_wrap.length ) {
195
- var mainWrapper = $( '.yith-plugin-fw-wp-page-wrapper' );
196
- if ( !mainWrapper.length ) {
197
- mainWrapper = $( '#wpbody-content > .yith-plugin-ui' );
198
- }
199
-
200
- if ( mainWrapper ) {
201
- var defaultWrap = mainWrapper.find( '.yit-admin-panel-content-wrap' ); // at first, search for default wrap.
202
- if ( defaultWrap.length ) {
203
- defaultWrap.addClass( 'has-subnav' );
204
- } else {
205
- // try to wrap a generic wrap div in main wrapper
206
- mainWrapper.find( '.wrap' ).wrap( '<div class="yith-plugin-fw-wp-page__sub-tab-wrap"></div>' );
207
- }
208
- }
209
- }
210
- } )();
211
-
212
- // Float save button.
213
- ( function () {
214
- var floatSaveButton = $( '#yith-plugin-fw-float-save-button' ),
215
- mainForm = $( '#plugin-fw-wc' ),
216
- saveButton = document.querySelector( '#main-save-button' );
217
-
218
- function updateValuesForSpecialEditors() {
219
- if ( 'tinyMCE' in window && 'triggerSave' in window.tinyMCE ) {
220
- // Trigger saving to serialize the correct value for WP Editors.
221
- window.tinyMCE.triggerSave();
222
- }
223
-
224
- // Trigger saving to serialize the correct value for each Codemirror Editor.
225
- $( '.codemirror.codemirror--initialized' ).each( function () {
226
- var editor = $( this ).data( 'codemirrorInstance' ) || false;
227
- if ( editor && 'codemirror' in editor ) {
228
- editor.codemirror.save();
229
- }
230
- } );
231
- }
232
-
233
- function checkButtonPosition() {
234
- if ( isInViewport( saveButton ) ) {
235
- floatSaveButton.removeClass( 'visible' );
236
- } else {
237
- floatSaveButton.addClass( 'visible' );
238
- }
239
- }
240
-
241
- function isInViewport( el ) {
242
- var rect = el.getBoundingClientRect(),
243
- viewport = {
244
- width : window.innerWidth || document.documentElement.clientWidth,
245
- height: window.innerHeight || document.documentElement.clientHeight
246
- };
247
- return (
248
- rect.top >= 0 &&
249
- rect.left >= 0 &&
250
- rect.top <= viewport.height &&
251
- rect.left <= viewport.width
252
- );
253
- }
254
-
255
- if ( floatSaveButton.length > 0 && mainForm.length > 0 ) {
256
- checkButtonPosition();
257
- document.addEventListener( 'scroll', checkButtonPosition, { passive: true } );
258
-
259
- $( document ).on( 'click', '#yith-plugin-fw-float-save-button', function ( e ) {
260
- e.preventDefault();
261
-
262
- updateValuesForSpecialEditors();
263
-
264
- floatSaveButton.block(
265
- {
266
- message : null,
267
- overlayCSS: {
268
- background: 'transparent',
269
- opacity : 0.6
270
- }
271
- }
272
- );
273
- $.post( document.location.href, mainForm.serialize() )
274
- .done( function ( response ) {
275
- floatSaveButton.unblock()
276
- .addClass( 'green' )
277
- .fadeOut( 300 )
278
- .html( '<i class="yith-icon yith-icon-check"></i>' + floatSaveButton.data( 'saved-label' ) )
279
- .fadeIn( 300 )
280
- .delay( 2500 )
281
- .queue(
282
- function ( next ) {
283
- floatSaveButton.fadeOut(
284
- 500,
285
- function () {
286
- $( this ).removeClass( 'green' );
287
- $( this ).html( '<i class="yith-icon yith-icon-save"></i>' + $( this ).data( 'default-label' ) ).fadeIn( 500 );
288
- }
289
- );
290
- next();
291
- } );
292
-
293
- // Prevent WooCommerce warning for changes without saving.
294
- window.onbeforeunload = null;
295
-
296
- $( document ).trigger( 'yith-plugin-fw-float-save-button-after-saving', [response] );
297
- } );
298
- } )
299
- }
300
- } )();
301
-
302
- } );
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
+ jQuery( function ( $ ) {
11
+ // Handle dependencies.
12
+ function dependencies_handler( id, deps, values, type ) {
13
+ var result = true;
14
+ if ( typeof ( deps ) == 'string' ) {
15
+ if ( deps.substr( 0, 6 ) === ':radio' ) {
16
+ deps = deps + ':checked';
17
+ }
18
+
19
+ var depsOn = $( deps ),
20
+ depsOnType = depsOn.attr( 'type' ),
21
+ val = depsOn.val();
22
+
23
+ switch ( depsOnType ) {
24
+ case 'checkbox':
25
+ val = depsOn.is( ':checked' ) ? 'yes' : 'no';
26
+ break;
27
+ case 'radio':
28
+ val = depsOn.find( 'input[type="radio"]' ).filter( ':checked' ).val();
29
+ break;
30
+ }
31
+
32
+ values = values.split( ',' );
33
+
34
+ for ( var i = 0; i < values.length; i++ ) {
35
+ if ( val != values[ i ] ) {
36
+ result = false;
37
+ } else {
38
+ result = true;
39
+ break;
40
+ }
41
+ }
42
+ }
43
+
44
+ var $current_field = $( id ),
45
+ $current_container = $( id + '-container' ).closest( 'tr' ); // container for YIT Plugin Panel
46
+
47
+ if ( $current_container.length < 1 ) {
48
+ // container for YIT Plugin Panel WooCommerce
49
+ $current_container = $current_field.closest( '.yith-plugin-fw-panel-wc-row, .yith-toggle-content-row' );
50
+ }
51
+
52
+ var types = type.split( '-' ), j;
53
+ for ( j in types ) {
54
+ var current_type = types[ j ];
55
+
56
+ if ( !result ) {
57
+ switch ( current_type ) {
58
+ case 'disable':
59
+ $current_container.addClass( 'yith-disabled' );
60
+ $current_field.attr( 'disabled', true );
61
+ break;
62
+ case 'hide':
63
+ case 'hideNow':
64
+ $current_container.hide();
65
+ break;
66
+ case 'hideme':
67
+ $current_field.hide();
68
+ break;
69
+ case 'fadeInOut':
70
+ case 'fadeOut':
71
+ $current_container.hide( 500 );
72
+ break;
73
+ case 'fadeIn':
74
+ default:
75
+ $current_container.hide();
76
+ }
77
+ } else {
78
+ switch ( current_type ) {
79
+ case 'disable':
80
+ $current_container.removeClass( 'yith-disabled' );
81
+ $current_field.attr( 'disabled', false );
82
+ break;
83
+ case 'hide':
84
+ case 'hideNow':
85
+ $current_container.show();
86
+ break;
87
+ case 'hideme':
88
+ $current_field.show();
89
+ break;
90
+ case 'fadeOut':
91
+ $current_container.show();
92
+ break;
93
+ case 'fadeInOut':
94
+ case 'fadeIn':
95
+ default:
96
+ $current_container.show( 500 );
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ function init_dependencies() {
103
+ $( '[data-dep-target]:not( .deps-initialized )' ).each( function () {
104
+ var t = $( this );
105
+
106
+ if ( t.closest( '.metaboxes-tab' ).length ) {
107
+ // Let meta-boxes handle their own deps.
108
+ return;
109
+ }
110
+
111
+ // init field deps
112
+ t.addClass( 'deps-initialized' );
113
+
114
+ var field = '#' + t.data( 'dep-target' ),
115
+ dep = '#' + t.data( 'dep-id' ),
116
+ value = t.data( 'dep-value' ),
117
+ type = t.data( 'dep-type' );
118
+
119
+ $( dep ).on( 'change', function () {
120
+ dependencies_handler( field, dep, value.toString(), type );
121
+ } ).trigger( 'change' );
122
+ } );
123
+ }
124
+
125
+ init_dependencies();
126
+ // re-init deps after an add toggle action
127
+ $( document ).on( 'yith-add-box-button-toggle', init_dependencies );
128
+
129
+ //connected list
130
+ $( '.rm_connectedlist' ).each( function () {
131
+ var ul = $( this ).find( 'ul' );
132
+ var input = $( this ).find( ':hidden' );
133
+ var sortable = ul.sortable( {
134
+ connectWith: ul,
135
+ update : function ( event, ui ) {
136
+ var value = {};
137
+
138
+ ul.each( function () {
139
+ var options = {};
140
+
141
+ $( this ).children().each( function () {
142
+ options[ $( this ).data( 'option' ) ] = $( this ).text();
143
+ } );
144
+
145
+ value[ $( this ).data( 'list' ) ] = options;
146
+ } );
147
+
148
+ input.val( ( JSON.stringify( value ) ).replace( /[\\"']/g, '\\$&' ).replace( /\u0000/g, '\\0' ) );
149
+ }
150
+ } ).disableSelection();
151
+ } );
152
+
153
+ //google analytics generation
154
+ $( function () {
155
+ $( '.google-analytic-generate' ).click( function () {
156
+ var editor = $( '#' + $( this ).data( 'textarea' ) ).data( 'codemirrorInstance' );
157
+ var gatc = $( '#' + $( this ).data( 'input' ) ).val();
158
+ var basename = $( this ).data( 'basename' );
159
+
160
+ var text = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n";
161
+ text += "(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement( o ),\n";
162
+ text += "m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n";
163
+ text += "})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n";
164
+ text += "ga('create', '" + gatc + "', '" + basename + "');\n";
165
+ text += "ga('send', 'pageview');\n";
166
+ editor.replaceRange(
167
+ text,
168
+ editor.getCursor( 'start' ),
169
+ editor.getCursor( 'end' )
170
+ );
171
+ } );
172
+ } );
173
+
174
+
175
+ // Prevent the WC message for changes when leaving the panel page
176
+ $( '.yith-plugin-fw-panel .woo-nav-tab-wrapper' ).removeClass( 'woo-nav-tab-wrapper' ).addClass( 'yith-nav-tab-wrapper' );
177
+
178
+ var wrap = $( '.wrap.yith-plugin-ui' ).first(),
179
+ notices = $( 'div.updated, div.error, div.notice' );
180
+
181
+ // Prevent moving notices into the wrapper
182
+ notices.addClass( 'inline' );
183
+ if ( wrap.length ) {
184
+ wrap.prepend( notices );
185
+ }
186
+
187
+
188
+ // Additional wrapping just in case 'wrap' div is placed within a sub-tab and it's not already wrapped twice.
189
+ // TODO: Deprecated usage, it'll be removed, since also custom panels should use the automatic-wrapping through 'show_container' param.
190
+ ( function () {
191
+ var active_subnav = $( '.yith-nav-sub-tab.nav-tab-active' ),
192
+ subnav_wrap = $( '.yith-plugin-fw-wp-page__sub-tab-wrap' );
193
+
194
+ if ( active_subnav.length && !subnav_wrap.length ) {
195
+ var mainWrapper = $( '.yith-plugin-fw-wp-page-wrapper' );
196
+ if ( !mainWrapper.length ) {
197
+ mainWrapper = $( '#wpbody-content > .yith-plugin-ui' );
198
+ }
199
+
200
+ if ( mainWrapper ) {
201
+ var defaultWrap = mainWrapper.find( '.yit-admin-panel-content-wrap' ); // at first, search for default