Import any XML or CSV File to WordPress - Version 3.0.3

Version Description

  • Now using enhanced session functionality
Download this release

Release Info

Developer soflyy
Plugin Icon 128x128 Import any XML or CSV File to WordPress
Version 3.0.3
Comparing to
See all releases

Code changes from version 3.0.2 to 3.0.3

Files changed (59) hide show
  1. actions/plugins_loaded.php +9 -0
  2. actions/shutdown.php +7 -0
  3. actions/wp.php +7 -0
  4. actions/wp_session_garbage_collection.php +36 -0
  5. classes/arrayaccess.php +139 -0
  6. classes/chunk.php +14 -6
  7. classes/session.php +317 -0
  8. config/options.php +2 -1
  9. controllers/admin/import.php +269 -283
  10. controllers/admin/manage.php +14 -9
  11. controllers/controller/admin.php +101 -101
  12. helpers/import_custom_meta_box.php +2 -2
  13. helpers/pmxi_functions.php +33 -0
  14. libraries/XmlImportCsvParse.php +4 -2
  15. libraries/XmlImportTemplateCodeGenerator.php +33 -2
  16. libraries/ast/XmlImportAstElseif.php +76 -76
  17. libraries/ast/XmlImportAstExpression.php +15 -15
  18. libraries/ast/XmlImportAstFloat.php +15 -15
  19. libraries/ast/XmlImportAstForeach.php +14 -14
  20. libraries/ast/XmlImportAstFunction.php +89 -89
  21. libraries/ast/XmlImportAstIf.php +161 -161
  22. libraries/ast/XmlImportAstInteger.php +15 -15
  23. libraries/ast/XmlImportAstLiteral.php +52 -52
  24. libraries/ast/XmlImportAstMath.php +72 -72
  25. libraries/ast/XmlImportAstPrint.php +59 -59
  26. libraries/ast/XmlImportAstSequence.php +160 -160
  27. libraries/ast/XmlImportAstSpintax.php +72 -72
  28. libraries/ast/XmlImportAstStatement.php +14 -14
  29. libraries/ast/XmlImportAstString.php +14 -14
  30. libraries/ast/XmlImportAstText.php +59 -59
  31. libraries/ast/XmlImportAstWith.php +15 -15
  32. libraries/ast/XmlImportAstXPath.php +15 -15
  33. libraries/ast/XmlImportAstXpathClause.php +83 -83
  34. models/import/record.php +371 -273
  35. models/model.php +197 -197
  36. plugin.php +54 -1
  37. readme.txt +5 -2
  38. schema.php +1 -1
  39. static/js/jquery/css/redmond/jquery-ui.css +1177 -1177
  40. static/js/jquery/css/smoothness/jquery-ui.css +404 -404
  41. static/js/jquery/css/smoothness/jquery.tipsy.css +11 -11
  42. static/js/jquery/jquery.mjs.nestedSortable.js +425 -425
  43. static/js/jquery/jquery.tipsy.js +198 -198
  44. static/js/jquery/moment.js +5 -5
  45. static/js/jquery/ui.autocomplete.js +606 -606
  46. static/js/jquery/ui.datepicker.js +1636 -1636
  47. static/js/plupload/plupload.full.js +1 -1
  48. static/js/plupload/wplupload.js +119 -115
  49. views/admin/help/index.php +22 -22
  50. views/admin/import/element_after.php +2 -2
  51. views/admin/import/evaluate.php +19 -19
  52. views/admin/import/evaluate_variations.php +32 -0
  53. views/admin/import/options/_buttons_template.php +1 -1
  54. views/admin/import/options/_featured_template.php +20 -1
  55. views/admin/import/options/_reimport_template.php +36 -10
  56. views/admin/import/process.php +3 -3
  57. views/admin/import/tag.php +3 -3
  58. views/admin/import/template.php +2 -1
  59. views/admin/settings/index.php +5 -0
actions/plugins_loaded.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function pmxi_plugins_loaded() {
4
+
5
+ PMXI_Plugin::$session = PMXI_Session::get_instance();
6
+ do_action( 'pmxi_session_start' );
7
+
8
+ return PMXI_Plugin::$session->session_started();
9
+ }
actions/shutdown.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function pmxi_shutdown() {
4
+ PMXI_Plugin::$session = PMXI_Session::get_instance();
5
+ PMXI_Plugin::$session->write_data();
6
+ do_action( 'pmxi_session_commit' );
7
+ }
actions/wp.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function pmxi_wp() {
4
+ if ( ! wp_next_scheduled( 'wp_session_garbage_collection' ) ) {
5
+ wp_schedule_event( time(), 'twicedaily', 'wp_session_garbage_collection' );
6
+ }
7
+ }
actions/wp_session_garbage_collection.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function pmxi_wp_session_garbage_collection() {
4
+ global $wpdb;
5
+
6
+ if ( defined( 'WP_SETUP_CONFIG' ) ) {
7
+ return;
8
+ }
9
+
10
+ if ( ! defined( 'WP_INSTALLING' ) ) {
11
+ $expiration_keys = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_pmxi_session_expires_%'" );
12
+
13
+ $now = time();
14
+ $expired_sessions = array();
15
+
16
+ foreach( $expiration_keys as $expiration ) {
17
+ // If the session has expired
18
+ if ( $now > intval( $expiration->option_value ) ) {
19
+ // Get the session ID by parsing the option_name
20
+ $session_id = substr( $expiration->option_name, 20 );
21
+
22
+ $expired_sessions[] = $expiration->option_name;
23
+ $expired_sessions[] = "_pmxi_session_$session_id";
24
+ }
25
+ }
26
+
27
+ // Delete all expired sessions in a single query
28
+ if ( ! empty( $expired_sessions ) ) {
29
+ $option_names = implode( "','", $expired_sessions );
30
+ $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name IN ('$option_names')" );
31
+ }
32
+ }
33
+
34
+ // Allow other plugins to hook in to the garbage collection process.
35
+ do_action( 'pmxi_session_cleanup' );
36
+ }
classes/arrayaccess.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Multidimensional ArrayAccess
4
+ *
5
+ * Allows ArrayAccess-like functionality with multidimensional arrays. Fully supports
6
+ * both sets and unsets.
7
+ *
8
+ * @package WordPress
9
+ * @subpackage Session
10
+ * @since 3.7.0
11
+ */
12
+
13
+ /**
14
+ * Recursive array class to allow multidimensional array access.
15
+ *
16
+ * @package WordPress
17
+ * @since 3.7.0
18
+ */
19
+ class PMXI_ArrayAccess implements ArrayAccess {
20
+ /**
21
+ * Internal data collection.
22
+ *
23
+ * @var array
24
+ */
25
+ protected $container = array();
26
+
27
+ /**
28
+ * Flag whether or not the internal collection has been changed.
29
+ *
30
+ * @var bool
31
+ */
32
+ protected $dirty = false;
33
+
34
+ /**
35
+ * Default object constructor.
36
+ *
37
+ * @param array $data
38
+ */
39
+ protected function __construct( $data = array() ) {
40
+ foreach ( $data as $key => $value ) {
41
+ $this[ $key ] = $value;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Allow deep copies of objects
47
+ */
48
+ public function __clone() {
49
+ foreach ( $this->container as $key => $value ) {
50
+ if ( $value instanceof self ) {
51
+ $this[ $key ] = clone $value;
52
+ }
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Output the data container as a multidimensional array.
58
+ *
59
+ * @return array
60
+ */
61
+ public function toArray() {
62
+ $data = $this->container;
63
+ foreach ( $data as $key => $value ) {
64
+ if ( $value instanceof self ) {
65
+ $data[ $key ] = $value->toArray();
66
+ }
67
+ }
68
+ return $data;
69
+ }
70
+
71
+ /*****************************************************************/
72
+ /* ArrayAccess Implementation */
73
+ /*****************************************************************/
74
+
75
+ /**
76
+ * Whether a offset exists
77
+ *
78
+ * @link http://php.net/manual/en/arrayaccess.offsetexists.php
79
+ *
80
+ * @param mixed $offset An offset to check for.
81
+ *
82
+ * @return boolean true on success or false on failure.
83
+ */
84
+ public function offsetExists( $offset ) {
85
+ return isset( $this->container[ $offset ]) ;
86
+ }
87
+
88
+ /**
89
+ * Offset to retrieve
90
+ *
91
+ * @link http://php.net/manual/en/arrayaccess.offsetget.php
92
+ *
93
+ * @param mixed $offset The offset to retrieve.
94
+ *
95
+ * @return mixed Can return all value types.
96
+ */
97
+ public function offsetGet( $offset ) {
98
+ return isset( $this->container[ $offset ] ) ? $this->container[ $offset ] : null;
99
+ }
100
+
101
+ /**
102
+ * Offset to set
103
+ *
104
+ * @link http://php.net/manual/en/arrayaccess.offsetset.php
105
+ *
106
+ * @param mixed $offset The offset to assign the value to.
107
+ * @param mixed $value The value to set.
108
+ *
109
+ * @return void
110
+ */
111
+ public function offsetSet( $offset, $data ) {
112
+ if ( is_array( $data ) ) {
113
+ $data = new self( $data );
114
+ }
115
+ if ( $offset === null ) { // don't forget this!
116
+ $this->container[] = $data;
117
+ } else {
118
+ $this->container[ $offset ] = $data;
119
+ }
120
+
121
+ $this->dirty = true;
122
+ }
123
+
124
+ /**
125
+ * Offset to unset
126
+ *
127
+ * @link http://php.net/manual/en/arrayaccess.offsetunset.php
128
+ *
129
+ * @param mixed $offset The offset to unset.
130
+ *
131
+ * @return void
132
+ */
133
+ public function offsetUnset( $offset ) {
134
+ unset( $this->container[ $offset ] );
135
+
136
+ $this->dirty = true;
137
+ }
138
+ }
139
+ ?>
classes/chunk.php CHANGED
@@ -184,9 +184,11 @@ class PMXI_Chunk {
184
 
185
  if ( preg_match_all("/<\\w+\\s*[^<|^\n]*\\s*\/?>/i", $c, $matches, PREG_PATTERN_ORDER) ){
186
  foreach ($matches[0] as $tag) {
187
- $tag = explode(" ", trim(str_replace(array('<','>','/'), '', $tag)));
188
- array_push($founded_tags, $tag[0]);
189
- }
 
 
190
  }
191
  $this->reading = (!@feof($this->handle));
192
  }
@@ -314,15 +316,17 @@ class PMXI_Chunk {
314
 
315
  // check for the close string
316
  $checkClose = preg_match_all("/<\/".$element.">/i", $tmp, $closematches, PREG_OFFSET_CAPTURE);
317
- $withoutcloseelement = false;
 
 
318
 
319
  if (!$checkClose){
320
- $checkClose = (preg_match("%<".$element."\s{1,}[^<]*\/>%i", $tmp, $matches)) ? strpos($tmp, $matches[0]) : false;
321
 
322
  if ($checkClose !== false)
323
  $withoutcloseelement = true;
324
  else{
325
- $checkClose = (preg_match_all("%<".$element."\s{1,}[^<]*\/>%i", $this->readBuffer, $matches)) ? strpos($this->readBuffer, $matches[0][count($matches[0]) - 1]) : false;
326
  if ($checkClose !== false) {
327
  $withoutcloseelement = true;
328
  $matches[0] = $matches[0][count($matches[0]) - 1];
@@ -431,6 +435,10 @@ class PMXI_Chunk {
431
  $pattern = '/(<\/\w+):(\w+>)/i';
432
  $replacement = '$1_$2';
433
  $feed = preg_replace($pattern, $replacement, $feed);
 
 
 
 
434
  return $feed;
435
  }
436
  }
184
 
185
  if ( preg_match_all("/<\\w+\\s*[^<|^\n]*\\s*\/?>/i", $c, $matches, PREG_PATTERN_ORDER) ){
186
  foreach ($matches[0] as $tag) {
187
+ if (strpos($tag, "<br") === false) {
188
+ $tag = explode(" ", trim(str_replace(array('<','>','/'), '', $tag)));
189
+ array_push($founded_tags, $tag[0]);
190
+ }
191
+ }
192
  }
193
  $this->reading = (!@feof($this->handle));
194
  }
316
 
317
  // check for the close string
318
  $checkClose = preg_match_all("/<\/".$element.">/i", $tmp, $closematches, PREG_OFFSET_CAPTURE);
319
+ $withoutcloseelement = (preg_match("%<".$element."(^<)*\/>%", $tmp, $matches)) ? strpos($tmp, $matches[0]) : false;
320
+
321
+ if ($withoutcloseelement and $checkClose and $closematches[0][0][1] > $withoutcloseelement) $checkClose = false;
322
 
323
  if (!$checkClose){
324
+ $checkClose = (preg_match("%<".$element."(^<)*\/>%", $tmp, $matches)) ? strpos($tmp, $matches[0]) : false;
325
 
326
  if ($checkClose !== false)
327
  $withoutcloseelement = true;
328
  else{
329
+ $checkClose = (preg_match_all("%<".$element."(^<)*\/>%", $this->readBuffer, $matches)) ? strpos($this->readBuffer, $matches[0][count($matches[0]) - 1]) : false;
330
  if ($checkClose !== false) {
331
  $withoutcloseelement = true;
332
  $matches[0] = $matches[0][count($matches[0]) - 1];
435
  $pattern = '/(<\/\w+):(\w+>)/i';
436
  $replacement = '$1_$2';
437
  $feed = preg_replace($pattern, $replacement, $feed);
438
+ // pull out colons from attributes
439
+ $pattern = '/(\s+\w+):(\w+[=]{1})/i';
440
+ $replacement = '$1_$2';
441
+ $feed = preg_replace($pattern, $replacement, $feed);
442
  return $feed;
443
  }
444
  }
classes/session.php ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WordPress session managment.
4
+ *
5
+ * Standardizes WordPress session data using database-backed options for storage.
6
+ * for storing user session information.
7
+ *
8
+ * @package WordPress
9
+ * @subpackage Session
10
+ * @since 3.7.0
11
+ */
12
+
13
+ /**
14
+ * WordPress Session class for managing user session data.
15
+ *
16
+ * @package WordPress
17
+ * @since 3.7.0
18
+ */
19
+ final class PMXI_Session extends PMXI_ArrayAccess implements Iterator, Countable {
20
+ /**
21
+ * ID of the current session.
22
+ *
23
+ * @var string
24
+ */
25
+ protected $session_id;
26
+
27
+ /**
28
+ * Unix timestamp when session expires.
29
+ *
30
+ * @var int
31
+ */
32
+ protected $expires;
33
+
34
+ /**
35
+ * Unix timestamp indicating when the expiration time needs to be reset.
36
+ *
37
+ * @var int
38
+ */
39
+ protected $exp_variant;
40
+
41
+ /**
42
+ * Singleton instance.
43
+ *
44
+ * @var bool|WP_Session
45
+ */
46
+ private static $instance = false;
47
+
48
+ public $data = array();
49
+
50
+ /**
51
+ * Retrieve the current session instance.
52
+ *
53
+ * @param bool $session_id Session ID from which to populate data.
54
+ *
55
+ * @return bool|WP_Session
56
+ */
57
+ public static function get_instance() {
58
+ if ( ! self::$instance ) {
59
+ self::$instance = new self();
60
+ }
61
+
62
+ return self::$instance;
63
+ }
64
+
65
+ /**
66
+ * Default constructor.
67
+ * Will rebuild the session collection from the given session ID if it exists. Otherwise, will
68
+ * create a new session with that ID.
69
+ *
70
+ * @param $session_id
71
+ * @uses apply_filters Calls `wp_session_expiration` to determine how long until sessions expire.
72
+ */
73
+ protected function __construct() {
74
+ if ( isset( $_COOKIE[PMXI_SESSION_COOKIE] ) ) {
75
+ $cookie = stripslashes( $_COOKIE[PMXI_SESSION_COOKIE] );
76
+ $cookie_crumbs = explode( '||', $cookie );
77
+
78
+ $this->session_id = $cookie_crumbs[0];
79
+ $this->expires = $cookie_crumbs[1];
80
+ $this->exp_variant = $cookie_crumbs[2];
81
+
82
+ // Update the session expiration if we're past the variant time
83
+ if ( time() > $this->exp_variant ) {
84
+ $this->set_expiration();
85
+ update_option( "_pmxi_session_expires_{$this->session_id}", $this->expires );
86
+ }
87
+ } else {
88
+ $this->session_id = $this->generate_id();
89
+ $this->set_expiration();
90
+ }
91
+
92
+ $this->read_data();
93
+
94
+ $this->set_cookie();
95
+
96
+ }
97
+
98
+ /**
99
+ * Set both the expiration time and the expiration variant.
100
+ *
101
+ * If the current time is below the variant, we don't update the session's expiration time. If it's
102
+ * greater than the variant, then we update the expiration time in the database. This prevents
103
+ * writing to the database on every page load for active sessions and only updates the expiration
104
+ * time if we're nearing when the session actually expires.
105
+ *
106
+ * By default, the expiration time is set to 30 minutes.
107
+ * By default, the expiration variant is set to 24 minutes.
108
+ *
109
+ * As a result, the session expiration time - at a maximum - will only be written to the database once
110
+ * every 24 minutes. After 30 minutes, the session will have been expired. No cookie will be sent by
111
+ * the browser, and the old session will be queued for deletion by the garbage collector.
112
+ *
113
+ * @uses apply_filters Calls `wp_session_expiration_variant` to get the max update window for session data.
114
+ * @uses apply_filters Calls `wp_session_expiration` to get the standard expiration time for sessions.
115
+ */
116
+ protected function set_expiration() {
117
+ $this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 );
118
+ $this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
119
+ }
120
+
121
+ /**
122
+ * Set the session cookie
123
+ */
124
+ protected function set_cookie() {
125
+ setcookie( PMXI_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant , $this->expires, COOKIEPATH, COOKIE_DOMAIN );
126
+ }
127
+
128
+ /**
129
+ * Generate a cryptographically strong unique ID for the session token.
130
+ *
131
+ * @return string
132
+ */
133
+ protected function generate_id() {
134
+ require_once( ABSPATH . 'wp-includes/class-phpass.php');
135
+ $hasher = new PasswordHash( 8, false );
136
+
137
+ return md5( $hasher->get_random_bytes( 32 ) );
138
+ }
139
+
140
+ /**
141
+ * Read data from a transient for the current session.
142
+ *
143
+ * Automatically resets the expiration time for the session transient to some time in the future.
144
+ *
145
+ * @return array
146
+ */
147
+ protected function read_data() {
148
+ $this->container = get_option( "_pmxi_session_{$this->session_id}", array() );
149
+
150
+ $this->data = $this->toArray();
151
+
152
+ return $this->container;
153
+ }
154
+
155
+ /**
156
+ * Write the data from the current session to the data storage system.
157
+ */
158
+ public function write_data() {
159
+
160
+ $option_key = "_pmxi_session_{$this->session_id}";
161
+
162
+ $this->data = $this->toArray();
163
+
164
+ // Only write the collection to the DB if it's changed.
165
+ //if ( $this->dirty ) {
166
+ if ( false === get_option( $option_key ) ) {
167
+ add_option( "_pmxi_session_{$this->session_id}", $this->container, '', 'no' );
168
+ add_option( "_pmxi_session_expires_{$this->session_id}", $this->expires, '', 'no' );
169
+ } else {
170
+ delete_option("_pmxi_session_{$this->session_id}");
171
+ add_option( "_pmxi_session_{$this->session_id}", $this->container, '', 'no' );
172
+ }
173
+ //}
174
+
175
+ }
176
+
177
+ /**
178
+ * Output the current container contents as a JSON-encoded string.
179
+ *
180
+ * @return string
181
+ */
182
+ public function json_out() {
183
+ return json_encode( $this->container );
184
+ }
185
+
186
+ /**
187
+ * Decodes a JSON string and, if the object is an array, overwrites the session container with its contents.
188
+ *
189
+ * @param string $data
190
+ *
191
+ * @return bool
192
+ */
193
+ public function json_in( $data ) {
194
+ $array = json_decode( $data );
195
+
196
+ if ( is_array( $array ) ) {
197
+ $this->container = $array;
198
+ return true;
199
+ }
200
+
201
+ return false;
202
+ }
203
+
204
+ /**
205
+ * Regenerate the current session's ID.
206
+ *
207
+ * @param bool $delete_old Flag whether or not to delete the old session data from the server.
208
+ */
209
+ public function regenerate_id( $delete_old = false ) {
210
+ if ( $delete_old ) {
211
+ delete_option( "_pmxi_session_{$this->session_id}" );
212
+ }
213
+
214
+ $this->session_id = $this->generate_id();
215
+
216
+ $this->set_cookie();
217
+ }
218
+
219
+ /**
220
+ * Check if a session has been initialized.
221
+ *
222
+ * @return bool
223
+ */
224
+ public function session_started() {
225
+ return !!self::$instance;
226
+ }
227
+
228
+ /**
229
+ * Return the read-only cache expiration value.
230
+ *
231
+ * @return int
232
+ */
233
+ public function cache_expiration() {
234
+ return $this->expires;
235
+ }
236
+
237
+ /**
238
+ * Flushes all session variables.
239
+ */
240
+ public function reset() {
241
+ $this->container = array();
242
+ }
243
+
244
+ /*****************************************************************/
245
+ /* Iterator Implementation */
246
+ /*****************************************************************/
247
+
248
+ /**
249
+ * Current position of the array.
250
+ *
251
+ * @link http://php.net/manual/en/iterator.current.php
252
+ *
253
+ * @return mixed
254
+ */
255
+ public function current() {
256
+ return current( $this->container );
257
+ }
258
+
259
+ /**
260
+ * Key of the current element.
261
+ *
262
+ * @link http://php.net/manual/en/iterator.key.php
263
+ *
264
+ * @return mixed
265
+ */
266
+ public function key() {
267
+ return key( $this->container );
268
+ }
269
+
270
+ /**
271
+ * Move the internal point of the container array to the next item
272
+ *
273
+ * @link http://php.net/manual/en/iterator.next.php
274
+ *
275
+ * @return void
276
+ */
277
+ public function next() {
278
+ next( $this->container );
279
+ }
280
+
281
+ /**
282
+ * Rewind the internal point of the container array.
283
+ *
284
+ * @link http://php.net/manual/en/iterator.rewind.php
285
+ *
286
+ * @return void
287
+ */
288
+ public function rewind() {
289
+ reset( $this->container );
290
+ }
291
+
292
+ /**
293
+ * Is the current key valid?
294
+ *
295
+ * @link http://php.net/manual/en/iterator.rewind.php
296
+ *
297
+ * @return bool
298
+ */
299
+ public function valid() {
300
+ return $this->offsetExists( $this->key() );
301
+ }
302
+
303
+ /*****************************************************************/
304
+ /* Countable Implementation */
305
+ /*****************************************************************/
306
+
307
+ /**
308
+ * Get the count of elements in the container array.
309
+ *
310
+ * @link http://php.net/manual/en/countable.count.php
311
+ *
312
+ * @return int
313
+ */
314
+ public function count() {
315
+ return count( $this->container );
316
+ }
317
+ }
config/options.php CHANGED
@@ -19,5 +19,6 @@ $config = array(
19
  "utf8_decode" => 0,
20
  "cron_job_key" => url_title(rand_char(12)),
21
  "chunk_size" => 64,
22
- "pingbacks" => 1
 
23
  );
19
  "utf8_decode" => 0,
20
  "cron_job_key" => url_title(rand_char(12)),
21
  "chunk_size" => 64,
22
+ "pingbacks" => 1,
23
+ "legacy_special_character_handling" => 0
24
  );
controllers/admin/import.php CHANGED
@@ -10,20 +10,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
10
  protected $isTemplateEdit = false; // indicates whether controlled is deligated by manage imports controller
11
 
12
  protected function init() {
13
- parent::init();
14
-
15
- try{
16
- $path = session_save_path();
17
- if ( ! @is_dir($path) or ! @is_writable($path)){
18
- @ini_set("session.save_handler", "files");
19
- session_save_path(sys_get_temp_dir());
20
- }
21
- } catch (XmlImportException $e) {
22
- $this->errors->add('form-validation', __('Can not create session.', 'pmxi_plugin'));
23
- }
24
-
25
- // enable sessions
26
- if ( ! session_id()) session_start();
27
 
28
  if ('PMXI_Admin_Manage' == PMXI_Plugin::getInstance()->getAdminCurrentScreen()->base) { // prereqisites are not checked when flow control is deligated
29
  $id = $this->input->get('id');
@@ -65,37 +52,47 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
65
  // step #2: element selection
66
  $this->data['dom'] = $dom = new DOMDocument('1.0', 'UTF-8');
67
  $this->data['update_previous'] = $update_previous = new PMXI_Import_Record();
68
- $old = libxml_use_internal_errors(true);
 
 
 
 
 
 
 
69
 
70
- if (empty($_SESSION['pmxi_import'])
71
- or ! $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $_SESSION['pmxi_import']['xml']))// FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
72
- //or empty($_SESSION['pmxi_import']['source'])
73
- or ! empty($_SESSION['pmxi_import']['update_previous']) and $update_previous->getById($_SESSION['pmxi_import']['update_previous'])->isEmpty()
74
  ) {
75
- $this->errors->add('form-validation', __('Can not create DOM object for provided feed.', 'pmxi_plugin'));
76
- wp_redirect_or_javascript($this->baseUrl); die();
 
 
77
  }
78
- libxml_use_internal_errors($old);
79
  if ('element' == $action) return true;
80
  if ('evaluate' == $action) return true;
81
  if ('evaluate_variations' == $action) return true;
82
 
83
  // step #3: template
84
  $xpath = new DOMXPath($dom);
85
-
86
- if (empty($_SESSION['pmxi_import']['xpath']) or ! ($this->data['elements'] = $elements = $xpath->query($_SESSION['pmxi_import']['xpath'])) or ! $elements->length) {
 
87
  $this->errors->add('form-validation', __('No matching elements found.', 'pmxi_plugin'));
88
  wp_redirect_or_javascript(add_query_arg('action', 'element', $this->baseUrl)); die();
89
  }
90
  if ('template' == $action or 'preview' == $action or 'tag' == $action) return true;
91
 
92
  // step #4: options
93
- if (empty($_SESSION['pmxi_import']['template']) or empty($_SESSION['pmxi_import']['template']['title']) or empty($_SESSION['pmxi_import']['template']['title'])) {
94
  wp_redirect_or_javascript(add_query_arg('action', 'template', $this->baseUrl)); die();
95
  }
96
  if ('options' == $action) return true;
97
 
98
- if (empty($_SESSION['pmxi_import']['options'])) {
99
  wp_redirect(add_query_arg('action', 'options', $this->baseUrl)); die();
100
  }
101
  }
@@ -126,7 +123,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
126
  ));
127
 
128
  if ($this->input->post('is_submitted_continue')) {
129
- if ( ! empty($_SESSION['pmxi_import']['xml'])) {
130
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
131
  }
132
  } elseif ('upload' == $this->input->post('type')) {
@@ -361,8 +358,8 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
361
 
362
  $source['first_import'] = date("Y-m-d H:i:s");
363
 
364
- $_SESSION['pmxi_import'] = array(
365
- 'xml' => $xml,
366
  'filePath' => $filePath,
367
  'xpath' => (!empty($xpath)) ? $xpath : '',
368
  'source' => $source,
@@ -387,16 +384,16 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
387
  unset($xml);
388
  $update_previous = new PMXI_Import_Record();
389
  if ($post['is_update_previous'] and ! $update_previous->getById($post['update_previous'])->isEmpty()) {
390
- $_SESSION['pmxi_import'] += array(
391
- 'update_previous' => $update_previous->id,
392
- 'xpath' => $update_previous->xpath,
393
- 'template' => $update_previous->template,
394
- 'options' => $update_previous->options,
395
- );
396
  } else {
397
- $_SESSION['pmxi_import']['update_previous'] = '';
398
  }
399
-
 
 
400
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
401
 
402
  }
@@ -417,21 +414,21 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
417
  $xpath = new DOMXPath($this->data['dom']);
418
  $post = $this->input->post(array('xpath' => ''));
419
  $this->data['post'] =& $post;
420
- $this->data['elements_cloud'] = $_SESSION['pmxi_import']['elements_cloud'];
421
 
422
  $wp_uploads = wp_upload_dir();
423
-
424
- if ($this->input->post('is_submitted')) {
425
  check_admin_referer('choose-elements', '_wpnonce_choose-elements');
426
  if ('' == $post['xpath']) {
427
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
428
  } else {
429
  $node_list = @ $xpath->query($post['xpath']); // make sure only element selection is allowed; prevent parsing warning to be displayed
430
-
431
  if (FALSE === $node_list) {
432
  $this->errors->add('form-validation', __('Invalid XPath expression', 'pmxi_plugin'));
433
- } elseif ( ! $node_list->length) {
434
- $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
435
  } else {
436
  foreach ($node_list as $el) {
437
  if ( ! $el instanceof DOMElement) {
@@ -444,20 +441,20 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
444
 
445
  if ( ! $this->errors->get_error_codes()) {
446
 
447
- $_SESSION['pmxi_import']['xpath'] = $post['xpath'];
448
  // counting element selected by xPath
449
- if ($_SESSION['pmxi_import']['large_file']){
450
 
451
- $_SESSION['pmxi_import']['count'] = 0;
452
 
453
  $this->data['node_list_count'] = 0;
454
 
455
  // loop through the file until all lines are read
456
  $first_loop = true;
457
 
458
- foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
459
 
460
- $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path'], 'type' => $this->input->post('type')));
461
 
462
  while ($xml = $file->read()) {
463
 
@@ -472,10 +469,10 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
472
  libxml_use_internal_errors($old);
473
  $xpath = new DOMXPath($dom);
474
  if (($this->data['elements'] = $elements = @$xpath->query($post['xpath'])) and $elements->length){
475
- $_SESSION['pmxi_import']['count']++;
476
  $this->data['node_list_count']++;
477
  if ($first_loop){
478
- $_SESSION['pmxi_import']['xml'] = $xml;
479
  $first_loop = false;
480
  }
481
  }
@@ -488,15 +485,19 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
488
  if ( ! $this->data['node_list_count']) {
489
  $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
490
  }
 
 
 
491
  }
492
  wp_redirect(add_query_arg('action', 'template', $this->baseUrl)); die();
493
  }
 
494
  } else {
495
 
496
- if (isset($_SESSION['pmxi_import']['xpath']) and $_SESSION['pmxi_import']['large_file']) {
497
- $post['xpath'] = $_SESSION['pmxi_import']['xpath'];
498
  $this->data['elements'] = $elements = $xpath->query($post['xpath']);
499
- if ( ! $elements->length and ! empty($_SESSION['pmxi_import']['update_previous'])) {
500
  $_GET['pmxi_nt'] = __('<b>Warning</b>: No matching elements found for XPath expression from the import being updated. It probably means that new XML file has different format. Though you can update XPath, procceed only if you sure about update operation being valid.', 'pmxi_plugin');
501
  }
502
  } else {
@@ -525,38 +526,43 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
525
  {
526
  if ( ! PMXI_Plugin::getInstance()->getAdminCurrentScreen()->is_ajax) { // call is only valid when send with ajax
527
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
528
- }
529
 
530
  $xpath = new DOMXPath($this->data['dom']);
531
- $post = $this->input->post(array('xpath' => '', 'show_element' => 1, 'root_element' => $_SESSION['pmxi_import']['source']['root_element']));
532
  $wp_uploads = wp_upload_dir();
533
 
534
  if ('' == $post['xpath']) {
535
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
536
  } else {
537
  // counting selected elements
538
- if ($_SESSION['pmxi_import']['large_file']){ // in large mode
 
 
539
 
540
  if ($post['show_element'] == 1) {
541
- $_SESSION['pmxi_import']['count'] = $this->data['node_list_count'] = 0;
 
 
 
542
  }
543
- else
544
- $this->data['node_list_count'] = $_SESSION['pmxi_import']['count'];
545
 
546
 
547
  $xpath_elements = explode('[', $post['xpath']);
548
- $xpath_parts = explode('/', $xpath_elements[0]);
549
 
550
- $_SESSION['pmxi_import']['source']['root_element'] = $xpath_parts[count($xpath_parts) - 1];
551
 
552
- $loop = 1;
 
 
553
 
554
- foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
555
 
556
- $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
557
  // loop through the file until all lines are read
558
  while ($xml = $file->read()) {
559
-
560
  if (!empty($xml))
561
  {
562
  $xml = $file->encoding . "\n" . $xml;
@@ -567,25 +573,26 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
567
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
568
  libxml_use_internal_errors($old);
569
  $xpath = new DOMXPath($dom);
570
- if (($this->data['elements'] = $elements = @$xpath->query($post['xpath'])) and $elements->length){
571
-
572
  if ($post['show_element'] == 1){
573
- $_SESSION['pmxi_import']['count']++;
574
  $this->data['node_list_count']++;
 
575
  }
576
 
577
  if ($loop == $post['show_element'] ){
578
- $_SESSION['pmxi_import']['xml'] = $xml;
579
  $this->data['dom'] = $dom;
580
  if ($post['show_element'] > 1)
581
  break;
582
  }
583
  else unset($dom, $xpath, $elements);
584
  $loop++;
585
- }
586
- }
587
- }
588
- unset($file);
 
589
  }
590
  if ( ! $this->data['node_list_count']) {
591
  $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
@@ -606,14 +613,13 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
606
  };
607
  }
608
  }
609
- }
610
  }
611
  if ( ! $this->errors->get_error_codes()) {
612
 
613
  //$this->shrink_xml_element($this->data['dom']->documentElement);
614
  $xpath = new DOMXPath($this->data['dom']);
615
- $this->data['elements'] = $elements = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
616
-
617
  $paths = array(); $this->data['paths'] =& $paths;
618
  if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $elements->length <= PMXI_Plugin::getInstance()->getOption('highlight_limit')) {
619
  foreach ($elements as $el) {
@@ -622,6 +628,9 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
622
  $p = $this->get_xml_path($el, $xpath) and $paths[] = $p;
623
  }
624
  }
 
 
 
625
  $this->render();
626
  } else {
627
  $this->error();
@@ -638,7 +647,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
638
  }
639
 
640
  $xpath = new DOMXPath($this->data['dom']);
641
- $post = $this->input->post(array('xpath' => '', 'show_element' => 1, 'root_element' => $_SESSION['pmxi_import']['source']['root_element'], 'tagno' => 0));
642
  $wp_uploads = wp_upload_dir();
643
 
644
  $this->data['tagno'] = max(intval($this->input->getpost('tagno', 1)), 0);
@@ -646,7 +655,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
646
  if ('' == $post['xpath']) {
647
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
648
  } else {
649
- $post['xpath'] = '/' . $_SESSION['pmxi_import']['source']['root_element'] . '/'. ltrim(trim(str_replace("[*]","",$post['xpath']),'{}'), '/');
650
 
651
  // in default mode
652
  $this->data['variation_elements'] = $elements = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
@@ -700,7 +709,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
700
  );
701
  if ($this->isWizard) {
702
  $this->data['post'] = $post = $this->input->post(
703
- (isset($_SESSION['pmxi_import']['template']) ? $_SESSION['pmxi_import']['template'] : array())
704
  + $default
705
  );
706
  } else {
@@ -720,7 +729,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
720
  'fix_characters' => $template->fix_characters,
721
  'name' => '', // template is always empty
722
  );
723
- $_SESSION['pmxi_import']['is_loaded_template'] = $load_template;
724
  }
725
 
726
  } elseif ($this->input->post('is_submitted')) { // save template submission
@@ -741,18 +750,26 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
741
  if ( ! $this->errors->get_error_codes()) {
742
  if ( ! empty($post['name'])) { // save template in database
743
  $template->getByName($post['name'])->set($post)->save();
744
- $_SESSION['pmxi_import']['saved_template'] = $template->id;
745
  }
746
  if ($this->isWizard) {
747
- $_SESSION['pmxi_import']['template'] = $post;
 
 
 
748
  wp_redirect(add_query_arg('action', 'options', $this->baseUrl)); die();
749
  } else {
750
- $this->data['import']->set('template', $post)->save();
 
751
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode(__('Template updated', 'pmxi_plugin'))) + array_intersect_key($_GET, array_flip($this->baseUrlParamNames)), admin_url('admin.php'))); die();
752
  }
 
753
  }
 
754
  }
755
 
 
 
756
  if (user_can_richedit()) {
757
  wp_enqueue_script('editor');
758
  }
@@ -788,29 +805,31 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
788
  {
789
  $update_previous = new PMXI_Import_Record();
790
  if ($update_previous->getById($this->input->get('id'))) {
791
- $_SESSION['pmxi_import'] = array(
792
  'update_previous' => $update_previous->id,
793
  'xpath' => $update_previous->xpath,
794
  'template' => $update_previous->template,
795
- 'options' => $update_previous->options,
796
  );
797
  $history = new PMXI_File_List();
798
  $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $update_previous->id), 'id DESC');
 
799
  if ($history->count()){
800
  $history_file = new PMXI_File_Record();
801
  $history_file->getBy('id', $history[0]['id']);
802
 
803
  if ($update_previous->large_import == 'Yes'){
804
- $_SESSION['pmxi_import']['filePath'] = $history_file->path;
805
- if (!@file_exists($_SESSION['pmxi_import']['filePath'])) $_SESSION['pmxi_import']['filePath'] = $wp_uploads['basedir'] . '/wpallimport_history/' . $history_file->id;
806
- $_SESSION['pmxi_import']['source']['root_element'] = $update_previous->root_element;
807
- $_SESSION['pmxi_import']['large_file'] = true;
808
- $_SESSION['pmxi_import']['count'] = $update_previous->count;
 
809
  }
810
  else{
811
- $_SESSION['pmxi_import']['xml'] = @file_get_contents($history_file->path);
812
  $this->data['dom'] = $dom = new DOMDocument('1.0', 'UTF-8');
813
- $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $_SESSION['pmxi_import']['xml']));
814
  $xpath = new DOMXPath($dom);
815
 
816
  $this->data['elements'] = $elements = $xpath->query($update_previous->xpath);
@@ -819,18 +838,20 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
819
  }
820
 
821
  } else {
822
- $_SESSION['pmxi_import']['update_previous'] = '';
823
  }
824
  }
825
 
826
- $this->data['tagno'] = min(max(intval($this->input->getpost('tagno', 1)), 1), ( ! $_SESSION['pmxi_import']['large_file'] ) ? $this->data['elements']->length : $_SESSION['pmxi_import']['count']);
827
 
828
- if ($_SESSION['pmxi_import']['large_file'] and $this->data['tagno']){
829
- $loop = 1;
830
- $_SESSION['pmxi_import']['local_paths'] = (!empty($_SESSION['pmxi_import']['local_paths'])) ? $_SESSION['pmxi_import']['local_paths'] : array($_SESSION['pmxi_import']['filePath']);
831
- foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
 
832
  if (file_exists($path)){
833
- $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element']));
 
834
  // loop through the file until all lines are read
835
  while ($xml = $file->read()) {
836
  if (!empty($xml))
@@ -843,9 +864,9 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
843
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
844
  libxml_use_internal_errors($old);
845
  $xpath = new DOMXPath($dom);
846
- if (($this->data['elements'] = $elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
847
  if ($loop == $this->data['tagno']){
848
- $_SESSION['pmxi_import']['xml'] = $xml;
849
  break;
850
  } else unset($dom, $xpath, $elements);
851
  $loop++;
@@ -855,7 +876,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
855
  unset($file);
856
  }
857
  }
858
- }
859
 
860
  $this->render();
861
  }
@@ -874,11 +895,16 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
874
  ));
875
  $wp_uploads = wp_upload_dir();
876
 
877
- $tagno = min(max(intval($this->input->getpost('tagno', 1)), 1), ( ! $_SESSION['pmxi_import']['large_file']) ? $this->data['elements']->length : $_SESSION['pmxi_import']['count']);
878
- if ($_SESSION['pmxi_import']['large_file']){
 
 
 
 
 
879
  $loop = 1;
880
- foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
881
- $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
882
  // loop through the file until all lines are read
883
  while ($xml = $file->read()) {
884
  if (!empty($xml))
@@ -891,9 +917,9 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
891
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
892
  libxml_use_internal_errors($old);
893
  $xpath = new DOMXPath($dom);
894
- if (($this->data['elements'] = $elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
895
  if ( $loop == $tagno ) {
896
- $_SESSION['pmxi_import']['xml'] = $xml;
897
  break;
898
  }
899
  unset($dom, $xpath, $elements);
@@ -905,17 +931,17 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
905
  }
906
  $tagno = 1;
907
  }
908
- $xpath = "(" . $_SESSION['pmxi_import']['xpath'] . ")[$tagno]";
909
  // validate
910
  try {
911
  if (empty($post['title'])) {
912
  $this->errors->add('form-validation', __('Post title is empty', 'pmxi_plugin'));
913
- } else {
914
- list($this->data['title']) = XmlImportParser::factory($_SESSION['pmxi_import']['xml'], $xpath, $post['title'], $file)->parse(); unlink($file);
915
  if ( ! isset($this->data['title']) or '' == strval(trim(strip_tags($this->data['title'], '<img><input><textarea><iframe><object><embed>')))) {
916
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post title is empty', 'pmxi_plugin'));
917
  }
918
- else $this->data['title'] = ($post['fix_characters']) ? utf8_encode(html_entity_decode($this->data['title'])) : (($post['is_leave_html']) ? html_entity_decode($this->data['title']) : $this->data['title']);
919
  }
920
  } catch (XmlImportException $e) {
921
  $this->errors->add('form-validation', sprintf(__('Error parsing title: %s', 'pmxi_plugin'), $e->getMessage()));
@@ -924,11 +950,11 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
924
  if (empty($post['content'])) {
925
  $this->errors->add('form-validation', __('Post content is empty', 'pmxi_plugin'));
926
  } else {
927
- list($this->data['content']) = XmlImportParser::factory($post['is_keep_linebreaks'] ? $_SESSION['pmxi_import']['xml'] : preg_replace('%\r\n?|\n%', ' ', $_SESSION['pmxi_import']['xml']), $xpath, $post['content'], $file)->parse(); unlink($file);
928
  if ( ! isset($this->data['content']) or '' == strval(trim(strip_tags($this->data['content'], '<img><input><textarea><iframe><object><embed>')))) {
929
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post content is empty', 'pmxi_plugin'));
930
  }
931
- else $this->data['content'] = ($post['fix_characters']) ? utf8_encode(html_entity_decode($this->data['content'])) : (($post['is_leave_html']) ? html_entity_decode($this->data['content']) : $this->data['content']);
932
  }
933
  } catch (XmlImportException $e) {
934
  $this->errors->add('form-validation', sprintf(__('Error parsing content: %s', 'pmxi_plugin'), $e->getMessage()));
@@ -947,8 +973,8 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
947
  $default = PMXI_Plugin::get_default_import_options();
948
 
949
  if ($this->isWizard) {
950
- $this->data['source_type'] = $_SESSION['pmxi_import']['source']['type'];
951
- $default['unique_key'] = $_SESSION['pmxi_import']['template']['title'];
952
 
953
  // auto searching ID element
954
  if (!empty($this->data['dom'])){
@@ -972,23 +998,23 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
972
  }
973
  }
974
  }
975
- }
976
-
977
  if ( class_exists('PMWI_Plugin') )
978
  $post = $this->input->post(
979
- (isset($_SESSION['pmxi_import']['options']) ? $_SESSION['pmxi_import']['options'] : array())
980
  + $default
981
  + PMWI_Plugin::get_default_import_options()
982
  );
983
  else
984
  $post = $this->input->post(
985
- (isset($_SESSION['pmxi_import']['options']) ? $_SESSION['pmxi_import']['options'] : array())
986
  + $default
987
  );
988
 
989
  $scheduled = $this->input->post(array(
990
- 'is_scheduled' => ! empty($_SESSION['pmxi_import']['scheduled']),
991
- 'scheduled_period' => ! empty($_SESSION['pmxi_import']['scheduled']) ? $_SESSION['pmxi_import']['scheduled'] : '0 0 * * *', // daily by default
992
  ));
993
 
994
  } else {
@@ -1012,7 +1038,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1012
 
1013
  $this->data['post'] =& $post;
1014
  $this->data['scheduled'] =& $scheduled;
1015
- $this->data['is_loaded_template'] = $_SESSION['pmxi_import']['is_loaded_template'];
1016
 
1017
  // Get All meta keys in the system
1018
  $this->data['meta_keys'] = $keys = new PMXI_Model_List();
@@ -1021,7 +1047,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1021
 
1022
  $load_template = $this->input->post('load_template');
1023
  if ($load_template) { // init form with template selected
1024
- $_SESSION['pmxi_import']['is_loaded_template'] = $load_template;
1025
  $template = new PMXI_Template_Record();
1026
  if ( ! $template->getById($load_template)->isEmpty()) {
1027
  $post = (!empty($template->options) ? $template->options : array()) + $default;
@@ -1031,7 +1057,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1031
  );
1032
  }
1033
  } elseif ($load_template == -1){
1034
- $_SESSION['pmxi_import']['is_loaded_template'] = 0;
1035
 
1036
  $post = $default;
1037
  $scheduled = $this->input->post(array(
@@ -1088,7 +1114,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1088
  if ( ! preg_match('%^([1-9]\d*)( *- *([1-9]\d*))?$%', $chank, $mtch)) {
1089
  $this->errors->add('form-validation', __('Wrong format of `Import only specified records` value', 'pmxi_plugin'));
1090
  break;
1091
- } elseif ($this->isWizard and empty($_SESSION['pmxi_import']['large_file']) and (intval($mtch[1]) > $this->data['elements']->length or isset($mtch[3]) and intval($mtch[3]) > $this->data['elements']->length)) {
1092
  $this->errors->add('form-validation', __('One of the numbers in `Import only specified records` value exceeds record quantity in XML file', 'pmxi_plugin'));
1093
  break;
1094
  }
@@ -1113,33 +1139,35 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1113
  '' !== $post['date_start'] or $post['date_start'] = 'now';
1114
  '' !== $post['date_end'] or $post['date_end'] = 'now';
1115
 
 
 
 
 
 
 
 
 
 
 
1116
  if ($this->isWizard) {
1117
- $_SESSION['pmxi_import']['options'] = $post;
1118
- $_SESSION['pmxi_import']['scheduled'] = $scheduled['is_scheduled'] ? $scheduled['scheduled_period'] : '';
 
 
1119
 
1120
- if ( $this->input->post('name')) { // save template in database
1121
- $template = new PMXI_Template_Record();
1122
-
1123
- $template->getByName($this->input->post('name'))->set(array(
1124
- 'name' => $this->input->post('name'),
1125
- 'options' => $post,
1126
- 'scheduled' => (($scheduled['is_scheduled']) ? $scheduled['scheduled_period'] : '')
1127
- ))->save();
1128
- }
1129
-
1130
  if ( ! $this->input->post('save_only')) {
1131
  wp_redirect(add_query_arg('action', 'process', $this->baseUrl)); die();
1132
  } else {
1133
  $import = $this->data['update_previous'];
1134
  $is_update = ! $import->isEmpty();
1135
  $import->set(
1136
- $_SESSION['pmxi_import']['source']
1137
  + array(
1138
- 'xpath' => $_SESSION['pmxi_import']['xpath'],
1139
- 'template' => $_SESSION['pmxi_import']['template'],
1140
- 'options' => $_SESSION['pmxi_import']['options'],
1141
- 'scheduled' => $_SESSION['pmxi_import']['scheduled'],
1142
- 'count' => $_SESSION['pmxi_import']['count'],
1143
  'friendly_name' => $this->data['post']['friendly_name'],
1144
  )
1145
  )->save();
@@ -1148,11 +1176,15 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1148
  $history_file->set(array(
1149
  'name' => $import->name,
1150
  'import_id' => $import->id,
1151
- 'path' => $_SESSION['pmxi_import']['filePath'],
1152
- 'contents' => $_SESSION['pmxi_import']['xml'],
1153
  'registered_on' => date('Y-m-d H:i:s'),
1154
  ))->save();
1155
- unset($_SESSION['pmxi_import']); // clear session data
 
 
 
 
1156
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode($is_update ? __('Import updated', 'pmxi_plugin') : __('Import created', 'pmxi_plugin'))), admin_url('admin.php'))); die();
1157
  }
1158
  } else {
@@ -1169,6 +1201,8 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1169
  ! empty($post['attribute_name']) or $post['attribute_name'] = array('') and $post['attribute_value'] = array('');
1170
  }
1171
 
 
 
1172
  $this->render();
1173
  }
1174
 
@@ -1179,43 +1213,44 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1179
  {
1180
  $wp_uploads = wp_upload_dir();
1181
 
1182
- set_time_limit(0);
1183
 
1184
  $import = $this->data['update_previous'];
1185
  $import->set(
1186
- (empty($_SESSION['pmxi_import']['source']) ? array() : $_SESSION['pmxi_import']['source'])
1187
  + array(
1188
- 'xpath' => $_SESSION['pmxi_import']['xpath'],
1189
- 'template' => $_SESSION['pmxi_import']['template'],
1190
- 'options' => $_SESSION['pmxi_import']['options'],
1191
- 'scheduled' => $_SESSION['pmxi_import']['scheduled'],
1192
- 'count' => $_SESSION['pmxi_import']['count'],
1193
- 'friendly_name' => $_SESSION['pmxi_import']['options']['friendly_name'],
 
1194
  )
1195
  );
1196
 
1197
- if ( ! PMXI_Plugin::is_ajax()) {
1198
-
1199
  // Save import history
1200
- if ( $_SESSION['pmxi_import']['chunk_number'] === 1 ){
1201
  // store import info in database
1202
  $import->set(array(
1203
  'imported' => 0,
1204
  'created' => 0,
1205
  'updated' => 0,
1206
- 'skipped' => 0
1207
- ))->save();
 
1208
 
1209
  do_action( 'pmxi_before_xml_import', $import->id );
1210
 
1211
- if ($_SESSION['pmxi_import']['large_file']) $_SESSION['pmxi_import']['update_previous'] = $import->id;
1212
 
1213
  // unlick previous files
1214
  $history = new PMXI_File_List();
1215
  $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $import->id), 'id DESC');
1216
  if ($history->count()){
1217
  foreach ($history as $file){
1218
- if (@file_exists($file['path']) and $file['path'] != $_SESSION['pmxi_import']['filePath']) @unlink($file['path']);
1219
  $history_file = new PMXI_File_Record();
1220
  $history_file->getBy('id', $file['id']);
1221
  if ( ! $history_file->isEmpty()) $history_file->delete();
@@ -1227,125 +1262,41 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1227
  $history_file->set(array(
1228
  'name' => $import->name,
1229
  'import_id' => $import->id,
1230
- 'path' => $_SESSION['pmxi_import']['filePath'],
1231
- 'contents' => $_SESSION['pmxi_import']['xml'],
1232
  'registered_on' => date('Y-m-d H:i:s'),
1233
  ))->save();
1234
- }
 
1235
  }
1236
 
1237
  $this->render();
1238
- wp_ob_end_flush_all(); flush();
1239
- }
1240
-
1241
- // create chunks
1242
- if ($_SESSION['pmxi_import']['large_file'] and $_SESSION['pmxi_import']['chunk_number'] === 1 and $_SESSION['pmxi_import']['options']['create_chunks'] and ! PMXI_Plugin::is_ajax()){
1243
 
1244
- $_SESSION['pmxi_import']['chunks_files'] = array();
1245
-
1246
- foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
1247
- $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
1248
- $new_chunk = true;
1249
- $loop = 0;
1250
- $o = false;
1251
-
1252
- // loop through the file until all lines are read
1253
- while ($xml = $file->read()) {
1254
-
1255
- if (!empty($xml))
1256
- {
1257
-
1258
- PMXI_Import_Record::preprocessXml($xml);
1259
-
1260
- $dom = new DOMDocument('1.0', 'UTF-8');
1261
- $old = libxml_use_internal_errors(true);
1262
- $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
1263
- libxml_use_internal_errors($old);
1264
- $xpath = new DOMXPath($dom);
1265
- if (($elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
1266
-
1267
- if ($new_chunk){
1268
- $tmpname = $wp_uploads['path'] .'/'. wp_unique_filename($wp_uploads['path'], basename($path));
1269
- $c = fopen($tmpname, 'w');
1270
- fwrite($c, $file->encoding . "\n" . "<".$_SESSION['pmxi_import']['source']['root_element'] ."s>\n");
1271
- }
1272
-
1273
- fwrite($c, $xml . "\n");
1274
-
1275
- if ($loop == $_SESSION['pmxi_import']['options']['records_per_request'] - 1) {
1276
- fwrite($c, "</".$_SESSION['pmxi_import']['source']['root_element'] . "s>");
1277
- fclose($c);
1278
- $_SESSION['pmxi_import']['chunks_files'][] = $tmpname;
1279
-
1280
- $loop = 0;
1281
- $new_chunk = true;
1282
- }
1283
- else {
1284
- $loop++;
1285
- $new_chunk = false;
1286
- }
1287
- }
1288
- }
1289
- }
1290
- if ($loop){
1291
- fwrite($c, "</".$_SESSION['pmxi_import']['source']['root_element'] . "s>");
1292
- fclose($c);
1293
- $_SESSION['pmxi_import']['chunks_files'][] = $tmpname;
1294
- }
1295
- }
1296
- $_SESSION['pmxi_import']['local_paths'] = $_SESSION['pmxi_import']['chunks_files'];
1297
-
1298
- }
1299
 
1300
- $logger = create_function('$m', 'echo "<div class=\\"progress-msg\\">$m</div>\\n"; if ( "" != strip_tags(pmxi_strip_tags_content($m))) { $_SESSION[\'pmxi_import\'][\'log\'] .= "<p>".strip_tags(pmxi_strip_tags_content($m))."</p>"; flush(); }');
1301
 
1302
- $_SESSION['pmxi_import']['start_time'] = (empty($_SESSION['pmxi_import']['start_time'])) ? time() : $_SESSION['pmxi_import']['start_time'];
1303
 
1304
  in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, __('Reading files for import...', 'pmxi_plugin'));
1305
- in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, sprintf(_n('%s file found', '%s files found', count($_SESSION['pmxi_import']['local_paths']), 'pmxi_plugin'), count($_SESSION['pmxi_import']['local_paths'])));
1306
- in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, sprintf(__('Importing %s (%s of %s)', 'pmxi_plugin'), $_SESSION['pmxi_import']['local_paths'][0], 1, count($_SESSION['pmxi_import']['local_paths'])));
1307
 
1308
- if (empty($_SESSION['pmxi_import']['large_file'])){
1309
- $import->process($_SESSION['pmxi_import']['xml'], $logger, false);
1310
- }
1311
- elseif (PMXI_Plugin::is_ajax()) {
1312
 
1313
- $_SESSION['pmxi_import']['current_post_ids'] = (empty($_SESSION['pmxi_import']['current_post_ids'])) ? array() : $_SESSION['pmxi_import']['current_post_ids'];
1314
 
1315
- $_SESSION['pmxi_import']['pointer'] = (empty($_SESSION['pmxi_import']['pointer'])) ? 0 : $_SESSION['pmxi_import']['pointer'];
1316
 
1317
- $loop = 0;
1318
 
1319
- foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
1320
-
1321
- if ($_SESSION['pmxi_import']['options']['create_chunks'] and $_SESSION['pmxi_import']['action'] != 'continue'){
1322
-
1323
- if ($_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] == $_SESSION['pmxi_import']['count']) break;
1324
-
1325
- ob_start();
1326
 
1327
- $xml = file_get_contents($path);
1328
-
1329
- if (!empty($xml))
1330
- {
1331
- PMXI_Import_Record::preprocessXml($xml);
1332
-
1333
- $import->set(array('xpath' => '/' . $_SESSION['pmxi_import']['source']['root_element'] . 's' . $_SESSION['pmxi_import']['xpath']))->save();
1334
- $import->process($xml, $logger, $_SESSION['pmxi_import']['chunk_number']);
1335
- $import->set(array('xpath' => $_SESSION['pmxi_import']['xpath']))->save();
1336
-
1337
- array_shift($_SESSION['pmxi_import']['local_paths']);
1338
- if (!empty($_SESSION['pmxi_import']['chunks_files'])) {
1339
- $imported_file = array_shift($_SESSION['pmxi_import']['chunks_files']);
1340
- @unlink($imported_file);
1341
- }
1342
- }
1343
-
1344
- exit(ob_get_clean());
1345
- }
1346
- else{
1347
 
1348
- $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']), $_SESSION['pmxi_import']['pointer']);
1349
 
1350
  // loop through the file until all lines are read
1351
  while ($xml = $file->read()) {
@@ -1360,46 +1311,53 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1360
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
1361
  libxml_use_internal_errors($old);
1362
  $xpath = new DOMXPath($dom);
1363
- if (($this->data['elements'] = $elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
1364
- $_SESSION['pmxi_import']['pointer'] = $file->pointer;
1365
- $_SESSION['pmxi_import']['xml'] = $xml;
 
1366
  if ( ! $loop ) ob_start();
1367
- $import->process($_SESSION['pmxi_import']['xml'], $logger, $_SESSION['pmxi_import']['chunk_number']);
1368
- if ( $loop == $_SESSION['pmxi_import']['options']['records_per_request'] - 1 ) exit(ob_get_clean());
1369
  $loop++;
1370
  }
1371
  }
1372
 
1373
- if (($_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] == $_SESSION['pmxi_import']['count']) and !in_array($import->type, array('ftp'))){
1374
- $_SESSION['pmxi_import']['pointer'] = 0;
1375
- array_shift($_SESSION['pmxi_import']['local_paths']);
 
 
1376
  exit(ob_get_clean());
1377
  }
1378
  }
1379
 
1380
  if (in_array($import->type, array('ftp'))) {
1381
- $_SESSION['pmxi_import']['pointer'] = 0;
1382
- array_shift($_SESSION['pmxi_import']['local_paths']);
1383
- if (!empty($_SESSION['pmxi_import']['local_paths'])) {
1384
- $logger and call_user_func($logger, sprintf(__('Importing %s', 'pmxi_plugin'), $_SESSION['pmxi_import']['local_paths'][0]));
 
1385
  }
 
1386
  exit(ob_get_clean());
1387
- }
1388
  }
1389
  }
1390
  }
1391
-
1392
- if (! $_SESSION['pmxi_import']['large_file'] or PMXI_Plugin::is_ajax()){
1393
 
1394
  // Save import process log
1395
  $log_file = $wp_uploads['basedir'] . '/wpallimport_logs/' . $import->id . '.html';
1396
  if (file_exists($log_file)) unlink($log_file);
1397
- @file_put_contents($log_file, $_SESSION['pmxi_import']['log']);
1398
 
1399
- if (!empty($_SESSION['pmxi_import'])) do_action( 'pmxi_after_xml_import', $import->id );
1400
 
1401
  // clear import session
1402
- unset($_SESSION['pmxi_import']); // clear session data (prevent from reimporting the same data on page refresh)
 
 
1403
 
1404
  // [indicate in header process is complete]
1405
  $msg = addcslashes(__('Complete', 'pmxi_plugin'), "'\n\r");
@@ -1408,7 +1366,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1408
 
1409
  ob_start();
1410
 
1411
- echo '<a id="download_pmxi_log" class="update" href="'.esc_url(add_query_arg(array('id' => $import->id, 'action' => 'log', 'page' => 'pmxi-admin-manage'), $this->baseUrl)).'">Download log</a>';
1412
  echo <<<COMPLETE
1413
  <script type="text/javascript">
1414
  //<![CDATA[
@@ -1679,4 +1637,32 @@ COMPLETE;
1679
  $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
1680
  }
1681
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1682
  }
10
  protected $isTemplateEdit = false; // indicates whether controlled is deligated by manage imports controller
11
 
12
  protected function init() {
13
+ parent::init();
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  if ('PMXI_Admin_Manage' == PMXI_Plugin::getInstance()->getAdminCurrentScreen()->base) { // prereqisites are not checked when flow control is deligated
16
  $id = $this->input->get('id');
52
  // step #2: element selection
53
  $this->data['dom'] = $dom = new DOMDocument('1.0', 'UTF-8');
54
  $this->data['update_previous'] = $update_previous = new PMXI_Import_Record();
55
+ $old = libxml_use_internal_errors(true);
56
+
57
+ $xml = $this->get_xml();
58
+
59
+ if (empty($xml) and 'process' == $action){
60
+ ! empty(PMXI_Plugin::$session->data['pmxi_import']['update_previous']) and $update_previous->getById(PMXI_Plugin::$session->data['pmxi_import']['update_previous']);
61
+ return true;
62
+ }
63
 
64
+ if (empty(PMXI_Plugin::$session->data['pmxi_import'])
65
+ or ! $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml))// FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
66
+ //or empty(PMXI_Plugin::$session['pmxi_import']['source'])
67
+ or ! empty(PMXI_Plugin::$session->data['pmxi_import']['update_previous']) and $update_previous->getById(PMXI_Plugin::$session->data['pmxi_import']['update_previous'])->isEmpty()
68
  ) {
69
+ if (!PMXI_Plugin::is_ajax()){
70
+ $this->errors->add('form-validation', __('Can not create DOM object for provided feed.', 'pmxi_plugin'));
71
+ wp_redirect_or_javascript($this->baseUrl); die();
72
+ }
73
  }
74
+ libxml_use_internal_errors($old);
75
  if ('element' == $action) return true;
76
  if ('evaluate' == $action) return true;
77
  if ('evaluate_variations' == $action) return true;
78
 
79
  // step #3: template
80
  $xpath = new DOMXPath($dom);
81
+ $elements = $xpath->query(PMXI_Plugin::$session->data['pmxi_import']['xpath']);
82
+
83
+ if (empty(PMXI_Plugin::$session->data['pmxi_import']['xpath']) or ! ($this->data['elements'] = $elements = $xpath->query(PMXI_Plugin::$session->data['pmxi_import']['xpath'])) or ! $elements->length) {
84
  $this->errors->add('form-validation', __('No matching elements found.', 'pmxi_plugin'));
85
  wp_redirect_or_javascript(add_query_arg('action', 'element', $this->baseUrl)); die();
86
  }
87
  if ('template' == $action or 'preview' == $action or 'tag' == $action) return true;
88
 
89
  // step #4: options
90
+ if (empty(PMXI_Plugin::$session->data['pmxi_import']['template']) or empty(PMXI_Plugin::$session->data['pmxi_import']['template']['title']) or empty(PMXI_Plugin::$session->data['pmxi_import']['template']['title'])) {
91
  wp_redirect_or_javascript(add_query_arg('action', 'template', $this->baseUrl)); die();
92
  }
93
  if ('options' == $action) return true;
94
 
95
+ if (empty(PMXI_Plugin::$session->data['pmxi_import']['options'])) {
96
  wp_redirect(add_query_arg('action', 'options', $this->baseUrl)); die();
97
  }
98
  }
123
  ));
124
 
125
  if ($this->input->post('is_submitted_continue')) {
126
+ if ( ! empty(PMXI_Plugin::$session->data['pmxi_import']['xml'])) {
127
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
128
  }
129
  } elseif ('upload' == $this->input->post('type')) {
358
 
359
  $source['first_import'] = date("Y-m-d H:i:s");
360
 
361
+ PMXI_Plugin::$session['pmxi_import'] = array(
362
+ //'xml' => $xml,
363
  'filePath' => $filePath,
364
  'xpath' => (!empty($xpath)) ? $xpath : '',
365
  'source' => $source,
384
  unset($xml);
385
  $update_previous = new PMXI_Import_Record();
386
  if ($post['is_update_previous'] and ! $update_previous->getById($post['update_previous'])->isEmpty()) {
387
+ PMXI_Plugin::$session['pmxi_import']['update_previous'] = $update_previous->id;
388
+ PMXI_Plugin::$session['pmxi_import']['xpath'] = $update_previous->xpath;
389
+ PMXI_Plugin::$session['pmxi_import']['template'] = $update_previous->template;
390
+ PMXI_Plugin::$session['pmxi_import']['options'] = $update_previous->options;
 
 
391
  } else {
392
+ PMXI_Plugin::$session['pmxi_import']['update_previous'] = '';
393
  }
394
+
395
+ pmxi_session_commit();
396
+
397
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
398
 
399
  }
414
  $xpath = new DOMXPath($this->data['dom']);
415
  $post = $this->input->post(array('xpath' => ''));
416
  $this->data['post'] =& $post;
417
+ $this->data['elements_cloud'] = PMXI_Plugin::$session->data['pmxi_import']['elements_cloud'];
418
 
419
  $wp_uploads = wp_upload_dir();
420
+
421
+ if ($this->input->post('is_submitted')) {
422
  check_admin_referer('choose-elements', '_wpnonce_choose-elements');
423
  if ('' == $post['xpath']) {
424
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
425
  } else {
426
  $node_list = @ $xpath->query($post['xpath']); // make sure only element selection is allowed; prevent parsing warning to be displayed
427
+
428
  if (FALSE === $node_list) {
429
  $this->errors->add('form-validation', __('Invalid XPath expression', 'pmxi_plugin'));
430
+ /*} elseif ( ! $node_list->length) {
431
+ $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));*/
432
  } else {
433
  foreach ($node_list as $el) {
434
  if ( ! $el instanceof DOMElement) {
441
 
442
  if ( ! $this->errors->get_error_codes()) {
443
 
444
+ PMXI_Plugin::$session['pmxi_import']['xpath'] = $post['xpath'];
445
  // counting element selected by xPath
446
+ if (PMXI_Plugin::$session->data['pmxi_import']['large_file']){
447
 
448
+ PMXI_Plugin::$session->data['pmxi_import']['count'] = 0;
449
 
450
  $this->data['node_list_count'] = 0;
451
 
452
  // loop through the file until all lines are read
453
  $first_loop = true;
454
 
455
+ foreach (PMXI_Plugin::$session->data['pmxi_import']['local_paths'] as $key => $path) {
456
 
457
+ $file = new PMXI_Chunk($path, array('element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path'], 'type' => $this->input->post('type')));
458
 
459
  while ($xml = $file->read()) {
460
 
469
  libxml_use_internal_errors($old);
470
  $xpath = new DOMXPath($dom);
471
  if (($this->data['elements'] = $elements = @$xpath->query($post['xpath'])) and $elements->length){
472
+ PMXI_Plugin::$session['pmxi_import']['count']++;
473
  $this->data['node_list_count']++;
474
  if ($first_loop){
475
+ //PMXI_Plugin::$session['pmxi_import']['xml'] = $xml;
476
  $first_loop = false;
477
  }
478
  }
485
  if ( ! $this->data['node_list_count']) {
486
  $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
487
  }
488
+
489
+ pmxi_session_commit();
490
+
491
  }
492
  wp_redirect(add_query_arg('action', 'template', $this->baseUrl)); die();
493
  }
494
+
495
  } else {
496
 
497
+ if (isset(PMXI_Plugin::$session->data['pmxi_import']['xpath']) and PMXI_Plugin::$session->data['pmxi_import']['large_file']) {
498
+ $post['xpath'] = PMXI_Plugin::$session->data['pmxi_import']['xpath'];
499
  $this->data['elements'] = $elements = $xpath->query($post['xpath']);
500
+ if ( ! $elements->length and ! empty(PMXI_Plugin::$session->data['pmxi_import']['update_previous'])) {
501
  $_GET['pmxi_nt'] = __('<b>Warning</b>: No matching elements found for XPath expression from the import being updated. It probably means that new XML file has different format. Though you can update XPath, procceed only if you sure about update operation being valid.', 'pmxi_plugin');
502
  }
503
  } else {
526
  {
527
  if ( ! PMXI_Plugin::getInstance()->getAdminCurrentScreen()->is_ajax) { // call is only valid when send with ajax
528
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
529
+ }
530
 
531
  $xpath = new DOMXPath($this->data['dom']);
532
+ $post = $this->input->post(array('xpath' => '', 'show_element' => 1, 'root_element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element']));
533
  $wp_uploads = wp_upload_dir();
534
 
535
  if ('' == $post['xpath']) {
536
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
537
  } else {
538
  // counting selected elements
539
+ if (PMXI_Plugin::$session->data['pmxi_import']['large_file']){ // in large mode
540
+
541
+ PMXI_Plugin::$session['pmxi_import']['xpath'] = $post['xpath'];
542
 
543
  if ($post['show_element'] == 1) {
544
+ PMXI_Plugin::$session['pmxi_import']['count'] = $this->data['node_list_count'] = 0;
545
+ }
546
+ else{
547
+ $this->data['node_list_count'] = PMXI_Plugin::$session->data['pmxi_import']['count'];
548
  }
 
 
549
 
550
 
551
  $xpath_elements = explode('[', $post['xpath']);
552
+ $xpath_parts = explode('/', $xpath_elements[0]);
553
 
554
+ PMXI_Plugin::$session['pmxi_import']['source']['root_element'] = $xpath_parts[count($xpath_parts) - 1];
555
 
556
+ pmxi_session_commit();
557
+
558
+ $loop = 1;
559
 
560
+ foreach (PMXI_Plugin::$session->data['pmxi_import']['local_paths'] as $key => $path) {
561
 
562
+ $file = new PMXI_Chunk($path, array('element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
563
  // loop through the file until all lines are read
564
  while ($xml = $file->read()) {
565
+
566
  if (!empty($xml))
567
  {
568
  $xml = $file->encoding . "\n" . $xml;
573
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
574
  libxml_use_internal_errors($old);
575
  $xpath = new DOMXPath($dom);
576
+ if (($this->data['elements'] = $elements = @$xpath->query($post['xpath'])) and $elements->length){
577
+
578
  if ($post['show_element'] == 1){
 
579
  $this->data['node_list_count']++;
580
+ PMXI_Plugin::$session['pmxi_import']['count'] = $this->data['node_list_count'];
581
  }
582
 
583
  if ($loop == $post['show_element'] ){
584
+ //PMXI_Plugin::$session['pmxi_import']['xml'] = $xml;
585
  $this->data['dom'] = $dom;
586
  if ($post['show_element'] > 1)
587
  break;
588
  }
589
  else unset($dom, $xpath, $elements);
590
  $loop++;
591
+ }
592
+ }
593
+ }
594
+
595
+ unset($file);
596
  }
597
  if ( ! $this->data['node_list_count']) {
598
  $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
613
  };
614
  }
615
  }
616
+ }
617
  }
618
  if ( ! $this->errors->get_error_codes()) {
619
 
620
  //$this->shrink_xml_element($this->data['dom']->documentElement);
621
  $xpath = new DOMXPath($this->data['dom']);
622
+ $this->data['elements'] = $elements = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
 
623
  $paths = array(); $this->data['paths'] =& $paths;
624
  if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $elements->length <= PMXI_Plugin::getInstance()->getOption('highlight_limit')) {
625
  foreach ($elements as $el) {
628
  $p = $this->get_xml_path($el, $xpath) and $paths[] = $p;
629
  }
630
  }
631
+
632
+ pmxi_session_commit();
633
+
634
  $this->render();
635
  } else {
636
  $this->error();
647
  }
648
 
649
  $xpath = new DOMXPath($this->data['dom']);
650
+ $post = $this->input->post(array('xpath' => '', 'show_element' => 1, 'root_element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'], 'tagno' => 0));
651
  $wp_uploads = wp_upload_dir();
652
 
653
  $this->data['tagno'] = max(intval($this->input->getpost('tagno', 1)), 0);
655
  if ('' == $post['xpath']) {
656
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
657
  } else {
658
+ $post['xpath'] = '/' . PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'] . '/'. ltrim(trim(str_replace("[*]","",$post['xpath']),'{}'), '/');
659
 
660
  // in default mode
661
  $this->data['variation_elements'] = $elements = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
709
  );
710
  if ($this->isWizard) {
711
  $this->data['post'] = $post = $this->input->post(
712
+ (isset(PMXI_Plugin::$session->data['pmxi_import']['template']) ? PMXI_Plugin::$session->data['pmxi_import']['template'] : array())
713
  + $default
714
  );
715
  } else {
729
  'fix_characters' => $template->fix_characters,
730
  'name' => '', // template is always empty
731
  );
732
+ PMXI_Plugin::$session['pmxi_import']['is_loaded_template'] = $load_template;
733
  }
734
 
735
  } elseif ($this->input->post('is_submitted')) { // save template submission
750
  if ( ! $this->errors->get_error_codes()) {
751
  if ( ! empty($post['name'])) { // save template in database
752
  $template->getByName($post['name'])->set($post)->save();
753
+ PMXI_Plugin::$session['pmxi_import']['saved_template'] = $template->id;
754
  }
755
  if ($this->isWizard) {
756
+ PMXI_Plugin::$session['pmxi_import']['template'] = $post;
757
+
758
+ pmxi_session_commit();
759
+
760
  wp_redirect(add_query_arg('action', 'options', $this->baseUrl)); die();
761
  } else {
762
+ $this->data['import']->set('template', $post)->save();
763
+ pmxi_session_commit();
764
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode(__('Template updated', 'pmxi_plugin'))) + array_intersect_key($_GET, array_flip($this->baseUrlParamNames)), admin_url('admin.php'))); die();
765
  }
766
+
767
  }
768
+ else $this->errors->add('form-validation', __('Make sure the shortcodes are escaped.', 'pmxi_plugin'));
769
  }
770
 
771
+ pmxi_session_commit();
772
+
773
  if (user_can_richedit()) {
774
  wp_enqueue_script('editor');
775
  }
805
  {
806
  $update_previous = new PMXI_Import_Record();
807
  if ($update_previous->getById($this->input->get('id'))) {
808
+ PMXI_Plugin::$session['pmxi_import'] = array(
809
  'update_previous' => $update_previous->id,
810
  'xpath' => $update_previous->xpath,
811
  'template' => $update_previous->template,
812
+ 'options' => $update_previous->options,
813
  );
814
  $history = new PMXI_File_List();
815
  $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $update_previous->id), 'id DESC');
816
+
817
  if ($history->count()){
818
  $history_file = new PMXI_File_Record();
819
  $history_file->getBy('id', $history[0]['id']);
820
 
821
  if ($update_previous->large_import == 'Yes'){
822
+ PMXI_Plugin::$session['pmxi_import']['filePath'] = $history_file->path;
823
+ if (!@file_exists($history_file->path)) PMXI_Plugin::$session['pmxi_import']['filePath'] = $wp_uploads['basedir'] . '/wpallimport_history/' . $history_file->id;
824
+ PMXI_Plugin::$session['pmxi_import']['source']['root_element'] = $update_previous->root_element;
825
+ PMXI_Plugin::$session['pmxi_import']['large_file'] = true;
826
+ PMXI_Plugin::$session['pmxi_import']['count'] = $update_previous->count;
827
+ pmxi_session_commit();
828
  }
829
  else{
830
+ $xml = @file_get_contents($history_file->path);
831
  $this->data['dom'] = $dom = new DOMDocument('1.0', 'UTF-8');
832
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml));
833
  $xpath = new DOMXPath($dom);
834
 
835
  $this->data['elements'] = $elements = $xpath->query($update_previous->xpath);
838
  }
839
 
840
  } else {
841
+ PMXI_Plugin::$session['pmxi_import']['update_previous'] = '';
842
  }
843
  }
844
 
845
+ $this->data['tagno'] = min(max(intval($this->input->getpost('tagno', 1)), 1), ( ! PMXI_Plugin::$session->data['pmxi_import']['large_file'] ) ? $this->data['elements']->length : PMXI_Plugin::$session->data['pmxi_import']['count']);
846
 
847
+ if (PMXI_Plugin::$session->data['pmxi_import']['large_file'] and $this->data['tagno']){
848
+
849
+ PMXI_Plugin::$session['pmxi_import']['local_paths'] = $local_paths = (!empty(PMXI_Plugin::$session->data['pmxi_import']['local_paths'])) ? PMXI_Plugin::$session->data['pmxi_import']['local_paths'] : array(PMXI_Plugin::$session->data['pmxi_import']['filePath']);
850
+
851
+ foreach ($local_paths as $key => $path) {
852
  if (file_exists($path)){
853
+
854
+ $file = new PMXI_Chunk($path, array('element' => (!empty($update_previous)) ? $update_previous->root_element : PMXI_Plugin::$session->data['pmxi_import']['source']['root_element']));
855
  // loop through the file until all lines are read
856
  while ($xml = $file->read()) {
857
  if (!empty($xml))
864
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
865
  libxml_use_internal_errors($old);
866
  $xpath = new DOMXPath($dom);
867
+ if (($this->data['elements'] = $elements = @$xpath->query(PMXI_Plugin::$session->data['pmxi_import']['xpath'])) and $elements->length){
868
  if ($loop == $this->data['tagno']){
869
+ //PMXI_Plugin::$session['pmxi_import']['xml'] = $xml;
870
  break;
871
  } else unset($dom, $xpath, $elements);
872
  $loop++;
876
  unset($file);
877
  }
878
  }
879
+ }
880
 
881
  $this->render();
882
  }
895
  ));
896
  $wp_uploads = wp_upload_dir();
897
 
898
+ $legacy_handling = PMXI_Plugin::getInstance()->getOption('legacy_special_character_handling');
899
+
900
+ $tagno = min(max(intval($this->input->getpost('tagno', 1)), 1), ( ! PMXI_Plugin::$session->data['pmxi_import']['large_file']) ? $this->data['elements']->length : PMXI_Plugin::$session->data['pmxi_import']['count']);
901
+
902
+ $xml = '';
903
+
904
+ if (PMXI_Plugin::$session->data['pmxi_import']['large_file']){
905
  $loop = 1;
906
+ foreach (PMXI_Plugin::$session->data['pmxi_import']['local_paths'] as $key => $path) {
907
+ $file = new PMXI_Chunk($path, array('element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
908
  // loop through the file until all lines are read
909
  while ($xml = $file->read()) {
910
  if (!empty($xml))
917
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
918
  libxml_use_internal_errors($old);
919
  $xpath = new DOMXPath($dom);
920
+ if (($this->data['elements'] = $elements = @$xpath->query(PMXI_Plugin::$session->data['pmxi_import']['xpath'])) and $elements->length){
921
  if ( $loop == $tagno ) {
922
+ //PMXI_Plugin::$session['pmxi_import']['xml'] = $xml;
923
  break;
924
  }
925
  unset($dom, $xpath, $elements);
931
  }
932
  $tagno = 1;
933
  }
934
+ $xpath = "(" . PMXI_Plugin::$session->data['pmxi_import']['xpath'] . ")[$tagno]";
935
  // validate
936
  try {
937
  if (empty($post['title'])) {
938
  $this->errors->add('form-validation', __('Post title is empty', 'pmxi_plugin'));
939
+ } else {
940
+ list($this->data['title']) = XmlImportParser::factory($xml, $xpath, $post['title'], $file)->parse(); unlink($file);
941
  if ( ! isset($this->data['title']) or '' == strval(trim(strip_tags($this->data['title'], '<img><input><textarea><iframe><object><embed>')))) {
942
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post title is empty', 'pmxi_plugin'));
943
  }
944
+ else $this->data['title'] = ($post['fix_characters']) ? utf8_encode( ( ! $legacy_handling) ? html_entity_decode($this->data['title']) : htmlspecialchars_decode($this->data['title'])) : (($post['is_leave_html']) ? (( ! $legacy_handling) ? html_entity_decode($this->data['title']) : htmlspecialchars_decode($this->data['title'])) : $this->data['title']);
945
  }
946
  } catch (XmlImportException $e) {
947
  $this->errors->add('form-validation', sprintf(__('Error parsing title: %s', 'pmxi_plugin'), $e->getMessage()));
950
  if (empty($post['content'])) {
951
  $this->errors->add('form-validation', __('Post content is empty', 'pmxi_plugin'));
952
  } else {
953
+ list($this->data['content']) = XmlImportParser::factory($post['is_keep_linebreaks'] ? $xml : preg_replace('%\r\n?|\n%', ' ', $xml), $xpath, $post['content'], $file)->parse(); unlink($file);
954
  if ( ! isset($this->data['content']) or '' == strval(trim(strip_tags($this->data['content'], '<img><input><textarea><iframe><object><embed>')))) {
955
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post content is empty', 'pmxi_plugin'));
956
  }
957
+ else $this->data['content'] = ($post['fix_characters']) ? utf8_encode(( ! $legacy_handling) ? html_entity_decode($this->data['content']) : htmlspecialchars_decode($this->data['content'])) : (($post['is_leave_html']) ? (( ! $legacy_handling) ? html_entity_decode($this->data['content']) : htmlspecialchars_decode($this->data['content'])) : $this->data['content']);
958
  }
959
  } catch (XmlImportException $e) {
960
  $this->errors->add('form-validation', sprintf(__('Error parsing content: %s', 'pmxi_plugin'), $e->getMessage()));
973
  $default = PMXI_Plugin::get_default_import_options();
974
 
975
  if ($this->isWizard) {
976
+ $this->data['source_type'] = PMXI_Plugin::$session->data['pmxi_import']['source']['type'];
977
+ $default['unique_key'] = PMXI_Plugin::$session->data['pmxi_import']['template']['title'];
978
 
979
  // auto searching ID element
980
  if (!empty($this->data['dom'])){
998
  }
999
  }
1000
  }
1001
+ }
1002
+
1003
  if ( class_exists('PMWI_Plugin') )
1004
  $post = $this->input->post(
1005
+ (isset(PMXI_Plugin::$session->data['pmxi_import']['options']) ? PMXI_Plugin::$session->data['pmxi_import']['options'] : array())
1006
  + $default
1007
  + PMWI_Plugin::get_default_import_options()
1008
  );
1009
  else
1010
  $post = $this->input->post(
1011
+ (isset(PMXI_Plugin::$session->data['pmxi_import']['options']) ? PMXI_Plugin::$session->data['pmxi_import']['options'] : array())
1012
  + $default
1013
  );
1014
 
1015
  $scheduled = $this->input->post(array(
1016
+ 'is_scheduled' => ! empty(PMXI_Plugin::$session->data['pmxi_import']['scheduled']),
1017
+ 'scheduled_period' => ! empty(PMXI_Plugin::$session->data['pmxi_import']['scheduled']) ? PMXI_Plugin::$session->data['pmxi_import']['scheduled'] : '0 0 * * *', // daily by default
1018
  ));
1019
 
1020
  } else {
1038
 
1039
  $this->data['post'] =& $post;
1040
  $this->data['scheduled'] =& $scheduled;
1041
+ $this->data['is_loaded_template'] = PMXI_Plugin::$session['pmxi_import']['is_loaded_template'];
1042
 
1043
  // Get All meta keys in the system
1044
  $this->data['meta_keys'] = $keys = new PMXI_Model_List();
1047
 
1048
  $load_template = $this->input->post('load_template');
1049
  if ($load_template) { // init form with template selected
1050
+ PMXI_Plugin::$session['pmxi_import']['is_loaded_template'] = $load_template;
1051
  $template = new PMXI_Template_Record();
1052
  if ( ! $template->getById($load_template)->isEmpty()) {
1053
  $post = (!empty($template->options) ? $template->options : array()) + $default;
1057
  );
1058
  }
1059
  } elseif ($load_template == -1){
1060
+ PMXI_Plugin::$session['pmxi_import']['is_loaded_template'] = 0;
1061
 
1062
  $post = $default;
1063
  $scheduled = $this->input->post(array(
1114
  if ( ! preg_match('%^([1-9]\d*)( *- *([1-9]\d*))?$%', $chank, $mtch)) {
1115
  $this->errors->add('form-validation', __('Wrong format of `Import only specified records` value', 'pmxi_plugin'));
1116
  break;
1117
+ } elseif ($this->isWizard and empty(PMXI_Plugin::$session->data['pmxi_import']['large_file']) and (intval($mtch[1]) > $this->data['elements']->length or isset($mtch[3]) and intval($mtch[3]) > $this->data['elements']->length)) {
1118
  $this->errors->add('form-validation', __('One of the numbers in `Import only specified records` value exceeds record quantity in XML file', 'pmxi_plugin'));
1119
  break;
1120
  }
1139
  '' !== $post['date_start'] or $post['date_start'] = 'now';
1140
  '' !== $post['date_end'] or $post['date_end'] = 'now';
1141
 
1142
+ if ( $this->input->post('name')) { // save template in database
1143
+ $template = new PMXI_Template_Record();
1144
+
1145
+ $template->getByName($this->input->post('name'))->set(array(
1146
+ 'name' => $this->input->post('name'),
1147
+ 'options' => $post,
1148
+ 'scheduled' => (($scheduled['is_scheduled']) ? $scheduled['scheduled_period'] : '')
1149
+ ))->save();
1150
+ }
1151
+
1152
  if ($this->isWizard) {
1153
+ PMXI_Plugin::$session['pmxi_import']['options'] = $post;
1154
+ PMXI_Plugin::$session['pmxi_import']['scheduled'] = $scheduled['is_scheduled'] ? $scheduled['scheduled_period'] : '';
1155
+
1156
+ pmxi_session_commit();
1157
 
 
 
 
 
 
 
 
 
 
 
1158
  if ( ! $this->input->post('save_only')) {
1159
  wp_redirect(add_query_arg('action', 'process', $this->baseUrl)); die();
1160
  } else {
1161
  $import = $this->data['update_previous'];
1162
  $is_update = ! $import->isEmpty();
1163
  $import->set(
1164
+ PMXI_Plugin::$session->data['pmxi_import']['source']
1165
  + array(
1166
+ 'xpath' => PMXI_Plugin::$session->data['pmxi_import']['xpath'],
1167
+ 'template' => PMXI_Plugin::$session->data['pmxi_import']['template'],
1168
+ 'options' => PMXI_Plugin::$session->data['pmxi_import']['options'],
1169
+ 'scheduled' => PMXI_Plugin::$session->data['pmxi_import']['scheduled'],
1170
+ 'count' => PMXI_Plugin::$session->data['pmxi_import']['count'],
1171
  'friendly_name' => $this->data['post']['friendly_name'],
1172
  )
1173
  )->save();
1176
  $history_file->set(array(
1177
  'name' => $import->name,
1178
  'import_id' => $import->id,
1179
+ 'path' => PMXI_Plugin::$session->data['pmxi_import']['filePath'],
1180
+ 'contents' => $this->get_xml(), //PMXI_Plugin::$session->data['pmxi_import']['xml'],
1181
  'registered_on' => date('Y-m-d H:i:s'),
1182
  ))->save();
1183
+
1184
+ pmxi_session_unset();
1185
+
1186
+ //unset(PMXI_Plugin::$session->data['pmxi_import']); // clear session data
1187
+
1188
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode($is_update ? __('Import updated', 'pmxi_plugin') : __('Import created', 'pmxi_plugin'))), admin_url('admin.php'))); die();
1189
  }
1190
  } else {
1201
  ! empty($post['attribute_name']) or $post['attribute_name'] = array('') and $post['attribute_value'] = array('');
1202
  }
1203
 
1204
+ pmxi_session_commit();
1205
+
1206
  $this->render();
1207
  }
1208
 
1213
  {
1214
  $wp_uploads = wp_upload_dir();
1215
 
1216
+ @set_time_limit(0);
1217
 
1218
  $import = $this->data['update_previous'];
1219
  $import->set(
1220
+ (empty(PMXI_Plugin::$session->data['pmxi_import']['source']) ? array() : PMXI_Plugin::$session->data['pmxi_import']['source'])
1221
  + array(
1222
+ 'xpath' => PMXI_Plugin::$session->data['pmxi_import']['xpath'],
1223
+ 'template' => PMXI_Plugin::$session->data['pmxi_import']['template'],
1224
+ 'options' => PMXI_Plugin::$session->data['pmxi_import']['options'],
1225
+ 'scheduled' => PMXI_Plugin::$session->data['pmxi_import']['scheduled'],
1226
+ 'count' => PMXI_Plugin::$session->data['pmxi_import']['count'],
1227
+ 'friendly_name' => PMXI_Plugin::$session->data['pmxi_import']['options']['friendly_name'],
1228
+ 'feed_type' => PMXI_Plugin::$session->data['pmxi_import']['feed_type']
1229
  )
1230
  );
1231
 
1232
+ if ( ! PMXI_Plugin::is_ajax()) {
 
1233
  // Save import history
1234
+ if ( PMXI_Plugin::$session->data['pmxi_import']['chunk_number'] === 1 ){
1235
  // store import info in database
1236
  $import->set(array(
1237
  'imported' => 0,
1238
  'created' => 0,
1239
  'updated' => 0,
1240
+ 'skipped' => 0,
1241
+ 'feed_type' => ''
1242
+ ))->save();
1243
 
1244
  do_action( 'pmxi_before_xml_import', $import->id );
1245
 
1246
+ if (PMXI_Plugin::$session->data['pmxi_import']['large_file']) PMXI_Plugin::$session['pmxi_import']['update_previous'] = $import->id;
1247
 
1248
  // unlick previous files
1249
  $history = new PMXI_File_List();
1250
  $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $import->id), 'id DESC');
1251
  if ($history->count()){
1252
  foreach ($history as $file){
1253
+ if (@file_exists($file['path']) and $file['path'] != PMXI_Plugin::$session->data['pmxi_import']['filePath']) @unlink($file['path']);
1254
  $history_file = new PMXI_File_Record();
1255
  $history_file->getBy('id', $file['id']);
1256
  if ( ! $history_file->isEmpty()) $history_file->delete();
1262
  $history_file->set(array(
1263
  'name' => $import->name,
1264
  'import_id' => $import->id,
1265
+ 'path' => PMXI_Plugin::$session->data['pmxi_import']['filePath'],
1266
+ 'contents' => $this->get_xml(), //PMXI_Plugin::$session->data['pmxi_import']['xml'],
1267
  'registered_on' => date('Y-m-d H:i:s'),
1268
  ))->save();
1269
+ }
1270
+
1271
  }
1272
 
1273
  $this->render();
1274
+ wp_ob_end_flush_all(); flush();
 
 
 
 
1275
 
1276
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1277
 
1278
+ $logger = create_function('$m', 'echo "<div class=\\"progress-msg\\">$m</div>\\n"; if ( "" != strip_tags(pmxi_strip_tags_content($m))) { PMXI_Plugin::$session[\'pmxi_import\'][\'log\'] .= "<p>".strip_tags(pmxi_strip_tags_content($m))."</p>"; flush(); }');
1279
 
1280
+ PMXI_Plugin::$session['pmxi_import']['start_time'] = (empty(PMXI_Plugin::$session->data['pmxi_import']['start_time'])) ? time() : PMXI_Plugin::$session->data['pmxi_import']['start_time'];
1281
 
1282
  in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, __('Reading files for import...', 'pmxi_plugin'));
1283
+ in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, sprintf(_n('%s file found', '%s files found', count(PMXI_Plugin::$session->data['pmxi_import']['local_paths']), 'pmxi_plugin'), count(PMXI_Plugin::$session->data['pmxi_import']['local_paths'])));
1284
+ in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and !empty(PMXI_Plugin::$session->data['pmxi_import']['local_paths']) and call_user_func($logger, sprintf(__('Importing %s (%s of %s)', 'pmxi_plugin'), PMXI_Plugin::$session->data['pmxi_import']['local_paths'][0], 1, count(PMXI_Plugin::$session->data['pmxi_import']['local_paths'])));
1285
 
1286
+ if (PMXI_Plugin::is_ajax()) {
 
 
 
1287
 
1288
+ PMXI_Plugin::$session['pmxi_import']['current_post_ids'] = (empty(PMXI_Plugin::$session->data['pmxi_import']['current_post_ids'])) ? array() : PMXI_Plugin::$session->data['pmxi_import']['current_post_ids'];
1289
 
1290
+ PMXI_Plugin::$session['pmxi_import']['pointer'] = (empty(PMXI_Plugin::$session->data['pmxi_import']['pointer'])) ? 0 : PMXI_Plugin::$session->data['pmxi_import']['pointer'];
1291
 
1292
+ pmxi_session_commit();
1293
 
1294
+ $loop = 0;
 
 
 
 
 
 
1295
 
1296
+ if (!empty(PMXI_Plugin::$session->data['pmxi_import']['local_paths'])){
1297
+ foreach (PMXI_Plugin::$session->data['pmxi_import']['local_paths'] as $key => $path) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1298
 
1299
+ $file = new PMXI_Chunk($path, array('element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']), PMXI_Plugin::$session->data['pmxi_import']['pointer']);
1300
 
1301
  // loop through the file until all lines are read
1302
  while ($xml = $file->read()) {
1311
  $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
1312
  libxml_use_internal_errors($old);
1313
  $xpath = new DOMXPath($dom);
1314
+ if (($this->data['elements'] = $elements = @$xpath->query(PMXI_Plugin::$session->data['pmxi_import']['xpath'])) and $elements->length){
1315
+ PMXI_Plugin::$session['pmxi_import']['pointer'] = $file->pointer;
1316
+ //PMXI_Plugin::$session['pmxi_import']['xml'] = $xml;
1317
+
1318
  if ( ! $loop ) ob_start();
1319
+ $import->process($xml, $logger, PMXI_Plugin::$session->data['pmxi_import']['chunk_number']);
1320
+ if ( $loop == PMXI_Plugin::$session->data['pmxi_import']['options']['records_per_request'] - 1 ) exit(ob_get_clean());
1321
  $loop++;
1322
  }
1323
  }
1324
 
1325
+ if (($import->created + $import->updated + $import->skipped + PMXI_Plugin::$session->data['pmxi_import']['errors'] == PMXI_Plugin::$session->data['pmxi_import']['count']) and !in_array($import->type, array('ftp'))){
1326
+ PMXI_Plugin::$session['pmxi_import']['pointer'] = 0;
1327
+ array_shift(PMXI_Plugin::$session->data['pmxi_import']['local_paths']);
1328
+ PMXI_Plugin::$session['pmxi_import']['local_paths'] = PMXI_Plugin::$session->data['pmxi_import']['local_paths'];
1329
+ pmxi_session_commit();
1330
  exit(ob_get_clean());
1331
  }
1332
  }
1333
 
1334
  if (in_array($import->type, array('ftp'))) {
1335
+ PMXI_Plugin::$session['pmxi_import']['pointer'] = 0;
1336
+ array_shift(PMXI_Plugin::$session->data['pmxi_import']['local_paths']);
1337
+ PMXI_Plugin::$session['pmxi_import']['local_paths'] = PMXI_Plugin::$session->data['pmxi_import']['local_paths'];
1338
+ if (!empty(PMXI_Plugin::$session->data['pmxi_import']['local_paths'])) {
1339
+ $logger and call_user_func($logger, sprintf(__('Importing %s', 'pmxi_plugin'), PMXI_Plugin::$session->data['pmxi_import']['local_paths'][0]));
1340
  }
1341
+ pmxi_session_commit();
1342
  exit(ob_get_clean());
1343
+ }
1344
  }
1345
  }
1346
  }
1347
+
1348
+ if (! PMXI_Plugin::$session->data['pmxi_import']['large_file'] or PMXI_Plugin::is_ajax()){
1349
 
1350
  // Save import process log
1351
  $log_file = $wp_uploads['basedir'] . '/wpallimport_logs/' . $import->id . '.html';
1352
  if (file_exists($log_file)) unlink($log_file);
1353
+ @file_put_contents($log_file, PMXI_Plugin::$session->data['pmxi_import']['log']);
1354
 
1355
+ if (!empty(PMXI_Plugin::$session->data['pmxi_import'])) do_action( 'pmxi_after_xml_import', $import->id );
1356
 
1357
  // clear import session
1358
+ //unset(PMXI_Plugin::$session['pmxi_import']); // clear session data (prevent from reimporting the same data on page refresh)
1359
+
1360
+ pmxi_session_unset();
1361
 
1362
  // [indicate in header process is complete]
1363
  $msg = addcslashes(__('Complete', 'pmxi_plugin'), "'\n\r");
1366
 
1367
  ob_start();
1368
 
1369
+ echo '<a id="download_pmxi_log" class="update" href="'.esc_url(add_query_arg(array('id' => $import->id, 'action' => 'log', 'page' => 'pmxi-admin-manage'), $this->baseUrl)).'">'.__('Download log','pmxi_plugin').'</a>';
1370
  echo <<<COMPLETE
1371
  <script type="text/javascript">
1372
  //<![CDATA[
1637
  $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
1638
  }
1639
 
1640
+ protected function get_xml(){
1641
+ $xml = '';
1642
+ $wp_uploads = wp_upload_dir();
1643
+ if (!empty(PMXI_Plugin::$session->data['pmxi_import']['local_paths'])) {
1644
+ foreach (PMXI_Plugin::$session->data['pmxi_import']['local_paths'] as $key => $path) {
1645
+ if ( @file_exists($path) ){
1646
+ $file = new PMXI_Chunk($path, array('element' => PMXI_Plugin::$session->data['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']), (!empty(PMXI_Plugin::$session->data['pmxi_import']['pointer'])) ? PMXI_Plugin::$session->data['pmxi_import']['pointer'] : 0);
1647
+ while ($xml = $file->read()) {
1648
+ if (!empty($xml))
1649
+ {
1650
+ $xml = $file->encoding . "\n" . $xml;
1651
+ PMXI_Import_Record::preprocessXml($xml);
1652
+ if ( '' != PMXI_Plugin::$session->data['pmxi_import']['xpath']){
1653
+ $dom = new DOMDocument('1.0', 'UTF-8');
1654
+ $old = libxml_use_internal_errors(true);
1655
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
1656
+ libxml_use_internal_errors($old);
1657
+ $xpath = new DOMXPath($dom);
1658
+ if (($elements = @$xpath->query(PMXI_Plugin::$session->data['pmxi_import']['xpath'])) and $elements->length) break;
1659
+ }
1660
+ else break;
1661
+ }
1662
+ }
1663
+ }
1664
+ }
1665
+ }
1666
+ return $xml;
1667
+ }
1668
  }
controllers/admin/manage.php CHANGED
@@ -10,8 +10,7 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
10
  parent::init();
11
 
12
  if ('update' == PMXI_Plugin::getInstance()->getAdminCurrentScreen()->action) {
13
- $this->isInline = true;
14
- if ( ! session_id()) session_start(); // prevent session initialization throw a notification in inline mode of delegated plugin
15
  }
16
  }
17
 
@@ -55,7 +54,9 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
55
  'current' => $pagenum,
56
  ));
57
 
58
- unset($_SESSION['pmxi_import']);
 
 
59
 
60
  $this->render();
61
  }
@@ -93,7 +94,8 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
93
  wp_redirect($this->baseUrl); die();
94
  }
95
 
96
- unset($_SESSION['pmxi_import']);
 
97
 
98
  if ($this->input->post('is_confirmed')) {
99
 
@@ -101,7 +103,7 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
101
 
102
  $uploads = wp_upload_dir();
103
 
104
- if ($item->large_import == 'No' or ($item->large_import == 'Yes' and empty($_SESSION['pmxi_import']['chunk_number']))) {
105
 
106
  if ( in_array($item->type, array('upload')) ) { // if import type NOT URL
107
 
@@ -290,11 +292,11 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
290
  }
291
  }
292
 
293
- if (!empty($_SESSION['pmxi_import']['xml'])) $xml = $_SESSION['pmxi_import']['xml'];
294
 
295
  if ($item->large_import == 'Yes' or PMXI_Import_Record::validateXml($xml, $this->errors)) { // xml is valid
296
 
297
- if ( ! PMXI_Plugin::is_ajax() and empty($_SESSION['pmxi_import']['chunk_number'])){
298
 
299
  $item->set(array(
300
  'processing' => 0,
@@ -312,8 +314,8 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
312
  }
313
 
314
  // compose data to look like result of wizard steps
315
- $_SESSION['pmxi_import'] = array(
316
- 'xml' => (isset($xml)) ? $xml : '',
317
  'filePath' => $filePath,
318
  'source' => array(
319
  'name' => $item->name,
@@ -342,6 +344,9 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
342
  'local_paths' => (!empty($local_paths)) ? $local_paths : array(), // ftp import local copies of remote files
343
  'action' => (!empty($action_type) and $action_type == 'continue') ? 'continue' : 'update',
344
  );
 
 
 
345
  }
346
 
347
  // deligate operation to other controller
10
  parent::init();
11
 
12
  if ('update' == PMXI_Plugin::getInstance()->getAdminCurrentScreen()->action) {
13
+ $this->isInline = true;
 
14
  }
15
  }
16
 
54
  'current' => $pagenum,
55
  ));
56
 
57
+ //unset(PMXI_Plugin::$session['pmxi_import']);
58
+
59
+ pmxi_session_unset();
60
 
61
  $this->render();
62
  }
94
  wp_redirect($this->baseUrl); die();
95
  }
96
 
97
+ //unset(PMXI_Plugin::$session['pmxi_import']);
98
+ pmxi_session_unset();
99
 
100
  if ($this->input->post('is_confirmed')) {
101
 
103
 
104
  $uploads = wp_upload_dir();
105
 
106
+ if ($item->large_import == 'No' or ($item->large_import == 'Yes' and empty(PMXI_Plugin::$session->data['pmxi_import']['chunk_number']))) {
107
 
108
  if ( in_array($item->type, array('upload')) ) { // if import type NOT URL
109
 
292
  }
293
  }
294
 
295
+ //if (!empty(PMXI_Plugin::$session['pmxi_import']['xml'])) $xml = PMXI_Plugin::$session['pmxi_import']['xml'];
296
 
297
  if ($item->large_import == 'Yes' or PMXI_Import_Record::validateXml($xml, $this->errors)) { // xml is valid
298
 
299
+ if ( ! PMXI_Plugin::is_ajax() and empty(PMXI_Plugin::$session->data['pmxi_import']['chunk_number'])){
300
 
301
  $item->set(array(
302
  'processing' => 0,
314
  }
315
 
316
  // compose data to look like result of wizard steps
317
+ PMXI_Plugin::$session['pmxi_import'] = array(
318
+ //'xml' => (isset($xml)) ? $xml : '',
319
  'filePath' => $filePath,
320
  'source' => array(
321
  'name' => $item->name,
344
  'local_paths' => (!empty($local_paths)) ? $local_paths : array(), // ftp import local copies of remote files
345
  'action' => (!empty($action_type) and $action_type == 'continue') ? 'continue' : 'update',
346
  );
347
+
348
+ pmxi_session_commit();
349
+
350
  }
351
 
352
  // deligate operation to other controller
controllers/controller/admin.php CHANGED
@@ -1,102 +1,102 @@
1
- <?php
2
- /**
3
- * Introduce special type for controllers which render pages inside admin area
4
- *
5
- * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
- */
7
- abstract class PMXI_Controller_Admin extends PMXI_Controller {
8
- /**
9
- * Admin page base url (request url without all get parameters but `page`)
10
- * @var string
11
- */
12
- public $baseUrl;
13
- /**
14
- * Parameters which is left when baseUrl is detected
15
- * @var array
16
- */
17
- public $baseUrlParamNames = array('page', 'pagenum', 'order', 'order_by', 'type', 's', 'f');
18
- /**
19
- * Whether controller is rendered inside wordpress page
20
- * @var bool
21
- */
22
- public $isInline = false;
23
- /**
24
- * Constructor
25
- */
26
- public function __construct() {
27
- $remove = array_diff(array_keys($_GET), $this->baseUrlParamNames);
28
- if ($remove) {
29
- $this->baseUrl = remove_query_arg($remove);
30
- } else {
31
- $this->baseUrl = $_SERVER['REQUEST_URI'];
32
- }
33
- parent::__construct();
34
-
35
- // add special filter for url fields
36
- $this->input->addFilter(create_function('$str', 'return "http://" == $str || "ftp://" == $str ? "" : $str;'));
37
-
38
- // enqueue required sripts and styles
39
- global $wp_styles;
40
- if ( ! is_a($wp_styles, 'WP_Styles'))
41
- $wp_styles = new WP_Styles();
42
-
43
- wp_enqueue_style('jquery-ui', PMXI_ROOT_URL . '/static/js/jquery/css/redmond/jquery-ui.css');
44
- wp_enqueue_style('jquery-tipsy', PMXI_ROOT_URL . '/static/js/jquery/css/smoothness/jquery.tipsy.css');
45
- wp_enqueue_style('pmxi-admin-style', PMXI_ROOT_URL . '/static/css/admin.css');
46
- wp_enqueue_style('pmxi-admin-style-ie', PMXI_ROOT_URL . '/static/css/admin-ie.css');
47
- $wp_styles->add_data('pmxi-admin-style-ie', 'conditional', 'lte IE 7');
48
-
49
- $scheme_color = get_user_option('admin_color') and is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css') or $scheme_color = 'fresh';
50
- if (is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css')) {
51
- wp_enqueue_style('pmxi-admin-style-color', PMXI_ROOT_URL . '/static/css/admin-colors-' . $scheme_color . '.css');
52
- }
53
-
54
- wp_enqueue_script('jquery-ui-datepicker', PMXI_ROOT_URL . '/static/js/jquery/ui.datepicker.js', 'jquery-ui-core');
55
- wp_enqueue_script('jquery-ui-autocomplete', PMXI_ROOT_URL . '/static/js/jquery/ui.autocomplete.js', array('jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-position'));
56
- wp_enqueue_script('jquery-tipsy', PMXI_ROOT_URL . '/static/js/jquery/jquery.tipsy.js', 'jquery');
57
- wp_enqueue_script('jquery-nestable', PMXI_ROOT_URL . '/static/js/jquery/jquery.mjs.nestedSortable.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-tabs', 'jquery-ui-progressbar'));
58
- wp_enqueue_script('jquery-moment', PMXI_ROOT_URL . '/static/js/jquery/moment.js', 'jquery');
59
-
60
- /* load plupload scripts */
61
- wp_deregister_script('swfupload-all');
62
- wp_deregister_script('swfupload-handlers');
63
- wp_enqueue_script('swfupload-handlers', get_option('siteurl') . "/wp-includes/js/swfupload/handlers.js", array('jquery'), '2201-20100523');
64
-
65
- wp_enqueue_script('jquery-browserplus-min', 'http://bp.yahooapis.com/2.4.21/browserplus-min.js', array('jquery'));
66
- wp_enqueue_script('full-plupload', PMXI_ROOT_URL . '/static/js/plupload/plupload.full.js', array('jquery-browserplus-min'));
67
- wp_enqueue_script('jquery-plupload', PMXI_ROOT_URL . '/static/js/plupload/wplupload.js', array('full-plupload', 'jquery'));
68
-
69
- wp_enqueue_script('pmxi-admin-script', PMXI_ROOT_URL . '/static/js/admin.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-datepicker', 'jquery-ui-draggable', 'jquery-ui-droppable'));
70
-
71
- }
72
-
73
- /**
74
- * @see Controller::render()
75
- */
76
- protected function render($viewPath = NULL)
77
- {
78
- // assume template file name depending on calling function
79
- if (is_null($viewPath)) {
80
- $trace = debug_backtrace();
81
- $viewPath = str_replace('_', '/', preg_replace('%^' . preg_quote(PMXI_Plugin::PREFIX, '%') . '%', '', strtolower($trace[1]['class']))) . '/' . $trace[1]['function'];
82
- }
83
-
84
- // render contextual help automatically
85
- $viewHelpPath = $viewPath;
86
- // append file extension if not specified
87
- if ( ! preg_match('%\.php$%', $viewHelpPath)) {
88
- $viewHelpPath .= '.php';
89
- }
90
- $viewHelpPath = preg_replace('%\.php$%', '-help.php', $viewHelpPath);
91
- $fileHelpPath = PMXI_Plugin::ROOT_DIR . '/views/' . $viewHelpPath;
92
-
93
- if (is_file($fileHelpPath)) { // there is help file defined
94
- ob_start();
95
- include $fileHelpPath;
96
- add_contextual_help(PMXI_Plugin::getInstance()->getAdminCurrentScreen()->id, ob_get_clean());
97
- }
98
-
99
- parent::render($viewPath);
100
- }
101
-
102
  }
1
+ <?php
2
+ /**
3
+ * Introduce special type for controllers which render pages inside admin area
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ abstract class PMXI_Controller_Admin extends PMXI_Controller {
8
+ /**
9
+ * Admin page base url (request url without all get parameters but `page`)
10
+ * @var string
11
+ */
12
+ public $baseUrl;
13
+ /**
14
+ * Parameters which is left when baseUrl is detected
15
+ * @var array
16
+ */
17
+ public $baseUrlParamNames = array('page', 'pagenum', 'order', 'order_by', 'type', 's', 'f');
18
+ /**
19
+ * Whether controller is rendered inside wordpress page
20
+ * @var bool
21
+ */
22
+ public $isInline = false;
23
+ /**
24
+ * Constructor
25
+ */
26
+ public function __construct() {
27
+ $remove = array_diff(array_keys($_GET), $this->baseUrlParamNames);
28
+ if ($remove) {
29
+ $this->baseUrl = remove_query_arg($remove);
30
+ } else {
31
+ $this->baseUrl = $_SERVER['REQUEST_URI'];
32
+ }
33
+ parent::__construct();
34
+
35
+ // add special filter for url fields
36
+ $this->input->addFilter(create_function('$str', 'return "http://" == $str || "ftp://" == $str ? "" : $str;'));
37
+
38
+ // enqueue required sripts and styles
39
+ global $wp_styles;
40
+ if ( ! is_a($wp_styles, 'WP_Styles'))
41
+ $wp_styles = new WP_Styles();
42
+
43
+ wp_enqueue_style('jquery-ui', PMXI_ROOT_URL . '/static/js/jquery/css/redmond/jquery-ui.css');
44
+ wp_enqueue_style('jquery-tipsy', PMXI_ROOT_URL . '/static/js/jquery/css/smoothness/jquery.tipsy.css');
45
+ wp_enqueue_style('pmxi-admin-style', PMXI_ROOT_URL . '/static/css/admin.css');
46
+ wp_enqueue_style('pmxi-admin-style-ie', PMXI_ROOT_URL . '/static/css/admin-ie.css');
47
+ $wp_styles->add_data('pmxi-admin-style-ie', 'conditional', 'lte IE 7');
48
+
49
+ $scheme_color = get_user_option('admin_color') and is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css') or $scheme_color = 'fresh';
50
+ if (is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css')) {
51
+ wp_enqueue_style('pmxi-admin-style-color', PMXI_ROOT_URL . '/static/css/admin-colors-' . $scheme_color . '.css');
52
+ }
53
+
54
+ wp_enqueue_script('jquery-ui-datepicker', PMXI_ROOT_URL . '/static/js/jquery/ui.datepicker.js', 'jquery-ui-core');
55
+ wp_enqueue_script('jquery-ui-autocomplete', PMXI_ROOT_URL . '/static/js/jquery/ui.autocomplete.js', array('jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-position'));
56
+ wp_enqueue_script('jquery-tipsy', PMXI_ROOT_URL . '/static/js/jquery/jquery.tipsy.js', 'jquery');
57
+ wp_enqueue_script('jquery-nestable', PMXI_ROOT_URL . '/static/js/jquery/jquery.mjs.nestedSortable.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-tabs', 'jquery-ui-progressbar'));
58
+ wp_enqueue_script('jquery-moment', PMXI_ROOT_URL . '/static/js/jquery/moment.js', 'jquery');
59
+
60
+ /* load plupload scripts */
61
+ wp_deregister_script('swfupload-all');
62
+ wp_deregister_script('swfupload-handlers');
63
+ wp_enqueue_script('swfupload-handlers', get_option('siteurl') . "/wp-includes/js/swfupload/handlers.js", array('jquery'), '2201-20100523');
64
+
65
+ wp_enqueue_script('jquery-browserplus-min', 'http://bp.yahooapis.com/2.4.21/browserplus-min.js', array('jquery'));
66
+ wp_enqueue_script('full-plupload', PMXI_ROOT_URL . '/static/js/plupload/plupload.full.js', array('jquery-browserplus-min'));
67
+ wp_enqueue_script('jquery-plupload', PMXI_ROOT_URL . '/static/js/plupload/wplupload.js', array('full-plupload', 'jquery'));
68
+
69
+ wp_enqueue_script('pmxi-admin-script', PMXI_ROOT_URL . '/static/js/admin.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-datepicker', 'jquery-ui-draggable', 'jquery-ui-droppable'));
70
+
71
+ }
72
+
73
+ /**
74
+ * @see Controller::render()
75
+ */
76
+ protected function render($viewPath = NULL)
77
+ {
78
+ // assume template file name depending on calling function
79
+ if (is_null($viewPath)) {
80
+ $trace = debug_backtrace();
81
+ $viewPath = str_replace('_', '/', preg_replace('%^' . preg_quote(PMXI_Plugin::PREFIX, '%') . '%', '', strtolower($trace[1]['class']))) . '/' . $trace[1]['function'];
82
+ }
83
+
84
+ // render contextual help automatically
85
+ $viewHelpPath = $viewPath;
86
+ // append file extension if not specified
87
+ if ( ! preg_match('%\.php$%', $viewHelpPath)) {
88
+ $viewHelpPath .= '.php';
89
+ }
90
+ $viewHelpPath = preg_replace('%\.php$%', '-help.php', $viewHelpPath);
91
+ $fileHelpPath = PMXI_Plugin::ROOT_DIR . '/views/' . $viewHelpPath;
92
+
93
+ if (is_file($fileHelpPath)) { // there is help file defined
94
+ ob_start();
95
+ include $fileHelpPath;
96
+ add_contextual_help(PMXI_Plugin::getInstance()->getAdminCurrentScreen()->id, ob_get_clean());
97
+ }
98
+
99
+ parent::render($viewPath);
100
+ }
101
+
102
  }
helpers/import_custom_meta_box.php CHANGED
@@ -5,7 +5,7 @@ if (!function_exists('import_custom_meta_box')){
5
  <div id="postcustomstuff">
6
  <table id="list-table">
7
  <tbody class="list:meta" id="the-list">
8
- <?php if (!empty($_SESSION['pmxi_import']['options']['custom_name'])): foreach ($_SESSION['pmxi_import']['options']['custom_name'] as $i => $name): ?>
9
  <tr>
10
  <td class="left">
11
  <label class="screen-reader-text">Key</label>
@@ -14,7 +14,7 @@ if (!function_exists('import_custom_meta_box')){
14
  </td>
15
  <td>
16
  <label class="screen-reader-text">Value</label>
17
- <textarea name="custom_value[]" rows="2" cols="30" class="widefat"><?php echo esc_html($_SESSION['pmxi_import']['options']['custom_value'][$i]) ?></textarea>
18
  </td>
19
  </tr>
20
  <?php endforeach; endif; ?>
5
  <div id="postcustomstuff">
6
  <table id="list-table">
7
  <tbody class="list:meta" id="the-list">
8
+ <?php if (!empty(PMXI_Plugin::$session->data['pmxi_import']['options']['custom_name'])): foreach (PMXI_Plugin::$session->data['pmxi_import']['options']['custom_name'] as $i => $name): ?>
9
  <tr>
10
  <td class="left">
11
  <label class="screen-reader-text">Key</label>
14
  </td>
15
  <td>
16
  <label class="screen-reader-text">Value</label>
17
+ <textarea name="custom_value[]" rows="2" cols="30" class="widefat"><?php echo esc_html(PMXI_Plugin::$session->data['pmxi_import']['options']['custom_value'][$i]) ?></textarea>
18
  </td>
19
  </tr>
20
  <?php endforeach; endif; ?>
helpers/pmxi_functions.php CHANGED
@@ -382,3 +382,36 @@
382
  }
383
 
384
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  }
383
 
384
 
385
+ /* Session */
386
+
387
+ /**
388
+ * Return the current session status.
389
+ *
390
+ * @return int
391
+ */
392
+ function pmxi_session_status() {
393
+
394
+ PMXI_Plugin::$session = PMXI_Session::get_instance();
395
+
396
+ if ( PMXI_Plugin::$session->session_started() ) {
397
+ return PHP_SESSION_ACTIVE;
398
+ }
399
+
400
+ return PHP_SESSION_NONE;
401
+ }
402
+
403
+ /**
404
+ * Unset all session variables.
405
+ */
406
+ function pmxi_session_unset() {
407
+ PMXI_Plugin::$session = PMXI_Session::get_instance();
408
+
409
+ PMXI_Plugin::$session->reset();
410
+ }
411
+
412
+ /**
413
+ * Alias of wp_session_write_close()
414
+ */
415
+ function pmxi_session_commit() {
416
+ pmxi_shutdown();
417
+ }
libraries/XmlImportCsvParse.php CHANGED
@@ -956,6 +956,8 @@ class PMXI_CsvParser
956
  }
957
  $create_new_headers = false;
958
 
 
 
959
  while ($keys = fgetcsv($res, $l, $d, $e)) {
960
 
961
  if ($c == 0) {
@@ -981,8 +983,8 @@ class PMXI_CsvParser
981
  $chunk = array();
982
 
983
  foreach ($this->headers as $key => $header) {
984
- $chunk[$header] = $this->fixEncoding(htmlentities($keys[$key]));
985
- }
986
 
987
  if (!empty($chunk))
988
  {
956
  }
957
  $create_new_headers = false;
958
 
959
+ $legacy_special_character_handling = PMXI_Plugin::getInstance()->getOption('legacy_special_character_handling');
960
+
961
  while ($keys = fgetcsv($res, $l, $d, $e)) {
962
 
963
  if ($c == 0) {
983
  $chunk = array();
984
 
985
  foreach ($this->headers as $key => $header) {
986
+ $chunk[$header] = $this->fixEncoding( ($legacy_special_character_handling) ? htmlspecialchars($keys[$key]) : htmlentities($keys[$key]));
987
+ }
988
 
989
  if (!empty($chunk))
990
  {
libraries/XmlImportTemplateCodeGenerator.php CHANGED
@@ -12,6 +12,7 @@ require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
12
  require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
13
  require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
14
  require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
 
15
  require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
16
  require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
17
  require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
@@ -102,7 +103,11 @@ class XmlImportTemplateCodeGenerator
102
  {
103
  $filename = tempnam(XmlImportConfig::getInstance()->getCacheDirectory(), 'xim');
104
  }
105
-
 
 
 
 
106
  file_put_contents($filename, $result);
107
  return $filename;
108
  }
@@ -240,6 +245,10 @@ class XmlImportTemplateCodeGenerator
240
  $result = $variables[$expression->getValue()];
241
  }
242
  break;
 
 
 
 
243
 
244
  case 'XmlImportAstMath':
245
  $result = $this->generateForMath($expression);
@@ -251,7 +260,29 @@ class XmlImportTemplateCodeGenerator
251
  }
252
  return $result;
253
  }
254
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  /**
256
  * Generates code for a function
257
  *
12
  require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
13
  require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
14
  require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
15
+ require_once dirname(__FILE__) . '/ast/XmlImportAstFunction.php';
16
  require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
17
  require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
18
  require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
103
  {
104
  $filename = tempnam(XmlImportConfig::getInstance()->getCacheDirectory(), 'xim');
105
  }
106
+ if ( ! $filename or ! is_writable($filename) ){
107
+ $uploads = wp_upload_dir();
108
+ $filename = $uploads['path'] . '/' . wp_unique_filename($uploads['path']);
109
+ }
110
+
111
  file_put_contents($filename, $result);
112
  return $filename;
113
  }
245
  $result = $variables[$expression->getValue()];
246
  }
247
  break;
248
+
249
+ case 'XmlImportAstFunction':
250
+ $result = $this->generateForFunction($expression);
251
+ break;
252
 
253
  case 'XmlImportAstMath':
254
  $result = $this->generateForMath($expression);
260
  }
261
  return $result;
262
  }
263
+
264
+ /**
265
+ * Generates code for a function
266
+ *
267
+ * @param XmlImportAstFunction $function
268
+ * @return string
269
+ */
270
+ private function generateForFunction(XmlImportAstFunction $function)
271
+ {
272
+ $result = $function->getName() . '(';
273
+ $arguments = $function->getArguments();
274
+
275
+ for($i = 0; $i < count($arguments); $i++)
276
+ {
277
+ $result .= $this->generateForExpression($arguments[$i], true);
278
+ if ($i < (count($arguments) - 1))
279
+ $result .= ', ';
280
+ }
281
+ $result .= ')';
282
+
283
+ return $result;
284
+ }
285
+
286
  /**
287
  * Generates code for a function
288
  *
libraries/ast/XmlImportAstElseif.php CHANGED
@@ -1,76 +1,76 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- /**
8
- * Represents ELSEIF branch of IF clause
9
- */
10
- class XmlImportAstElseif
11
- {
12
- /**
13
- * ELSEIF branch condition
14
- *
15
- * @var XmlImportAstExpression
16
- */
17
- private $condition;
18
-
19
- /**
20
- * ELSEIF branch body
21
- *
22
- * @var XmlImportAstSequence
23
- */
24
- private $body;
25
-
26
- /**
27
- * Creates new instance
28
- *
29
- * @param XmlImportAstExpression $condition
30
- * @param XmlImportAstSequence $body
31
- */
32
- public function __construct(XmlImportAstExpression $condition, XmlImportAstSequence $body)
33
- {
34
- $this->condition = $condition;
35
- $this->body = $body;
36
- }
37
-
38
- /**
39
- * Gets ELSEIF branch condition
40
- *
41
- * @return XmlImportAstExpression
42
- */
43
- public function getCondition()
44
- {
45
- return $this->condition;
46
- }
47
-
48
- /**
49
- * Gets body
50
- *
51
- * @return XmlImportAstSequence
52
- */
53
- public function getBody()
54
- {
55
- return $this->body;
56
- }
57
-
58
- /**
59
- * String representation of an object
60
- *
61
- * @return string
62
- */
63
- public function __toString()
64
- {
65
- $result = " Elseif:\n";
66
- $result .= ' Condition: ' . $this->condition . "\n";
67
- $result .= " Body:\n";
68
- $array = explode("\n", $this->body);
69
- for ($i = 0; $i < count($array); $i++)
70
- {
71
- $array[$i] = ' ' . $array[$i];
72
- }
73
- $result .= implode("\n", $array) . "\n";
74
- return $result;
75
- }
76
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ /**
8
+ * Represents ELSEIF branch of IF clause
9
+ */
10
+ class XmlImportAstElseif
11
+ {
12
+ /**
13
+ * ELSEIF branch condition
14
+ *
15
+ * @var XmlImportAstExpression
16
+ */
17
+ private $condition;
18
+
19
+ /**
20
+ * ELSEIF branch body
21
+ *
22
+ * @var XmlImportAstSequence
23
+ */
24
+ private $body;
25
+
26
+ /**
27
+ * Creates new instance
28
+ *
29
+ * @param XmlImportAstExpression $condition
30
+ * @param XmlImportAstSequence $body
31
+ */
32
+ public function __construct(XmlImportAstExpression $condition, XmlImportAstSequence $body)
33
+ {
34
+ $this->condition = $condition;
35
+ $this->body = $body;
36
+ }
37
+
38
+ /**
39
+ * Gets ELSEIF branch condition
40
+ *
41
+ * @return XmlImportAstExpression
42
+ */
43
+ public function getCondition()
44
+ {
45
+ return $this->condition;
46
+ }
47
+
48
+ /**
49
+ * Gets body
50
+ *
51
+ * @return XmlImportAstSequence
52
+ */
53
+ public function getBody()
54
+ {
55
+ return $this->body;
56
+ }
57
+
58
+ /**
59
+ * String representation of an object
60
+ *
61
+ * @return string
62
+ */
63
+ public function __toString()
64
+ {
65
+ $result = " Elseif:\n";
66
+ $result .= ' Condition: ' . $this->condition . "\n";
67
+ $result .= " Body:\n";
68
+ $array = explode("\n", $this->body);
69
+ for ($i = 0; $i < count($array); $i++)
70
+ {
71
+ $array[$i] = ' ' . $array[$i];
72
+ }
73
+ $result .= implode("\n", $array) . "\n";
74
+ return $result;
75
+ }
76
+ }
libraries/ast/XmlImportAstExpression.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- /**
8
- * Represents expression
9
- *
10
- * @abstract
11
- */
12
- abstract class XmlImportAstExpression
13
- {
14
-
15
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ /**
8
+ * Represents expression
9
+ *
10
+ * @abstract
11
+ */
12
+ abstract class XmlImportAstExpression
13
+ {
14
+
15
+ }
libraries/ast/XmlImportAstFloat.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
-
9
- /**
10
- * Represents float number
11
- */
12
- class XmlImportAstFloat extends XmlImportAstLiteral
13
- {
14
-
15
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
+
9
+ /**
10
+ * Represents float number
11
+ */
12
+ class XmlImportAstFloat extends XmlImportAstLiteral
13
+ {
14
+
15
+ }
libraries/ast/XmlImportAstForeach.php CHANGED
@@ -1,14 +1,14 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstXpathClause.php';
8
-
9
- /**
10
- * Represents a FOREACH clause
11
- */
12
- class XmlImportAstForeach extends XmlImportAstXPathClause
13
- {
14
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstXpathClause.php';
8
+
9
+ /**
10
+ * Represents a FOREACH clause
11
+ */
12
+ class XmlImportAstForeach extends XmlImportAstXPathClause
13
+ {
14
+ }
libraries/ast/XmlImportAstFunction.php CHANGED
@@ -1,90 +1,90 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
-
9
- /**
10
- * Represents a function
11
- */
12
- class XmlImportAstFunction extends XmlImportAstExpression
13
- {
14
- /**
15
- * Name of a function
16
- *
17
- * @var string
18
- */
19
- private $name;
20
-
21
- /**
22
- * Function arguments
23
- *
24
- * @var array
25
- */
26
- private $arguments = array();
27
-
28
- /**
29
- * Creates new instance
30
- *
31
- * @param string $name
32
- */
33
- public function __construct($name)
34
- {
35
- $this->name = $name;
36
- }
37
-
38
- /**
39
- * Gets name of a function
40
- *
41
- * @return string
42
- */
43
- public function getName()
44
- {
45
- return $this->name;
46
- }
47
-
48
- /**
49
- * Adds argument to a function
50
- *
51
- * @param XmlImportAstExpression $argument
52
- */
53
- public function addArgument(XmlImportAstExpression $argument)
54
- {
55
- $this->arguments[] = $argument;
56
- }
57
-
58
- /**
59
- * Gets function arguments
60
- *
61
- * @return array
62
- */
63
- public function getArguments()
64
- {
65
- return $this->arguments;
66
- }
67
-
68
- /**
69
- * String representation of a function
70
- *
71
- * @return string
72
- */
73
- public function __toString()
74
- {
75
- $result = "--> begin " . get_class($this) . "\n";
76
- foreach ($this->getArguments() as $argument)
77
- {
78
- $array = explode("\n", $argument);
79
- for ($i = 0; $i < count($array); $i++)
80
- {
81
- $array[$i] = ' ' . $array[$i];
82
- }
83
- $result .= implode("\n", $array) . "\n";
84
- }
85
-
86
- $result .= "--> end " . get_class($this);
87
-
88
- return $result;
89
- }
90
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
+
9
+ /**
10
+ * Represents a function
11
+ */
12
+ class XmlImportAstFunction extends XmlImportAstExpression
13
+ {
14
+ /**
15
+ * Name of a function
16
+ *
17
+ * @var string
18
+ */
19
+ private $name;
20
+
21
+ /**
22
+ * Function arguments
23
+ *
24
+ * @var array
25
+ */
26
+ private $arguments = array();
27
+
28
+ /**
29
+ * Creates new instance
30
+ *
31
+ * @param string $name
32
+ */
33
+ public function __construct($name)
34
+ {
35
+ $this->name = $name;
36
+ }
37
+
38
+ /**
39
+ * Gets name of a function
40
+ *
41
+ * @return string
42
+ */
43
+ public function getName()
44
+ {
45
+ return $this->name;
46
+ }
47
+
48
+ /**
49
+ * Adds argument to a function
50
+ *
51
+ * @param XmlImportAstExpression $argument
52
+ */
53
+ public function addArgument(XmlImportAstExpression $argument)
54
+ {
55
+ $this->arguments[] = $argument;
56
+ }
57
+
58
+ /**
59
+ * Gets function arguments
60
+ *
61
+ * @return array
62
+ */
63
+ public function getArguments()
64
+ {
65
+ return $this->arguments;
66
+ }
67
+
68
+ /**
69
+ * String representation of a function
70
+ *
71
+ * @return string
72
+ */
73
+ public function __toString()
74
+ {
75
+ $result = "--> begin " . get_class($this) . "\n";
76
+ foreach ($this->getArguments() as $argument)
77
+ {
78
+ $array = explode("\n", $argument);
79
+ for ($i = 0; $i < count($array); $i++)
80
+ {
81
+ $array[$i] = ' ' . $array[$i];
82
+ }
83
+ $result .= implode("\n", $array) . "\n";
84
+ }
85
+
86
+ $result .= "--> end " . get_class($this);
87
+
88
+ return $result;
89
+ }
90
  }
libraries/ast/XmlImportAstIf.php CHANGED
@@ -1,161 +1,161 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
- require_once dirname(__FILE__) . '/XmlImportAstElseif.php';
9
-
10
- /**
11
- * Represents an IF clause
12
- */
13
- class XmlImportAstIf extends XmlImportAstStatement
14
- {
15
- /**
16
- * Condition
17
- *
18
- * @var XmlImportAstExpression
19
- */
20
- private $condition;
21
-
22
- /**
23
- * If body
24
- *
25
- * @var XmlImportAstSequence
26
- */
27
- private $ifBody;
28
-
29
- /**
30
- * List of elseif subclauses
31
- *
32
- * @var array
33
- */
34
- private $elseIfs = array();
35
-
36
- /**
37
- * Else body
38
- *
39
- * @var XmlImportAstSequence
40
- */
41
- private $elseBody;
42
-
43
- /**
44
- * Creates new instance
45
- *
46
- * @param XmlImportAstExpression $condition
47
- */
48
- public function __construct(XmlImportAstExpression $condition)
49
- {
50
- $this->condition = $condition;
51
- }
52
-
53
- /**
54
- * Gets condition
55
- *
56
- * @return XmlImportAstExpression
57
- */
58
- public function getCondition()
59
- {
60
- return $this->condition;
61
- }
62
-
63
- /**
64
- * Gets if body
65
- *
66
- * @return XmlImportAstSequence
67
- */
68
- public function getIfBody()
69
- {
70
- return $this->ifBody;
71
- }
72
-
73
- /**
74
- * Adds If body
75
- *
76
- * @param XmlImportAstSequence $body
77
- */
78
- public function addIfBody(XmlImportAstSequence $body)
79
- {
80
- $this->ifBody = $body;
81
- }
82
-
83
- /**
84
- * Gets list of elseif subcloses
85
- *
86
- * @return array
87
- */
88
- public function getElseIfs()
89
- {
90
- return $this->elseIfs;
91
- }
92
-
93
- /**
94
- * Gets else body
95
- *
96
- * @return XmlImportAstSequence
97
- */
98
- public function getElseBody()
99
- {
100
- return $this->elseBody;
101
- }
102
-
103
- /**
104
- * Adds else body
105
- *
106
- * @param XmlImportAstSequence $body
107
- */
108
- public function addElseBody(XmlImportAstSequence $body)
109
- {
110
- $this->elseBody = $body;
111
- }
112
-
113
- /**
114
- * Adds elseif subclause
115
- *
116
- * @param XmlImportAstElseif $elseif
117
- */
118
- public function addElseif(XmlImportAstElseif $elseif)
119
- {
120
- $this->elseIfs[] = $elseif;
121
- }
122
-
123
- /**
124
- * String represetation of an IF clause
125
- *
126
- * @return string
127
- */
128
- public function __toString()
129
- {
130
- $result = "--> begin " . get_class($this) . "\n";
131
- $result .= ' Condition: ' . $this->condition . "\n";
132
- $result .= " Body:\n";
133
- $array = explode("\n", $this->ifBody);
134
- for ($i = 0; $i < count($array); $i++)
135
- {
136
- $array[$i] = ' ' . $array[$i];
137
- }
138
- $result .= implode("\n", $array) . "\n";
139
- foreach($this->elseIfs as $elseIf)
140
- {
141
- $array = explode("\n", $elseIf);
142
- for ($i = 0; $i < count($array); $i++)
143
- {
144
- $array[$i] = '' . $array[$i];
145
- }
146
- $result .= implode("\n", $array) . "\n";
147
- }
148
- if (!is_null($this->elseBody))
149
- {
150
- $result .= " Else:\n";
151
- $array = explode("\n", $this->elseBody);
152
- for ($i = 0; $i < count($array); $i++)
153
- {
154
- $array[$i] = ' ' . $array[$i];
155
- }
156
- $result .= implode("\n", $array) . "\n";
157
- }
158
- $result .= "--> end " . get_class($this) . "\n";
159
- return $result;
160
- }
161
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
+ require_once dirname(__FILE__) . '/XmlImportAstElseif.php';
9
+
10
+ /**
11
+ * Represents an IF clause
12
+ */
13
+ class XmlImportAstIf extends XmlImportAstStatement
14
+ {
15
+ /**
16
+ * Condition
17
+ *
18
+ * @var XmlImportAstExpression
19
+ */
20
+ private $condition;
21
+
22
+ /**
23
+ * If body
24
+ *
25
+ * @var XmlImportAstSequence
26
+ */
27
+ private $ifBody;
28
+
29
+ /**
30
+ * List of elseif subclauses
31
+ *
32
+ * @var array
33
+ */
34
+ private $elseIfs = array();
35
+
36
+ /**
37
+ * Else body
38
+ *
39
+ * @var XmlImportAstSequence
40
+ */
41
+ private $elseBody;
42
+
43
+ /**
44
+ * Creates new instance
45
+ *
46
+ * @param XmlImportAstExpression $condition
47
+ */
48
+ public function __construct(XmlImportAstExpression $condition)
49
+ {
50
+ $this->condition = $condition;
51
+ }
52
+
53
+ /**
54
+ * Gets condition
55
+ *
56
+ * @return XmlImportAstExpression
57
+ */
58
+ public function getCondition()
59
+ {
60
+ return $this->condition;
61
+ }
62
+
63
+ /**
64
+ * Gets if body
65
+ *
66
+ * @return XmlImportAstSequence
67
+ */
68
+ public function getIfBody()
69
+ {
70
+ return $this->ifBody;
71
+ }
72
+
73
+ /**
74
+ * Adds If body
75
+ *
76
+ * @param XmlImportAstSequence $body
77
+ */
78
+ public function addIfBody(XmlImportAstSequence $body)
79
+ {
80
+ $this->ifBody = $body;
81
+ }
82
+
83
+ /**
84
+ * Gets list of elseif subcloses
85
+ *
86
+ * @return array
87
+ */
88
+ public function getElseIfs()
89
+ {
90
+ return $this->elseIfs;
91
+ }
92
+
93
+ /**
94
+ * Gets else body
95
+ *
96
+ * @return XmlImportAstSequence
97
+ */
98
+ public function getElseBody()
99
+ {
100
+ return $this->elseBody;
101
+ }
102
+
103
+ /**
104
+ * Adds else body
105
+ *
106
+ * @param XmlImportAstSequence $body
107
+ */
108
+ public function addElseBody(XmlImportAstSequence $body)
109
+ {
110
+ $this->elseBody = $body;
111
+ }
112
+
113
+ /**
114
+ * Adds elseif subclause
115
+ *
116
+ * @param XmlImportAstElseif $elseif
117
+ */
118
+ public function addElseif(XmlImportAstElseif $elseif)
119
+ {
120
+ $this->elseIfs[] = $elseif;
121
+ }
122
+
123
+ /**
124
+ * String represetation of an IF clause
125
+ *
126
+ * @return string
127
+ */
128
+ public function __toString()
129
+ {
130
+ $result = "--> begin " . get_class($this) . "\n";
131
+ $result .= ' Condition: ' . $this->condition . "\n";
132
+ $result .= " Body:\n";
133
+ $array = explode("\n", $this->ifBody);
134
+ for ($i = 0; $i < count($array); $i++)
135
+ {
136
+ $array[$i] = ' ' . $array[$i];
137
+ }
138
+ $result .= implode("\n", $array) . "\n";
139
+ foreach($this->elseIfs as $elseIf)
140
+ {
141
+ $array = explode("\n", $elseIf);
142
+ for ($i = 0; $i < count($array); $i++)
143
+ {
144
+ $array[$i] = '' . $array[$i];
145
+ }
146
+ $result .= implode("\n", $array) . "\n";
147
+ }
148
+ if (!is_null($this->elseBody))
149
+ {
150
+ $result .= " Else:\n";
151
+ $array = explode("\n", $this->elseBody);
152
+ for ($i = 0; $i < count($array); $i++)
153
+ {
154
+ $array[$i] = ' ' . $array[$i];
155
+ }
156
+ $result .= implode("\n", $array) . "\n";
157
+ }
158
+ $result .= "--> end " . get_class($this) . "\n";
159
+ return $result;
160
+ }
161
+ }
libraries/ast/XmlImportAstInteger.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
-
9
- /**
10
- * Represents an integer number
11
- */
12
- class XmlImportAstInteger extends XmlImportAstLiteral
13
- {
14
-
15
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
+
9
+ /**
10
+ * Represents an integer number
11
+ */
12
+ class XmlImportAstInteger extends XmlImportAstLiteral
13
+ {
14
+
15
+ }
libraries/ast/XmlImportAstLiteral.php CHANGED
@@ -1,52 +1,52 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
-
9
- /**
10
- * Represents a literal node
11
- *
12
- * @abstract
13
- */
14
- abstract class XmlImportAstLiteral extends XmlImportAstExpression
15
- {
16
- /**
17
- * Vsalue of a node
18
- *
19
- * @var mixed
20
- */
21
- private $value;
22
-
23
- /**
24
- * Creates new instance of a token
25
- *
26
- * @param mixed $value
27
- */
28
- public function __construct($value)
29
- {
30
- $this->value = $value;
31
- }
32
-
33
- /**
34
- * Gets a value of a node
35
- *
36
- * @return mixed
37
- */
38
- public function getValue()
39
- {
40
- return $this->value;
41
- }
42
-
43
- /**
44
- * String representation of an literal
45
- *
46
- * @return string
47
- */
48
- public function __toString()
49
- {
50
- return get_class($this) . ': "' . $this->getValue() . "\"";
51
- }
52
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
+
9
+ /**
10
+ * Represents a literal node
11
+ *
12
+ * @abstract
13
+ */
14
+ abstract class XmlImportAstLiteral extends XmlImportAstExpression
15
+ {
16
+ /**
17
+ * Vsalue of a node
18
+ *
19
+ * @var mixed
20
+ */
21
+ private $value;
22
+
23
+ /**
24
+ * Creates new instance of a token
25
+ *
26
+ * @param mixed $value
27
+ */
28
+ public function __construct($value)
29
+ {
30
+ $this->value = $value;
31
+ }
32
+
33
+ /**
34
+ * Gets a value of a node
35
+ *
36
+ * @return mixed
37
+ */
38
+ public function getValue()
39
+ {
40
+ return $this->value;
41
+ }
42
+
43
+ /**
44
+ * String representation of an literal
45
+ *
46
+ * @return string
47
+ */
48
+ public function __toString()
49
+ {
50
+ return get_class($this) . ': "' . $this->getValue() . "\"";
51
+ }
52
+ }
libraries/ast/XmlImportAstMath.php CHANGED
@@ -1,73 +1,73 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
-
9
- /**
10
- * Represents a function
11
- */
12
- class XmlImportAstMath extends XmlImportAstExpression
13
- {
14
- /**
15
- * Function arguments
16
- *
17
- * @var array
18
- */
19
- private $arguments = array();
20
-
21
- /**
22
- * Creates new instance
23
- *
24
- * @param string $name
25
- */
26
- public function __construct($name)
27
- {
28
- $this->name = $name;
29
- }
30
-
31
- /**
32
- * Adds argument to a function
33
- *
34
- * @param XmlImportAstExpression $argument
35
- */
36
- public function addArgument(XmlImportAstExpression $argument)
37
- {
38
- $this->arguments[] = $argument;
39
- }
40
-
41
- /**
42
- * Gets function arguments
43
- *
44
- * @return array
45
- */
46
- public function getArguments()
47
- {
48
- return $this->arguments;
49
- }
50
-
51
- /**
52
- * String representation of a function
53
- *
54
- * @return string
55
- */
56
- public function __toString()
57
- {
58
- $result = "--> begin " . get_class($this) . "\n";
59
- foreach ($this->getArguments() as $argument)
60
- {
61
- $array = explode("\n", $argument);
62
- for ($i = 0; $i < count($array); $i++)
63
- {
64
- $array[$i] = ' ' . $array[$i];
65
- }
66
- $result .= implode("\n", $array) . "\n";
67
- }
68
-
69
- $result .= "--> end " . get_class($this);
70
-
71
- return $result;
72
- }
73
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
+
9
+ /**
10
+ * Represents a function
11
+ */
12
+ class XmlImportAstMath extends XmlImportAstExpression
13
+ {
14
+ /**
15
+ * Function arguments
16
+ *
17
+ * @var array
18
+ */
19
+ private $arguments = array();
20
+
21
+ /**
22
+ * Creates new instance
23
+ *
24
+ * @param string $name
25
+ */
26
+ public function __construct($name)
27
+ {
28
+ $this->name = $name;
29
+ }
30
+
31
+ /**
32
+ * Adds argument to a function
33
+ *
34
+ * @param XmlImportAstExpression $argument
35
+ */
36
+ public function addArgument(XmlImportAstExpression $argument)
37
+ {
38
+ $this->arguments[] = $argument;
39
+ }
40
+
41
+ /**
42
+ * Gets function arguments
43
+ *
44
+ * @return array
45
+ */
46
+ public function getArguments()
47
+ {
48
+ return $this->arguments;
49
+ }
50
+
51
+ /**
52
+ * String representation of a function
53
+ *
54
+ * @return string
55
+ */
56
+ public function __toString()
57
+ {
58
+ $result = "--> begin " . get_class($this) . "\n";
59
+ foreach ($this->getArguments() as $argument)
60
+ {
61
+ $array = explode("\n", $argument);
62
+ for ($i = 0; $i < count($array); $i++)
63
+ {
64
+ $array[$i] = ' ' . $array[$i];
65
+ }
66
+ $result .= implode("\n", $array) . "\n";
67
+ }
68
+
69
+ $result .= "--> end " . get_class($this);
70
+
71
+ return $result;
72
+ }
73
  }
libraries/ast/XmlImportAstPrint.php CHANGED
@@ -1,60 +1,60 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
-
9
- /**
10
- * Represents a PRINT node
11
- */
12
- class XmlImportAstPrint extends XmlImportAstStatement
13
- {
14
- /**
15
- * Expression to print
16
- *
17
- * @var XmlImportAstExpression
18
- */
19
- private $value;
20
-
21
- /**
22
- * Creates new instance of a statement
23
- *
24
- * @param XmlImportAstExpression $value
25
- */
26
- public function __construct(XmlImportAstExpression $value)
27
- {
28
- $this->value = $value;
29
- }
30
-
31
- /**
32
- * Get value to be printed
33
- *
34
- * @return XmlImportAstExpression
35
- */
36
- public function getValue()
37
- {
38
- return $this->value;
39
- }
40
-
41
- /**
42
- * String representation of a PRINT clause
43
- *
44
- * @return string
45
- */
46
- public function __toString()
47
- {
48
- $result = "--> begin " . get_class($this) . "\n";
49
- $array = explode("\n", $this->value);
50
- for ($i = 0; $i < count($array); $i++)
51
- {
52
- $array[$i] = ' ' . $array[$i];
53
- }
54
- $result .= implode("\n", $array) . "\n";
55
-
56
- $result .= "--> end " . get_class($this);
57
-
58
- return $result;
59
- }
60
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
+
9
+ /**
10
+ * Represents a PRINT node
11
+ */
12
+ class XmlImportAstPrint extends XmlImportAstStatement
13
+ {
14
+ /**
15
+ * Expression to print
16
+ *
17
+ * @var XmlImportAstExpression
18
+ */
19
+ private $value;
20
+
21
+ /**
22
+ * Creates new instance of a statement
23
+ *
24
+ * @param XmlImportAstExpression $value
25
+ */
26
+ public function __construct(XmlImportAstExpression $value)
27
+ {
28
+ $this->value = $value;
29
+ }
30
+
31
+ /**
32
+ * Get value to be printed
33
+ *
34
+ * @return XmlImportAstExpression
35
+ */
36
+ public function getValue()
37
+ {
38
+ return $this->value;
39
+ }
40
+
41
+ /**
42
+ * String representation of a PRINT clause
43
+ *
44
+ * @return string
45
+ */
46
+ public function __toString()
47
+ {
48
+ $result = "--> begin " . get_class($this) . "\n";
49
+ $array = explode("\n", $this->value);
50
+ for ($i = 0; $i < count($array); $i++)
51
+ {
52
+ $array[$i] = ' ' . $array[$i];
53
+ }
54
+ $result .= implode("\n", $array) . "\n";
55
+
56
+ $result .= "--> end " . get_class($this);
57
+
58
+ return $result;
59
+ }
60
  }
libraries/ast/XmlImportAstSequence.php CHANGED
@@ -1,161 +1,161 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
-
9
- /**
10
- * Represents statement sequence
11
- */
12
- class XmlImportAstSequence extends XmlImportAstStatement
13
- {
14
-
15
- /**
16
- * Sequence instance number
17
- *
18
- * @var int
19
- */
20
- private static $sequenceInstanceNumber = 0;
21
-
22
- /**
23
- * Current sequence number
24
- *
25
- * @var int
26
- */
27
- private $sequenceNumber;
28
-
29
- /**
30
- * Current variable number
31
- *
32
- * @var int
33
- */
34
- private $varNumber = 0;
35
-
36
- /**
37
- * List of statements
38
- *
39
- * @var array
40
- */
41
- private $statements = array();
42
-
43
- /**
44
- * Variable definitions
45
- *
46
- * @var array
47
- */
48
- private $variableDefinitions = array();
49
-
50
- /**
51
- * Variables
52
- *
53
- * @var array
54
- */
55
- private $variables = array();
56
-
57
- /**
58
- * Creates new instance
59
- */
60
- public function __construct()
61
- {
62
- $this->sequenceNumber = self::$sequenceInstanceNumber++;
63
- }
64
-
65
- /**
66
- * Adds statement to a sequence
67
- *
68
- * @param XmlImportAstStatement $statement
69
- */
70
- public function addStatement(XmlImportAstStatement $statement)
71
- {
72
- $this->statements[] = $statement;
73
- }
74
-
75
- /**
76
- * Gets the list of statements
77
- *
78
- * @return array
79
- */
80
- public function getStatements()
81
- {
82
- return $this->statements;
83
- }
84
-
85
- /**
86
- * Adds variable to a sequence
87
- *
88
- * @param XmlImportAstXPath $xpath
89
- */
90
- public function addVariable(XmlImportAstXPath $xpath)
91
- {
92
- if (!array_key_exists($xpath->getValue(), $this->variables))
93
- {
94
- $var = '$v' . $this->sequenceNumber . '_' . $this->varNumber++;
95
- $value = $escapedValue = strtr($xpath->getValue(), array(
96
- "\n" => "\\n",
97
- "\t" => "\\t",
98
- "\r" => "\\r",
99
- "$" => "\\$",
100
- "\"" => "\\\"",
101
- "\\" => "\\\\",
102
- ));
103
- $result = $var . ' = {{XML}}->xpath("' . $value . '");';
104
- $this->variables[$xpath->getValue()] = $var;
105
- $this->variableDefinitions[] = $result;
106
- }
107
- }
108
-
109
- /**
110
- * Gets variable definitions
111
- *
112
- * @return array
113
- */
114
- public function getVariableDefinitions()
115
- {
116
- return $this->variableDefinitions;
117
- }
118
-
119
- /**
120
- * Gets variables
121
- *
122
- * @return array
123
- */
124
- public function getVariables()
125
- {
126
- return $this->variables;
127
- }
128
-
129
- /**
130
- * Returns the number of current instance
131
- *
132
- * @return int
133
- */
134
- public function getSequenceNumber()
135
- {
136
- return $this->sequenceNumber;
137
- }
138
-
139
- /**
140
- * String representation of a sequence node
141
- *
142
- * @return string
143
- */
144
- public function __toString()
145
- {
146
- $result = "--> begin " . get_class($this) . "\n";
147
- foreach ($this->getStatements() as $statement)
148
- {
149
- $array = explode("\n", $statement);
150
- for ($i = 0; $i < count($array); $i++)
151
- {
152
- $array[$i] = ' ' . $array[$i];
153
- }
154
- $result .= implode("\n", $array) . "\n";
155
- }
156
-
157
- $result .= "--> end " . get_class($this);
158
-
159
- return $result;
160
- }
161
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
+
9
+ /**
10
+ * Represents statement sequence
11
+ */
12
+ class XmlImportAstSequence extends XmlImportAstStatement
13
+ {
14
+
15
+ /**
16
+ * Sequence instance number
17
+ *
18
+ * @var int
19
+ */
20
+ private static $sequenceInstanceNumber = 0;
21
+
22
+ /**
23
+ * Current sequence number
24
+ *
25
+ * @var int
26
+ */
27
+ private $sequenceNumber;
28
+
29
+ /**
30
+ * Current variable number
31
+ *
32
+ * @var int
33
+ */
34
+ private $varNumber = 0;
35
+
36
+ /**
37
+ * List of statements
38
+ *
39
+ * @var array
40
+ */
41
+ private $statements = array();
42
+
43
+ /**
44
+ * Variable definitions
45
+ *
46
+ * @var array
47
+ */
48
+ private $variableDefinitions = array();
49
+
50
+ /**
51
+ * Variables
52
+ *
53
+ * @var array
54
+ */
55
+ private $variables = array();
56
+
57
+ /**
58
+ * Creates new instance
59
+ */
60
+ public function __construct()
61
+ {
62
+ $this->sequenceNumber = self::$sequenceInstanceNumber++;
63
+ }
64
+
65
+ /**
66
+ * Adds statement to a sequence
67
+ *
68
+ * @param XmlImportAstStatement $statement
69
+ */
70
+ public function addStatement(XmlImportAstStatement $statement)
71
+ {
72
+ $this->statements[] = $statement;
73
+ }
74
+
75
+ /**
76
+ * Gets the list of statements
77
+ *
78
+ * @return array
79
+ */
80
+ public function getStatements()
81
+ {
82
+ return $this->statements;
83
+ }
84
+
85
+ /**
86
+ * Adds variable to a sequence
87
+ *
88
+ * @param XmlImportAstXPath $xpath
89
+ */
90
+ public function addVariable(XmlImportAstXPath $xpath)
91
+ {
92
+ if (!array_key_exists($xpath->getValue(), $this->variables))
93
+ {
94
+ $var = '$v' . $this->sequenceNumber . '_' . $this->varNumber++;
95
+ $value = $escapedValue = strtr($xpath->getValue(), array(
96
+ "\n" => "\\n",
97
+ "\t" => "\\t",
98
+ "\r" => "\\r",
99
+ "$" => "\\$",
100
+ "\"" => "\\\"",
101
+ "\\" => "\\\\",
102
+ ));
103
+ $result = $var . ' = {{XML}}->xpath("' . $value . '");';
104
+ $this->variables[$xpath->getValue()] = $var;
105
+ $this->variableDefinitions[] = $result;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Gets variable definitions
111
+ *
112
+ * @return array
113
+ */
114
+ public function getVariableDefinitions()
115
+ {
116
+ return $this->variableDefinitions;
117
+ }
118
+
119
+ /**
120
+ * Gets variables
121
+ *
122
+ * @return array
123
+ */
124
+ public function getVariables()
125
+ {
126
+ return $this->variables;
127
+ }
128
+
129
+ /**
130
+ * Returns the number of current instance
131
+ *
132
+ * @return int
133
+ */
134
+ public function getSequenceNumber()
135
+ {
136
+ return $this->sequenceNumber;
137
+ }
138
+
139
+ /**
140
+ * String representation of a sequence node
141
+ *
142
+ * @return string
143
+ */
144
+ public function __toString()
145
+ {
146
+ $result = "--> begin " . get_class($this) . "\n";
147
+ foreach ($this->getStatements() as $statement)
148
+ {
149
+ $array = explode("\n", $statement);
150
+ for ($i = 0; $i < count($array); $i++)
151
+ {
152
+ $array[$i] = ' ' . $array[$i];
153
+ }
154
+ $result .= implode("\n", $array) . "\n";
155
+ }
156
+
157
+ $result .= "--> end " . get_class($this);
158
+
159
+ return $result;
160
+ }
161
  }
libraries/ast/XmlImportAstSpintax.php CHANGED
@@ -1,73 +1,73 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
-
9
- /**
10
- * Represents a function
11
- */
12
- class XmlImportAstSpintax extends XmlImportAstExpression
13
- {
14
- /**
15
- * Function arguments
16
- *
17
- * @var array
18
- */
19
- private $arguments = array();
20
-
21
- /**
22
- * Creates new instance
23
- *
24
- * @param string $name
25
- */
26
- public function __construct($name)
27
- {
28
- $this->name = $name;
29
- }
30
-
31
- /**
32
- * Adds argument to a function
33
- *
34
- * @param XmlImportAstExpression $argument
35
- */
36
- public function addArgument(XmlImportAstExpression $argument)
37
- {
38
- $this->arguments[] = $argument;
39
- }
40
-
41
- /**
42
- * Gets function arguments
43
- *
44
- * @return array
45
- */
46
- public function getArguments()
47
- {
48
- return $this->arguments;
49
- }
50
-
51
- /**
52
- * String representation of a function
53
- *
54
- * @return string
55
- */
56
- public function __toString()
57
- {
58
- $result = "--> begin " . get_class($this) . "\n";
59
- foreach ($this->getArguments() as $argument)
60
- {
61
- $array = explode("\n", $argument);
62
- for ($i = 0; $i < count($array); $i++)
63
- {
64
- $array[$i] = ' ' . $array[$i];
65
- }
66
- $result .= implode("\n", $array) . "\n";
67
- }
68
-
69
- $result .= "--> end " . get_class($this);
70
-
71
- return $result;
72
- }
73
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstExpression.php';
8
+
9
+ /**
10
+ * Represents a function
11
+ */
12
+ class XmlImportAstSpintax extends XmlImportAstExpression
13
+ {
14
+ /**
15
+ * Function arguments
16
+ *
17
+ * @var array
18
+ */
19
+ private $arguments = array();
20
+
21
+ /**
22
+ * Creates new instance
23
+ *
24
+ * @param string $name
25
+ */
26
+ public function __construct($name)
27
+ {
28
+ $this->name = $name;
29
+ }
30
+
31
+ /**
32
+ * Adds argument to a function
33
+ *
34
+ * @param XmlImportAstExpression $argument
35
+ */
36
+ public function addArgument(XmlImportAstExpression $argument)
37
+ {
38
+ $this->arguments[] = $argument;
39
+ }
40
+
41
+ /**
42
+ * Gets function arguments
43
+ *
44
+ * @return array
45
+ */
46
+ public function getArguments()
47
+ {
48
+ return $this->arguments;
49
+ }
50
+
51
+ /**
52
+ * String representation of a function
53
+ *
54
+ * @return string
55
+ */
56
+ public function __toString()
57
+ {
58
+ $result = "--> begin " . get_class($this) . "\n";
59
+ foreach ($this->getArguments() as $argument)
60
+ {
61
+ $array = explode("\n", $argument);
62
+ for ($i = 0; $i < count($array); $i++)
63
+ {
64
+ $array[$i] = ' ' . $array[$i];
65
+ }
66
+ $result .= implode("\n", $array) . "\n";
67
+ }
68
+
69
+ $result .= "--> end " . get_class($this);
70
+
71
+ return $result;
72
+ }
73
  }
libraries/ast/XmlImportAstStatement.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- /**
8
- * Represents a statement
9
- *
10
- * @abstract
11
- */
12
- abstract class XmlImportAstStatement
13
- {
14
-
15
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ /**
8
+ * Represents a statement
9
+ *
10
+ * @abstract
11
+ */
12
+ abstract class XmlImportAstStatement
13
+ {
14
+
15
  }
libraries/ast/XmlImportAstString.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
-
9
- /**
10
- * Represents a string
11
- */
12
- class XmlImportAstString extends XmlImportAstLiteral
13
- {
14
-
15
  }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
+
9
+ /**
10
+ * Represents a string
11
+ */
12
+ class XmlImportAstString extends XmlImportAstLiteral
13
+ {
14
+
15
  }
libraries/ast/XmlImportAstText.php CHANGED
@@ -1,59 +1,59 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
-
9
- /**
10
- * Represents a text
11
- */
12
- class XmlImportAstText extends XmlImportAstStatement
13
- {
14
- /**
15
- * Value of a text node
16
- *
17
- * @var string
18
- */
19
- private $value;
20
-
21
- /**
22
- * Creates new instance
23
- *
24
- * @param string $value
25
- */
26
- public function __construct($value)
27
- {
28
- $this->value = $value;
29
- }
30
-
31
- /**
32
- * Gets value of a text node
33
- *
34
- * @return string
35
- */
36
- public function getValue()
37
- {
38
- return $this->value;
39
- }
40
-
41
- /**
42
- * String representation of the node
43
- *
44
- * @return string
45
- */
46
- public function __toString()
47
- {
48
- $result = "--> begin " . get_class($this) . "\n";
49
- $array = explode("\n", trim($this->getValue()));
50
- for ($i = 0; $i < count($array); $i++)
51
- {
52
- $array[$i] = ' ' . $array[$i];
53
- }
54
- $result .= implode("\n", $array) . "\n";
55
- $result .= "--> end " . get_class($this);
56
-
57
- return $result;
58
- }
59
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
+
9
+ /**
10
+ * Represents a text
11
+ */
12
+ class XmlImportAstText extends XmlImportAstStatement
13
+ {
14
+ /**
15
+ * Value of a text node
16
+ *
17
+ * @var string
18
+ */
19
+ private $value;
20
+
21
+ /**
22
+ * Creates new instance
23
+ *
24
+ * @param string $value
25
+ */
26
+ public function __construct($value)
27
+ {
28
+ $this->value = $value;
29
+ }
30
+
31
+ /**
32
+ * Gets value of a text node
33
+ *
34
+ * @return string
35
+ */
36
+ public function getValue()
37
+ {
38
+ return $this->value;
39
+ }
40
+
41
+ /**
42
+ * String representation of the node
43
+ *
44
+ * @return string
45
+ */
46
+ public function __toString()
47
+ {
48
+ $result = "--> begin " . get_class($this) . "\n";
49
+ $array = explode("\n", trim($this->getValue()));
50
+ for ($i = 0; $i < count($array); $i++)
51
+ {
52
+ $array[$i] = ' ' . $array[$i];
53
+ }
54
+ $result .= implode("\n", $array) . "\n";
55
+ $result .= "--> end " . get_class($this);
56
+
57
+ return $result;
58
+ }
59
+ }
libraries/ast/XmlImportAstWith.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstXpathClause.php';
8
-
9
- /**
10
- * Represents a WITH clause
11
- */
12
- class XmlImportAstWith extends XmlImportAstXPathClause
13
- {
14
-
15
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstXpathClause.php';
8
+
9
+ /**
10
+ * Represents a WITH clause
11
+ */
12
+ class XmlImportAstWith extends XmlImportAstXPathClause
13
+ {
14
+
15
+ }
libraries/ast/XmlImportAstXPath.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
-
9
- /**
10
- * Represents XPath literal
11
- */
12
- class XmlImportAstXPath extends XmlImportAstLiteral
13
- {
14
-
15
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstLiteral.php';
8
+
9
+ /**
10
+ * Represents XPath literal
11
+ */
12
+ class XmlImportAstXPath extends XmlImportAstLiteral
13
+ {
14
+
15
+ }
libraries/ast/XmlImportAstXpathClause.php CHANGED
@@ -1,83 +1,83 @@
1
- <?php
2
- /**
3
- * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
- * @package AST
5
- */
6
-
7
- require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
- require_once dirname(__FILE__) . '/XmlImportAstXPath.php';
9
- require_once dirname(__FILE__) . '/XmlImportAstSequence.php';
10
-
11
- /**
12
- * Represents a clause that is based on XPath
13
- */
14
- abstract class XmlImportAstXPathClause extends XmlImportAstStatement
15
- {
16
- /**
17
- * XPath expression
18
- *
19
- * @var XmlImportAstXPath
20
- */
21
- private $xpath;
22
-
23
- /**
24
- * Clause body
25
- *
26
- * @var XmlImportAstSequence
27
- */
28
- private $body;
29
-
30
- /**
31
- * Creates new instance
32
- *
33
- * @param XmlImportAstXPath $xpath
34
- * @param XmlImportAstSequence $body
35
- */
36
- public function __construct(XmlImportAstXPath $xpath, XmlImportAstSequence $body)
37
- {
38
- $this->xpath = $xpath;
39
- $this->body = $body;
40
- }
41
-
42
- /**
43
- * Gets XPath
44
- *
45
- * @return XmlImportAstXPath
46
- */
47
- public function getXpath()
48
- {
49
- return $this->xpath;
50
- }
51
-
52
- /**
53
- * Gets clause body
54
- *
55
- * @return XmlImportAstSequence
56
- */
57
- public function getBody()
58
- {
59
- return $this->body;
60
- }
61
-
62
- /**
63
- * String representation of a clause
64
- *
65
- * @return string
66
- */
67
- public function __toString()
68
- {
69
- $result = "--> begin " . get_class($this) . "\n";
70
- $result .= ' XPath: ' . $this->xpath . "\n";
71
- $result .= " Body:\n";
72
-
73
- $array = explode("\n", $this->body);
74
- for ($i = 0; $i < count($array); $i++)
75
- {
76
- $array[$i] = ' ' . $array[$i];
77
- }
78
-
79
- $result .= implode("\n", $array) . "\n";
80
- $result .= "--> end " . get_class($this) . "\n";
81
- return $result;
82
- }
83
- }
1
+ <?php
2
+ /**
3
+ * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4
+ * @package AST
5
+ */
6
+
7
+ require_once dirname(__FILE__) . '/XmlImportAstStatement.php';
8
+ require_once dirname(__FILE__) . '/XmlImportAstXPath.php';
9
+ require_once dirname(__FILE__) . '/XmlImportAstSequence.php';
10
+
11
+ /**
12
+ * Represents a clause that is based on XPath
13
+ */
14
+ abstract class XmlImportAstXPathClause extends XmlImportAstStatement
15
+ {
16
+ /**
17
+ * XPath expression
18
+ *
19
+ * @var XmlImportAstXPath
20
+ */
21
+ private $xpath;
22
+
23
+ /**
24
+ * Clause body
25
+ *
26
+ * @var XmlImportAstSequence
27
+ */
28
+ private $body;
29
+
30
+ /**
31
+ * Creates new instance
32
+ *
33
+ * @param XmlImportAstXPath $xpath
34
+ * @param XmlImportAstSequence $body
35
+ */
36
+ public function __construct(XmlImportAstXPath $xpath, XmlImportAstSequence $body)
37
+ {
38
+ $this->xpath = $xpath;
39
+ $this->body = $body;
40
+ }
41
+
42
+ /**
43
+ * Gets XPath
44
+ *
45
+ * @return XmlImportAstXPath
46
+ */
47
+ public function getXpath()
48
+ {
49
+ return $this->xpath;
50
+ }
51
+
52
+ /**
53
+ * Gets clause body
54
+ *
55
+ * @return XmlImportAstSequence
56
+ */
57
+ public function getBody()
58
+ {
59
+ return $this->body;
60
+ }
61
+
62
+ /**
63
+ * String representation of a clause
64
+ *
65
+ * @return string
66
+ */
67
+ public function __toString()
68
+ {
69
+ $result = "--> begin " . get_class($this) . "\n";
70
+ $result .= ' XPath: ' . $this->xpath . "\n";
71
+ $result .= " Body:\n";
72
+
73
+ $array = explode("\n", $this->body);
74
+ for ($i = 0; $i < count($array); $i++)
75
+ {
76
+ $array[$i] = ' ' . $array[$i];
77
+ }
78
+
79
+ $result .= implode("\n", $array) . "\n";
80
+ $result .= "--> end " . get_class($this) . "\n";
81
+ return $result;
82
+ }
83
+ }
models/import/record.php CHANGED
@@ -72,6 +72,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
72
  // If import process NOT in large file mode the save history file
73
 
74
  $avoid_pingbacks = PMXI_Plugin::getInstance()->getOption('pingbacks');
 
75
 
76
  if ( $avoid_pingbacks and ! defined( 'WP_IMPORTING' ) ) define( 'WP_IMPORTING', true );
77
 
@@ -94,19 +95,23 @@ class PMXI_Import_Record extends PMXI_Model_Record {
94
 
95
  if ($this->large_import == 'Yes' and !empty($records)){
96
 
97
- $_SESSION['pmxi_import']['count'] = count($records);
98
 
99
- $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
100
 
101
- if (!in_array($chunk, $records) and (!$this->options['create_chunks'] or $is_cron)){
 
 
 
 
102
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'pmxi_plugin'));
103
- $_SESSION['pmxi_import']['warnings']++;
104
  // Time Elapsed
105
  if ( ! $is_cron ){
106
- $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
107
  $logger and call_user_func($logger, $progress_msg);
108
  }
109
- $_SESSION['pmxi_import']['chunk_number']++;
110
  return;
111
  }
112
  else $records = array();
@@ -116,7 +121,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
116
 
117
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing titles...', 'pmxi_plugin'));
118
  $titles = XmlImportParser::factory($xml, $this->xpath, $this->template['title'], $file)->parse($records); $tmp_files[] = $file;
119
- if ($this->large_import != 'Yes') $_SESSION['pmxi_import']['count'] = count($titles);
120
 
121
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing excerpts...', 'pmxi_plugin'));
122
  $post_excerpt = array();
@@ -167,7 +172,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
167
  $time = strtotime($d);
168
  if (FALSE === $time) {
169
  in_array($d, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $d));
170
- $_SESSION['pmxi_import']['warnings']++;
171
  $time = time();
172
  }
173
  $dates[$i] = date('Y-m-d H:i:s', $time);
@@ -180,13 +185,13 @@ class PMXI_Import_Record extends PMXI_Model_Record {
180
  $time_start = strtotime($dates_start[$i]);
181
  if (FALSE === $time_start) {
182
  in_array($dates_start[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_start[$i]));
183
- $_SESSION['pmxi_import']['warnings']++;
184
  $time_start = time();
185
  }
186
  $time_end = strtotime($dates_end[$i]);
187
  if (FALSE === $time_end) {
188
  in_array($dates_end[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_end[$i]));
189
- $_SESSION['pmxi_import']['warnings']++;
190
  $time_end = time();
191
  }
192
  $dates[$i] = date('Y-m-d H:i:s', mt_rand($time_start, $time_end));
@@ -278,7 +283,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
278
  count($titles) and $cats = array_fill(0, count($titles), '');
279
  }
280
 
281
- }
282
  // [/posts categories]
283
 
284
  // [custom taxonomies]
@@ -293,8 +298,9 @@ class PMXI_Import_Record extends PMXI_Model_Record {
293
  }
294
 
295
  if (!empty($this->options[$taxonomies_param]) and is_array($this->options[$taxonomies_param])): foreach ($this->options[$taxonomies_param] as $tx_name => $tx_template) if ('' != $tx_template) {
296
- $tx = get_taxonomy($tx_name);
297
- if (in_array($taxonomies_object_type, $tx->object_type)) {
 
298
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, sprintf(__('Composing terms for `%s` taxonomy...', 'pmxi_plugin'), $tx->labels->name));
299
  $txes = array();
300
 
@@ -363,7 +369,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
363
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
364
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
365
  $logger and call_user_func($logger, __('<b>WARNING</b>: No featured images will be created', 'pmxi_plugin'));
366
- $_SESSION['pmxi_import']['warnings']++;
367
  } else {
368
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing URLs for featured images...', 'pmxi_plugin'));
369
  $featured_images = array();
@@ -391,13 +397,23 @@ class PMXI_Import_Record extends PMXI_Model_Record {
391
  } else {
392
  count($titles) and $featured_images = array_fill(0, count($titles), '');
393
  }
 
 
 
 
 
 
 
 
 
 
394
  }
395
 
396
  // serialized attachments
397
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
398
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
399
  $logger and call_user_func($logger, __('<b>WARNING</b>: No attachments will be created', 'pmxi_plugin'));
400
- $_SESSION['pmxi_import']['warnings']++;
401
  } else {
402
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing URLs for attachments files...', 'pmxi_plugin'));
403
  $attachments = array();
@@ -450,41 +466,19 @@ class PMXI_Import_Record extends PMXI_Model_Record {
450
  $current_post_ids = array();
451
  foreach ($titles as $i => $void) {
452
 
453
- if (!empty($chunk_records) and $this->large_import == 'Yes' and $this->options['create_chunks'] and !$is_cron and !in_array($_SESSION['pmxi_import']['chunk_number'], $chunk_records)) {
454
- $_SESSION['pmxi_import']['skipped_records']++;
455
- $_SESSION['pmxi_import']['chunk_number']++;
456
-
457
- $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'pmxi_plugin'));
458
- $_SESSION['pmxi_import']['warnings']++;
459
- // Time Elapsed
460
- if ( ! $is_cron ){
461
- $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
462
- $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
463
- $logger and call_user_func($logger, $progress_msg);
464
- }
465
- $this->set(array(
466
- 'imported' => $this->imported + 1,
467
- 'created' => $_SESSION['pmxi_import']['created_records'],
468
- 'updated' => $_SESSION['pmxi_import']['updated_records']
469
- ))->save();
470
- continue;
471
- }
472
-
473
  if (empty($titles[$i])) {
474
  if (class_exists('PMWI_Plugin') and !empty($single_product_parent_ID[$i])){
475
  $titles[$i] = $single_product_parent_ID[$i] . ' Product Variation';
476
  }
477
- else{
478
- $logger and call_user_func($logger, __('<b>SKIPPED</b>: by empty title', 'pmxi_plugin'));
479
- $_SESSION['pmxi_import']['skipped_records']++;
480
- $_SESSION['pmxi_import']['chunk_number']++;
481
- $_SESSION['pmxi_import']['warnings']++;
482
- $this->set(array(
483
- 'imported' => $this->imported + 1,
484
- 'created' => $_SESSION['pmxi_import']['created_records'],
485
- 'updated' => $_SESSION['pmxi_import']['updated_records']
486
- ))->save();
487
- continue;
488
  }
489
  }
490
 
@@ -493,10 +487,10 @@ class PMXI_Import_Record extends PMXI_Model_Record {
493
  'post_status' => $this->options['status'],
494
  'comment_status' => $this->options['comment_status'],
495
  'ping_status' => $this->options['ping_status'],
496
- 'post_title' => ($this->template['fix_characters']) ? utf8_encode(html_entity_decode($titles[$i])) : (($this->template['is_leave_html']) ? html_entity_decode($titles[$i]) : $titles[$i]),
497
- 'post_excerpt' => ($this->template['fix_characters']) ? utf8_encode(html_entity_decode($post_excerpt[$i])) : (($this->template['is_leave_html']) ? html_entity_decode($post_excerpt[$i]) : $post_excerpt[$i]),
498
  'post_name' => $post_slug[$i],
499
- 'post_content' => ($this->template['fix_characters']) ? utf8_encode(html_entity_decode($contents[$i])) : (($this->template['is_leave_html']) ? html_entity_decode($contents[$i]) : $contents[$i]),
500
  'post_date' => $dates[$i],
501
  'post_date_gmt' => get_gmt_from_date($dates[$i]),
502
  'post_author' => $post_author[$i] ,
@@ -555,14 +549,13 @@ class PMXI_Import_Record extends PMXI_Model_Record {
555
  if ($post_to_update){
556
  // Do not update already existing records option selected
557
  if ("yes" == $this->options['is_keep_former_posts']) {
558
- $current_post_ids[] = $_SESSION['pmxi_import']['current_post_ids'][] = $post_to_update_id;
559
- if ($is_cron){
560
- $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
561
- $tmp_array[] = $post_to_update_id;
562
- $this->set(array(
563
- 'current_post_ids' => json_encode($tmp_array)
564
- ))->save();
565
- }
566
  // Do not update product variations
567
  if ($post_type == "product" and class_exists('PMWI_Plugin')){
568
 
@@ -576,47 +569,51 @@ class PMXI_Import_Record extends PMXI_Model_Record {
576
 
577
  if ( $children ) {
578
  foreach ( $children as $child ) {
579
- $current_post_ids[] = $_SESSION['pmxi_import']['current_post_ids'][] = $child;
580
- if ($is_cron){
581
- $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
582
- $tmp_array[] = $child;
583
- $this->set(array(
584
- 'current_post_ids' => json_encode($tmp_array)
585
- ))->save();
586
- }
587
  }
588
  }
589
- }
590
- $_SESSION['pmxi_import']['skipped_records']++;
 
 
 
591
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'pmxi_plugin'), $articleData['post_title']));
592
- $_SESSION['pmxi_import']['warnings']++;
593
  if ( ! $is_cron ){
594
- $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
595
- $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
596
  $logger and call_user_func($logger, $progress_msg);
597
  }
598
- $_SESSION['pmxi_import']['chunk_number']++;
599
  continue;
600
- }
 
601
  $articleData['ID'] = $post_to_update_id;
602
  // preserve date of already existing article when duplicate is found
603
  if ($this->options['is_keep_categories']) { // preserve categories and tags of already existing article if corresponding setting is specified
604
  $cats_list = get_the_category($articleData['ID']);
 
605
  if (is_wp_error($cats_list)) {
606
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current categories for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
607
- $_SESSION['pmxi_import']['warnings']++;
608
  } else {
609
  $cats_new = array();
610
  foreach ($cats_list as $c) {
611
- $cats_new[] = $c->cat_ID;
612
  }
613
- $cats[$i] = $cats_new;
614
  }
615
 
616
  $tags_list = get_the_tags($articleData['ID']);
617
  if (is_wp_error($tags_list)) {
618
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current tags for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
619
- $_SESSION['pmxi_import']['warnings']++;
620
  } else {
621
  $tags_new = array();
622
  if ($tags_list) foreach ($tags_list as $t) {
@@ -624,20 +621,20 @@ class PMXI_Import_Record extends PMXI_Model_Record {
624
  }
625
  $articleData['tags_input'] = implode(', ', $tags_new);
626
  }
627
-
628
  foreach (array_keys($taxonomies) as $tx_name) {
629
  $txes_list = get_the_terms($articleData['ID'], $tx_name);
630
  if (is_wp_error($txes_list)) {
631
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current taxonomies for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
632
- $_SESSION['pmxi_import']['warnings']++;
633
  } else {
634
  $txes_new = array();
635
  if (!empty($txes_list)):
636
  foreach ($txes_list as $t) {
637
- $txes_new[] = $t->name;
638
  }
639
  endif;
640
- $taxonomies[$tx_name][$i] = $txes_new;
641
  }
642
  }
643
  }
@@ -660,10 +657,14 @@ class PMXI_Import_Record extends PMXI_Model_Record {
660
  if ($this->options['is_keep_menu_order']){
661
  $articleData['menu_order'] = $post_to_update->menu_order;
662
  }
 
 
 
663
  // handle obsolete attachments (i.e. delete or keep) according to import settings
664
- if ( ! $this->options['is_keep_images'] and ! $this->options['no_create_featured_image']){
665
  wp_delete_attachments($articleData['ID']);
666
  }
 
667
  }
668
  elseif ( ! $postRecord->isEmpty() ){
669
 
@@ -674,14 +675,18 @@ class PMXI_Import_Record extends PMXI_Model_Record {
674
 
675
  // no new records are created. it will only update posts it finds matching duplicates for
676
  if ($this->options['not_create_records'] and empty($articleData['ID'])){
677
- $_SESSION['pmxi_import']['skipped_records']++;
 
 
 
 
678
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: by "Not add new records" option for `%s`', 'pmxi_plugin'), $articleData['post_title']));
679
  if ( ! $is_cron ){
680
- $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
681
- $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
682
  $logger and call_user_func($logger, $progress_msg);
683
  }
684
- $_SESSION['pmxi_import']['chunk_number']++;
685
  continue;
686
  }
687
 
@@ -750,7 +755,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
750
  $dest->insert();
751
  } else {
752
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create cloaked link for %s', 'pmxi_plugin'), $url));
753
- $_SESSION['pmxi_import']['warnings']++;
754
  $link = NULL;
755
  }
756
  }
@@ -767,25 +772,24 @@ class PMXI_Import_Record extends PMXI_Model_Record {
767
 
768
  if (is_wp_error($pid)) {
769
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
770
- $_SESSION['pmxi_import']['errors']++;
771
  } else {
772
 
773
- $current_post_ids[] = $_SESSION['pmxi_import']['current_post_ids'][] = $pid;
774
- if ($is_cron){
775
- $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
776
- $tmp_array[] = $pid;
777
- $this->set(array(
778
- 'current_post_ids' => json_encode($tmp_array)
779
- ))->save();
780
- }
781
  if ("manual" != $this->options['duplicate_matching'] or empty($articleData['ID'])){
782
  // associate post with import
783
  $postRecord->isEmpty() and $postRecord->set(array(
784
  'post_id' => $pid,
785
  'import_id' => $this->id,
786
- 'unique_key' => $unique_keys[$i]
 
787
  ))->insert();
788
- }
789
 
790
  // Woocommerce add-on
791
  if ( $post_type == "product" and class_exists('PMWI_Plugin')){
@@ -798,102 +802,120 @@ class PMXI_Import_Record extends PMXI_Model_Record {
798
 
799
  // [featured image]
800
  if ( ! empty($uploads) and false === $uploads['error'] and !empty($featured_images[$i]) and (empty($articleData['ID']) or empty($this->options['is_keep_images']))) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
801
 
802
- if ( $this->options['no_create_featured_image'] and has_post_thumbnail($pid) ){
803
- // do not download files if "no create featured image" is checked
804
- $logger and call_user_func($logger, sprintf(__('<b>Featured image SKIPPED</b>: The featured image is always exists fot the %s', 'pmxi_plugin'), $articleData['post_title']));
805
- }
806
- else{
807
- require_once(ABSPATH . 'wp-admin/includes/image.php');
808
-
809
- if ( ! is_array($featured_images[$i]) ) $featured_images[$i] = array($featured_images[$i]);
810
- $post_thumbnail = false;
811
- $success_images = false;
812
- $gallery_attachment_ids = array();
813
- foreach ($featured_images[$i] as $featured_image)
814
- {
815
- $imgs = str_getcsv($featured_image, $this->options['featured_delim']);
816
- if (!empty($imgs)) {
817
- foreach ($imgs as $img_url) { if (empty($img_url)) continue;
818
- $create_image = false;
819
- if (base64_decode($img_url, true) !== false){
820
- $img = @imagecreatefromstring(base64_decode($img_url));
821
- if($img)
822
- {
823
- $image_filename = md5(time()) . '.jpg';
824
- $image_filepath = $uploads['path'] . '/' . $image_filename;
825
- imagejpeg($img, $image_filepath);
826
- if( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
827
- $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $image_filepath));
828
- $_SESSION['pmxi_import']['warnings']++;
829
- } else {
830
- $create_image = true;
831
- }
832
- }
833
- }
834
- else {
835
-
836
- $img_ext = pmxi_get_remote_image_ext($img_url);
837
-
838
- $image_filename = wp_unique_filename($uploads['path'], (($this->options['auto_rename_images'] and "" != $auto_rename_images[$i]) ? url_title($auto_rename_images[$i]) : uniqid()) . (("" != $img_ext) ? '.'.$img_ext : ''));
839
- $image_filepath = $uploads['path'] . '/' . url_title($image_filename);
840
 
841
  $img_url = str_replace(" ", "%20", trim($img_url));
842
 
843
  if ( ! get_file_curl($img_url, $image_filepath) and ! @file_put_contents($image_filepath, @file_get_contents($img_url))) {
844
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: File %s cannot be saved locally as %s', 'pmxi_plugin'), $img_url, $image_filepath));
845
- $_SESSION['pmxi_import']['warnings']++;
846
  unlink($image_filepath); // delete file since failed upload may result in empty file created
847
  } elseif( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
848
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $img_url));
849
- $_SESSION['pmxi_import']['warnings']++;
850
  } else {
851
  $create_image = true;
852
- }
853
- }
854
-
855
- if ($create_image){
856
- $attachment = array(
857
- 'post_mime_type' => image_type_to_mime_type($image_info[2]),
858
- 'guid' => $uploads['url'] . '/' . $image_filename,
859
- 'post_title' => $image_filename,
860
- 'post_content' => '',
861
- );
862
- if (($image_meta = wp_read_image_metadata($image_filepath))) {
863
- if (trim($image_meta['title']) && ! is_numeric(sanitize_title($image_meta['title'])))
864
- $attachment['post_title'] = $image_meta['title'];
865
- if (trim($image_meta['caption']))
866
- $attachment['post_content'] = $image_meta['caption'];
867
  }
868
- $attid = wp_insert_attachment($attachment, $image_filepath, $pid);
869
- if (is_wp_error($attid)) {
870
- $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
871
- $_SESSION['pmxi_import']['warnings']++;
872
- } else {
873
- // you must first include the image.php file
874
- // for the function wp_generate_attachment_metadata() to work
875
- require_once(ABSPATH . 'wp-admin/includes/image.php');
876
- wp_update_attachment_metadata($attid, wp_generate_attachment_metadata($attid, $image_filepath));
877
- $success_images = true;
878
- if ( ! $post_thumbnail ) {
879
- if ( ! $this->options['no_create_featured_image'] or ! has_post_thumbnail($pid)){
880
- set_post_thumbnail($pid, $attid);
881
- $post_thumbnail = true;
882
- }
883
- else $gallery_attachment_ids[] = $attid;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
884
  }
885
- else $gallery_attachment_ids[] = $attid;
886
  }
887
- }
888
- }
889
- }
 
890
  }
891
- // Set product gallery images
892
- if ( $post_type == "product" and class_exists('PMWI_Plugin') and !empty($gallery_attachment_ids))
893
- update_post_meta($pid, '_product_image_gallery', implode(',', $gallery_attachment_ids));
894
- // Create entry as Draft if no images are downloaded successfully
895
- if ( ! $success_images and "yes" == $this->options['create_draft'] ) wp_update_post(array('ID' => $pid, 'post_status' => 'draft'));
896
  }
 
 
 
 
 
897
  }
898
  // [/featured image]
899
 
@@ -916,17 +938,17 @@ class PMXI_Import_Record extends PMXI_Model_Record {
916
  $attachment_filename = wp_unique_filename($uploads['path'], basename(parse_url(trim($atch_url), PHP_URL_PATH)));
917
  $attachment_filepath = $uploads['path'] . '/' . url_title($attachment_filename);
918
 
919
- if ( ! file_put_contents($attachment_filepath, @file_get_contents(trim($atch_url))) and ! get_file_curl(trim($atch_url), $attachment_filepath)) {
920
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Attachment file %s cannot be saved locally as %s', 'pmxi_plugin'), trim($atch_url), $attachment_filepath));
921
- $_SESSION['pmxi_import']['warnings']++;
922
  unlink($attachment_filepath); // delete file since failed upload may result in empty file created
923
  } elseif( ! $wp_filetype = wp_check_filetype(basename($attachment_filename), null )) {
924
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Can\'t detect attachment file type %s', 'pmxi_plugin'), trim($atch_url)));
925
- $_SESSION['pmxi_import']['warnings']++;
926
  } else {
927
 
928
  $attachment_data = array(
929
- 'guid' => $uploads['baseurl'] . _wp_relative_upload_path( $attachment_filepath ),
930
  'post_mime_type' => $wp_filetype['type'],
931
  'post_title' => preg_replace('/\.[^.]+$/', '', basename($attachment_filepath)),
932
  'post_content' => '',
@@ -936,7 +958,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
936
 
937
  if (is_wp_error($attach_id)) {
938
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
939
- $_SESSION['pmxi_import']['warnings']++;
940
  } else {
941
  wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attachment_filepath));
942
  }
@@ -948,141 +970,185 @@ class PMXI_Import_Record extends PMXI_Model_Record {
948
  // [/attachments]
949
 
950
  // [custom taxonomies]
951
- foreach ($taxonomies as $tx_name => $txes) {
 
 
 
 
952
 
953
- $assign_taxes = array();
954
 
955
- // create term if not exists
956
- foreach ($txes[$i] as $key => $single_tax) {
957
- if (is_array($single_tax)){
 
958
 
959
- $parent_id = (!empty($single_tax['parent'])) ? $this->recursion_taxes($single_tax['parent'], $tx_name, $txes[$i], $key) : '';
 
 
960
 
961
- $term = term_exists( trim(htmlspecialchars($single_tax['name'])), $tx_name, $parent_id );
962
 
963
- if ( empty($term) and !is_wp_error($term) ){
964
- $term_attr = array('parent'=> (!empty($parent_id)) ? $parent_id : 0);
965
- $term = wp_insert_term(
966
- $single_tax['name'], // the term
967
- $tx_name, // the taxonomy
968
- $term_attr
969
- );
970
- }
971
-
972
- if ( is_wp_error($term) ){
973
- $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: `%s`', 'pmxi_plugin'), $term->get_error_message()));
974
- $_SESSION['pmxi_import']['warnings']++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
975
  }
976
- elseif (!empty($term)) {
977
- $cat_id = $term['term_id'];
978
- if ($cat_id and $single_tax['assign'])
979
- {
980
- $term = get_term_by('id', $cat_id, $tx_name);
981
- $assign_taxes[] = $term->slug;
982
- }
983
- }
984
  }
985
  }
986
-
987
- // associate taxes with post
988
- $term_ids = wp_set_object_terms($pid, $assign_taxes, $tx_name);
989
- if (is_wp_error($term_ids)) {
990
- $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$term_ids->get_error_message());
991
- $_SESSION['pmxi_import']['warnings']++;
 
 
 
 
992
  }
993
- }
994
  // [/custom taxonomies]
995
 
996
  // [categories]
997
- if (!empty($cats[$i])){
 
 
998
 
999
- if ( ! $this->options['is_keep_categories']) wp_set_object_terms( $pid, NULL, 'category' );
1000
 
1001
- $assign_cats = array();
1002
- // create categories if it's doesn't exists
1003
- foreach ($cats[$i] as $key => $single_cat) {
1004
 
1005
- if (is_array($single_cat)){
 
 
 
1006
 
1007
- $parent_id = (!empty($single_cat['parent'])) ? $this->recursion_taxes($single_cat['parent'], 'category', $cats[$i], $key) : '';
 
1008
 
1009
- $term = term_exists( trim(htmlspecialchars($single_cat['name'])), 'category', $parent_id );
1010
 
1011
- if ( empty($term) and !is_wp_error($term) ){
1012
- $term_attr = array('parent'=> (!empty($parent_id)) ? $parent_id : 0);
1013
- $term = wp_insert_term(
1014
- $single_cat['name'], // the term
1015
- 'category', // the taxonomy
1016
- $term_attr
1017
- );
1018
- }
1019
-
1020
- if ( is_wp_error($term) ){
1021
- $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: `%s`', 'pmxi_plugin'), $term->get_error_message()));
1022
- $_SESSION['pmxi_import']['warnings']++;
1023
- }
1024
- elseif ( !empty($term) ) {
1025
- $cat_id = $term['term_id'];
1026
- if ($cat_id and $single_cat['assign'])
1027
- {
1028
- $term = get_term_by('id', $cat_id, 'category');
1029
- $assign_cats[] = $term->slug;
 
 
 
 
 
1030
  }
1031
- }
1032
- }
1033
- }
1034
 
1035
- // associate categories with post
1036
- $cats_ids = wp_set_object_terms($pid, $assign_cats, 'category');
 
 
 
 
 
 
 
 
 
 
1037
  if (is_wp_error($cats_ids)) {
1038
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$cats_ids->get_error_message());
1039
- $_SESSION['pmxi_import']['warnings']++;
1040
  }
1041
  }
1042
  // [/categories]
1043
 
1044
  if (empty($articleData['ID'])) {
1045
- $_SESSION['pmxi_import']['created_records']++;
1046
  $logger and call_user_func($logger, sprintf(__('`%s` post created successfully', 'pmxi_plugin'), $articleData['post_title']));
1047
  } else {
1048
- $_SESSION['pmxi_import']['updated_records']++;
1049
  $logger and call_user_func($logger, sprintf(__('`%s` post updated successfully', 'pmxi_plugin'), $articleData['post_title']));
1050
  }
1051
-
1052
  do_action( 'pmxi_saved_post', $pid); // hook that was triggered immediately after post saved
1053
 
 
 
 
 
 
 
 
 
 
1054
  $records_count = 0;
1055
 
1056
  // Time Elapsed
1057
  if ( ! $is_cron){
1058
 
1059
- if ($this->large_import == 'No') $_SESSION['pmxi_import']['count'] = count($titles);
1060
 
1061
- $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
1062
 
1063
- $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
1064
  $logger and call_user_func($logger, $progress_msg);
1065
  }
1066
 
1067
- }
1068
-
1069
- if ($this->large_import == 'Yes' and $chunk){
1070
- $this->set(array(
1071
- 'imported' => $this->imported + 1,
1072
- 'created' => $_SESSION['pmxi_import']['created_records'],
1073
- 'updated' => $_SESSION['pmxi_import']['updated_records']
1074
- ))->save();
1075
- $_SESSION['pmxi_import']['chunk_number']++;
1076
- }
1077
 
1078
  wp_cache_flush();
1079
- }
1080
- if (!$is_cron and ($records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and ! empty($this->options['is_delete_missing'])) { // delete posts which are not in current import set
 
 
 
 
1081
  $logger and call_user_func($logger, 'Removing previously imported posts which are no longer actual...');
1082
  $postList = new PMXI_Post_List();
1083
-
 
1084
  $missing_ids = array();
1085
- foreach ($postList->getBy(array('import_id' => $this->id, 'post_id NOT IN' => $_SESSION['pmxi_import']['current_post_ids'])) as $missingPost) {
1086
  empty($this->options['is_keep_attachments']) and wp_delete_attachments($missingPost['post_id']);
1087
  $missing_ids[] = $missingPost['post_id'];
1088
 
@@ -1105,29 +1171,61 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1105
  $this->wpdb->query(
1106
  $this->wpdb->prepare($sql, '')
1107
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1108
  }
1109
 
1110
  }
1111
 
1112
  } catch (XmlImportException $e) {
1113
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $e->getMessage());
1114
- $_SESSION['pmxi_import']['errors']++;
1115
  }
1116
 
1117
  $this->set('registered_on', date('Y-m-d H:i:s'))->save(); // specify execution is successful
1118
 
1119
- !$is_cron and ($records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and $logger and call_user_func($logger, __('Cleaning temporary data...', 'pmxi_plugin'));
1120
  foreach ($tmp_files as $file) { // remove all temporary files created
1121
  unlink($file);
1122
  }
1123
 
1124
- if (($is_cron or $records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and $this->options['is_delete_source']) {
1125
  $logger and call_user_func($logger, __('Deleting source XML file...', 'pmxi_plugin'));
1126
  if ( ! @unlink($this->path)) {
1127
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to remove %s', 'pmxi_plugin'), $this->path));
1128
  }
1129
  }
1130
- !$is_cron and ($records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and $logger and call_user_func($logger, 'Done');
 
 
 
 
 
 
 
 
1131
 
1132
  remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
1133
 
72
  // If import process NOT in large file mode the save history file
73
 
74
  $avoid_pingbacks = PMXI_Plugin::getInstance()->getOption('pingbacks');
75
+ $legacy_handling = PMXI_Plugin::getInstance()->getOption('legacy_special_character_handling');
76
 
77
  if ( $avoid_pingbacks and ! defined( 'WP_IMPORTING' ) ) define( 'WP_IMPORTING', true );
78
 
95
 
96
  if ($this->large_import == 'Yes' and !empty($records)){
97
 
98
+ PMXI_Plugin::$session['pmxi_import']['count'] = count($records);
99
 
100
+ $records_count = $this->created + $this->updated + $this->skipped + PMXI_Plugin::$session->data['pmxi_import']['errors'];
101
 
102
+ if (!in_array($chunk, $records)){
103
+ $this->set(array(
104
+ 'skipped' => $this->skipped + 1
105
+ ))->save();
106
+ PMXI_Plugin::$session['pmxi_import']['skipped_records'] = $this->skipped;
107
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'pmxi_plugin'));
108
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
109
  // Time Elapsed
110
  if ( ! $is_cron ){
111
+ $progress_msg = '<p class="import_process_bar"> Created ' . $this->created . ' / Updated ' . $this->updated . ' of '. PMXI_Plugin::$session->data['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/PMXI_Plugin::$session['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . PMXI_Plugin::$session['pmxi_import']['warnings'] . '</span><span class="errors_count">' . PMXI_Plugin::$session['pmxi_import']['errors'] . '</span>';
112
  $logger and call_user_func($logger, $progress_msg);
113
  }
114
+ PMXI_Plugin::$session['pmxi_import']['chunk_number'] = PMXI_Plugin::$session->data['pmxi_import']['chunk_number']++;
115
  return;
116
  }
117
  else $records = array();
121
 
122
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing titles...', 'pmxi_plugin'));
123
  $titles = XmlImportParser::factory($xml, $this->xpath, $this->template['title'], $file)->parse($records); $tmp_files[] = $file;
124
+ if ($this->large_import != 'Yes') PMXI_Plugin::$session['pmxi_import']['count'] = count($titles);
125
 
126
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing excerpts...', 'pmxi_plugin'));
127
  $post_excerpt = array();
172
  $time = strtotime($d);
173
  if (FALSE === $time) {
174
  in_array($d, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $d));
175
+ PMXI_Plugin::$session['pmxi_import']['warnings']++;
176
  $time = time();
177
  }
178
  $dates[$i] = date('Y-m-d H:i:s', $time);
185
  $time_start = strtotime($dates_start[$i]);
186
  if (FALSE === $time_start) {
187
  in_array($dates_start[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_start[$i]));
188
+ PMXI_Plugin::$session['pmxi_import']['warnings']++;
189
  $time_start = time();
190
  }
191
  $time_end = strtotime($dates_end[$i]);
192
  if (FALSE === $time_end) {
193
  in_array($dates_end[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_end[$i]));
194
+ PMXI_Plugin::$session['pmxi_import']['warnings']++;
195
  $time_end = time();
196
  }
197
  $dates[$i] = date('Y-m-d H:i:s', mt_rand($time_start, $time_end));
283
  count($titles) and $cats = array_fill(0, count($titles), '');
284
  }
285
 
286
+ }
287
  // [/posts categories]
288
 
289
  // [custom taxonomies]
298
  }
299
 
300
  if (!empty($this->options[$taxonomies_param]) and is_array($this->options[$taxonomies_param])): foreach ($this->options[$taxonomies_param] as $tx_name => $tx_template) if ('' != $tx_template) {
301
+ $tx = get_taxonomy($tx_name);
302
+
303
+ if (!empty($tx->object_type) and in_array($taxonomies_object_type, $tx->object_type)) {
304
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, sprintf(__('Composing terms for `%s` taxonomy...', 'pmxi_plugin'), $tx->labels->name));
305
  $txes = array();
306
 
369
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
370
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
371
  $logger and call_user_func($logger, __('<b>WARNING</b>: No featured images will be created', 'pmxi_plugin'));
372
+ PMXI_Plugin::$session['pmxi_import']['warnings']++;
373
  } else {
374
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing URLs for featured images...', 'pmxi_plugin'));
375
  $featured_images = array();
397
  } else {
398
  count($titles) and $featured_images = array_fill(0, count($titles), '');
399
  }
400
+ }
401
+
402
+ // Composing images suffix
403
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $this->options['auto_rename_images'] and $logger and call_user_func($logger, __('Composing images suffix...', 'pmxi_plugin'));
404
+ $auto_rename_images = array();
405
+ if ( $this->options['auto_rename_images'] and ! empty($this->options['auto_rename_images_suffix'])){
406
+ $auto_rename_images = XmlImportParser::factory($xml, $this->xpath, $this->options['auto_rename_images_suffix'], $file)->parse($records); $tmp_files[] = $file;
407
+ }
408
+ else{
409
+ count($titles) and $auto_rename_images = array_fill(0, count($titles), '');
410
  }
411
 
412
  // serialized attachments
413
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
414
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
415
  $logger and call_user_func($logger, __('<b>WARNING</b>: No attachments will be created', 'pmxi_plugin'));
416
+ PMXI_Plugin::$session['pmxi_import']['warnings']++;
417
  } else {
418
  ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing URLs for attachments files...', 'pmxi_plugin'));
419
  $attachments = array();
466
  $current_post_ids = array();
467
  foreach ($titles as $i => $void) {
468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  if (empty($titles[$i])) {
470
  if (class_exists('PMWI_Plugin') and !empty($single_product_parent_ID[$i])){
471
  $titles[$i] = $single_product_parent_ID[$i] . ' Product Variation';
472
  }
473
+ else{
474
+ $logger and call_user_func($logger, __('<b>SKIPPED</b>: by empty title', 'pmxi_plugin'));
475
+ PMXI_Plugin::$session['pmxi_import']['chunk_number'] = PMXI_Plugin::$session->data['pmxi_import']['chunk_number']++;
476
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
477
+ $this->set(array(
478
+ 'skipped' => $this->skipped + 1
479
+ ))->save();
480
+ PMXI_Plugin::$session['pmxi_import']['skipped_records'] = $this->skipped;
481
+ continue;
 
 
482
  }
483
  }
484
 
487
  'post_status' => $this->options['status'],
488
  'comment_status' => $this->options['comment_status'],
489
  'ping_status' => $this->options['ping_status'],
490
+ 'post_title' => ($this->template['fix_characters']) ? utf8_encode(( ! $legacy_handling) ? html_entity_decode($titles[$i]) : htmlspecialchars_decode($titles[$i])) : (($this->template['is_leave_html']) ? (( ! $legacy_handling) ? html_entity_decode($titles[$i]) : htmlspecialchars_decode($titles[$i])) : $titles[$i]),
491
+ 'post_excerpt' => ($this->template['fix_characters']) ? utf8_encode(( ! $legacy_handling) ? html_entity_decode($post_excerpt[$i]) : htmlspecialchars_decode($post_excerpt[$i])) : (($this->template['is_leave_html']) ? (( ! $legacy_handling) ? html_entity_decode($post_excerpt[$i]) : htmlspecialchars_decode($post_excerpt[$i])) : $post_excerpt[$i]),
492
  'post_name' => $post_slug[$i],
493
+ 'post_content' => ($this->template['fix_characters']) ? utf8_encode(( ! $legacy_handling) ? html_entity_decode($contents[$i]) : htmlspecialchars_decode($contents[$i])) : (($this->template['is_leave_html']) ? (( ! $legacy_handling) ? html_entity_decode($contents[$i]) : htmlspecialchars_decode($contents[$i])) : $contents[$i]),
494
  'post_date' => $dates[$i],
495
  'post_date_gmt' => get_gmt_from_date($dates[$i]),
496
  'post_author' => $post_author[$i] ,
549
  if ($post_to_update){
550
  // Do not update already existing records option selected
551
  if ("yes" == $this->options['is_keep_former_posts']) {
552
+
553
+ $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
554
+ $tmp_array[] = $post_to_update_id;
555
+ $this->set(array(
556
+ 'current_post_ids' => json_encode($tmp_array)
557
+ ))->save();
558
+
 
559
  // Do not update product variations
560
  if ($post_type == "product" and class_exists('PMWI_Plugin')){
561
 
569
 
570
  if ( $children ) {
571
  foreach ( $children as $child ) {
572
+
573
+ $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
574
+ $tmp_array[] = $child;
575
+ $this->set(array(
576
+ 'current_post_ids' => json_encode($tmp_array)
577
+ ))->save();
578
+
 
579
  }
580
  }
581
+ }
582
+ $this->set(array(
583
+ 'skipped' => $this->skipped + 1
584
+ ))->save();
585
+ PMXI_Plugin::$session['pmxi_import']['skipped_records'] = $this->skipped;
586
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'pmxi_plugin'), $articleData['post_title']));
587
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
588
  if ( ! $is_cron ){
589
+ $records_count = $this->created + $this->updated + $this->skipped + PMXI_Plugin::$session->data['pmxi_import']['errors'];
590
+ $progress_msg = '<p class="import_process_bar"> ' . __('Created', 'pmxi_plugin') . ' ' . $this->created . ' / ' . __('Updated','pmxi_plugin') . ' ' . $this->updated . ' of '. PMXI_Plugin::$session->data['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/PMXI_Plugin::$session->data['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . PMXI_Plugin::$session->data['pmxi_import']['warnings'] . '</span><span class="errors_count">' . PMXI_Plugin::$session->data['pmxi_import']['errors'] . '</span>';
591
  $logger and call_user_func($logger, $progress_msg);
592
  }
593
+ PMXI_Plugin::$session['pmxi_import']['chunk_number']++;
594
  continue;
595
+ }
596
+
597
  $articleData['ID'] = $post_to_update_id;
598
  // preserve date of already existing article when duplicate is found
599
  if ($this->options['is_keep_categories']) { // preserve categories and tags of already existing article if corresponding setting is specified
600
  $cats_list = get_the_category($articleData['ID']);
601
+ $existing_cats = array();
602
  if (is_wp_error($cats_list)) {
603
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current categories for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
604
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
605
  } else {
606
  $cats_new = array();
607
  foreach ($cats_list as $c) {
608
+ $cats_new[] = $c->slug;
609
  }
610
+ $existing_cats[$i] = $cats_new;
611
  }
612
 
613
  $tags_list = get_the_tags($articleData['ID']);
614
  if (is_wp_error($tags_list)) {
615
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current tags for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
616
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
617
  } else {
618
  $tags_new = array();
619
  if ($tags_list) foreach ($tags_list as $t) {
621
  }
622
  $articleData['tags_input'] = implode(', ', $tags_new);
623
  }
624
+ $existing_taxonomies = array();
625
  foreach (array_keys($taxonomies) as $tx_name) {
626
  $txes_list = get_the_terms($articleData['ID'], $tx_name);
627
  if (is_wp_error($txes_list)) {
628
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current taxonomies for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
629
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
630
  } else {
631
  $txes_new = array();
632
  if (!empty($txes_list)):
633
  foreach ($txes_list as $t) {
634
+ $txes_new[] = $t->slug;
635
  }
636
  endif;
637
+ $existing_taxonomies[$tx_name][$i] = $txes_new;
638
  }
639
  }
640
  }
657
  if ($this->options['is_keep_menu_order']){
658
  $articleData['menu_order'] = $post_to_update->menu_order;
659
  }
660
+ if ($this->options['is_keep_parent']){
661
+ $articleData['post_parent'] = $post_to_update->post_parent;
662
+ }
663
  // handle obsolete attachments (i.e. delete or keep) according to import settings
664
+ if ( ! $this->options['is_keep_images'] and ! $this->options['is_keep_attachments_on_update'] and ! $this->options['no_create_featured_image'] ){
665
  wp_delete_attachments($articleData['ID']);
666
  }
667
+
668
  }
669
  elseif ( ! $postRecord->isEmpty() ){
670
 
675
 
676
  // no new records are created. it will only update posts it finds matching duplicates for
677
  if ($this->options['not_create_records'] and empty($articleData['ID'])){
678
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
679
+ $this->set(array(
680
+ 'skipped' => $this->skipped + 1
681
+ ))->save();
682
+ PMXI_Plugin::$session['pmxi_import']['skipped_records'] = $this->skipped;
683
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: by "Not add new records" option for `%s`', 'pmxi_plugin'), $articleData['post_title']));
684
  if ( ! $is_cron ){
685
+ $records_count = $this->created + $this->updated + $this->skipped + PMXI_Plugin::$session->data['pmxi_import']['errors'];
686
+ $progress_msg = '<p class="import_process_bar"> '. __('Created','pmxi_plugin') . ' ' . $this->created . ' / ' . __('Updated','pmxi_plugin') . ' ' . $this->updated . ' of '. PMXI_Plugin::$session->data['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/PMXI_Plugin::$session->data['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . PMXI_Plugin::$session->data['pmxi_import']['warnings'] . '</span><span class="errors_count">' . PMXI_Plugin::$session->data['pmxi_import']['errors'] . '</span>';
687
  $logger and call_user_func($logger, $progress_msg);
688
  }
689
+ PMXI_Plugin::$session['pmxi_import']['chunk_number'] = PMXI_Plugin::$session->data['pmxi_import']['chunk_number']++;
690
  continue;
691
  }
692
 
755
  $dest->insert();
756
  } else {
757
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create cloaked link for %s', 'pmxi_plugin'), $url));
758
+ PMXI_Plugin::$session['pmxi_import']['warnings']++;
759
  $link = NULL;
760
  }
761
  }
772
 
773
  if (is_wp_error($pid)) {
774
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
775
+ PMXI_Plugin::$session['pmxi_import']['errors'] = PMXI_Plugin::$session->data['pmxi_import']['errors']++;
776
  } else {
777
 
778
+ $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
779
+ $tmp_array[] = $pid;
780
+ $this->set(array(
781
+ 'current_post_ids' => json_encode($tmp_array)
782
+ ))->save();
783
+
 
 
784
  if ("manual" != $this->options['duplicate_matching'] or empty($articleData['ID'])){
785
  // associate post with import
786
  $postRecord->isEmpty() and $postRecord->set(array(
787
  'post_id' => $pid,
788
  'import_id' => $this->id,
789
+ 'unique_key' => $unique_keys[$i],
790
+ 'product_key' => (class_exists('PMWI_Plugin')) ? $single_product_ID[$i] : ''
791
  ))->insert();
792
+ }
793
 
794
  // Woocommerce add-on
795
  if ( $post_type == "product" and class_exists('PMWI_Plugin')){
802
 
803
  // [featured image]
804
  if ( ! empty($uploads) and false === $uploads['error'] and !empty($featured_images[$i]) and (empty($articleData['ID']) or empty($this->options['is_keep_images']))) {
805
+
806
+ require_once(ABSPATH . 'wp-admin/includes/image.php');
807
+
808
+ if ( ! is_array($featured_images[$i]) ) $featured_images[$i] = array($featured_images[$i]);
809
+ $post_thumbnail = false;
810
+ $success_images = false;
811
+ $gallery_attachment_ids = array();
812
+ foreach ($featured_images[$i] as $featured_image)
813
+ {
814
+ $imgs = str_getcsv($featured_image, $this->options['featured_delim']);
815
+ if (!empty($imgs)) {
816
+ foreach ($imgs as $img_url) { if (empty($img_url)) continue;
817
+ $create_image = false;
818
+ $download_image = true;
819
+ if (base64_decode($img_url, true) !== false){
820
+ $img = @imagecreatefromstring(base64_decode($img_url));
821
+ if($img)
822
+ {
823
+ $image_filename = md5(time()) . '.jpg';
824
+ $image_filepath = $uploads['path'] . '/' . $image_filename;
825
+ imagejpeg($img, $image_filepath);
826
+ if( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
827
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $image_filepath));
828
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
829
+ } else {
830
+ $create_image = true;
831
+ }
832
+ }
833
+ }
834
+ else {
835
 
836
+ $img_ext = pmxi_get_remote_image_ext($img_url);
837
+
838
+ $image_name = (($this->options['auto_rename_images'] and "" != $auto_rename_images[$i]) ? url_title($auto_rename_images[$i] . '_' . (($this->options['images_name'] != 'auto') ? basename($img_url) : uniqid())) : (($this->options['images_name'] != 'auto') ? basename($img_url) : uniqid())) . (("" != $img_ext and $this->options['images_name'] == 'auto') ? '.'.$img_ext : '');
839
+ $image_filename = wp_unique_filename($uploads['path'], $image_name);
840
+ $image_filepath = $uploads['path'] . '/' . url_title($image_filename);
841
+
842
+ // keep existing and add newest images
843
+ if ( $this->options['no_create_featured_image'] ){
844
+ $attachment_imgs = get_posts( array(
845
+ 'post_type' => 'attachment',
846
+ 'posts_per_page' => -1,
847
+ 'post_parent' => $pid,
848
+ ) );
849
+
850
+ if ( $attachment_imgs ) {
851
+ foreach ( $attachment_imgs as $attachment_img ) {
852
+ if ($attachment_img->guid == $uploads['url'] . '/' . $image_name){
853
+ $download_image = false;
854
+ $logger and call_user_func($logger, sprintf(__('<b>Image SKIPPED</b>: The image %s is always exists for the %s', 'pmxi_plugin'), basename($attachment_img->guid), $articleData['post_title']));
855
+ }
856
+ }
857
+
858
+ }
859
+ }
860
+
861
+ if ($download_image){
 
 
 
 
 
 
 
 
 
 
 
 
862
 
863
  $img_url = str_replace(" ", "%20", trim($img_url));
864
 
865
  if ( ! get_file_curl($img_url, $image_filepath) and ! @file_put_contents($image_filepath, @file_get_contents($img_url))) {
866
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: File %s cannot be saved locally as %s', 'pmxi_plugin'), $img_url, $image_filepath));
867
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
868
  unlink($image_filepath); // delete file since failed upload may result in empty file created
869
  } elseif( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
870
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $img_url));
871
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
872
  } else {
873
  $create_image = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
874
  }
875
+ }
876
+ }
877
+
878
+ if ($create_image){
879
+ $attachment = array(
880
+ 'post_mime_type' => image_type_to_mime_type($image_info[2]),
881
+ 'guid' => $uploads['url'] . '/' . $image_filename,
882
+ 'post_title' => $image_filename,
883
+ 'post_content' => '',
884
+ );
885
+ if (($image_meta = wp_read_image_metadata($image_filepath))) {
886
+ if (trim($image_meta['title']) && ! is_numeric(sanitize_title($image_meta['title'])))
887
+ $attachment['post_title'] = $image_meta['title'];
888
+ if (trim($image_meta['caption']))
889
+ $attachment['post_content'] = $image_meta['caption'];
890
+ }
891
+ $attid = wp_insert_attachment($attachment, $image_filepath, $pid);
892
+ if (is_wp_error($attid)) {
893
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
894
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
895
+ } else {
896
+ // you must first include the image.php file
897
+ // for the function wp_generate_attachment_metadata() to work
898
+ require_once(ABSPATH . 'wp-admin/includes/image.php');
899
+ wp_update_attachment_metadata($attid, wp_generate_attachment_metadata($attid, $image_filepath));
900
+ $success_images = true;
901
+ if ( ! $post_thumbnail ) {
902
+ if ( ! $this->options['no_create_featured_image'] or ! has_post_thumbnail($pid)){
903
+ set_post_thumbnail($pid, $attid);
904
+ $post_thumbnail = true;
905
  }
906
+ else $gallery_attachment_ids[] = $attid;
907
  }
908
+ else $gallery_attachment_ids[] = $attid;
909
+ }
910
+ }
911
+ }
912
  }
 
 
 
 
 
913
  }
914
+ // Set product gallery images
915
+ if ( $post_type == "product" and class_exists('PMWI_Plugin') and !empty($gallery_attachment_ids))
916
+ update_post_meta($pid, '_product_image_gallery', implode(',', $gallery_attachment_ids));
917
+ // Create entry as Draft if no images are downloaded successfully
918
+ if ( ! $success_images and "yes" == $this->options['create_draft'] ) wp_update_post(array('ID' => $pid, 'post_status' => 'draft'));
919
  }
920
  // [/featured image]
921
 
938
  $attachment_filename = wp_unique_filename($uploads['path'], basename(parse_url(trim($atch_url), PHP_URL_PATH)));
939
  $attachment_filepath = $uploads['path'] . '/' . url_title($attachment_filename);
940
 
941
+ if ( ! get_file_curl(trim($atch_url), $attachment_filepath) and ! @file_put_contents($attachment_filepath, @file_get_contents(trim($atch_url)))) {
942
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Attachment file %s cannot be saved locally as %s', 'pmxi_plugin'), trim($atch_url), $attachment_filepath));
943
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
944
  unlink($attachment_filepath); // delete file since failed upload may result in empty file created
945
  } elseif( ! $wp_filetype = wp_check_filetype(basename($attachment_filename), null )) {
946
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Can\'t detect attachment file type %s', 'pmxi_plugin'), trim($atch_url)));
947
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
948
  } else {
949
 
950
  $attachment_data = array(
951
+ 'guid' => $uploads['baseurl'] . '/' . _wp_relative_upload_path( $attachment_filepath ),
952
  'post_mime_type' => $wp_filetype['type'],
953
  'post_title' => preg_replace('/\.[^.]+$/', '', basename($attachment_filepath)),
954
  'post_content' => '',
958
 
959
  if (is_wp_error($attach_id)) {
960
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
961
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
962
  } else {
963
  wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attachment_filepath));
964
  }
970
  // [/attachments]
971
 
972
  // [custom taxonomies]
973
+ if (!empty($taxonomies)){
974
+
975
+ foreach ($taxonomies as $tx_name => $txes) {
976
+
977
+ if ( empty($articleData['ID']) or !$this->options['is_keep_categories'] or ( $this->options['is_keep_categories'] and $this->options['is_add_newest_categories'] ) ){
978
 
979
+ $assign_taxes = array();
980
 
981
+ if ($this->options['is_add_newest_categories'] and !empty($existing_taxonomies[$tx_name][$i])){
982
+ $assign_taxes = $existing_taxonomies[$tx_name][$i];
983
+ unset($existing_taxonomies[$tx_name][$i]);
984
+ }
985
 
986
+ // create term if not exists
987
+ foreach ($txes[$i] as $key => $single_tax) {
988
+ if (is_array($single_tax)){
989
 
990
+ $parent_id = (!empty($single_tax['parent'])) ? $this->recursion_taxes($single_tax['parent'], $tx_name, $txes[$i], $key) : '';
991
 
992
+ $term = term_exists( trim(htmlspecialchars($single_tax['name'])), $tx_name, $parent_id );
993
+
994
+ if ( empty($term) and !is_wp_error($term) ){
995
+ $term_attr = array('parent'=> (!empty($parent_id)) ? $parent_id : 0);
996
+ $term = wp_insert_term(
997
+ $single_tax['name'], // the term
998
+ $tx_name, // the taxonomy
999
+ $term_attr
1000
+ );
1001
+ }
1002
+
1003
+ if ( is_wp_error($term) ){
1004
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: `%s`', 'pmxi_plugin'), $term->get_error_message()));
1005
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
1006
+ }
1007
+ elseif (!empty($term)) {
1008
+ $cat_id = $term['term_id'];
1009
+ if ($cat_id and $single_tax['assign'])
1010
+ {
1011
+ $term = get_term_by('id', $cat_id, $tx_name);
1012
+ $assign_taxes[] = $term->slug;
1013
+ }
1014
+ }
1015
+ }
1016
+ }
1017
+ // associate taxes with post
1018
+ $term_ids = wp_set_object_terms($pid, $assign_taxes, $tx_name);
1019
+ if (is_wp_error($term_ids)) {
1020
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$term_ids->get_error_message());
1021
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
1022
  }
 
 
 
 
 
 
 
 
1023
  }
1024
  }
1025
+ if (!empty($existing_taxonomies) and $this->options['is_keep_categories'] and $this->options['is_add_newest_categories']) {
1026
+ foreach ($existing_taxonomies as $tx_name => $txes) {
1027
+ if (!empty($txes[$i])){
1028
+ $term_ids = wp_set_object_terms($pid, $txes[$i], $tx_name);
1029
+ if (is_wp_error($term_ids)) {
1030
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$term_ids->get_error_message());
1031
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
1032
+ }
1033
+ }
1034
+ }
1035
  }
1036
+ }
1037
  // [/custom taxonomies]
1038
 
1039
  // [categories]
1040
+ if (!empty($cats[$i])) {
1041
+
1042
+ if ( empty($articleData['ID']) or !$this->options['is_keep_categories'] or ( $this->options['is_keep_categories'] and $this->options['is_add_newest_categories'] ) ){
1043
 
1044
+ wp_set_object_terms( $pid, NULL, 'category' );
1045
 
1046
+ $assign_cats = array();
 
 
1047
 
1048
+ if ($this->options['is_add_newest_categories'] and !empty($existing_cats[$i])){
1049
+ $assign_cats = $existing_cats[$i];
1050
+ unset($existing_cats[$i]);
1051
+ }
1052
 
1053
+ // create categories if it's doesn't exists
1054
+ foreach ($cats[$i] as $key => $single_cat) {
1055
 
1056
+ if (is_array($single_cat)){
1057
 
1058
+ $parent_id = (!empty($single_cat['parent'])) ? $this->recursion_taxes($single_cat['parent'], 'category', $cats[$i], $key) : '';
1059
+
1060
+ $term = term_exists( trim(htmlspecialchars($single_cat['name'])), 'category', $parent_id );
1061
+
1062
+ if ( empty($term) and !is_wp_error($term) ){
1063
+ $term_attr = array('parent'=> (!empty($parent_id)) ? $parent_id : 0);
1064
+ $term = wp_insert_term(
1065
+ $single_cat['name'], // the term
1066
+ 'category', // the taxonomy
1067
+ $term_attr
1068
+ );
1069
+ }
1070
+
1071
+ if ( is_wp_error($term) ){
1072
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: `%s`', 'pmxi_plugin'), $term->get_error_message()));
1073
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
1074
+ }
1075
+ elseif ( ! empty($term) ) {
1076
+ $cat_id = $term['term_id'];
1077
+ if ($cat_id and $single_cat['assign'])
1078
+ {
1079
+ $term = get_term_by('id', $cat_id, 'category');
1080
+ if ( ! in_array($term->slug, $assign_cats)) $assign_cats[] = $term->slug;
1081
+ }
1082
  }
1083
+ }
1084
+ }
 
1085
 
1086
+ // associate categories with post
1087
+ $cats_ids = wp_set_object_terms($pid, $assign_cats, 'category');
1088
+ if (is_wp_error($cats_ids)) {
1089
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$cats_ids->get_error_message());
1090
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
1091
+ }
1092
+ }
1093
+ }
1094
+
1095
+ if (!empty($existing_cats[$i]) and $this->options['is_keep_categories']) {
1096
+ $cats_ids = wp_set_object_terms($pid, $existing_cats[$i], 'category');
1097
+
1098
  if (is_wp_error($cats_ids)) {
1099
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$cats_ids->get_error_message());
1100
+ PMXI_Plugin::$session['pmxi_import']['warnings'] = PMXI_Plugin::$session->data['pmxi_import']['warnings']++;
1101
  }
1102
  }
1103
  // [/categories]
1104
 
1105
  if (empty($articleData['ID'])) {
1106
+ PMXI_Plugin::$session['pmxi_import']['created_records'] = $this->created + 1;
1107
  $logger and call_user_func($logger, sprintf(__('`%s` post created successfully', 'pmxi_plugin'), $articleData['post_title']));
1108
  } else {
1109
+ PMXI_Plugin::$session['pmxi_import']['updated_records'] = $this->updated + 1;
1110
  $logger and call_user_func($logger, sprintf(__('`%s` post updated successfully', 'pmxi_plugin'), $articleData['post_title']));
1111
  }
1112
+
1113
  do_action( 'pmxi_saved_post', $pid); // hook that was triggered immediately after post saved
1114
 
1115
+ if ($this->large_import == 'Yes' and $chunk){
1116
+ $this->set(array(
1117
+ 'imported' => $this->imported + 1,
1118
+ 'created' => (empty($articleData['ID'])) ? $this->created + 1 : $this->created,
1119
+ 'updated' => (empty($articleData['ID'])) ? $this->updated : $this->updated + 1
1120
+ ))->save();
1121
+ PMXI_Plugin::$session['pmxi_import']['chunk_number'] = PMXI_Plugin::$session->data['pmxi_import']['chunk_number']++;
1122
+ }
1123
+
1124
  $records_count = 0;
1125
 
1126
  // Time Elapsed
1127
  if ( ! $is_cron){
1128
 
1129
+ if ($this->large_import == 'No') PMXI_Plugin::$session['pmxi_import']['count'] = count($titles);
1130
 
1131
+ $records_count = $this->created + $this->updated + $this->skipped + PMXI_Plugin::$session->data['pmxi_import']['errors'];
1132
 
1133
+ $progress_msg = '<p class="import_process_bar"> '.__('Created','pmxi_plugin'). ' ' . $this->created . ' / '.__('Updated','pmxi_plugin') . ' ' . $this->updated . ' of '. PMXI_Plugin::$session->data['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/PMXI_Plugin::$session->data['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . PMXI_Plugin::$session->data['pmxi_import']['warnings'] . '</span><span class="errors_count">' . PMXI_Plugin::$session->data['pmxi_import']['errors'] . '</span>';
1134
  $logger and call_user_func($logger, $progress_msg);
1135
  }
1136
 
1137
+ }
 
 
 
 
 
 
 
 
 
1138
 
1139
  wp_cache_flush();
1140
+ }
1141
+
1142
+ $is_import_complete = ($records_count == PMXI_Plugin::$session->data['pmxi_import']['count']);
1143
+
1144
+ if ( ! $is_cron and $is_import_complete and ! empty($this->options['is_delete_missing'])) { // delete posts which are not in current import set
1145
+
1146
  $logger and call_user_func($logger, 'Removing previously imported posts which are no longer actual...');
1147
  $postList = new PMXI_Post_List();
1148
+ $current_post_ids = (empty($this->current_post_ids)) ? array() : json_decode($this->current_post_ids, true);
1149
+
1150
  $missing_ids = array();
1151
+ foreach ($postList->getBy(array('import_id' => $this->id, 'post_id NOT IN' => $current_post_ids)) as $missingPost) {
1152
  empty($this->options['is_keep_attachments']) and wp_delete_attachments($missingPost['post_id']);
1153
  $missing_ids[] = $missingPost['post_id'];
1154
 
1171
  $this->wpdb->query(
1172
  $this->wpdb->prepare($sql, '')
1173
  );
1174
+ }
1175
+
1176
+ }
1177
+
1178
+ // Set out of stock status for missing records [Woocommerce add-on option]
1179
+ if ( ! $is_cron and $is_import_complete and empty($this->options['is_delete_missing']) and $post_type == "product" and class_exists('PMWI_Plugin') and !empty($this->options['missing_records_stock_status'])) {
1180
+
1181
+ $logger and call_user_func($logger, 'Update stock status previously imported posts which are no longer actual...');
1182
+ $postList = new PMXI_Post_List();
1183
+ $current_post_ids = (empty($this->current_post_ids)) ? array() : json_decode($this->current_post_ids, true);
1184
+ foreach ($postList->getBy(array('import_id' => $this->id, 'post_id NOT IN' => $current_post_ids)) as $missingPost) {
1185
+ update_post_meta( $missingPost['post_id'], '_stock_status', 'outofstock' );
1186
+ update_post_meta( $missingPost['post_id'], '_stock', 0 );
1187
+ }
1188
+
1189
+ }
1190
+
1191
+ if ( ! $is_cron and $is_import_complete and empty($this->options['is_delete_missing']) and $this->options['is_update_missing_cf'] ) {
1192
+
1193
+ $logger and call_user_func($logger, 'Update custom fields previously imported posts which are no longer actual...');
1194
+ $postList = new PMXI_Post_List();
1195
+ $current_post_ids = (empty($this->current_post_ids)) ? array() : json_decode($this->current_post_ids, true);
1196
+ foreach ($postList->getBy(array('import_id' => $this->id, 'post_id NOT IN' => $current_post_ids)) as $missingPost) {
1197
+ update_post_meta( $missingPost['post_id'], $this->options['update_missing_cf_name'], $this->options['update_missing_cf_value'] );
1198
  }
1199
 
1200
  }
1201
 
1202
  } catch (XmlImportException $e) {
1203
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $e->getMessage());
1204
+ PMXI_Plugin::$session['pmxi_import']['errors'] = PMXI_Plugin::$session->data['pmxi_import']['errors']++;
1205
  }
1206
 
1207
  $this->set('registered_on', date('Y-m-d H:i:s'))->save(); // specify execution is successful
1208
 
1209
+ !$is_cron and $is_import_complete and $logger and call_user_func($logger, __('Cleaning temporary data...', 'pmxi_plugin'));
1210
  foreach ($tmp_files as $file) { // remove all temporary files created
1211
  unlink($file);
1212
  }
1213
 
1214
+ if (($is_cron or $is_import_complete) and $this->options['is_delete_source']) {
1215
  $logger and call_user_func($logger, __('Deleting source XML file...', 'pmxi_plugin'));
1216
  if ( ! @unlink($this->path)) {
1217
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to remove %s', 'pmxi_plugin'), $this->path));
1218
  }
1219
  }
1220
+ if ( ! $is_cron and $is_import_complete ){
1221
+ $this->set(array(
1222
+ 'processing' => 0,
1223
+ 'triggered' => 0,
1224
+ 'queue_chunk_number' => 0,
1225
+ 'current_post_ids' => ''
1226
+ ))->save();
1227
+ $logger and call_user_func($logger, 'Done');
1228
+ }
1229
 
1230
  remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
1231
 
models/model.php CHANGED
@@ -1,198 +1,198 @@
1
- <?php
2
- /**
3
- * Base class for models
4
- *
5
- * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
- */
7
- abstract class PMXI_Model extends ArrayObject {
8
- /**
9
- * WPDB instance
10
- * @var wpdb
11
- */
12
- protected $wpdb;
13
- /**
14
- * Table name the model is linked to
15
- * @var string
16
- */
17
- protected $table;
18
- /**
19
- * Array of columns representing primary key
20
- * @var array
21
- */
22
- protected $primary = array('id');
23
- /**
24
- * Wether key field is auto_increment (sure make scence only if key s
25
- * @var bool
26
- */
27
- protected $auto_increment = FALSE;
28
-
29
- /**
30
- * Cached data retrieved from database
31
- * @var array
32
- */
33
- private static $meta_cache = array();
34
-
35
- /**
36
- * Initialize model
37
- * @param array[optional] $data Array of record data to initialize object with
38
- */
39
- public function __construct() {
40
- $this->wpdb = $GLOBALS['wpdb'];
41
- }
42
-
43
- /**
44
- * Read records from database by specified fields and values
45
- * When 1st parameter is an array, it expected to be an associative array of field => value pairs to read data by
46
- * If 2 parameters are set, first one is expected to be a field name and second - it's value
47
- *
48
- * @param string|array $field
49
- * @param mixed[optional] $value
50
- * @return PMXI_Model
51
- */
52
- abstract public function getBy($field = NULL, $value = NULL);
53
-
54
- /**
55
- * Magic function to automatically resolve calls like $obj->getBy%FIELD_NAME%
56
- * @param string $method
57
- * @param array $args
58
- * @return PMXI_Model
59
- */
60
- public function __call($method, $args) {
61
- if (preg_match('%^get_?by_?(.+)%i', $method, $mtch)) {
62
- array_unshift($args, $mtch[1]);
63
- return call_user_func_array(array($this, 'getBy'), $args);
64
- } else {
65
- throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
66
- }
67
- }
68
-
69
- /**
70
- * Bind model to database table
71
- * @param string $tableName
72
- * @return PMXI_Model
73
- */
74
- public function setTable($tableName) {
75
- if ( ! is_null($this->table)) {
76
- throw new Exception('Table name cannot be changed once being set.');
77
- }
78
- $this->table = $tableName;
79
- if ( ! isset(self::$meta_cache[$this->table])) {
80
- $tableMeta = $this->wpdb->get_results("SHOW COLUMNS FROM $this->table", ARRAY_A);
81
- $primary = array();
82
- $auto_increment = false;
83
- foreach ($tableMeta as $colMeta) {
84
- if ('PRI' == $colMeta['Key']) {
85
- $primary[] = $colMeta['Field'];
86
- }
87
- if ('auto_increment' == $colMeta['Extra']) {
88
- $auto_increment = true;
89
- break; // no point to iterate futher since auto_increment means corresponding primary key is simple
90
- }
91
- }
92
- self::$meta_cache[$this->table] = array('primary' => $primary, 'auto_increment' => $auto_increment);
93
- }
94
- $this->primary = self::$meta_cache[$this->table]['primary'];
95
- $this->auto_increment = self::$meta_cache[$this->table]['auto_increment'];
96
-
97
- return $this;
98
- }
99
-
100
- /**
101
- * Return database table name this object is bound to
102
- * @return string
103
- */
104
- public function getTable() {
105
- return $this->table;
106
- }
107
- /**
108
- * Return column name with table name
109
- * @param string $col
110
- * @return string
111
- */
112
- public function getFieldName($col) {
113
- return $this->table . '.' . $col;
114
- }
115
-
116
- /**
117
- * Compose WHERE clause based on parameters provided
118
- * @param string|array $field
119
- * @param mixed[optional] $value
120
- * @param string[optional] $operator AND or OR string, 'AND' by default
121
- * @return string
122
- */
123
- protected function buildWhere($field, $value = NULL, $operator = NULL) {
124
- if ( ! is_array($field)) {
125
- $field = array($field => $value);
126
- } else { // shift arguments
127
- $operator = $value;
128
- }
129
- ! is_null($operator) or $operator = 'AND'; // apply default operator value
130
-
131
- $where = array();
132
- foreach ($field as $key => $val) {
133
- if (is_int($key)) {
134
- $where[] = '(' . call_user_func_array(array($this, 'buildWhere'), $val) . ')';
135
- } else {
136
- if ( ! preg_match('%^(.+?) *(=|<>|!=|<|>|<=|>=| (NOT +)?(IN|(LIKE|REGEXP|RLIKE)( BINARY)?))?$%i', trim($key), $mtch)) {
137
- throw new Exception('Wrong field name format.');
138
- }
139
- $key = $mtch[1];
140
- if (is_array($val) and (empty($mtch[2]) or 'IN' == strtoupper($mtch[4]))) {
141
- $op = empty($mtch[2]) ? 'IN' : strtoupper(trim($mtch[2]));
142
- $where[] = $this->wpdb->prepare("$key $op (" . implode(', ', array_fill(0, count($val), "%s")) . ")", $val);
143
- } else {
144
- $op = empty($mtch[2]) ? '=' : strtoupper(trim($mtch[2]));
145
- $where[] = $this->wpdb->prepare("$key $op %s", $val);
146
- }
147
- }
148
- }
149
- return implode(" $operator ", $where);
150
- }
151
-
152
-
153
- /**
154
- * Return associative array with record data
155
- * @param bool[optional] $serialize Whether returned fields should be serialized
156
- * @return array
157
- */
158
- public function toArray($serialize = FALSE) {
159
- $result = (array)$this;
160
- if ($serialize) {
161
- foreach ($result as $k => $v) {
162
- if ( ! is_scalar($v)) {
163
- $result[$k] = serialize($v);
164
- }
165
- }
166
- }
167
- return $result;
168
- }
169
-
170
- /**
171
- * Check whether object data is empty
172
- * @return bool
173
- */
174
- public function isEmpty() {
175
- return $this->count() == 0;
176
- }
177
-
178
- /**
179
- * Empty object data
180
- * @return PMXI_Model
181
- */
182
- public function clear() {
183
- $this->exchangeArray(array());
184
- return $this;
185
- }
186
-
187
- /**
188
- * Delete all content from model's table
189
- * @return PMXI_Model
190
- */
191
- public function truncateTable() {
192
- if (FALSE !== $this->wpdb->query("TRUNCATE $this->table")) {
193
- return $this;
194
- } else {
195
- throw new Exception($this->wpdb->last_error);
196
- }
197
- }
198
  }
1
+ <?php
2
+ /**
3
+ * Base class for models
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ abstract class PMXI_Model extends ArrayObject {
8
+ /**
9
+ * WPDB instance
10
+ * @var wpdb
11
+ */
12
+ protected $wpdb;
13
+ /**
14
+ * Table name the model is linked to
15
+ * @var string
16
+ */
17
+ protected $table;
18
+ /**
19
+ * Array of columns representing primary key
20
+ * @var array
21
+ */
22
+ protected $primary = array('id');
23
+ /**
24
+ * Wether key field is auto_increment (sure make scence only if key s
25
+ * @var bool
26
+ */
27
+ protected $auto_increment = FALSE;
28
+
29
+ /**
30
+ * Cached data retrieved from database
31
+ * @var array
32
+ */
33
+ private static $meta_cache = array();
34
+
35
+ /**
36
+ * Initialize model
37
+ * @param array[optional] $data Array of record data to initialize object with
38
+ */
39
+ public function __construct() {
40
+ $this->wpdb = $GLOBALS['wpdb'];
41
+ }
42
+
43
+ /**
44
+ * Read records from database by specified fields and values
45
+ * When 1st parameter is an array, it expected to be an associative array of field => value pairs to read data by
46
+ * If 2 parameters are set, first one is expected to be a field name and second - it's value
47
+ *
48
+ * @param string|array $field
49
+ * @param mixed[optional] $value
50
+ * @return PMXI_Model
51
+ */
52
+ abstract public function getBy($field = NULL, $value = NULL);
53
+
54
+ /**
55
+ * Magic function to automatically resolve calls like $obj->getBy%FIELD_NAME%
56
+ * @param string $method
57
+ * @param array $args
58
+ * @return PMXI_Model
59
+ */
60
+ public function __call($method, $args) {
61
+ if (preg_match('%^get_?by_?(.+)%i', $method, $mtch)) {
62
+ array_unshift($args, $mtch[1]);
63
+ return call_user_func_array(array($this, 'getBy'), $args);
64
+ } else {
65
+ throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Bind model to database table
71
+ * @param string $tableName
72
+ * @return PMXI_Model
73
+ */
74
+ public function setTable($tableName) {
75
+ if ( ! is_null($this->table)) {
76
+ throw new Exception('Table name cannot be changed once being set.');
77
+ }
78
+ $this->table = $tableName;
79
+ if ( ! isset(self::$meta_cache[$this->table])) {
80
+ $tableMeta = $this->wpdb->get_results("SHOW COLUMNS FROM $this->table", ARRAY_A);
81
+ $primary = array();
82
+ $auto_increment = false;
83
+ foreach ($tableMeta as $colMeta) {
84
+ if ('PRI' == $colMeta['Key']) {
85
+ $primary[] = $colMeta['Field'];
86
+ }
87
+ if ('auto_increment' == $colMeta['Extra']) {
88
+ $auto_increment = true;
89
+ break; // no point to iterate futher since auto_increment means corresponding primary key is simple
90
+ }
91
+ }
92
+ self::$meta_cache[$this->table] = array('primary' => $primary, 'auto_increment' => $auto_increment);
93
+ }
94
+ $this->primary = self::$meta_cache[$this->table]['primary'];
95
+ $this->auto_increment = self::$meta_cache[$this->table]['auto_increment'];
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * Return database table name this object is bound to
102
+ * @return string
103
+ */
104
+ public function getTable() {
105
+ return $this->table;
106
+ }
107
+ /**
108
+ * Return column name with table name
109
+ * @param string $col
110
+ * @return string
111
+ */
112
+ public function getFieldName($col) {
113
+ return $this->table . '.' . $col;
114
+ }
115
+
116
+ /**
117
+ * Compose WHERE clause based on parameters provided
118
+ * @param string|array $field
119
+ * @param mixed[optional] $value
120
+ * @param string[optional] $operator AND or OR string, 'AND' by default
121
+ * @return string
122
+ */
123
+ protected function buildWhere($field, $value = NULL, $operator = NULL) {
124
+ if ( ! is_array($field)) {
125
+ $field = array($field => $value);
126
+ } else { // shift arguments
127
+ $operator = $value;
128
+ }
129
+ ! is_null($operator) or $operator = 'AND'; // apply default operator value
130
+
131
+ $where = array();
132
+ foreach ($field as $key => $val) {
133
+ if (is_int($key)) {
134
+ $where[] = '(' . call_user_func_array(array($this, 'buildWhere'), $val) . ')';
135
+ } else {
136
+ if ( ! preg_match('%^(.+?) *(=|<>|!=|<|>|<=|>=| (NOT +)?(IN|(LIKE|REGEXP|RLIKE)( BINARY)?))?$%i', trim($key), $mtch)) {
137
+ throw new Exception('Wrong field name format.');
138
+ }
139
+ $key = $mtch[1];
140
+ if (is_array($val) and (empty($mtch[2]) or 'IN' == strtoupper($mtch[4]))) {
141
+ $op = empty($mtch[2]) ? 'IN' : strtoupper(trim($mtch[2]));
142
+ if (count($val)) $where[] = $this->wpdb->prepare("$key $op (" . implode(', ', array_fill(0, count($val), "%s")) . ")", $val);
143
+ } else {
144
+ $op = empty($mtch[2]) ? '=' : strtoupper(trim($mtch[2]));
145
+ $where[] = $this->wpdb->prepare("$key $op %s", $val);
146
+ }
147
+ }
148
+ }
149
+ return implode(" $operator ", $where);
150
+ }
151
+
152
+
153
+ /**
154
+ * Return associative array with record data
155
+ * @param bool[optional] $serialize Whether returned fields should be serialized
156
+ * @return array
157
+ */
158
+ public function toArray($serialize = FALSE) {
159
+ $result = (array)$this;
160
+ if ($serialize) {
161
+ foreach ($result as $k => $v) {
162
+ if ( ! is_scalar($v)) {
163
+ $result[$k] = serialize($v);
164
+ }
165
+ }
166
+ }
167
+ return $result;
168
+ }
169
+
170
+ /**
171
+ * Check whether object data is empty
172
+ * @return bool
173
+ */
174
+ public function isEmpty() {
175
+ return $this->count() == 0;
176
+ }
177
+
178
+ /**
179
+ * Empty object data
180
+ * @return PMXI_Model
181
+ */
182
+ public function clear() {
183
+ $this->exchangeArray(array());
184
+ return $this;
185
+ }
186
+
187
+ /**
188
+ * Delete all content from model's table
189
+ * @return PMXI_Model
190
+ */
191
+ public function truncateTable() {
192
+ if (FALSE !== $this->wpdb->query("TRUNCATE $this->table")) {
193
+ return $this;
194
+ } else {
195
+ throw new Exception($this->wpdb->last_error);
196
+ }
197
+ }
198
  }
plugin.php CHANGED
@@ -6,6 +6,10 @@ Description: The most powerful solution for importing XML and CSV files to Word
6
  Version: 3.0.2
7
  Author: Soflyy
8
  */
 
 
 
 
9
  /**
10
  * Plugin root dir with forward slashes as directory separator regardless of actuall DIRECTORY_SEPARATOR value
11
  * @var string
@@ -73,6 +77,8 @@ final class PMXI_Plugin {
73
  */
74
  const LARGE_SIZE = 0; // all files will importing in large import mode
75
 
 
 
76
  /**
77
  * Return singletone instance
78
  * @return PMXI_Plugin
@@ -223,6 +229,23 @@ final class PMXI_Plugin {
223
  // register admin page pre-dispatcher
224
  add_action('admin_init', array($this, '__adminInit'));
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  $this->__add_feed_type_fix(); // feature to version 2.22
227
 
228
  }
@@ -402,12 +425,36 @@ final class PMXI_Plugin {
402
  // create/update required database tables
403
  require_once ABSPATH . 'wp-admin/includes/upgrade.php';
404
  require self::ROOT_DIR . '/schema.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  dbDelta($plugin_queries);
406
 
407
  $this->__ver_1_04_transition_fix();
408
 
409
  // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
410
- global $wpdb;
411
  $post = new PMXI_Post_Record();
412
  $wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
413
 
@@ -595,6 +642,12 @@ final class PMXI_Plugin {
595
  'custom_duplicate_value' => '',
596
  'duplicate_matching' => 'auto',
597
  'create_chunks' => 0,
 
 
 
 
 
 
598
  );
599
  }
600
 
6
  Version: 3.0.2
7
  Author: Soflyy
8
  */
9
+
10
+ if( ! defined( 'PMXI_SESSION_COOKIE' ) )
11
+ define( 'PMXI_SESSION_COOKIE', '_pmxi_session' );
12
+
13
  /**
14
  * Plugin root dir with forward slashes as directory separator regardless of actuall DIRECTORY_SEPARATOR value
15
  * @var string
77
  */
78
  const LARGE_SIZE = 0; // all files will importing in large import mode
79
 
80
+ public static $session;
81
+
82
  /**
83
  * Return singletone instance
84
  * @return PMXI_Plugin
229
  // register admin page pre-dispatcher
230
  add_action('admin_init', array($this, '__adminInit'));
231
 
232
+ global $wpdb;
233
+
234
+ if (function_exists('is_multisite') && is_multisite()) {
235
+ // check if it is a network activation - if so, run the activation function for each blog id
236
+ if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
237
+ $old_blog = $wpdb->blogid;
238
+ // Get all blog ids
239
+ $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
240
+ foreach ($blogids as $blog_id) {
241
+ switch_to_blog($blog_id);
242
+ $this->__add_feed_type_fix(); // feature to version 2.22
243
+ }
244
+ switch_to_blog($old_blog);
245
+ return;
246
+ }
247
+ }
248
+
249
  $this->__add_feed_type_fix(); // feature to version 2.22
250
 
251
  }
425
  // create/update required database tables
426
  require_once ABSPATH . 'wp-admin/includes/upgrade.php';
427
  require self::ROOT_DIR . '/schema.php';
428
+ global $wpdb;
429
+
430
+ if (function_exists('is_multisite') && is_multisite()) {
431
+ // check if it is a network activation - if so, run the activation function for each blog id
432
+ if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
433
+ $old_blog = $wpdb->blogid;
434
+ // Get all blog ids
435
+ $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
436
+ foreach ($blogids as $blog_id) {
437
+ switch_to_blog($blog_id);
438
+ require self::ROOT_DIR . '/schema.php';
439
+ dbDelta($plugin_queries);
440
+ $this->__ver_1_04_transition_fix();
441
+
442
+ // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
443
+
444
+ $post = new PMXI_Post_Record();
445
+ $wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
446
+ }
447
+ switch_to_blog($old_blog);
448
+ return;
449
+ }
450
+ }
451
+
452
  dbDelta($plugin_queries);
453
 
454
  $this->__ver_1_04_transition_fix();
455
 
456
  // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
457
+
458
  $post = new PMXI_Post_Record();
459
  $wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
460
 
642
  'custom_duplicate_value' => '',
643
  'duplicate_matching' => 'auto',
644
  'create_chunks' => 0,
645
+ 'update_missing_cf_name' => '',
646
+ 'update_missing_cf_value' => '',
647
+ 'auto_rename_images' => 0,
648
+ 'auto_rename_images_suffix' => '',
649
+ 'images_name' => 'auto',
650
+ 'is_add_newest_categories' => 0
651
  );
652
  }
653
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: soflyy
3
  Tags: wordpress, xml, csv, datafeed, import
4
  Requires at least: 3.5
5
  Tested up to: 3.5.2
6
- Stable tag: 3.0.2
7
 
8
  WP All Import is an extremely powerful plugin that makes it easy to import any XML or CSV file to WordPress.
9
 
@@ -85,8 +85,11 @@ Does it work with special character encoding like Hebrew, Arabic, Chinese, etc?
85
 
86
  == Changelog ==
87
 
 
 
 
88
  = 3.0.2 =
89
- * Free edition of 3.0 pro release with added support for the WooCommerce add-on
90
 
91
  = 3.0 =
92
  * Free edition of 3.0 pro release
3
  Tags: wordpress, xml, csv, datafeed, import
4
  Requires at least: 3.5
5
  Tested up to: 3.5.2
6
+ Stable tag: 3.0.3
7
 
8
  WP All Import is an extremely powerful plugin that makes it easy to import any XML or CSV file to WordPress.
9
 
85
 
86
  == Changelog ==
87
 
88
+ = 3.0.3 =
89
+ * Now using enhanced session functionality
90
+
91
  = 3.0.2 =
92
+ * Added support for the WooCommerce add-on
93
 
94
  = 3.0 =
95
  * Free edition of 3.0 pro release
schema.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin database schema
4
  * WARNING:
5
  * dbDelta() doesn't like empty lines in schema string, so don't put them there;
6
- * WPDB doesn't like NULL values so better not to have them in the tables;
7
  */
8
 
9
  /**
3
  * Plugin database schema
4
  * WARNING:
5
  * dbDelta() doesn't like empty lines in schema string, so don't put them there;
6
+ * WPDB doesn't like NULL values so better not to have them in the tables;
7
  */
8
 
9
  /**
static/js/jquery/css/redmond/jquery-ui.css CHANGED
@@ -1,1177 +1,1177 @@
1
- /*! jQuery UI - v1.10.0 - 2013-02-06
2
- * http://jqueryui.com
3
- * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
4
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
- * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
6
-
7
- /* Layout helpers
8
- ----------------------------------*/
9
- .ui-helper-hidden {
10
- display: none;
11
- }
12
- .ui-helper-hidden-accessible {
13
- border: 0;
14
- clip: rect(0 0 0 0);
15
- height: 1px;
16
- margin: -1px;
17
- overflow: hidden;
18
- padding: 0;
19
- position: absolute;
20
- width: 1px;
21
- }
22
- .ui-helper-reset {
23
- margin: 0;
24
- padding: 0;
25
- border: 0;
26
- outline: 0;
27
- line-height: 1.3;
28
- text-decoration: none;
29
- font-size: 100%;
30
- list-style: none;
31
- }
32
- .ui-helper-clearfix:before,
33
- .ui-helper-clearfix:after {
34
- content: "";
35
- display: table;
36
- }
37
- .ui-helper-clearfix:after {
38
- clear: both;
39
- }
40
- .ui-helper-clearfix {
41
- min-height: 0; /* support: IE7 */
42
- }
43
- .ui-helper-zfix {
44
- width: 100%;
45
- height: 100%;
46
- top: 0;
47
- left: 0;
48
- position: absolute;
49
- opacity: 0;
50
- filter:Alpha(Opacity=0);
51
- }
52
-
53
- .ui-front {
54
- z-index: 100;
55
- }
56
-
57
-
58
- /* Interaction Cues
59
- ----------------------------------*/
60
- .ui-state-disabled {
61
- cursor: default !important;
62
- }
63
-
64
-
65
- /* Icons
66
- ----------------------------------*/
67
-
68
- /* states and images */
69
- .ui-icon {
70
- display: block;
71
- text-indent: -99999px;
72
- overflow: hidden;
73
- background-repeat: no-repeat;
74
- }
75
-
76
-
77
- /* Misc visuals
78
- ----------------------------------*/
79
-
80
- /* Overlays */
81
- .ui-widget-overlay {
82
- position: fixed;
83
- top: 0;
84
- left: 0;
85
- width: 100%;
86
- height: 100%;
87
- }
88
- .ui-resizable {
89
- position: relative;
90
- }
91
- .ui-resizable-handle {
92
- position: absolute;
93
- font-size: 0.1px;
94
- display: block;
95
- }
96
- .ui-resizable-disabled .ui-resizable-handle,
97
- .ui-resizable-autohide .ui-resizable-handle {
98
- display: none;
99
- }
100
- .ui-resizable-n {
101
- cursor: n-resize;
102
- height: 7px;
103
- width: 100%;
104
- top: -5px;
105
- left: 0;
106
- }
107
- .ui-resizable-s {
108
- cursor: s-resize;
109
- height: 7px;
110
- width: 100%;
111
- bottom: -5px;
112
- left: 0;
113
- }
114
- .ui-resizable-e {
115
- cursor: e-resize;
116
- width: 7px;
117
- right: -5px;
118
- top: 0;
119
- height: 100%;
120
- }
121
- .ui-resizable-w {
122
- cursor: w-resize;
123
- width: 7px;
124
- left: -5px;
125
- top: 0;
126
- height: 100%;
127
- }
128
- .ui-resizable-se {
129
- cursor: se-resize;
130
- width: 12px;
131
- height: 12px;
132
- right: 1px;
133
- bottom: 1px;
134
- }
135
- .ui-resizable-sw {
136
- cursor: sw-resize;
137
- width: 9px;
138
- height: 9px;
139
- left: -5px;
140
- bottom: -5px;
141
- }
142
- .ui-resizable-nw {
143
- cursor: nw-resize;
144
- width: 9px;
145
- height: 9px;
146
- left: -5px;
147
- top: -5px;
148
- }
149
- .ui-resizable-ne {
150
- cursor: ne-resize;
151
- width: 9px;
152
- height: 9px;
153
- right: -5px;
154
- top: -5px;
155
- }
156
- .ui-selectable-helper {
157
- position: absolute;
158
- z-index: 100;
159
- border: 1px dotted black;
160
- }
161
- .ui-accordion .ui-accordion-header {
162
- display: block;
163
- cursor: pointer;
164
- position: relative;
165
- margin-top: 2px;
166
- padding: .5em .5em .5em .7em;
167
- min-height: 0; /* support: IE7 */
168
- }
169
- .ui-accordion .ui-accordion-icons {
170
- padding-left: 2.2em;
171
- }
172
- .ui-accordion .ui-accordion-noicons {
173
- padding-left: .7em;
174
- }
175
- .ui-accordion .ui-accordion-icons .ui-accordion-icons {
176
- padding-left: 2.2em;
177
- }
178
- .ui-accordion .ui-accordion-header .ui-accordion-header-icon {
179
- position: absolute;
180
- left: .5em;
181
- top: 50%;
182
- margin-top: -8px;
183
- }
184
- .ui-accordion .ui-accordion-content {
185
- padding: 1em 2.2em;
186
- border-top: 0;
187
- overflow: auto;
188
- }
189
- .ui-autocomplete {
190
- position: absolute;
191
- top: 0;
192
- left: 0;
193
- cursor: default;
194
- }
195
- .ui-button {
196
- display: inline-block;
197
- position: relative;
198
- padding: 0;
199
- line-height: normal;
200
- margin-right: .1em;
201
- cursor: pointer;
202
- vertical-align: middle;
203
- text-align: center;
204
- overflow: visible; /* removes extra width in IE */
205
- }
206
- .ui-button,
207
- .ui-button:visited,
208
- .ui-button:hover,
209
- .ui-button:active,
210
- .large_button:hover {
211
- background: url("images/ui-bg_glass_75_d0e5f5_1x400.png") repeat-x scroll 50% 50% #D0E5F5;
212
- border: 1px solid #79B7E7;
213
- color: #1D5987;
214
- font-weight: bold;
215
- }
216
- /* to make room for the icon, a width needs to be set here */
217
- .ui-button-icon-only {
218
- width: 2.2em;
219
- }
220
- /* button elements seem to need a little more width */
221
- button.ui-button-icon-only {
222
- width: 2.4em;
223
- }
224
- .ui-button-icons-only {
225
- width: 3.4em;
226
- }
227
- button.ui-button-icons-only {
228
- width: 3.7em;
229
- }
230
-
231
- /* button text element */
232
- .ui-button .ui-button-text {
233
- display: block;
234
- line-height: normal;
235
- }
236
- .ui-button-text-only .ui-button-text {
237
- padding: .4em 1em;
238
- }
239
- .ui-button-icon-only .ui-button-text,
240
- .ui-button-icons-only .ui-button-text {
241
- padding: .4em;
242
- text-indent: -9999999px;
243
- }
244
- .ui-button-text-icon-primary .ui-button-text,
245
- .ui-button-text-icons .ui-button-text {
246
- padding: .4em 1em .4em 2.1em;
247
- }
248
- .ui-button-text-icon-secondary .ui-button-text,
249
- .ui-button-text-icons .ui-button-text {
250
- padding: .4em 2.1em .4em 1em;
251
- }
252
- .ui-button-text-icons .ui-button-text {
253
- padding-left: 2.1em;
254
- padding-right: 2.1em;
255
- }
256
- /* no icon support for input elements, provide padding by default */
257
- input.ui-button {
258
- padding: .4em 1em;
259
- }
260
-
261
- /* button icon element(s) */
262
- .ui-button-icon-only .ui-icon,
263
- .ui-button-text-icon-primary .ui-icon,
264
- .ui-button-text-icon-secondary .ui-icon,
265
- .ui-button-text-icons .ui-icon,
266
- .ui-button-icons-only .ui-icon {
267
- position: absolute;
268
- top: 50%;
269
- margin-top: -8px;
270
- }
271
- .ui-button-icon-only .ui-icon {
272
- left: 50%;
273
- margin-left: -8px;
274
- }
275
- .ui-button-text-icon-primary .ui-button-icon-primary,
276
- .ui-button-text-icons .ui-button-icon-primary,
277
- .ui-button-icons-only .ui-button-icon-primary {
278
- left: .5em;
279
- }
280
- .ui-button-text-icon-secondary .ui-button-icon-secondary,
281
- .ui-button-text-icons .ui-button-icon-secondary,
282
- .ui-button-icons-only .ui-button-icon-secondary {
283
- right: .5em;
284
- }
285
-
286
- /* button sets */
287
- .ui-buttonset {
288
- margin-right: 7px;
289
- }
290
- .ui-buttonset .ui-button {
291
- margin-left: 0;
292
- margin-right: -.3em;
293
- }
294
-
295
- /* workarounds */
296
- /* reset extra padding in Firefox, see h5bp.com/l */
297
- input.ui-button::-moz-focus-inner,
298
- button.ui-button::-moz-focus-inner {
299
- border: 0;
300
- padding: 0;
301
- }
302
- .ui-datepicker {
303
- width: 17em;
304
- padding: .2em .2em 0;
305
- display: none;
306
- }
307
- .ui-datepicker .ui-datepicker-header {
308
- position: relative;
309
- padding: .2em 0;
310
- }
311
- .ui-datepicker .ui-datepicker-prev,
312
- .ui-datepicker .ui-datepicker-next {
313
- position: absolute;
314
- top: 2px;
315
- width: 1.8em;
316
- height: 1.8em;
317
- }
318
- .ui-datepicker .ui-datepicker-prev-hover,
319
- .ui-datepicker .ui-datepicker-next-hover {
320
- top: 1px;
321
- }
322
- .ui-datepicker .ui-datepicker-prev {
323
- left: 2px;
324
- }
325
- .ui-datepicker .ui-datepicker-next {
326
- right: 2px;
327
- }
328
- .ui-datepicker .ui-datepicker-prev-hover {
329
- left: 1px;
330
- }
331
- .ui-datepicker .ui-datepicker-next-hover {
332
- right: 1px;
333
- }
334
- .ui-datepicker .ui-datepicker-prev span,
335
- .ui-datepicker .ui-datepicker-next span {
336
- display: block;
337
- position: absolute;
338
- left: 50%;
339
- margin-left: -8px;
340
- top: 50%;
341
- margin-top: -8px;
342
- }
343
- .ui-datepicker .ui-datepicker-title {
344
- margin: 0 2.3em;
345
- line-height: 1.8em;
346
- text-align: center;
347
- }
348
- .ui-datepicker .ui-datepicker-title select {
349
- font-size: 1em;
350
- margin: 1px 0;
351
- }
352
- .ui-datepicker select.ui-datepicker-month-year {
353
- width: 100%;
354
- }
355
- .ui-datepicker select.ui-datepicker-month,
356
- .ui-datepicker select.ui-datepicker-year {
357
- width: 49%;
358
- }
359
- .ui-datepicker table {
360
- width: 100%;
361
- font-size: .9em;
362
- border-collapse: collapse;
363
- margin: 0 0 .4em;
364
- }
365
- .ui-datepicker th {
366
- padding: .7em .3em;
367
- text-align: center;
368
- font-weight: bold;
369
- border: 0;
370
- }
371
- .ui-datepicker td {
372
- border: 0;
373
- padding: 1px;
374
- }
375
- .ui-datepicker td span,
376
- .ui-datepicker td a {
377
- display: block;
378
- padding: .2em;
379
- text-align: right;
380
- text-decoration: none;
381
- }
382
- .ui-datepicker .ui-datepicker-buttonpane {
383
- background-image: none;
384
- margin: .7em 0 0 0;
385
- padding: 0 .2em;
386
- border-left: 0;
387
- border-right: 0;
388
- border-bottom: 0;
389
- }
390
- .ui-datepicker .ui-datepicker-buttonpane button {
391
- float: right;
392
- margin: .5em .2em .4em;
393
- cursor: pointer;
394
- padding: .2em .6em .3em .6em;
395
- width: auto;
396
- overflow: visible;
397
- }
398
- .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
399
- float: left;
400
- }
401
-
402
- /* with multiple calendars */
403
- .ui-datepicker.ui-datepicker-multi {
404
- width: auto;
405
- }
406
- .ui-datepicker-multi .ui-datepicker-group {
407
- float: left;
408
- }
409
- .ui-datepicker-multi .ui-datepicker-group table {
410
- width: 95%;
411
- margin: 0 auto .4em;
412
- }
413
- .ui-datepicker-multi-2 .ui-datepicker-group {
414
- width: 50%;
415
- }
416
- .ui-datepicker-multi-3 .ui-datepicker-group {
417
- width: 33.3%;
418
- }
419
- .ui-datepicker-multi-4 .ui-datepicker-group {
420
- width: 25%;
421
- }
422
- .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
423
- .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
424
- border-left-width: 0;
425
- }
426
- .ui-datepicker-multi .ui-datepicker-buttonpane {
427
- clear: left;
428
- }
429
- .ui-datepicker-row-break {
430
- clear: both;
431
- width: 100%;
432
- font-size: 0;
433
- }
434
-
435
- /* RTL support */
436
- .ui-datepicker-rtl {
437
- direction: rtl;
438
- }
439
- .ui-datepicker-rtl .ui-datepicker-prev {
440
- right: 2px;
441
- left: auto;
442
- }
443
- .ui-datepicker-rtl .ui-datepicker-next {
444
- left: 2px;
445
- right: auto;
446
- }
447
- .ui-datepicker-rtl .ui-datepicker-prev:hover {
448
- right: 1px;
449
- left: auto;
450
- }
451
- .ui-datepicker-rtl .ui-datepicker-next:hover {
452
- left: 1px;
453
- right: auto;
454
- }
455
- .ui-datepicker-rtl .ui-datepicker-buttonpane {
456
- clear: right;
457
- }
458
- .ui-datepicker-rtl .ui-datepicker-buttonpane button {
459
- float: left;
460
- }
461
- .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
462
- .ui-datepicker-rtl .ui-datepicker-group {
463
- float: right;
464
- }
465
- .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
466
- .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
467
- border-right-width: 0;
468
- border-left-width: 1px;
469
- }
470
- .ui-dialog {
471
- position: absolute;
472
- top: 0;
473
- left: 0;
474
- padding: .2em;
475
- outline: 0;
476
- }
477
- .ui-dialog .ui-dialog-titlebar {
478
- padding: .4em 1em;
479
- position: relative;
480
- }
481
- .ui-dialog .ui-dialog-title {
482
- float: left;
483
- margin: .1em 0;
484
- white-space: nowrap;
485
- width: 90%;
486
- overflow: hidden;
487
- text-overflow: ellipsis;
488
- }
489
- .ui-dialog .ui-dialog-titlebar-close {
490
- position: absolute;
491
- right: .3em;
492
- top: 50%;
493
- width: 21px;
494
- margin: -10px 0 0 0;
495
- padding: 1px;
496
- height: 20px;
497
- }
498
- .ui-dialog .ui-dialog-content {
499
- position: relative;
500
- border: 0;
501
- padding: .5em 1em;
502
- background: none;
503
- overflow: auto;
504
- }
505
- .ui-dialog .ui-dialog-buttonpane {
506
- text-align: left;
507
- border-width: 1px 0 0 0;
508
- background-image: none;
509
- margin-top: .5em;
510
- padding: .3em 1em .5em .4em;
511
- }
512
- .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
513
- float: right;
514
- }
515
- .ui-dialog .ui-dialog-buttonpane button {
516
- margin: .5em .4em .5em 0;
517
- cursor: pointer;
518
- }
519
- .ui-dialog .ui-resizable-se {
520
- width: 12px;
521
- height: 12px;
522
- right: -5px;
523
- bottom: -5px;
524
- background-position: 16px 16px;
525
- }
526
- .ui-draggable .ui-dialog-titlebar {
527
- cursor: move;
528
- }
529
- .ui-menu {
530
- list-style: none;
531
- padding: 2px;
532
- margin: 0;
533
- display: block;
534
- outline: none;
535
- }
536
- .ui-menu .ui-menu {
537
- margin-top: -3px;
538
- position: absolute;
539
- }
540
- .ui-menu .ui-menu-item {
541
- margin: 0;
542
- padding: 0;
543
- width: 100%;
544
- }
545
- .ui-menu .ui-menu-divider {
546
- margin: 5px -2px 5px -2px;
547
- height: 0;
548
- font-size: 0;
549
- line-height: 0;
550
- border-width: 1px 0 0 0;
551
- }
552
- .ui-menu .ui-menu-item a {
553
- text-decoration: none;
554
- display: block;
555
- padding: 2px .4em;
556
- line-height: 1.5;
557
- min-height: 0; /* support: IE7 */
558
- font-weight: normal;
559
- }
560
- .ui-menu .ui-menu-item a.ui-state-focus,
561
- .ui-menu .ui-menu-item a.ui-state-active {
562
- font-weight: normal;
563
- margin: -1px;
564
- }
565
-
566
- .ui-menu .ui-state-disabled {
567
- font-weight: normal;
568
- margin: .4em 0 .2em;
569
- line-height: 1.5;
570
- }
571
- .ui-menu .ui-state-disabled a {
572
- cursor: default;
573
- }
574
-
575
- /* icon support */
576
- .ui-menu-icons {
577
- position: relative;
578
- }
579
- .ui-menu-icons .ui-menu-item a {
580
- position: relative;
581
- padding-left: 2em;
582
- }
583
-
584
- /* left-aligned */
585
- .ui-menu .ui-icon {
586
- position: absolute;
587
- top: .2em;
588
- left: .2em;
589
- }
590
-
591
- /* right-aligned */
592
- .ui-menu .ui-menu-icon {
593
- position: static;
594
- float: right;
595
- }
596
- .ui-progressbar {
597
- height: 2em;
598
- text-align: left;
599
- overflow: hidden;
600
- }
601
- .ui-progressbar .ui-progressbar-value {
602
- margin: -1px;
603
- height: 100%;
604
- }
605
- .ui-progressbar .ui-progressbar-overlay {
606
- background: url("images/animated-overlay.gif");
607
- height: 100%;
608
- filter: alpha(opacity=25);
609
- opacity: 0.25;
610
- }
611
- .ui-progressbar-indeterminate .ui-progressbar-value {
612
- background-image: none;
613
- }
614
- .ui-slider {
615
- position: relative;
616
- text-align: left;
617
- }
618
- .ui-slider .ui-slider-handle {
619
- position: absolute;
620
- z-index: 2;
621
- width: 1.2em;
622
- height: 1.2em;
623
- cursor: default;
624
- }
625
- .ui-slider .ui-slider-range {
626
- position: absolute;
627
- z-index: 1;
628
- font-size: .7em;
629
- display: block;
630
- border: 0;
631
- background-position: 0 0;
632
- }
633
-
634
- /* For IE8 - See #6727 */
635
- .ui-slider.ui-state-disabled .ui-slider-handle,
636
- .ui-slider.ui-state-disabled .ui-slider-range {
637
- filter: inherit;
638
- }
639
-
640
- .ui-slider-horizontal {
641
- height: .8em;
642
- }
643
- .ui-slider-horizontal .ui-slider-handle {
644
- top: -.3em;
645
- margin-left: -.6em;
646
- }
647
- .ui-slider-horizontal .ui-slider-range {
648
- top: 0;
649
- height: 100%;
650
- }
651
- .ui-slider-horizontal .ui-slider-range-min {
652
- left: 0;
653
- }
654
- .ui-slider-horizontal .ui-slider-range-max {
655
- right: 0;
656
- }
657
-
658
- .ui-slider-vertical {
659
- width: .8em;
660
- height: 100px;
661
- }
662
- .ui-slider-vertical .ui-slider-handle {
663
- left: -.3em;
664
- margin-left: 0;
665
- margin-bottom: -.6em;
666
- }
667
- .ui-slider-vertical .ui-slider-range {
668
- left: 0;
669
- width: 100%;
670
- }
671
- .ui-slider-vertical .ui-slider-range-min {
672
- bottom: 0;
673
- }
674
- .ui-slider-vertical .ui-slider-range-max {
675
- top: 0;
676
- }
677
- .ui-spinner {
678
- position: relative;
679
- display: inline-block;
680
- overflow: hidden;
681
- padding: 0;
682
- vertical-align: middle;
683
- }
684
- .ui-spinner-input {
685
- border: none;
686
- background: none;
687
- color: inherit;
688
- padding: 0;
689
- margin: .2em 0;
690
- vertical-align: middle;
691
- margin-left: .4em;
692
- margin-right: 22px;
693
- }
694
- .ui-spinner-button {
695
- width: 16px;
696
- height: 50%;
697
- font-size: .5em;
698
- padding: 0;
699
- margin: 0;
700
- text-align: center;
701
- position: absolute;
702
- cursor: default;
703
- display: block;
704
- overflow: hidden;
705
- right: 0;
706
- }
707
- /* more specificity required here to overide default borders */
708
- .ui-spinner a.ui-spinner-button {
709
- border-top: none;
710
- border-bottom: none;
711
- border-right: none;
712
- }
713
- /* vertical centre icon */
714
- .ui-spinner .ui-icon {
715
- position: absolute;
716
- margin-top: -8px;
717
- top: 50%;
718
- left: 0;
719
- }
720
- .ui-spinner-up {
721
- top: 0;
722
- }
723
- .ui-spinner-down {
724
- bottom: 0;
725
- }
726
-
727
- /* TR overrides */
728
- .ui-spinner .ui-icon-triangle-1-s {
729
- /* need to fix icons sprite */
730
- background-position: -65px -16px;
731
- }
732
- .ui-tabs {
733
- position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
734
- padding: .2em;
735
- }
736
- .ui-tabs .ui-tabs-nav {
737
- margin: 0;
738
- padding: .2em .2em 0;
739
- }
740
- .ui-tabs .ui-tabs-nav li {
741
- list-style: none;
742
- float: left;
743
- position: relative;
744
- top: 0;
745
- margin: 1px .2em 0 0;
746
- border-bottom: 0;
747
- padding: 0;
748
- white-space: nowrap;
749
- }
750
- .ui-tabs .ui-tabs-nav li a {
751
- float: left;
752
- padding: .5em 1em;
753
- text-decoration: none;
754
- }
755
- .ui-tabs .ui-tabs-nav li.ui-tabs-active {
756
- margin-bottom: -1px;
757
- padding-bottom: 1px;
758
- }
759
- .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
760
- .ui-tabs .ui-tabs-nav li.ui-state-disabled a,
761
- .ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
762
- cursor: text;
763
- }
764
- .ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
765
- .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
766
- cursor: pointer;
767
- }
768
- .ui-tabs .ui-tabs-panel {
769
- display: block;
770
- border-width: 0;
771
- padding: 1em 1.4em;
772
- background: none;
773
- }
774
- .ui-tooltip {
775
- padding: 8px;
776
- position: absolute;
777
- z-index: 9999;
778
- max-width: 300px;
779
- -webkit-box-shadow: 0 0 5px #aaa;
780
- box-shadow: 0 0 5px #aaa;
781
- }
782
- body .ui-tooltip {
783
- border-width: 2px;
784
- }
785
-
786
- /* Component containers
787
- ----------------------------------*/
788
- .ui-widget {
789
- font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
790
- font-size: 1.1em;
791
- }
792
- .ui-widget .ui-widget {
793
- font-size: 1em;
794
- }
795
- .ui-widget input,
796
- .ui-widget select,
797
- .ui-widget textarea,
798
- .ui-widget button {
799
- font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
800
- font-size: 1em;
801
- }
802
- .ui-widget-content {
803
- border: 1px solid #a6c9e2;
804
- background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;
805
- color: #222222;
806
- }
807
- .ui-widget-content a {
808
- color: #222222;
809
- }
810
- .ui-widget-header {
811
- border: 1px solid #4297d7;
812
- background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x;
813
- color: #ffffff;
814
- font-weight: bold;
815
- }
816
- .ui-widget-header a {
817
- color: #ffffff;
818
- }
819
-
820
- /* Interaction states
821
- ----------------------------------*/
822
- .ui-state-default,
823
- .ui-widget-content .ui-state-default,
824
- .ui-widget-header .ui-state-default {
825
- border: 1px solid #c5dbec;
826
- background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x;
827
- font-weight: bold;
828
- color: #2e6e9e;
829
- }
830
- .ui-state-default a,
831
- .ui-state-default a:link,
832
- .ui-state-default a:visited {
833
- color: #2e6e9e;
834
- text-decoration: none;
835
- }
836
- .ui-state-hover,
837
- .ui-widget-content .ui-state-hover,
838
- .ui-widget-header .ui-state-hover,
839
- .ui-state-focus,
840
- .ui-widget-content .ui-state-focus,
841
- .ui-widget-header .ui-state-focus {
842
- border: 1px solid #79b7e7;
843
- background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x;
844
- font-weight: bold;
845
- color: #1d5987;
846
- }
847
- .ui-state-hover a,
848
- .ui-state-hover a:hover,
849
- .ui-state-hover a:link,
850
- .ui-state-hover a:visited {
851
- color: #1d5987;
852
- text-decoration: none;
853
- }
854
- .ui-state-active,
855
- .ui-widget-content .ui-state-active,
856
- .ui-widget-header .ui-state-active {
857
- border: 1px solid #79b7e7;
858
- background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x;
859
- font-weight: bold;
860
- color: #e17009;
861
- }
862
- .ui-state-active a,
863
- .ui-state-active a:link,
864
- .ui-state-active a:visited {
865
- color: #e17009;
866
- text-decoration: none;
867
- }
868
-
869
- /* Interaction Cues
870
- ----------------------------------*/
871
- .ui-state-highlight,
872
- .ui-widget-content .ui-state-highlight,
873
- .ui-widget-header .ui-state-highlight {
874
- border: 1px solid #fad42e;
875
- background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;
876
- color: #363636;
877
- }
878
- .ui-state-highlight a,
879
- .ui-widget-content .ui-state-highlight a,
880
- .ui-widget-header .ui-state-highlight a {
881
- color: #363636;
882
- }
883
- .ui-state-error,
884
- .ui-widget-content .ui-state-error,
885
- .ui-widget-header .ui-state-error {
886
- border: 1px solid #cd0a0a;
887
- background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;
888
- color: #cd0a0a;
889
- }
890
- .ui-state-error a,
891
- .ui-widget-content .ui-state-error a,
892
- .ui-widget-header .ui-state-error a {
893
- color: #cd0a0a;
894
- }
895
- .ui-state-error-text,
896
- .ui-widget-content .ui-state-error-text,
897
- .ui-widget-header .ui-state-error-text {
898
- color: #cd0a0a;
899
- }
900
- .ui-priority-primary,
901
- .ui-widget-content .ui-priority-primary,
902
- .ui-widget-header .ui-priority-primary {
903
- font-weight: bold;
904
- }
905
- .ui-priority-secondary,
906
- .ui-widget-content .ui-priority-secondary,
907
- .ui-widget-header .ui-priority-secondary {
908
- opacity: .7;
909
- filter:Alpha(Opacity=70);
910
- font-weight: normal;
911
- }
912
- .ui-state-disabled,
913
- .ui-widget-content .ui-state-disabled,
914
- .ui-widget-header .ui-state-disabled {
915
- opacity: .35;
916
- filter:Alpha(Opacity=35);
917
- background-image: none;
918
- }
919
- .ui-state-disabled .ui-icon {
920
- filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
921
- }
922
-
923
- /* Icons
924
- ----------------------------------*/
925
-
926
- /* states and images */
927
- .ui-icon {
928
- width: 16px;
929
- height: 16px;
930
- background-position: 16px 16px;
931
- }
932
- .ui-icon,
933
- .ui-widget-content .ui-icon {
934
- background-image: url(images/ui-icons_469bdd_256x240.png);
935
- }
936
- .ui-widget-header .ui-icon {
937
- background-image: url(images/ui-icons_d8e7f3_256x240.png);
938
- }
939
- .ui-state-default .ui-icon {
940
- background-image: url(images/ui-icons_6da8d5_256x240.png);
941
- }
942
- .ui-state-hover .ui-icon,
943
- .ui-state-focus .ui-icon {
944
- background-image: url(images/ui-icons_217bc0_256x240.png);
945
- }
946
- .ui-state-active .ui-icon {
947
- background-image: url(images/ui-icons_f9bd01_256x240.png);
948
- }
949
- .ui-state-highlight .ui-icon {
950
- background-image: url(images/ui-icons_2e83ff_256x240.png);
951
- }
952
- .ui-state-error .ui-icon,
953
- .ui-state-error-text .ui-icon {
954
- background-image: url(images/ui-icons_cd0a0a_256x240.png);
955
- }
956
-
957
- /* positioning */
958
- .ui-icon-carat-1-n { background-position: 0 0; }
959
- .ui-icon-carat-1-ne { background-position: -16px 0; }
960
- .ui-icon-carat-1-e { background-position: -32px 0; }
961
- .ui-icon-carat-1-se { background-position: -48px 0; }
962
- .ui-icon-carat-1-s { background-position: -64px 0; }
963
- .ui-icon-carat-1-sw { background-position: -80px 0; }
964
- .ui-icon-carat-1-w { background-position: -96px 0; }
965
- .ui-icon-carat-1-nw { background-position: -112px 0; }
966
- .ui-icon-carat-2-n-s { background-position: -128px 0; }
967
- .ui-icon-carat-2-e-w { background-position: -144px 0; }
968
- .ui-icon-triangle-1-n { background-position: 0 -16px; }
969
- .ui-icon-triangle-1-ne { background-position: -16px -16px; }
970
- .ui-icon-triangle-1-e { background-position: -32px -16px; }
971
- .ui-icon-triangle-1-se { background-position: -48px -16px; }
972
- .ui-icon-triangle-1-s { background-position: -64px -16px; }
973
- .ui-icon-triangle-1-sw { background-position: -80px -16px; }
974
- .ui-icon-triangle-1-w { background-position: -96px -16px; }
975
- .ui-icon-triangle-1-nw { background-position: -112px -16px; }
976
- .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
977
- .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
978
- .ui-icon-arrow-1-n { background-position: 0 -32px; }
979
- .ui-icon-arrow-1-ne { background-position: -16px -32px; }
980
- .ui-icon-arrow-1-e { background-position: -32px -32px; }
981
- .ui-icon-arrow-1-se { background-position: -48px -32px; }
982
- .ui-icon-arrow-1-s { background-position: -64px -32px; }
983
- .ui-icon-arrow-1-sw { background-position: -80px -32px; }
984
- .ui-icon-arrow-1-w { background-position: -96px -32px; }
985
- .ui-icon-arrow-1-nw { background-position: -112px -32px; }
986
- .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
987
- .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
988
- .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
989
- .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
990
- .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
991
- .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
992
- .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
993
- .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
994
- .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
995
- .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
996
- .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
997
- .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
998
- .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
999
- .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
1000
- .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
1001
- .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
1002
- .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
1003
- .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
1004
- .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
1005
- .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
1006
- .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
1007
- .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
1008
- .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
1009
- .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
1010
- .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
1011
- .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
1012
- .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
1013
- .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
1014
- .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
1015
- .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
1016
- .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
1017
- .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
1018
- .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
1019
- .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
1020
- .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
1021
- .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
1022
- .ui-icon-arrow-4 { background-position: 0 -80px; }
1023
- .ui-icon-arrow-4-diag { background-position: -16px -80px; }
1024
- .ui-icon-extlink { background-position: -32px -80px; }
1025
- .ui-icon-newwin { background-position: -48px -80px; }
1026
- .ui-icon-refresh { background-position: -64px -80px; }
1027
- .ui-icon-shuffle { background-position: -80px -80px; }
1028
- .ui-icon-transfer-e-w { background-position: -96px -80px; }
1029
- .ui-icon-transferthick-e-w { background-position: -112px -80px; }
1030
- .ui-icon-folder-collapsed { background-position: 0 -96px; }
1031
- .ui-icon-folder-open { background-position: -16px -96px; }
1032
- .ui-icon-document { background-position: -32px -96px; }
1033
- .ui-icon-document-b { background-position: -48px -96px; }
1034
- .ui-icon-note { background-position: -64px -96px; }
1035
- .ui-icon-mail-closed { background-position: -80px -96px; }
1036
- .ui-icon-mail-open { background-position: -96px -96px; }
1037
- .ui-icon-suitcase { background-position: -112px -96px; }
1038
- .ui-icon-comment { background-position: -128px -96px; }
1039
- .ui-icon-person { background-position: -144px -96px; }
1040
- .ui-icon-print { background-position: -160px -96px; }
1041
- .ui-icon-trash { background-position: -176px -96px; }
1042
- .ui-icon-locked { background-position: -192px -96px; }
1043
- .ui-icon-unlocked { background-position: -208px -96px; }
1044
- .ui-icon-bookmark { background-position: -224px -96px; }
1045
- .ui-icon-tag { background-position: -240px -96px; }
1046
- .ui-icon-home { background-position: 0 -112px; }
1047
- .ui-icon-flag { background-position: -16px -112px; }
1048
- .ui-icon-calendar { background-position: -32px -112px; }
1049
- .ui-icon-cart { background-position: -48px -112px; }
1050
- .ui-icon-pencil { background-position: -64px -112px; }
1051
- .ui-icon-clock { background-position: -80px -112px; }
1052
- .ui-icon-disk { background-position: -96px -112px; }
1053
- .ui-icon-calculator { background-position: -112px -112px; }
1054
- .ui-icon-zoomin { background-position: -128px -112px; }
1055
- .ui-icon-zoomout { background-position: -144px -112px; }
1056
- .ui-icon-search { background-position: -160px -112px; }
1057
- .ui-icon-wrench { background-position: -176px -112px; }
1058
- .ui-icon-gear { background-position: -192px -112px; }
1059
- .ui-icon-heart { background-position: -208px -112px; }
1060
- .ui-icon-star { background-position: -224px -112px; }
1061
- .ui-icon-link { background-position: -240px -112px; }
1062
- .ui-icon-cancel { background-position: 0 -128px; }
1063
- .ui-icon-plus { background-position: -16px -128px; }
1064
- .ui-icon-plusthick { background-position: -32px -128px; }
1065
- .ui-icon-minus { background-position: -48px -128px; }
1066
- .ui-icon-minusthick { background-position: -64px -128px; }
1067
- .ui-icon-close { background-position: -80px -128px; }
1068
- .ui-icon-closethick { background-position: -96px -128px; }
1069
- .ui-icon-key { background-position: -112px -128px; }
1070
- .ui-icon-lightbulb { background-position: -128px -128px; }
1071
- .ui-icon-scissors { background-position: -144px -128px; }
1072
- .ui-icon-clipboard { background-position: -160px -128px; }
1073
- .ui-icon-copy { background-position: -176px -128px; }
1074
- .ui-icon-contact { background-position: -192px -128px; }
1075
- .ui-icon-image { background-position: -208px -128px; }
1076
- .ui-icon-video { background-position: -224px -128px; }
1077
- .ui-icon-script { background-position: -240px -128px; }
1078
- .ui-icon-alert { background-position: 0 -144px; }
1079
- .ui-icon-info { background-position: -16px -144px; }
1080
- .ui-icon-notice { background-position: -32px -144px; }
1081
- .ui-icon-help { background-position: -48px -144px; }
1082
- .ui-icon-check { background-position: -64px -144px; }
1083
- .ui-icon-bullet { background-position: -80px -144px; }
1084
- .ui-icon-radio-on { background-position: -96px -144px; }
1085
- .ui-icon-radio-off { background-position: -112px -144px; }
1086
- .ui-icon-pin-w { background-position: -128px -144px; }
1087
- .ui-icon-pin-s { background-position: -144px -144px; }
1088
- .ui-icon-play { background-position: 0 -160px; }
1089
- .ui-icon-pause { background-position: -16px -160px; }
1090
- .ui-icon-seek-next { background-position: -32px -160px; }
1091
- .ui-icon-seek-prev { background-position: -48px -160px; }
1092
- .ui-icon-seek-end { background-position: -64px -160px; }
1093
- .ui-icon-seek-start { background-position: -80px -160px; }
1094
- /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
1095
- .ui-icon-seek-first { background-position: -80px -160px; }
1096
- .ui-icon-stop { background-position: -96px -160px; }
1097
- .ui-icon-eject { background-position: -112px -160px; }
1098
- .ui-icon-volume-off { background-position: -128px -160px; }
1099
- .ui-icon-volume-on { background-position: -144px -160px; }
1100
- .ui-icon-power { background-position: 0 -176px; }
1101
- .ui-icon-signal-diag { background-position: -16px -176px; }
1102
- .ui-icon-signal { background-position: -32px -176px; }
1103
- .ui-icon-battery-0 { background-position: -48px -176px; }
1104
- .ui-icon-battery-1 { background-position: -64px -176px; }
1105
- .ui-icon-battery-2 { background-position: -80px -176px; }
1106
- .ui-icon-battery-3 { background-position: -96px -176px; }
1107
- .ui-icon-circle-plus { background-position: 0 -192px; }
1108
- .ui-icon-circle-minus { background-position: -16px -192px; }
1109
- .ui-icon-circle-close { background-position: -32px -192px; }
1110
- .ui-icon-circle-triangle-e { background-position: -48px -192px; }
1111
- .ui-icon-circle-triangle-s { background-position: -64px -192px; }
1112
- .ui-icon-circle-triangle-w { background-position: -80px -192px; }
1113
- .ui-icon-circle-triangle-n { background-position: -96px -192px; }
1114
- .ui-icon-circle-arrow-e { background-position: -112px -192px; }
1115
- .ui-icon-circle-arrow-s { background-position: -128px -192px; }
1116
- .ui-icon-circle-arrow-w { background-position: -144px -192px; }
1117
- .ui-icon-circle-arrow-n { background-position: -160px -192px; }
1118
- .ui-icon-circle-zoomin { background-position: -176px -192px; }
1119
- .ui-icon-circle-zoomout { background-position: -192px -192px; }
1120
- .ui-icon-circle-check { background-position: -208px -192px; }
1121
- .ui-icon-circlesmall-plus { background-position: 0 -208px; }
1122
- .ui-icon-circlesmall-minus { background-position: -16px -208px; }
1123
- .ui-icon-circlesmall-close { background-position: -32px -208px; }
1124
- .ui-icon-squaresmall-plus { background-position: -48px -208px; }
1125
- .ui-icon-squaresmall-minus { background-position: -64px -208px; }
1126
- .ui-icon-squaresmall-close { background-position: -80px -208px; }
1127
- .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
1128
- .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
1129
- .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
1130
- .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
1131
- .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
1132
- .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
1133
-
1134
-
1135
- /* Misc visuals
1136
- ----------------------------------*/
1137
-
1138
- /* Corner radius */
1139
- .ui-corner-all,
1140
- .ui-corner-top,
1141
- .ui-corner-left,
1142
- .ui-corner-tl {
1143
- border-top-left-radius: 5px;
1144
- }
1145
- .ui-corner-all,
1146
- .ui-corner-top,
1147
- .ui-corner-right,
1148
- .ui-corner-tr {
1149
- border-top-right-radius: 5px;
1150
- }
1151
- .ui-corner-all,
1152
- .ui-corner-bottom,
1153
- .ui-corner-left,
1154
- .ui-corner-bl {
1155
- border-bottom-left-radius: 5px;
1156
- }
1157
- .ui-corner-all,
1158
- .ui-corner-bottom,
1159
- .ui-corner-right,
1160
- .ui-corner-br {
1161
- border-bottom-right-radius: 5px;
1162
- }
1163
-
1164
- /* Overlays */
1165
- .ui-widget-overlay {
1166
- background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
1167
- opacity: .3;
1168
- filter: Alpha(Opacity=30);
1169
- }
1170
- .ui-widget-shadow {
1171
- margin: -8px 0 0 -8px;
1172
- padding: 8px;
1173
- background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
1174
- opacity: .3;
1175
- filter: Alpha(Opacity=30);
1176
- border-radius: 8px;
1177
- }
1
+ /*! jQuery UI - v1.10.0 - 2013-02-06
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
+ * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
6
+
7
+ /* Layout helpers
8
+ ----------------------------------*/
9
+ .ui-helper-hidden {
10
+ display: none;
11
+ }
12
+ .ui-helper-hidden-accessible {
13
+ border: 0;
14
+ clip: rect(0 0 0 0);
15
+ height: 1px;
16
+ margin: -1px;
17
+ overflow: hidden;
18
+ padding: 0;
19
+ position: absolute;
20
+ width: 1px;
21
+ }
22
+ .ui-helper-reset {
23
+ margin: 0;
24
+ padding: 0;
25
+ border: 0;
26
+ outline: 0;
27
+ line-height: 1.3;
28
+ text-decoration: none;
29
+ font-size: 100%;
30
+ list-style: none;
31
+ }
32
+ .ui-helper-clearfix:before,
33
+ .ui-helper-clearfix:after {
34
+ content: "";
35
+ display: table;
36
+ }
37
+ .ui-helper-clearfix:after {
38
+ clear: both;
39
+ }
40
+ .ui-helper-clearfix {
41
+ min-height: 0; /* support: IE7 */
42
+ }
43
+ .ui-helper-zfix {
44
+ width: 100%;
45
+ height: 100%;
46
+ top: 0;
47
+ left: 0;
48
+ position: absolute;
49
+ opacity: 0;
50
+ filter:Alpha(Opacity=0);
51
+ }
52
+
53
+ .ui-front {
54
+ z-index: 100;
55
+ }
56
+
57
+
58
+ /* Interaction Cues
59
+ ----------------------------------*/
60
+ .ui-state-disabled {
61
+ cursor: default !important;
62
+ }
63
+
64
+
65
+ /* Icons
66
+ ----------------------------------*/
67
+
68
+ /* states and images */
69
+ .ui-icon {
70
+ display: block;
71
+ text-indent: -99999px;
72
+ overflow: hidden;
73
+ background-repeat: no-repeat;
74
+ }
75
+
76
+
77
+ /* Misc visuals
78
+ ----------------------------------*/
79
+
80
+ /* Overlays */
81
+ .ui-widget-overlay {
82
+ position: fixed;
83
+ top: 0;
84
+ left: 0;
85
+ width: 100%;
86
+ height: 100%;
87
+ }
88
+ .ui-resizable {
89
+ position: relative;
90
+ }
91
+ .ui-resizable-handle {
92
+ position: absolute;
93
+ font-size: 0.1px;
94
+ display: block;
95
+ }
96
+ .ui-resizable-disabled .ui-resizable-handle,
97
+ .ui-resizable-autohide .ui-resizable-handle {
98
+ display: none;
99
+ }
100
+ .ui-resizable-n {
101
+ cursor: n-resize;
102
+ height: 7px;
103
+ width: 100%;
104
+ top: -5px;
105
+ left: 0;
106
+ }
107
+ .ui-resizable-s {
108
+ cursor: s-resize;
109
+ height: 7px;
110
+ width: 100%;
111
+ bottom: -5px;
112
+ left: 0;
113
+ }
114
+ .ui-resizable-e {
115
+ cursor: e-resize;
116
+ width: 7px;
117
+ right: -5px;
118
+ top: 0;
119
+ height: 100%;
120
+ }
121
+ .ui-resizable-w {
122
+ cursor: w-resize;
123
+ width: 7px;
124
+ left: -5px;
125
+ top: 0;
126
+ height: 100%;
127
+ }
128
+ .ui-resizable-se {
129
+ cursor: se-resize;
130
+ width: 12px;
131
+ height: 12px;
132
+ right: 1px;
133
+ bottom: 1px;
134
+ }
135
+ .ui-resizable-sw {
136
+ cursor: sw-resize;
137
+ width: 9px;
138
+ height: 9px;
139
+ left: -5px;
140
+ bottom: -5px;
141
+ }
142
+ .ui-resizable-nw {
143
+ cursor: nw-resize;
144
+ width: 9px;
145
+ height: 9px;
146
+ left: -5px;
147
+ top: -5px;
148
+ }
149
+ .ui-resizable-ne {
150
+ cursor: ne-resize;
151
+ width: 9px;
152
+ height: 9px;
153
+ right: -5px;
154
+ top: -5px;
155
+ }
156
+ .ui-selectable-helper {
157
+ position: absolute;
158
+ z-index: 100;
159
+ border: 1px dotted black;
160
+ }
161
+ .ui-accordion .ui-accordion-header {
162
+ display: block;
163
+ cursor: pointer;
164
+ position: relative;
165
+ margin-top: 2px;
166
+ padding: .5em .5em .5em .7em;
167
+ min-height: 0; /* support: IE7 */
168
+ }
169
+ .ui-accordion .ui-accordion-icons {
170
+ padding-left: 2.2em;
171
+ }
172
+ .ui-accordion .ui-accordion-noicons {
173
+ padding-left: .7em;
174
+ }
175
+ .ui-accordion .ui-accordion-icons .ui-accordion-icons {
176
+ padding-left: 2.2em;
177
+ }
178
+ .ui-accordion .ui-accordion-header .ui-accordion-header-icon {
179
+ position: absolute;
180
+ left: .5em;
181
+ top: 50%;
182
+ margin-top: -8px;
183
+ }
184
+ .ui-accordion .ui-accordion-content {
185
+ padding: 1em 2.2em;
186
+ border-top: 0;
187
+ overflow: auto;
188
+ }
189
+ .ui-autocomplete {
190
+ position: absolute;
191
+ top: 0;
192
+ left: 0;
193
+ cursor: default;
194
+ }
195
+ .ui-button {
196
+ display: inline-block;
197
+ position: relative;
198
+ padding: 0;
199
+ line-height: normal;
200
+ margin-right: .1em;
201
+ cursor: pointer;
202
+ vertical-align: middle;
203
+ text-align: center;
204
+ overflow: visible; /* removes extra width in IE */
205
+ }
206
+ .ui-button,
207
+ .ui-button:visited,
208
+ .ui-button:hover,
209
+ .ui-button:active,
210
+ .large_button:hover {
211
+ background: url("images/ui-bg_glass_75_d0e5f5_1x400.png") repeat-x scroll 50% 50% #D0E5F5;
212
+ border: 1px solid #79B7E7;
213
+ color: #1D5987;
214
+ font-weight: bold;
215
+ }
216
+ /* to make room for the icon, a width needs to be set here */
217
+ .ui-button-icon-only {
218
+ width: 2.2em;
219
+ }
220
+ /* button elements seem to need a little more width */
221
+ button.ui-button-icon-only {
222
+ width: 2.4em;
223
+ }
224
+ .ui-button-icons-only {
225
+ width: 3.4em;
226
+ }
227
+ button.ui-button-icons-only {
228
+ width: 3.7em;
229
+ }
230
+
231
+ /* button text element */
232
+ .ui-button .ui-button-text {
233
+ display: block;
234
+ line-height: normal;
235
+ }
236
+ .ui-button-text-only .ui-button-text {
237
+ padding: .4em 1em;
238
+ }
239
+ .ui-button-icon-only .ui-button-text,
240
+ .ui-button-icons-only .ui-button-text {
241
+ padding: .4em;
242
+ text-indent: -9999999px;
243
+ }
244
+ .ui-button-text-icon-primary .ui-button-text,
245
+ .ui-button-text-icons .ui-button-text {
246
+ padding: .4em 1em .4em 2.1em;
247
+ }
248
+ .ui-button-text-icon-secondary .ui-button-text,
249
+ .ui-button-text-icons .ui-button-text {
250
+ padding: .4em 2.1em .4em 1em;
251
+ }
252
+ .ui-button-text-icons .ui-button-text {
253
+ padding-left: 2.1em;
254
+ padding-right: 2.1em;
255
+ }
256
+ /* no icon support for input elements, provide padding by default */
257
+ input.ui-button {
258
+ padding: .4em 1em;
259
+ }
260
+
261
+ /* button icon element(s) */
262
+ .ui-button-icon-only .ui-icon,
263
+ .ui-button-text-icon-primary .ui-icon,
264
+ .ui-button-text-icon-secondary .ui-icon,
265
+ .ui-button-text-icons .ui-icon,
266
+ .ui-button-icons-only .ui-icon {
267
+ position: absolute;
268
+ top: 50%;
269
+ margin-top: -8px;
270
+ }
271
+ .ui-button-icon-only .ui-icon {
272
+ left: 50%;
273
+ margin-left: -8px;
274
+ }
275
+ .ui-button-text-icon-primary .ui-button-icon-primary,
276
+ .ui-button-text-icons .ui-button-icon-primary,
277
+ .ui-button-icons-only .ui-button-icon-primary {
278
+ left: .5em;
279
+ }
280
+ .ui-button-text-icon-secondary .ui-button-icon-secondary,
281
+ .ui-button-text-icons .ui-button-icon-secondary,
282
+ .ui-button-icons-only .ui-button-icon-secondary {
283
+ right: .5em;
284
+ }
285
+
286
+ /* button sets */
287
+ .ui-buttonset {
288
+ margin-right: 7px;
289
+ }
290
+ .ui-buttonset .ui-button {
291
+ margin-left: 0;
292
+ margin-right: -.3em;
293
+ }
294
+
295
+ /* workarounds */
296
+ /* reset extra padding in Firefox, see h5bp.com/l */
297
+ input.ui-button::-moz-focus-inner,
298
+ button.ui-button::-moz-focus-inner {
299
+ border: 0;
300
+ padding: 0;
301
+ }
302
+ .ui-datepicker {
303
+ width: 17em;
304
+ padding: .2em .2em 0;
305
+ display: none;
306
+ }
307
+ .ui-datepicker .ui-datepicker-header {
308
+ position: relative;
309
+ padding: .2em 0;
310
+ }
311
+ .ui-datepicker .ui-datepicker-prev,
312
+ .ui-datepicker .ui-datepicker-next {
313
+ position: absolute;
314
+ top: 2px;
315
+ width: 1.8em;
316
+ height: 1.8em;
317
+ }
318
+ .ui-datepicker .ui-datepicker-prev-hover,
319
+ .ui-datepicker .ui-datepicker-next-hover {
320
+ top: 1px;
321
+ }
322
+ .ui-datepicker .ui-datepicker-prev {
323
+ left: 2px;
324
+ }
325
+ .ui-datepicker .ui-datepicker-next {
326
+ right: 2px;
327
+ }
328
+ .ui-datepicker .ui-datepicker-prev-hover {
329
+ left: 1px;
330
+ }
331
+ .ui-datepicker .ui-datepicker-next-hover {
332
+ right: 1px;
333
+ }
334
+ .ui-datepicker .ui-datepicker-prev span,
335
+ .ui-datepicker .ui-datepicker-next span {
336
+ display: block;
337
+ position: absolute;
338
+ left: 50%;
339
+ margin-left: -8px;
340
+ top: 50%;
341
+ margin-top: -8px;
342
+ }
343
+ .ui-datepicker .ui-datepicker-title {
344
+ margin: 0 2.3em;
345
+ line-height: 1.8em;
346
+ text-align: center;
347
+ }
348
+ .ui-datepicker .ui-datepicker-title select {
349
+ font-size: 1em;
350
+ margin: 1px 0;
351
+ }
352
+ .ui-datepicker select.ui-datepicker-month-year {
353
+ width: 100%;
354
+ }
355
+ .ui-datepicker select.ui-datepicker-month,
356
+ .ui-datepicker select.ui-datepicker-year {
357
+ width: 49%;
358
+ }
359
+ .ui-datepicker table {
360
+ width: 100%;
361
+ font-size: .9em;
362
+ border-collapse: collapse;
363
+ margin: 0 0 .4em;
364
+ }
365
+ .ui-datepicker th {
366
+ padding: .7em .3em;
367
+ text-align: center;
368
+ font-weight: bold;
369
+ border: 0;
370
+ }
371
+ .ui-datepicker td {
372
+ border: 0;
373
+ padding: 1px;
374
+ }
375
+ .ui-datepicker td span,
376
+ .ui-datepicker td a {
377
+ display: block;
378
+ padding: .2em;
379
+ text-align: right;
380
+ text-decoration: none;
381
+ }
382
+ .ui-datepicker .ui-datepicker-buttonpane {
383
+ background-image: none;
384
+ margin: .7em 0 0 0;
385
+ padding: 0 .2em;
386
+ border-left: 0;
387
+ border-right: 0;
388
+ border-bottom: 0;
389
+ }
390
+ .ui-datepicker .ui-datepicker-buttonpane button {
391
+ float: right;
392
+ margin: .5em .2em .4em;
393
+ cursor: pointer;
394
+ padding: .2em .6em .3em .6em;
395
+ width: auto;
396
+ overflow: visible;
397
+ }
398
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
399
+ float: left;
400
+ }
401
+
402
+ /* with multiple calendars */
403
+ .ui-datepicker.ui-datepicker-multi {
404
+ width: auto;
405
+ }
406
+ .ui-datepicker-multi .ui-datepicker-group {
407
+ float: left;
408
+ }
409
+ .ui-datepicker-multi .ui-datepicker-group table {
410
+ width: 95%;
411
+ margin: 0 auto .4em;
412
+ }
413
+ .ui-datepicker-multi-2 .ui-datepicker-group {
414
+ width: 50%;
415
+ }
416
+ .ui-datepicker-multi-3 .ui-datepicker-group {
417
+ width: 33.3%;
418
+ }
419
+ .ui-datepicker-multi-4 .ui-datepicker-group {
420
+ width: 25%;
421
+ }
422
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
423
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
424
+ border-left-width: 0;
425
+ }
426
+ .ui-datepicker-multi .ui-datepicker-buttonpane {
427
+ clear: left;
428
+ }
429
+ .ui-datepicker-row-break {
430
+ clear: both;
431
+ width: 100%;
432
+ font-size: 0;
433
+ }
434
+
435
+ /* RTL support */
436
+ .ui-datepicker-rtl {
437
+ direction: rtl;
438
+ }
439
+ .ui-datepicker-rtl .ui-datepicker-prev {
440
+ right: 2px;
441
+ left: auto;
442
+ }
443
+ .ui-datepicker-rtl .ui-datepicker-next {
444
+ left: 2px;
445
+ right: auto;
446
+ }
447
+ .ui-datepicker-rtl .ui-datepicker-prev:hover {
448
+ right: 1px;
449
+ left: auto;
450
+ }
451
+ .ui-datepicker-rtl .ui-datepicker-next:hover {
452
+ left: 1px;
453
+ right: auto;
454
+ }
455
+ .ui-datepicker-rtl .ui-datepicker-buttonpane {
456
+ clear: right;
457
+ }
458
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button {
459
+ float: left;
460
+ }
461
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
462
+ .ui-datepicker-rtl .ui-datepicker-group {
463
+ float: right;
464
+ }
465
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
466
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
467
+ border-right-width: 0;
468
+ border-left-width: 1px;
469
+ }
470
+ .ui-dialog {
471
+ position: absolute;
472
+ top: 0;
473
+ left: 0;
474
+ padding: .2em;
475
+ outline: 0;
476
+ }
477
+ .ui-dialog .ui-dialog-titlebar {
478
+ padding: .4em 1em;
479
+ position: relative;
480
+ }
481
+ .ui-dialog .ui-dialog-title {
482
+ float: left;
483
+ margin: .1em 0;
484
+ white-space: nowrap;
485
+ width: 90%;
486
+ overflow: hidden;
487
+ text-overflow: ellipsis;
488
+ }
489
+ .ui-dialog .ui-dialog-titlebar-close {
490
+ position: absolute;
491
+ right: .3em;
492
+ top: 50%;
493
+ width: 21px;
494
+ margin: -10px 0 0 0;
495
+ padding: 1px;
496
+ height: 20px;
497
+ }
498
+ .ui-dialog .ui-dialog-content {
499
+ position: relative;
500
+ border: 0;
501
+ padding: .5em 1em;
502
+ background: none;
503
+ overflow: auto;
504
+ }
505
+ .ui-dialog .ui-dialog-buttonpane {
506
+ text-align: left;
507
+ border-width: 1px 0 0 0;
508
+ background-image: none;
509
+ margin-top: .5em;
510
+ padding: .3em 1em .5em .4em;
511
+ }
512
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
513
+ float: right;
514
+ }
515
+ .ui-dialog .ui-dialog-buttonpane button {
516
+ margin: .5em .4em .5em 0;
517
+ cursor: pointer;
518
+ }
519
+ .ui-dialog .ui-resizable-se {
520
+ width: 12px;
521
+ height: 12px;
522
+ right: -5px;
523
+ bottom: -5px;
524
+ background-position: 16px 16px;
525
+ }
526
+ .ui-draggable .ui-dialog-titlebar {
527
+ cursor: move;
528
+ }
529
+ .ui-menu {
530
+ list-style: none;
531
+ padding: 2px;
532
+ margin: 0;
533
+ display: block;
534
+ outline: none;
535
+ }
536
+ .ui-menu .ui-menu {
537
+ margin-top: -3px;
538
+ position: absolute;
539
+ }
540
+ .ui-menu .ui-menu-item {
541
+ margin: 0;
542
+ padding: 0;
543
+ width: 100%;
544
+ }
545
+ .ui-menu .ui-menu-divider {
546
+ margin: 5px -2px 5px -2px;
547
+ height: 0;
548
+ font-size: 0;
549
+ line-height: 0;
550
+ border-width: 1px 0 0 0;
551
+ }
552
+ .ui-menu .ui-menu-item a {
553
+ text-decoration: none;
554
+ display: block;
555
+ padding: 2px .4em;
556
+ line-height: 1.5;
557
+ min-height: 0; /* support: IE7 */
558
+ font-weight: normal;
559
+ }
560
+ .ui-menu .ui-menu-item a.ui-state-focus,
561
+ .ui-menu .ui-menu-item a.ui-state-active {
562
+ font-weight: normal;
563
+ margin: -1px;
564
+ }
565
+
566
+ .ui-menu .ui-state-disabled {
567
+ font-weight: normal;
568
+ margin: .4em 0 .2em;
569
+ line-height: 1.5;
570
+ }
571
+ .ui-menu .ui-state-disabled a {
572
+ cursor: default;
573
+ }
574
+
575
+ /* icon support */
576
+ .ui-menu-icons {
577
+ position: relative;
578
+ }
579
+ .ui-menu-icons .ui-menu-item a {
580
+ position: relative;
581
+ padding-left: 2em;
582
+ }
583
+
584
+ /* left-aligned */
585
+ .ui-menu .ui-icon {
586
+ position: absolute;
587
+ top: .2em;
588
+ left: .2em;
589
+ }
590
+
591
+ /* right-aligned */
592
+ .ui-menu .ui-menu-icon {
593
+ position: static;
594
+ float: right;
595
+ }
596
+ .ui-progressbar {
597
+ height: 2em;
598
+ text-align: left;
599
+ overflow: hidden;
600
+ }
601
+ .ui-progressbar .ui-progressbar-value {
602
+ margin: -1px;
603
+ height: 100%;
604
+ }
605
+ .ui-progressbar .ui-progressbar-overlay {
606
+ background: url("images/animated-overlay.gif");
607
+ height: 100%;
608
+ filter: alpha(opacity=25);
609
+ opacity: 0.25;
610
+ }
611
+ .ui-progressbar-indeterminate .ui-progressbar-value {
612
+ background-image: none;
613
+ }
614
+ .ui-slider {
615
+ position: relative;
616
+ text-align: left;
617
+ }
618
+ .ui-slider .ui-slider-handle {
619
+ position: absolute;
620
+ z-index: 2;
621
+ width: 1.2em;
622
+ height: 1.2em;
623
+ cursor: default;
624
+ }
625
+ .ui-slider .ui-slider-range {
626
+ position: absolute;
627
+ z-index: 1;
628
+ font-size: .7em;
629
+ display: block;
630
+ border: 0;
631
+ background-position: 0 0;
632
+ }
633
+
634
+ /* For IE8 - See #6727 */
635
+ .ui-slider.ui-state-disabled .ui-slider-handle,
636
+ .ui-slider.ui-state-disabled .ui-slider-range {
637
+ filter: inherit;
638
+ }
639
+
640
+ .ui-slider-horizontal {
641
+ height: .8em;
642
+ }
643
+ .ui-slider-horizontal .ui-slider-handle {
644
+ top: -.3em;
645
+ margin-left: -.6em;
646
+ }
647
+ .ui-slider-horizontal .ui-slider-range {
648
+ top: 0;
649
+ height: 100%;
650
+ }
651
+ .ui-slider-horizontal .ui-slider-range-min {
652
+ left: 0;
653
+ }
654
+ .ui-slider-horizontal .ui-slider-range-max {
655
+ right: 0;
656
+ }
657
+
658
+ .ui-slider-vertical {
659
+ width: .8em;
660
+ height: 100px;
661
+ }
662
+ .ui-slider-vertical .ui-slider-handle {
663
+ left: -.3em;
664
+ margin-left: 0;
665
+ margin-bottom: -.6em;
666
+ }
667
+ .ui-slider-vertical .ui-slider-range {
668
+ left: 0;
669
+ width: 100%;
670
+ }
671
+ .ui-slider-vertical .ui-slider-range-min {
672
+ bottom: 0;
673
+ }
674
+ .ui-slider-vertical .ui-slider-range-max {
675
+ top: 0;
676
+ }
677
+ .ui-spinner {
678
+ position: relative;
679
+ display: inline-block;
680
+ overflow: hidden;
681
+ padding: 0;
682
+ vertical-align: middle;
683
+ }
684
+ .ui-spinner-input {
685
+ border: none;
686
+ background: none;
687
+ color: inherit;
688
+ padding: 0;
689
+ margin: .2em 0;
690
+ vertical-align: middle;
691
+ margin-left: .4em;
692
+ margin-right: 22px;
693
+ }
694
+ .ui-spinner-button {
695
+ width: 16px;
696
+ height: 50%;
697
+ font-size: .5em;
698
+ padding: 0;
699
+ margin: 0;
700
+ text-align: center;
701
+ position: absolute;
702
+ cursor: default;
703
+ display: block;
704
+ overflow: hidden;
705
+ right: 0;
706
+ }
707
+ /* more specificity required here to overide default borders */
708
+ .ui-spinner a.ui-spinner-button {
709
+ border-top: none;
710
+ border-bottom: none;
711
+ border-right: none;
712
+ }
713
+ /* vertical centre icon */
714
+ .ui-spinner .ui-icon {
715
+ position: absolute;
716
+ margin-top: -8px;
717
+ top: 50%;
718
+ left: 0;
719
+ }
720
+ .ui-spinner-up {
721
+ top: 0;
722
+ }
723
+ .ui-spinner-down {
724
+ bottom: 0;
725
+ }
726
+
727
+ /* TR overrides */
728
+ .ui-spinner .ui-icon-triangle-1-s {
729
+ /* need to fix icons sprite */
730
+ background-position: -65px -16px;
731
+ }
732
+ .ui-tabs {
733
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
734
+ padding: .2em;
735
+ }
736
+ .ui-tabs .ui-tabs-nav {
737
+ margin: 0;
738
+ padding: .2em .2em 0;
739
+ }
740
+ .ui-tabs .ui-tabs-nav li {
741
+ list-style: none;
742
+ float: left;
743
+ position: relative;
744
+ top: 0;
745
+ margin: 1px .2em 0 0;
746
+ border-bottom: 0;
747
+ padding: 0;
748
+ white-space: nowrap;
749
+ }
750
+ .ui-tabs .ui-tabs-nav li a {
751
+ float: left;
752
+ padding: .5em 1em;
753
+ text-decoration: none;
754
+ }
755
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active {
756
+ margin-bottom: -1px;
757
+ padding-bottom: 1px;
758
+ }
759
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
760
+ .ui-tabs .ui-tabs-nav li.ui-state-disabled a,
761
+ .ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
762
+ cursor: text;
763
+ }
764
+ .ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
765
+ .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
766
+ cursor: pointer;
767
+ }
768
+ .ui-tabs .ui-tabs-panel {
769
+ display: block;
770
+ border-width: 0;
771
+ padding: 1em 1.4em;
772
+ background: none;
773
+ }
774
+ .ui-tooltip {
775
+ padding: 8px;
776
+ position: absolute;
777
+ z-index: 9999;
778
+ max-width: 300px;
779
+ -webkit-box-shadow: 0 0 5px #aaa;
780
+ box-shadow: 0 0 5px #aaa;
781
+ }
782
+ body .ui-tooltip {
783
+ border-width: 2px;
784
+ }
785
+
786
+ /* Component containers
787
+ ----------------------------------*/
788
+ .ui-widget {
789
+ font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
790
+ font-size: 1.1em;
791
+ }
792
+ .ui-widget .ui-widget {
793
+ font-size: 1em;
794
+ }
795
+ .ui-widget input,
796
+ .ui-widget select,
797
+ .ui-widget textarea,
798
+ .ui-widget button {
799
+ font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
800
+ font-size: 1em;
801
+ }
802
+ .ui-widget-content {
803
+ border: 1px solid #a6c9e2;
804
+ background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;
805
+ color: #222222;
806
+ }
807
+ .ui-widget-content a {
808
+ color: #222222;
809
+ }
810
+ .ui-widget-header {
811
+ border: 1px solid #4297d7;
812
+ background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x;
813
+ color: #ffffff;
814
+ font-weight: bold;
815
+ }
816
+ .ui-widget-header a {
817
+ color: #ffffff;
818
+ }
819
+
820
+ /* Interaction states
821
+ ----------------------------------*/
822
+ .ui-state-default,
823
+ .ui-widget-content .ui-state-default,
824
+ .ui-widget-header .ui-state-default {
825
+ border: 1px solid #c5dbec;
826
+ background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x;
827
+ font-weight: bold;
828
+ color: #2e6e9e;
829
+ }
830
+ .ui-state-default a,
831
+ .ui-state-default a:link,
832
+ .ui-state-default a:visited {
833
+ color: #2e6e9e;
834
+ text-decoration: none;
835
+ }
836
+ .ui-state-hover,
837
+ .ui-widget-content .ui-state-hover,
838
+ .ui-widget-header .ui-state-hover,
839
+ .ui-state-focus,
840
+ .ui-widget-content .ui-state-focus,
841
+ .ui-widget-header .ui-state-focus {
842
+ border: 1px solid #79b7e7;
843
+ background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x;
844
+ font-weight: bold;
845
+ color: #1d5987;
846
+ }
847
+ .ui-state-hover a,
848
+ .ui-state-hover a:hover,
849
+ .ui-state-hover a:link,
850
+ .ui-state-hover a:visited {
851
+ color: #1d5987;
852
+ text-decoration: none;
853
+ }
854
+ .ui-state-active,
855
+ .ui-widget-content .ui-state-active,
856
+ .ui-widget-header .ui-state-active {
857
+ border: 1px solid #79b7e7;
858
+ background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x;
859
+ font-weight: bold;
860
+ color: #e17009;
861
+ }
862
+ .ui-state-active a,
863
+ .ui-state-active a:link,
864
+ .ui-state-active a:visited {
865
+ color: #e17009;
866
+ text-decoration: none;
867
+ }
868
+
869
+ /* Interaction Cues
870
+ ----------------------------------*/
871
+ .ui-state-highlight,
872
+ .ui-widget-content .ui-state-highlight,
873
+ .ui-widget-header .ui-state-highlight {
874
+ border: 1px solid #fad42e;
875
+ background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;
876
+ color: #363636;
877
+ }
878
+ .ui-state-highlight a,
879
+ .ui-widget-content .ui-state-highlight a,
880
+ .ui-widget-header .ui-state-highlight a {
881
+ color: #363636;
882
+ }
883
+ .ui-state-error,
884
+ .ui-widget-content .ui-state-error,
885
+ .ui-widget-header .ui-state-error {
886
+ border: 1px solid #cd0a0a;
887
+ background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;
888
+ color: #cd0a0a;
889
+ }
890
+ .ui-state-error a,
891
+ .ui-widget-content .ui-state-error a,
892
+ .ui-widget-header .ui-state-error a {
893
+ color: #cd0a0a;
894
+ }
895
+ .ui-state-error-text,
896
+ .ui-widget-content .ui-state-error-text,
897
+ .ui-widget-header .ui-state-error-text {
898
+ color: #cd0a0a;
899
+ }
900
+ .ui-priority-primary,
901
+ .ui-widget-content .ui-priority-primary,
902
+ .ui-widget-header .ui-priority-primary {
903
+ font-weight: bold;
904
+ }
905
+ .ui-priority-secondary,
906
+ .ui-widget-content .ui-priority-secondary,
907
+ .ui-widget-header .ui-priority-secondary {
908
+ opacity: .7;
909
+ filter:Alpha(Opacity=70);
910
+ font-weight: normal;
911
+ }
912
+ .ui-state-disabled,
913
+ .ui-widget-content .ui-state-disabled,
914
+ .ui-widget-header .ui-state-disabled {
915
+ opacity: .35;
916
+ filter:Alpha(Opacity=35);
917
+ background-image: none;
918
+ }
919
+ .ui-state-disabled .ui-icon {
920
+ filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
921
+ }
922
+
923
+ /* Icons
924
+ ----------------------------------*/
925
+
926
+ /* states and images */
927
+ .ui-icon {
928
+ width: 16px;
929
+ height: 16px;
930
+ background-position: 16px 16px;
931
+ }
932
+ .ui-icon,
933
+ .ui-widget-content .ui-icon {
934
+ background-image: url(images/ui-icons_469bdd_256x240.png);
935
+ }
936
+ .ui-widget-header .ui-icon {
937
+ background-image: url(images/ui-icons_d8e7f3_256x240.png);
938
+ }
939
+ .ui-state-default .ui-icon {
940
+ background-image: url(images/ui-icons_6da8d5_256x240.png);
941
+ }
942
+ .ui-state-hover .ui-icon,
943
+ .ui-state-focus .ui-icon {
944
+ background-image: url(images/ui-icons_217bc0_256x240.png);
945
+ }
946
+ .ui-state-active .ui-icon {
947
+ background-image: url(images/ui-icons_f9bd01_256x240.png);
948
+ }
949
+ .ui-state-highlight .ui-icon {
950
+ background-image: url(images/ui-icons_2e83ff_256x240.png);
951
+ }
952
+ .ui-state-error .ui-icon,
953
+ .ui-state-error-text .ui-icon {
954
+ background-image: url(images/ui-icons_cd0a0a_256x240.png);
955
+ }
956
+
957
+ /* positioning */
958
+ .ui-icon-carat-1-n { background-position: 0 0; }
959
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
960
+ .ui-icon-carat-1-e { background-position: -32px 0; }
961
+ .ui-icon-carat-1-se { background-position: -48px 0; }
962
+ .ui-icon-carat-1-s { background-position: -64px 0; }
963
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
964
+ .ui-icon-carat-1-w { background-position: -96px 0; }
965
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
966
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
967
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
968
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
969
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
970
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
971
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
972
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
973
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
974
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
975
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
976
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
977
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
978
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
979
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
980
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
981
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
982
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
983
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
984
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
985
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
986
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
987
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
988
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
989
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
990
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
991
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
992
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
993
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
994
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
995
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
996
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
997
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
998
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
999
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
1000
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
1001
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
1002
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
1003
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
1004
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
1005
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
1006
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
1007
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
1008
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
1009
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
1010
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
1011
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
1012
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
1013
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
1014
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
1015
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
1016
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
1017
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
1018
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
1019
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
1020
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
1021
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
1022
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
1023
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
1024
+ .ui-icon-extlink { background-position: -32px -80px; }
1025
+ .ui-icon-newwin { background-position: -48px -80px; }
1026
+ .ui-icon-refresh { background-position: -64px -80px; }
1027
+ .ui-icon-shuffle { background-position: -80px -80px; }
1028
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
1029
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
1030
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
1031
+ .ui-icon-folder-open { background-position: -16px -96px; }
1032
+ .ui-icon-document { background-position: -32px -96px; }
1033
+ .ui-icon-document-b { background-position: -48px -96px; }
1034
+ .ui-icon-note { background-position: -64px -96px; }
1035
+ .ui-icon-mail-closed { background-position: -80px -96px; }
1036
+ .ui-icon-mail-open { background-position: -96px -96px; }
1037
+ .ui-icon-suitcase { background-position: -112px -96px; }
1038
+ .ui-icon-comment { background-position: -128px -96px; }
1039
+ .ui-icon-person { background-position: -144px -96px; }
1040
+ .ui-icon-print { background-position: -160px -96px; }
1041
+ .ui-icon-trash { background-position: -176px -96px; }
1042
+ .ui-icon-locked { background-position: -192px -96px; }
1043
+ .ui-icon-unlocked { background-position: -208px -96px; }
1044
+ .ui-icon-bookmark { background-position: -224px -96px; }
1045
+ .ui-icon-tag { background-position: -240px -96px; }
1046
+ .ui-icon-home { background-position: 0 -112px; }
1047
+ .ui-icon-flag { background-position: -16px -112px; }
1048
+ .ui-icon-calendar { background-position: -32px -112px; }
1049
+ .ui-icon-cart { background-position: -48px -112px; }
1050
+ .ui-icon-pencil { background-position: -64px -112px; }
1051
+ .ui-icon-clock { background-position: -80px -112px; }
1052
+ .ui-icon-disk { background-position: -96px -112px; }
1053
+ .ui-icon-calculator { background-position: -112px -112px; }
1054
+ .ui-icon-zoomin { background-position: -128px -112px; }
1055
+ .ui-icon-zoomout { background-position: -144px -112px; }
1056
+ .ui-icon-search { background-position: -160px -112px; }
1057
+ .ui-icon-wrench { background-position: -176px -112px; }
1058
+ .ui-icon-gear { background-position: -192px -112px; }
1059
+ .ui-icon-heart { background-position: -208px -112px; }
1060
+ .ui-icon-star { background-position: -224px -112px; }
1061
+ .ui-icon-link { background-position: -240px -112px; }
1062
+ .ui-icon-cancel { background-position: 0 -128px; }
1063
+ .ui-icon-plus { background-position: -16px -128px; }
1064
+ .ui-icon-plusthick { background-position: -32px -128px; }
1065
+ .ui-icon-minus { background-position: -48px -128px; }
1066
+ .ui-icon-minusthick { background-position: -64px -128px; }
1067
+ .ui-icon-close { background-position: -80px -128px; }
1068
+ .ui-icon-closethick { background-position: -96px -128px; }
1069
+ .ui-icon-key { background-position: -112px -128px; }
1070
+ .ui-icon-lightbulb { background-position: -128px -128px; }
1071
+ .ui-icon-scissors { background-position: -144px -128px; }
1072
+ .ui-icon-clipboard { background-position: -160px -128px; }
1073
+ .ui-icon-copy { background-position: -176px -128px; }
1074
+ .ui-icon-contact { background-position: -192px -128px; }
1075
+ .ui-icon-image { background-position: -208px -128px; }
1076
+ .ui-icon-video { background-position: -224px -128px; }
1077
+ .ui-icon-script { background-position: -240px -128px; }
1078
+ .ui-icon-alert { background-position: 0 -144px; }
1079
+ .ui-icon-info { background-position: -16px -144px; }
1080
+ .ui-icon-notice { background-position: -32px -144px; }
1081
+ .ui-icon-help { background-position: -48px -144px; }
1082
+ .ui-icon-check { background-position: -64px -144px; }
1083
+ .ui-icon-bullet { background-position: -80px -144px; }
1084
+ .ui-icon-radio-on { background-position: -96px -144px; }
1085
+ .ui-icon-radio-off { background-position: -112px -144px; }
1086
+ .ui-icon-pin-w { background-position: -128px -144px; }
1087
+ .ui-icon-pin-s { background-position: -144px -144px; }
1088
+ .ui-icon-play { background-position: 0 -160px; }
1089
+ .ui-icon-pause { background-position: -16px -160px; }
1090
+ .ui-icon-seek-next { background-position: -32px -160px; }
1091
+ .ui-icon-seek-prev { background-position: -48px -160px; }
1092
+ .ui-icon-seek-end { background-position: -64px -160px; }
1093
+ .ui-icon-seek-start { background-position: -80px -160px; }
1094
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
1095
+ .ui-icon-seek-first { background-position: -80px -160px; }
1096
+ .ui-icon-stop { background-position: -96px -160px; }
1097
+ .ui-icon-eject { background-position: -112px -160px; }
1098
+ .ui-icon-volume-off { background-position: -128px -160px; }
1099
+ .ui-icon-volume-on { background-position: -144px -160px; }
1100
+ .ui-icon-power { background-position: 0 -176px; }
1101
+ .ui-icon-signal-diag { background-position: -16px -176px; }
1102
+ .ui-icon-signal { background-position: -32px -176px; }
1103
+ .ui-icon-battery-0 { background-position: -48px -176px; }
1104
+ .ui-icon-battery-1 { background-position: -64px -176px; }
1105
+ .ui-icon-battery-2 { background-position: -80px -176px; }
1106
+ .ui-icon-battery-3 { background-position: -96px -176px; }
1107
+ .ui-icon-circle-plus { background-position: 0 -192px; }
1108
+ .ui-icon-circle-minus { background-position: -16px -192px; }
1109
+ .ui-icon-circle-close { background-position: -32px -192px; }
1110
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
1111
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
1112
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
1113
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
1114
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
1115
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
1116
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
1117
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
1118
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
1119
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
1120
+ .ui-icon-circle-check { background-position: -208px -192px; }
1121
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
1122
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
1123
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
1124
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
1125
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
1126
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
1127
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
1128
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
1129
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
1130
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
1131
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
1132
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
1133
+
1134
+
1135
+ /* Misc visuals
1136
+ ----------------------------------*/
1137
+
1138
+ /* Corner radius */
1139
+ .ui-corner-all,
1140
+ .ui-corner-top,
1141
+ .ui-corner-left,
1142
+ .ui-corner-tl {
1143
+ border-top-left-radius: 5px;
1144
+ }
1145
+ .ui-corner-all,
1146
+ .ui-corner-top,
1147
+ .ui-corner-right,
1148
+ .ui-corner-tr {
1149
+ border-top-right-radius: 5px;
1150
+ }
1151
+ .ui-corner-all,
1152
+ .ui-corner-bottom,
1153
+ .ui-corner-left,
1154
+ .ui-corner-bl {
1155
+ border-bottom-left-radius: 5px;
1156
+ }
1157
+ .ui-corner-all,
1158
+ .ui-corner-bottom,
1159
+ .ui-corner-right,
1160
+ .ui-corner-br {
1161
+ border-bottom-right-radius: 5px;
1162
+ }
1163
+
1164
+ /* Overlays */
1165
+ .ui-widget-overlay {
1166
+ background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
1167
+ opacity: .3;
1168
+ filter: Alpha(Opacity=30);
1169
+ }
1170
+ .ui-widget-shadow {
1171
+ margin: -8px 0 0 -8px;
1172
+ padding: 8px;
1173
+ background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
1174
+ opacity: .3;
1175
+ filter: Alpha(Opacity=30);
1176
+ border-radius: 8px;
1177
+ }
static/js/jquery/css/smoothness/jquery-ui.css CHANGED
@@ -1,405 +1,405 @@
1
- /*
2
- * jQuery UI CSS Framework
3
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4
- * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
5
- */
6
-
7
- /* Layout helpers
8
- ----------------------------------*/
9
- .ui-helper-hidden { display: none; }
10
- .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
11
- .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
12
- .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
13
- .ui-helper-clearfix { display: inline-block; }
14
- /* required comment for clearfix to work in Opera \*/
15
- * html .ui-helper-clearfix { height:1%; }
16
- .ui-helper-clearfix { display:block; }
17
- /* end clearfix */
18
- .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
19
-
20
-
21
- /* Interaction Cues
22
- ----------------------------------*/
23
- .ui-state-disabled { cursor: default !important; }
24
-
25
-
26
- /* Icons
27
- ----------------------------------*/
28
-
29
- /* states and images */
30
- .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
31
-
32
-
33
- /* Misc visuals
34
- ----------------------------------*/
35
-
36
- /* Overlays */
37
- .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
38
-
39
- /*
40
- * jQuery UI CSS Framework
41
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
42
- * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
43
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
44
- */
45
-
46
-
47
- /* Component containers
48
- ----------------------------------*/
49
- .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 0.85em; }
50
- .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
51
- .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
52
- .ui-widget-content a { color: #222222; }
53
- .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
54
- .ui-widget-header a { color: #222222; }
55
-
56
- /* Interaction states
57
- ----------------------------------*/
58
- .ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; }
59
- .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; }
60
- .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
61
- .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
62
- .ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
63
- .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
64
-
65
- /* Interaction Cues
66
- ----------------------------------*/
67
- .ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
68
- .ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
69
- .ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
70
- .ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
71
- .ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
72
- .ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
73
- .ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
74
- .ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
75
-
76
- /* Icons
77
- ----------------------------------*/
78
-
79
- /* states and images */
80
- .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
81
- .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
82
- .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
83
- .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
84
- .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
85
- .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
86
- .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
87
- .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
88
-
89
- /* positioning */
90
- .ui-icon-carat-1-n { background-position: 0 0; }
91
- .ui-icon-carat-1-ne { background-position: -16px 0; }
92
- .ui-icon-carat-1-e { background-position: -32px 0; }
93
- .ui-icon-carat-1-se { background-position: -48px 0; }
94
- .ui-icon-carat-1-s { background-position: -64px 0; }
95
- .ui-icon-carat-1-sw { background-position: -80px 0; }
96
- .ui-icon-carat-1-w { background-position: -96px 0; }
97
- .ui-icon-carat-1-nw { background-position: -112px 0; }
98
- .ui-icon-carat-2-n-s { background-position: -128px 0; }
99
- .ui-icon-carat-2-e-w { background-position: -144px 0; }
100
- .ui-icon-triangle-1-n { background-position: 0 -16px; }
101
- .ui-icon-triangle-1-ne { background-position: -16px -16px; }
102
- .ui-icon-triangle-1-e { background-position: -32px -16px; }
103
- .ui-icon-triangle-1-se { background-position: -48px -16px; }
104
- .ui-icon-triangle-1-s { background-position: -64px -16px; }
105
- .ui-icon-triangle-1-sw { background-position: -80px -16px; }
106
- .ui-icon-triangle-1-w { background-position: -96px -16px; }
107
- .ui-icon-triangle-1-nw { background-position: -112px -16px; }
108
- .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
109
- .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
110
- .ui-icon-arrow-1-n { background-position: 0 -32px; }
111
- .ui-icon-arrow-1-ne { background-position: -16px -32px; }
112
- .ui-icon-arrow-1-e { background-position: -32px -32px; }
113
- .ui-icon-arrow-1-se { background-position: -48px -32px; }
114
- .ui-icon-arrow-1-s { background-position: -64px -32px; }
115
- .ui-icon-arrow-1-sw { background-position: -80px -32px; }
116
- .ui-icon-arrow-1-w { background-position: -96px -32px; }
117
- .ui-icon-arrow-1-nw { background-position: -112px -32px; }
118
- .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
119
- .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
120
- .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
121
- .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
122
- .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
123
- .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
124
- .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
125
- .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
126
- .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
127
- .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
128
- .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
129
- .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
130
- .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
131
- .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
132
- .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
133
- .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
134
- .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
135
- .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
136
- .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
137
- .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
138
- .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
139
- .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
140
- .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
141
- .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
142
- .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
143
- .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
144
- .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
145
- .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
146
- .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
147
- .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
148
- .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
149
- .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
150
- .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
151
- .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
152
- .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
153
- .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
154
- .ui-icon-arrow-4 { background-position: 0 -80px; }
155
- .ui-icon-arrow-4-diag { background-position: -16px -80px; }
156
- .ui-icon-extlink { background-position: -32px -80px; }
157
- .ui-icon-newwin { background-position: -48px -80px; }
158
- .ui-icon-refresh { background-position: -64px -80px; }
159
- .ui-icon-shuffle { background-position: -80px -80px; }
160
- .ui-icon-transfer-e-w { background-position: -96px -80px; }
161
- .ui-icon-transferthick-e-w { background-position: -112px -80px; }
162
- .ui-icon-folder-collapsed { background-position: 0 -96px; }
163
- .ui-icon-folder-open { background-position: -16px -96px; }
164
- .ui-icon-document { background-position: -32px -96px; }
165
- .ui-icon-document-b { background-position: -48px -96px; }
166
- .ui-icon-note { background-position: -64px -96px; }
167
- .ui-icon-mail-closed { background-position: -80px -96px; }
168
- .ui-icon-mail-open { background-position: -96px -96px; }
169
- .ui-icon-suitcase { background-position: -112px -96px; }
170
- .ui-icon-comment { background-position: -128px -96px; }
171
- .ui-icon-person { background-position: -144px -96px; }
172
- .ui-icon-print { background-position: -160px -96px; }
173
- .ui-icon-trash { background-position: -176px -96px; }
174
- .ui-icon-locked { background-position: -192px -96px; }
175
- .ui-icon-unlocked { background-position: -208px -96px; }
176
- .ui-icon-bookmark { background-position: -224px -96px; }
177
- .ui-icon-tag { background-position: -240px -96px; }
178
- .ui-icon-home { background-position: 0 -112px; }
179
- .ui-icon-flag { background-position: -16px -112px; }
180
- .ui-icon-calendar { background-position: -32px -112px; }
181
- .ui-icon-cart { background-position: -48px -112px; }
182
- .ui-icon-pencil { background-position: -64px -112px; }
183
- .ui-icon-clock { background-position: -80px -112px; }
184
- .ui-icon-disk { background-position: -96px -112px; }
185
- .ui-icon-calculator { background-position: -112px -112px; }
186
- .ui-icon-zoomin { background-position: -128px -112px; }
187
- .ui-icon-zoomout { background-position: -144px -112px; }
188
- .ui-icon-search { background-position: -160px -112px; }
189
- .ui-icon-wrench { background-position: -176px -112px; }
190
- .ui-icon-gear { background-position: -192px -112px; }
191
- .ui-icon-heart { background-position: -208px -112px; }
192
- .ui-icon-star { background-position: -224px -112px; }
193
- .ui-icon-link { background-position: -240px -112px; }
194
- .ui-icon-cancel { background-position: 0 -128px; }
195
- .ui-icon-plus { background-position: -16px -128px; }
196
- .ui-icon-plusthick { background-position: -32px -128px; }
197
- .ui-icon-minus { background-position: -48px -128px; }
198
- .ui-icon-minusthick { background-position: -64px -128px; }
199
- .ui-icon-close { background-position: -80px -128px; }
200
- .ui-icon-closethick { background-position: -96px -128px; }
201
- .ui-icon-key { background-position: -112px -128px; }
202
- .ui-icon-lightbulb { background-position: -128px -128px; }
203
- .ui-icon-scissors { background-position: -144px -128px; }
204
- .ui-icon-clipboard { background-position: -160px -128px; }
205
- .ui-icon-copy { background-position: -176px -128px; }
206
- .ui-icon-contact { background-position: -192px -128px; }
207
- .ui-icon-image { background-position: -208px -128px; }
208
- .ui-icon-video { background-position: -224px -128px; }
209
- .ui-icon-script { background-position: -240px -128px; }
210
- .ui-icon-alert { background-position: 0 -144px; }
211
- .ui-icon-info { background-position: -16px -144px; }
212
- .ui-icon-notice { background-position: -32px -144px; }
213
- .ui-icon-help { background-position: -48px -144px; }
214
- .ui-icon-check { background-position: -64px -144px; }
215
- .ui-icon-bullet { background-position: -80px -144px; }
216
- .ui-icon-radio-off { background-position: -96px -144px; }
217
- .ui-icon-radio-on { background-position: -112px -144px; }
218
- .ui-icon-pin-w { background-position: -128px -144px; }
219
- .ui-icon-pin-s { background-position: -144px -144px; }
220
- .ui-icon-play { background-position: 0 -160px; }
221
- .ui-icon-pause { background-position: -16px -160px; }
222
- .ui-icon-seek-next { background-position: -32px -160px; }
223
- .ui-icon-seek-prev { background-position: -48px -160px; }
224
- .ui-icon-seek-end { background-position: -64px -160px; }
225
- .ui-icon-seek-first { background-position: -80px -160px; }
226
- .ui-icon-stop { background-position: -96px -160px; }
227
- .ui-icon-eject { background-position: -112px -160px; }
228
- .ui-icon-volume-off { background-position: -128px -160px; }
229
- .ui-icon-volume-on { background-position: -144px -160px; }
230
- .ui-icon-power { background-position: 0 -176px; }
231
- .ui-icon-signal-diag { background-position: -16px -176px; }
232
- .ui-icon-signal { background-position: -32px -176px; }
233
- .ui-icon-battery-0 { background-position: -48px -176px; }
234
- .ui-icon-battery-1 { background-position: -64px -176px; }
235
- .ui-icon-battery-2 { background-position: -80px -176px; }
236
- .ui-icon-battery-3 { background-position: -96px -176px; }
237
- .ui-icon-circle-plus { background-position: 0 -192px; }
238
- .ui-icon-circle-minus { background-position: -16px -192px; }
239
- .ui-icon-circle-close { background-position: -32px -192px; }
240
- .ui-icon-circle-triangle-e { background-position: -48px -192px; }
241
- .ui-icon-circle-triangle-s { background-position: -64px -192px; }
242
- .ui-icon-circle-triangle-w { background-position: -80px -192px; }
243
- .ui-icon-circle-triangle-n { background-position: -96px -192px; }
244
- .ui-icon-circle-arrow-e { background-position: -112px -192px; }
245
- .ui-icon-circle-arrow-s { background-position: -128px -192px; }
246
- .ui-icon-circle-arrow-w { background-position: -144px -192px; }
247
- .ui-icon-circle-arrow-n { background-position: -160px -192px; }
248
- .ui-icon-circle-zoomin { background-position: -176px -192px; }
249
- .ui-icon-circle-zoomout { background-position: -192px -192px; }
250
- .ui-icon-circle-check { background-position: -208px -192px; }
251
- .ui-icon-circlesmall-plus { background-position: 0 -208px; }
252
- .ui-icon-circlesmall-minus { background-position: -16px -208px; }
253
- .ui-icon-circlesmall-close { background-position: -32px -208px; }
254
- .ui-icon-squaresmall-plus { background-position: -48px -208px; }
255
- .ui-icon-squaresmall-minus { background-position: -64px -208px; }
256
- .ui-icon-squaresmall-close { background-position: -80px -208px; }
257
- .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
258
- .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
259
- .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
260
- .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
261
- .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
262
- .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
263
-
264
-
265
- /* Misc visuals
266
- ----------------------------------*/
267
-
268
- /* Corner radius */
269
- .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
270
- .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
271
- .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
272
- .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
273
- .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
274
- .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
275
- .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
276
- .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
277
- .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
278
-
279
- /* Overlays */
280
- .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
281
- .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Resizable
282
- ----------------------------------*/
283
- .ui-resizable { position: relative;}
284
- .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
285
- .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
286
- .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
287
- .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
288
- .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
289
- .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
290
- .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
291
- .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
292
- .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
293
- .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Accordion
294
- ----------------------------------*/
295
- .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
296
- .ui-accordion .ui-accordion-li-fix { display: inline; }
297
- .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
298
- .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
299
- .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
300
- .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
301
- .ui-accordion .ui-accordion-content-active { display: block; }/* Dialog
302
- ----------------------------------*/
303
- .ui-dialog { position: relative; padding: .2em; width: 300px; }
304
- .ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
305
- .ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
306
- .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
307
- .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
308
- .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
309
- .ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
310
- .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
311
- .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
312
- .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
313
- .ui-draggable .ui-dialog-titlebar { cursor: move; }
314
- /* Slider
315
- ----------------------------------*/
316
- .ui-slider { position: relative; text-align: left; }
317
- .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
318
- .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
319
-
320
- .ui-slider-horizontal { height: .8em; }
321
- .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
322
- .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
323
- .ui-slider-horizontal .ui-slider-range-min { left: 0; }
324
- .ui-slider-horizontal .ui-slider-range-max { right: 0; }
325
-
326
- .ui-slider-vertical { width: .8em; height: 100px; }
327
- .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
328
- .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
329
- .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
330
- .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
331
- ----------------------------------*/
332
- .ui-tabs { padding: .2em; zoom: 1; }
333
- .ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
334
- .ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
335
- .ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
336
- .ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
337
- .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
338
- .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
339
- .ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
340
- .ui-tabs .ui-tabs-hide { display: none !important; }
341
- /* Datepicker
342
- ----------------------------------*/
343
- .ui-datepicker { width: 17em; padding: .2em .2em 0; }
344
- .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
345
- .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
346
- .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
347
- .ui-datepicker .ui-datepicker-prev { left:2px; }
348
- .ui-datepicker .ui-datepicker-next { right:2px; }
349
- .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
350
- .ui-datepicker .ui-datepicker-next-hover { right:1px; }
351
- .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
352
- .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
353
- .ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
354
- .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
355
- .ui-datepicker select.ui-datepicker-month,
356
- .ui-datepicker select.ui-datepicker-year { width: 49%;}
357
- .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
358
- .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
359
- .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
360
- .ui-datepicker td { border: 0; padding: 1px; }
361
- .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
362
- .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
363
- .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
364
- .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
365
-
366
- /* with multiple calendars */
367
- .ui-datepicker.ui-datepicker-multi { width:auto; }
368
- .ui-datepicker-multi .ui-datepicker-group { float:left; }
369
- .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
370
- .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
371
- .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
372
- .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
373
- .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
374
- .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
375
- .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
376
- .ui-datepicker-row-break { clear:both; width:100%; }
377
-
378
- /* RTL support */
379
- .ui-datepicker-rtl { direction: rtl; }
380
- .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
381
- .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
382
- .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
383
- .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
384
- .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
385
- .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
386
- .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
387
- .ui-datepicker-rtl .ui-datepicker-group { float:right; }
388
- .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
389
- .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
390
-
391
- /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
392
- .ui-datepicker-cover {
393
- display: none; /*sorry for IE5*/
394
- display/**/: block; /*sorry for IE5*/
395
- position: absolute; /*must have*/
396
- z-index: -1; /*must have*/
397
- filter: mask(); /*must have*/
398
- top: -4px; /*must have*/
399
- left: -4px; /*must have*/
400
- width: 200px; /*must have*/
401
- height: 200px; /*must have*/
402
- }/* Progressbar
403
- ----------------------------------*/
404
- .ui-progressbar { height:2em; text-align: left; }
405
  .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
1
+ /*
2
+ * jQuery UI CSS Framework
3
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4
+ * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
5
+ */
6
+
7
+ /* Layout helpers
8
+ ----------------------------------*/
9
+ .ui-helper-hidden { display: none; }
10
+ .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
11
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
12
+ .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
13
+ .ui-helper-clearfix { display: inline-block; }
14
+ /* required comment for clearfix to work in Opera \*/
15
+ * html .ui-helper-clearfix { height:1%; }
16
+ .ui-helper-clearfix { display:block; }
17
+ /* end clearfix */
18
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
19
+
20
+
21
+ /* Interaction Cues
22
+ ----------------------------------*/
23
+ .ui-state-disabled { cursor: default !important; }
24
+
25
+
26
+ /* Icons
27
+ ----------------------------------*/
28
+
29
+ /* states and images */
30
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
31
+
32
+
33
+ /* Misc visuals
34
+ ----------------------------------*/
35
+
36
+ /* Overlays */
37
+ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
38
+
39
+ /*
40
+ * jQuery UI CSS Framework
41
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
42
+ * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
43
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
44
+ */
45
+
46
+
47
+ /* Component containers
48
+ ----------------------------------*/
49
+ .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 0.85em; }
50
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
51
+ .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
52
+ .ui-widget-content a { color: #222222; }
53
+ .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
54
+ .ui-widget-header a { color: #222222; }
55
+
56
+ /* Interaction states
57
+ ----------------------------------*/
58
+ .ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; }
59
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; }
60
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
61
+ .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
62
+ .ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
63
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
64
+
65
+ /* Interaction Cues
66
+ ----------------------------------*/
67
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
68
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
69
+ .ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
70
+ .ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
71
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
72
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
73
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
74
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
75
+
76
+ /* Icons
77
+ ----------------------------------*/
78
+
79
+ /* states and images */
80
+ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
81
+ .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
82
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
83
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
84
+ .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
85
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
86
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
87
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
88
+
89
+ /* positioning */
90
+ .ui-icon-carat-1-n { background-position: 0 0; }
91
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
92
+ .ui-icon-carat-1-e { background-position: -32px 0; }
93
+ .ui-icon-carat-1-se { background-position: -48px 0; }
94
+ .ui-icon-carat-1-s { background-position: -64px 0; }
95
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
96
+ .ui-icon-carat-1-w { background-position: -96px 0; }
97
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
98
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
99
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
100
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
101
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
102
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
103
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
104
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
105
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
106
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
107
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
108
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
109
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
110
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
111
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
112
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
113
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
114
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
115
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
116
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
117
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
118
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
119
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
120
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
121
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
122
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
123
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
124
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
125
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
126
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
127
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
128
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
129
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
130
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
131
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
132
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
133
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
134
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
135
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
136
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
137
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
138
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
139
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
140
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
141
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
142
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
143
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
144
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
145
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
146
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
147
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
148
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
149
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
150
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
151
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
152
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
153
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
154
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
155
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
156
+ .ui-icon-extlink { background-position: -32px -80px; }
157
+ .ui-icon-newwin { background-position: -48px -80px; }
158
+ .ui-icon-refresh { background-position: -64px -80px; }
159
+ .ui-icon-shuffle { background-position: -80px -80px; }
160
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
161
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
162
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
163
+ .ui-icon-folder-open { background-position: -16px -96px; }
164
+ .ui-icon-document { background-position: -32px -96px; }
165
+ .ui-icon-document-b { background-position: -48px -96px; }
166
+ .ui-icon-note { background-position: -64px -96px; }
167
+ .ui-icon-mail-closed { background-position: -80px -96px; }
168
+ .ui-icon-mail-open { background-position: -96px -96px; }
169
+ .ui-icon-suitcase { background-position: -112px -96px; }
170
+ .ui-icon-comment { background-position: -128px -96px; }
171
+ .ui-icon-person { background-position: -144px -96px; }
172
+ .ui-icon-print { background-position: -160px -96px; }
173
+ .ui-icon-trash { background-position: -176px -96px; }
174
+ .ui-icon-locked { background-position: -192px -96px; }
175
+ .ui-icon-unlocked { background-position: -208px -96px; }
176
+ .ui-icon-bookmark { background-position: -224px -96px; }
177
+ .ui-icon-tag { background-position: -240px -96px; }
178
+ .ui-icon-home { background-position: 0 -112px; }
179
+ .ui-icon-flag { background-position: -16px -112px; }
180
+ .ui-icon-calendar { background-position: -32px -112px; }
181
+ .ui-icon-cart { background-position: -48px -112px; }
182
+ .ui-icon-pencil { background-position: -64px -112px; }
183
+ .ui-icon-clock { background-position: -80px -112px; }
184
+ .ui-icon-disk { background-position: -96px -112px; }
185
+ .ui-icon-calculator { background-position: -112px -112px; }
186
+ .ui-icon-zoomin { background-position: -128px -112px; }
187
+ .ui-icon-zoomout { background-position: -144px -112px; }
188
+ .ui-icon-search { background-position: -160px -112px; }
189
+ .ui-icon-wrench { background-position: -176px -112px; }
190
+ .ui-icon-gear { background-position: -192px -112px; }
191
+ .ui-icon-heart { background-position: -208px -112px; }
192
+ .ui-icon-star { background-position: -224px -112px; }
193
+ .ui-icon-link { background-position: -240px -112px; }
194
+ .ui-icon-cancel { background-position: 0 -128px; }
195
+ .ui-icon-plus { background-position: -16px -128px; }
196
+ .ui-icon-plusthick { background-position: -32px -128px; }
197
+ .ui-icon-minus { background-position: -48px -128px; }
198
+ .ui-icon-minusthick { background-position: -64px -128px; }
199
+ .ui-icon-close { background-position: -80px -128px; }
200
+ .ui-icon-closethick { background-position: -96px -128px; }
201
+ .ui-icon-key { background-position: -112px -128px; }
202
+ .ui-icon-lightbulb { background-position: -128px -128px; }
203
+ .ui-icon-scissors { background-position: -144px -128px; }
204
+ .ui-icon-clipboard { background-position: -160px -128px; }
205
+ .ui-icon-copy { background-position: -176px -128px; }
206
+ .ui-icon-contact { background-position: -192px -128px; }
207
+ .ui-icon-image { background-position: -208px -128px; }
208
+ .ui-icon-video { background-position: -224px -128px; }
209
+ .ui-icon-script { background-position: -240px -128px; }
210
+ .ui-icon-alert { background-position: 0 -144px; }
211
+ .ui-icon-info { background-position: -16px -144px; }
212
+ .ui-icon-notice { background-position: -32px -144px; }
213
+ .ui-icon-help { background-position: -48px -144px; }
214
+ .ui-icon-check { background-position: -64px -144px; }
215
+ .ui-icon-bullet { background-position: -80px -144px; }
216
+ .ui-icon-radio-off { background-position: -96px -144px; }
217
+ .ui-icon-radio-on { background-position: -112px -144px; }
218
+ .ui-icon-pin-w { background-position: -128px -144px; }
219
+ .ui-icon-pin-s { background-position: -144px -144px; }
220
+ .ui-icon-play { background-position: 0 -160px; }
221
+ .ui-icon-pause { background-position: -16px -160px; }
222
+ .ui-icon-seek-next { background-position: -32px -160px; }
223
+ .ui-icon-seek-prev { background-position: -48px -160px; }
224
+ .ui-icon-seek-end { background-position: -64px -160px; }
225
+ .ui-icon-seek-first { background-position: -80px -160px; }
226
+ .ui-icon-stop { background-position: -96px -160px; }
227
+ .ui-icon-eject { background-position: -112px -160px; }
228
+ .ui-icon-volume-off { background-position: -128px -160px; }
229
+ .ui-icon-volume-on { background-position: -144px -160px; }
230
+ .ui-icon-power { background-position: 0 -176px; }
231
+ .ui-icon-signal-diag { background-position: -16px -176px; }
232
+ .ui-icon-signal { background-position: -32px -176px; }
233
+ .ui-icon-battery-0 { background-position: -48px -176px; }
234
+ .ui-icon-battery-1 { background-position: -64px -176px; }
235
+ .ui-icon-battery-2 { background-position: -80px -176px; }
236
+ .ui-icon-battery-3 { background-position: -96px -176px; }
237
+ .ui-icon-circle-plus { background-position: 0 -192px; }
238
+ .ui-icon-circle-minus { background-position: -16px -192px; }
239
+ .ui-icon-circle-close { background-position: -32px -192px; }
240
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
241
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
242
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
243
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
244
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
245
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
246
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
247
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
248
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
249
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
250
+ .ui-icon-circle-check { background-position: -208px -192px; }
251
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
252
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
253
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
254
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
255
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
256
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
257
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
258
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
259
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
260
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
261
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
262
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
263
+
264
+
265
+ /* Misc visuals
266
+ ----------------------------------*/
267
+
268
+ /* Corner radius */
269
+ .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
270
+ .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
271
+ .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
272
+ .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
273
+ .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
274
+ .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
275
+ .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
276
+ .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
277
+ .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
278
+
279
+ /* Overlays */
280
+ .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
281
+ .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Resizable
282
+ ----------------------------------*/
283
+ .ui-resizable { position: relative;}
284
+ .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
285
+ .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
286
+ .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
287
+ .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
288
+ .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
289
+ .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
290
+ .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
291
+ .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
292
+ .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
293
+ .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Accordion
294
+ ----------------------------------*/
295
+ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
296
+ .ui-accordion .ui-accordion-li-fix { display: inline; }
297
+ .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
298
+ .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
299
+ .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
300
+ .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
301
+ .ui-accordion .ui-accordion-content-active { display: block; }/* Dialog
302
+ ----------------------------------*/
303
+ .ui-dialog { position: relative; padding: .2em; width: 300px; }
304
+ .ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
305
+ .ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
306
+ .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
307
+ .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
308
+ .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
309
+ .ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
310
+ .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
311
+ .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
312
+ .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
313
+ .ui-draggable .ui-dialog-titlebar { cursor: move; }
314
+ /* Slider
315
+ ----------------------------------*/
316
+ .ui-slider { position: relative; text-align: left; }
317
+ .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
318
+ .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
319
+
320
+ .ui-slider-horizontal { height: .8em; }
321
+ .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
322
+ .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
323
+ .ui-slider-horizontal .ui-slider-range-min { left: 0; }
324
+ .ui-slider-horizontal .ui-slider-range-max { right: 0; }
325
+
326
+ .ui-slider-vertical { width: .8em; height: 100px; }
327
+ .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
328
+ .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
329
+ .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
330
+ .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
331
+ ----------------------------------*/
332
+ .ui-tabs { padding: .2em; zoom: 1; }
333
+ .ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
334
+ .ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
335
+ .ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
336
+ .ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
337
+ .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
338
+ .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
339
+ .ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
340
+ .ui-tabs .ui-tabs-hide { display: none !important; }
341
+ /* Datepicker
342
+ ----------------------------------*/
343
+ .ui-datepicker { width: 17em; padding: .2em .2em 0; }
344
+ .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
345
+ .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
346
+ .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
347
+ .ui-datepicker .ui-datepicker-prev { left:2px; }
348
+ .ui-datepicker .ui-datepicker-next { right:2px; }
349
+ .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
350
+ .ui-datepicker .ui-datepicker-next-hover { right:1px; }
351
+ .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
352
+ .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
353
+ .ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
354
+ .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
355
+ .ui-datepicker select.ui-datepicker-month,
356
+ .ui-datepicker select.ui-datepicker-year { width: 49%;}
357
+ .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
358
+ .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
359
+ .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
360
+ .ui-datepicker td { border: 0; padding: 1px; }
361
+ .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
362
+ .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
363
+ .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
364
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
365
+
366
+ /* with multiple calendars */
367
+ .ui-datepicker.ui-datepicker-multi { width:auto; }
368
+ .ui-datepicker-multi .ui-datepicker-group { float:left; }
369
+ .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
370
+ .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
371
+ .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
372
+ .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
373
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
374
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
375
+ .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
376
+ .ui-datepicker-row-break { clear:both; width:100%; }
377
+
378
+ /* RTL support */
379
+ .ui-datepicker-rtl { direction: rtl; }
380
+ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
381
+ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
382
+ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
383
+ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
384
+ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
385
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
386
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
387
+ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
388
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
389
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
390
+
391
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
392
+ .ui-datepicker-cover {
393
+ display: none; /*sorry for IE5*/
394
+ display/**/: block; /*sorry for IE5*/
395
+ position: absolute; /*must have*/
396
+ z-index: -1; /*must have*/
397
+ filter: mask(); /*must have*/
398
+ top: -4px; /*must have*/
399
+ left: -4px; /*must have*/
400
+ width: 200px; /*must have*/
401
+ height: 200px; /*must have*/
402
+ }/* Progressbar
403
+ ----------------------------------*/
404
+ .ui-progressbar { height:2em; text-align: left; }
405
  .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
static/js/jquery/css/smoothness/jquery.tipsy.css CHANGED
@@ -1,11 +1,11 @@
1
- .tipsy { padding: 5px; font-size: 0.85em; position: absolute; z-index: 100000; line-height: 1.3em; max-width: 320px;}
2
- .tipsy-inner { padding: 2px 4px 2px 4px; background-color: white; border: 1px solid #333;}
3
- .tipsy-arrow { position: absolute; background: url('images/tipsy.gif') no-repeat top left; width: 9px; height: 5px; }
4
- .tipsy-n .tipsy-arrow { top: 0; left: 50%; margin-left: -4px; }
5
- .tipsy-nw .tipsy-arrow { top: 0; left: 10px; }
6
- .tipsy-ne .tipsy-arrow { top: 0; right: 10px; }
7
- .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -4px; background-position: bottom left; }
8
- .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; background-position: bottom left; }
9
- .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; background-position: bottom left; }
10
- .tipsy-e .tipsy-arrow { top: 50%; margin-top: -4px; right: 0; width: 5px; height: 9px; background-position: top right; }
11
- .tipsy-w .tipsy-arrow { top: 50%; margin-top: -4px; left: 0; width: 5px; height: 9px; }
1
+ .tipsy { padding: 5px; font-size: 0.85em; position: absolute; z-index: 100000; line-height: 1.3em; max-width: 320px;}
2
+ .tipsy-inner { padding: 2px 4px 2px 4px; background-color: white; border: 1px solid #333;}
3
+ .tipsy-arrow { position: absolute; background: url('images/tipsy.gif') no-repeat top left; width: 9px; height: 5px; }
4
+ .tipsy-n .tipsy-arrow { top: 0; left: 50%; margin-left: -4px; }
5
+ .tipsy-nw .tipsy-arrow { top: 0; left: 10px; }
6
+ .tipsy-ne .tipsy-arrow { top: 0; right: 10px; }
7
+ .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -4px; background-position: bottom left; }
8
+ .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; background-position: bottom left; }
9
+ .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; background-position: bottom left; }
10
+ .tipsy-e .tipsy-arrow { top: 50%; margin-top: -4px; right: 0; width: 5px; height: 9px; background-position: top right; }
11
+ .tipsy-w .tipsy-arrow { top: 50%; margin-top: -4px; left: 0; width: 5px; height: 9px; }
static/js/jquery/jquery.mjs.nestedSortable.js CHANGED
@@ -1,426 +1,426 @@
1
- /*
2
- * jQuery UI Nested Sortable
3
- * v 1.3.5 / 21 jun 2012
4
- * http://mjsarfatti.com/code/nestedSortable
5
- *
6
- * Depends on:
7
- * jquery.ui.sortable.js 1.8+
8
- *
9
- * Copyright (c) 2010-2012 Manuele J Sarfatti
10
- * Licensed under the MIT License
11
- * http://www.opensource.org/licenses/mit-license.php
12
- */
13
-
14
- (function($) {
15
-
16
- $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
17
-
18
- options: {
19
- tabSize: 20,
20
- disableNesting: 'mjs-nestedSortable-no-nesting',
21
- errorClass: 'mjs-nestedSortable-error',
22
- listType: 'ol',
23
- maxLevels: 0,
24
- protectRoot: false,
25
- rootID: null,
26
- rtl: false,
27
- isAllowed: function(item, parent) { return true; }
28
- },
29
-
30
- _create: function() {
31
- this.element.data('sortable', this.element.data('nestedSortable'));
32
-
33
- if (!this.element.is(this.options.listType))
34
- throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
35
-
36
- return $.ui.sortable.prototype._create.apply(this, arguments);
37
- },
38
-
39
- destroy: function() {
40
- this.element
41
- .removeData("nestedSortable")
42
- .unbind(".nestedSortable");
43
- return $.ui.sortable.prototype.destroy.apply(this, arguments);
44
- },
45
-
46
- _mouseDrag: function(event) {
47
-
48
- //Compute the helpers position
49
- this.position = this._generatePosition(event);
50
- this.positionAbs = this._convertPositionTo("absolute");
51
-
52
- if (!this.lastPositionAbs) {
53
- this.lastPositionAbs = this.positionAbs;
54
- }
55
-
56
- //Do scrolling
57
- if(this.options.scroll) {
58
- var o = this.options, scrolled = false;
59
- if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
60
-
61
- if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
62
- this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
63
- else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
64
- this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
65
-
66
- if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
67
- this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
68
- else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
69
- this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
70
-
71
- } else {
72
-
73
- if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
74
- scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
75
- else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
76
- scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
77
-
78
- if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
79
- scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
80
- else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
81
- scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
82
-
83
- }
84
-
85
- if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
86
- $.ui.ddmanager.prepareOffsets(this, event);
87
- }
88
-
89
- //Regenerate the absolute position used for position checks
90
- this.positionAbs = this._convertPositionTo("absolute");
91
-
92
- // Find the top offset before rearrangement,
93
- var previousTopOffset = this.placeholder.offset().top;
94
-
95
- //Set the helper position
96
- if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
97
- if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
98
-
99
- //Rearrange
100
- for (var i = this.items.length - 1; i >= 0; i--) {
101
-
102
- //Cache variables and intersection, continue if no intersection
103
- var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
104
- if (!intersection) continue;
105
-
106
- if(itemElement != this.currentItem[0] //cannot intersect with itself
107
- && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
108
- && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
109
- && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
110
- //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
111
- ) {
112
-
113
- $(itemElement).mouseenter();
114
-
115
- this.direction = intersection == 1 ? "down" : "up";
116
-
117
- if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
118
- $(itemElement).mouseleave();
119
- this._rearrange(event, item);
120
- } else {
121
- break;
122
- }
123
-
124
- // Clear emtpy ul's/ol's
125
- this._clearEmpty(itemElement);
126
-
127
- this._trigger("change", event, this._uiHash());
128
- break;
129
- }
130
- }
131
-
132
- var parentItem = (this.placeholder[0].parentNode.parentNode &&
133
- $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
134
- ? $(this.placeholder[0].parentNode.parentNode)
135
- : null,
136
- level = this._getLevel(this.placeholder),
137
- childLevels = this._getChildLevels(this.helper);
138
-
139
- // To find the previous sibling in the list, keep backtracking until we hit a valid list item.
140
- var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
141
- if (previousItem != null) {
142
- while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
143
- if (previousItem[0].previousSibling) {
144
- previousItem = $(previousItem[0].previousSibling);
145
- } else {
146
- previousItem = null;
147
- break;
148
- }
149
- }
150
- }
151
-
152
- // To find the next sibling in the list, keep stepping forward until we hit a valid list item.
153
- var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
154
- if (nextItem != null) {
155
- while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
156
- if (nextItem[0].nextSibling) {
157
- nextItem = $(nextItem[0].nextSibling);
158
- } else {
159
- nextItem = null;
160
- break;
161
- }
162
- }
163
- }
164
-
165
- var newList = document.createElement(o.listType);
166
-
167
- this.beyondMaxLevels = 0;
168
-
169
- // If the item is moved to the left, send it to its parent's level unless there are siblings below it.
170
- if (parentItem != null && nextItem == null &&
171
- (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
172
- !o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
173
- parentItem.after(this.placeholder[0]);
174
- this._clearEmpty(parentItem[0]);
175
- this._trigger("change", event, this._uiHash());
176
- }
177
- // If the item is below a sibling and is moved to the right, make it a child of that sibling.
178
- else if (previousItem != null &&
179
- (o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
180
- !o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
181
- this._isAllowed(previousItem, level, level+childLevels+1);
182
- if (!previousItem.children(o.listType).length) {
183
- previousItem[0].appendChild(newList);
184
- }
185
- // If this item is being moved from the top, add it to the top of the list.
186
- if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
187
- previousItem.children(o.listType).prepend(this.placeholder);
188
- }
189
- // Otherwise, add it to the bottom of the list.
190
- else {
191
- previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
192
- }
193
- this._trigger("change", event, this._uiHash());
194
- }
195
- else {
196
- this._isAllowed(parentItem, level, level+childLevels);
197
- }
198
-
199
- //Post events to containers
200
- this._contactContainers(event);
201
-
202
- //Interconnect with droppables
203
- if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
204
-
205
- //Call callbacks
206
- this._trigger('sort', event, this._uiHash());
207
-
208
- this.lastPositionAbs = this.positionAbs;
209
- return false;
210
-
211
- },
212
-
213
- _mouseStop: function(event, noPropagation) {
214
-
215
- // If the item is in a position not allowed, send it back
216
- if (this.beyondMaxLevels) {
217
-
218
- this.placeholder.removeClass(this.options.errorClass);
219
-
220
- if (this.domPosition.prev) {
221
- $(this.domPosition.prev).after(this.placeholder);
222
- } else {
223
- $(this.domPosition.parent).prepend(this.placeholder);
224
- }
225
-
226
- this._trigger("revert", event, this._uiHash());
227
-
228
- }
229
-
230
- // Clean last empty ul/ol
231
- for (var i = this.items.length - 1; i >= 0; i--) {
232
- var item = this.items[i].item[0];
233
- this._clearEmpty(item);
234
- }
235
-
236
- $.ui.sortable.prototype._mouseStop.apply(this, arguments);
237
-
238
- },
239
-
240
- serialize: function(options) {
241
-
242
- var o = $.extend({}, this.options, options),
243
- items = this._getItemsAsjQuery(o && o.connected),
244
- str = [];
245
-
246
- $(items).each(function() {
247
- var res = ($(o.item || this).attr(o.attribute || 'id') || '')
248
- .match(o.expression || (/(.+)[-=_](.+)/)),
249
- pid = ($(o.item || this).parent(o.listType)
250
- .parent(o.items)
251
- .attr(o.attribute || 'id') || '')
252
- .match(o.expression || (/(.+)[-=_](.+)/));
253
-
254
- if (res) {
255
- str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
256
- + '='
257
- + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
258
- }
259
- });
260
-
261
- if(!str.length && o.key) {
262
- str.push(o.key + '=');
263
- }
264
-
265
- return str.join('&');
266
-
267
- },
268
-
269
- toHierarchy: function(options) {
270
-
271
- var o = $.extend({}, this.options, options),
272
- sDepth = o.startDepthCount || 0,
273
- ret = [];
274
-
275
- $(this.element).children(o.items).each(function () {
276
- var level = _recursiveItems(this);
277
- ret.push(level);
278
- });
279
-
280
- return ret;
281
-
282
- function _recursiveItems(item) {
283
- var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
284
- if (id) {
285
- var currentItem = {"id" : id[2]};
286
- if ($(item).children(o.listType).children(o.items).length > 0) {
287
- currentItem.children = [];
288
- $(item).children(o.listType).children(o.items).each(function() {
289
- var level = _recursiveItems(this);
290
- currentItem.children.push(level);
291
- });
292
- }
293
- return currentItem;
294
- }
295
- }
296
- },
297
-
298
- toArray: function(options) {
299
-
300
- var o = $.extend({}, this.options, options),
301
- sDepth = o.startDepthCount || 0,
302
- ret = [],
303
- left = 2;
304
-
305
- /*ret.push({
306
- "item_id": o.rootID,
307
- "parent_id": 'none',
308
- "depth": sDepth,
309
- "left": '1',
310
- "right": ($(o.items, this.element).length + 1) * 2
311
- });*/
312
-
313
- $(this.element).children(o.items).each(function () {
314
- left = _recursiveArray(this, sDepth + 1, left);
315
- });
316
-
317
- ret = ret.sort(function(a,b){ return (a.left - b.left); });
318
-
319
- return ret;
320
-
321
- function _recursiveArray(item, depth, left) {
322
-
323
- var right = left + 1,
324
- id,
325
- pid;
326
-
327
- if ($(item).children(o.listType).children(o.items).length > 0) {
328
- depth ++;
329
- $(item).children(o.listType).children(o.items).each(function () {
330
- right = _recursiveArray($(this), depth, right);
331
- });
332
- depth --;
333
- }
334
-
335
- id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
336
-
337
- if (depth === sDepth + 1) {
338
- pid = o.rootID;
339
- } else {
340
- var parentItem = ($(item).parent(o.listType)
341
- .parent(o.items)
342
- .attr(o.attribute || 'id'))
343
- .match(o.expression || (/(.+)[-=_](.+)/));
344
- pid = parentItem[2];
345
- }
346
-
347
- if (id) {
348
- ret.push({"item_id": id[2], "parent_id": pid, "delim": $(item).parents('.post_taxonomy:first').find('input.tax_delim').val(), "left": left, "right": right, "xpath":$(item).find('input.widefat').val(), "assign":$(item).find('input.assign_post:first').is(':checked'), "auto_nested":$(item).parents('.post_taxonomy:first').find('input.taxonomy_auto_nested').is(':checked')});
349
- }
350
-
351
- left = right + 1;
352
- return left;
353
- }
354
-
355
- },
356
-
357
- _clearEmpty: function(item) {
358
-
359
- var emptyList = $(item).children(this.options.listType);
360
- if (emptyList.length && !emptyList.children().length) {
361
- emptyList.remove();
362
- }
363
-
364
- },
365
-
366
- _getLevel: function(item) {
367
-
368
- var level = 1;
369
-
370
- if (this.options.listType) {
371
- var list = item.closest(this.options.listType);
372
- while (list && list.length > 0 &&
373
- !list.is('.ui-sortable')) {
374
- level++;
375
- list = list.parent().closest(this.options.listType);
376
- }
377
- }
378
-
379
- return level;
380
- },
381
-
382
- _getChildLevels: function(parent, depth) {
383
- var self = this,
384
- o = this.options,
385
- result = 0;
386
- depth = depth || 0;
387
-
388
- $(parent).children(o.listType).children(o.items).each(function (index, child) {
389
- result = Math.max(self._getChildLevels(child, depth + 1), result);
390
- });
391
-
392
- return depth ? result + 1 : result;
393
- },
394
-
395
- _isAllowed: function(parentItem, level, levels) {
396
- var o = this.options,
397
- isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
398
- maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
399
-
400
- // Is the root protected?
401
- // Are we trying to nest under a no-nest?
402
- // Are we nesting too deep?
403
- if (!o.isAllowed(parentItem, this.placeholder) ||
404
- parentItem && parentItem.hasClass(o.disableNesting) ||
405
- o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
406
- this.placeholder.addClass(o.errorClass);
407
- if (maxLevels < levels && maxLevels != 0) {
408
- this.beyondMaxLevels = levels - maxLevels;
409
- } else {
410
- this.beyondMaxLevels = 1;
411
- }
412
- } else {
413
- if (maxLevels < levels && maxLevels != 0) {
414
- this.placeholder.addClass(o.errorClass);
415
- this.beyondMaxLevels = levels - maxLevels;
416
- } else {
417
- this.placeholder.removeClass(o.errorClass);
418
- this.beyondMaxLevels = 0;
419
- }
420
- }
421
- }
422
-
423
- }));
424
-
425
- $.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
426
  })(jQuery);
1
+ /*
2
+ * jQuery UI Nested Sortable
3
+ * v 1.3.5 / 21 jun 2012
4
+ * http://mjsarfatti.com/code/nestedSortable
5
+ *
6
+ * Depends on:
7
+ * jquery.ui.sortable.js 1.8+
8
+ *
9
+ * Copyright (c) 2010-2012 Manuele J Sarfatti
10
+ * Licensed under the MIT License
11
+ * http://www.opensource.org/licenses/mit-license.php
12
+ */
13
+
14
+ (function($) {
15
+
16
+ $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
17
+
18
+ options: {
19
+ tabSize: 20,
20
+ disableNesting: 'mjs-nestedSortable-no-nesting',
21
+ errorClass: 'mjs-nestedSortable-error',
22
+ listType: 'ol',
23
+ maxLevels: 0,
24
+ protectRoot: false,
25
+ rootID: null,
26
+ rtl: false,
27
+ isAllowed: function(item, parent) { return true; }
28
+ },
29
+
30
+ _create: function() {
31
+ this.element.data('sortable', this.element.data('nestedSortable'));
32
+
33
+ if (!this.element.is(this.options.listType))
34
+ throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
35
+
36
+ return $.ui.sortable.prototype._create.apply(this, arguments);
37
+ },
38
+
39
+ destroy: function() {
40
+ this.element
41
+ .removeData("nestedSortable")
42
+ .unbind(".nestedSortable");
43
+ return $.ui.sortable.prototype.destroy.apply(this, arguments);
44
+ },
45
+
46
+ _mouseDrag: function(event) {
47
+
48
+ //Compute the helpers position
49
+ this.position = this._generatePosition(event);
50
+ this.positionAbs = this._convertPositionTo("absolute");
51
+
52
+ if (!this.lastPositionAbs) {
53
+ this.lastPositionAbs = this.positionAbs;
54
+ }
55
+
56
+ //Do scrolling
57
+ if(this.options.scroll) {
58
+ var o = this.options, scrolled = false;
59
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
60
+
61
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
62
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
63
+ else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
64
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
65
+
66
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
67
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
68
+ else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
69
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
70
+
71
+ } else {
72
+
73
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
74
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
75
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
76
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
77
+
78
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
79
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
80
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
81
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
82
+
83
+ }
84
+
85
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
86
+ $.ui.ddmanager.prepareOffsets(this, event);
87
+ }
88
+
89
+ //Regenerate the absolute position used for position checks
90
+ this.positionAbs = this._convertPositionTo("absolute");
91
+
92
+ // Find the top offset before rearrangement,
93
+ var previousTopOffset = this.placeholder.offset().top;
94
+
95
+ //Set the helper position
96
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
97
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
98
+
99
+ //Rearrange
100
+ for (var i = this.items.length - 1; i >= 0; i--) {
101
+
102
+ //Cache variables and intersection, continue if no intersection
103
+ var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
104
+ if (!intersection) continue;
105
+
106
+ if(itemElement != this.currentItem[0] //cannot intersect with itself
107
+ && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
108
+ && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
109
+ && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
110
+ //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
111
+ ) {
112
+
113
+ $(itemElement).mouseenter();
114
+
115
+ this.direction = intersection == 1 ? "down" : "up";
116
+
117
+ if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
118
+ $(itemElement).mouseleave();
119
+ this._rearrange(event, item);
120
+ } else {
121
+ break;
122
+ }
123
+
124
+ // Clear emtpy ul's/ol's
125
+ this._clearEmpty(itemElement);
126
+
127
+ this._trigger("change", event, this._uiHash());
128
+ break;
129
+ }
130
+ }
131
+
132
+ var parentItem = (this.placeholder[0].parentNode.parentNode &&
133
+ $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
134
+ ? $(this.placeholder[0].parentNode.parentNode)
135
+ : null,
136
+ level = this._getLevel(this.placeholder),
137
+ childLevels = this._getChildLevels(this.helper);
138
+
139
+ // To find the previous sibling in the list, keep backtracking until we hit a valid list item.
140
+ var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
141
+ if (previousItem != null) {
142
+ while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
143
+ if (previousItem[0].previousSibling) {
144
+ previousItem = $(previousItem[0].previousSibling);
145
+ } else {
146
+ previousItem = null;
147
+ break;
148
+ }
149
+ }
150
+ }
151
+
152
+ // To find the next sibling in the list, keep stepping forward until we hit a valid list item.
153
+ var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
154
+ if (nextItem != null) {
155
+ while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
156
+ if (nextItem[0].nextSibling) {
157
+ nextItem = $(nextItem[0].nextSibling);
158
+ } else {
159
+ nextItem = null;
160
+ break;
161
+ }
162
+ }
163
+ }
164
+
165
+ var newList = document.createElement(o.listType);
166
+
167
+ this.beyondMaxLevels = 0;
168
+
169
+ // If the item is moved to the left, send it to its parent's level unless there are siblings below it.
170
+ if (parentItem != null && nextItem == null &&
171
+ (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
172
+ !o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
173
+ parentItem.after(this.placeholder[0]);
174
+ this._clearEmpty(parentItem[0]);
175
+ this._trigger("change", event, this._uiHash());
176
+ }
177
+ // If the item is below a sibling and is moved to the right, make it a child of that sibling.
178
+ else if (previousItem != null &&
179
+ (o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
180
+ !o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
181
+ this._isAllowed(previousItem, level, level+childLevels+1);
182
+ if (!previousItem.children(o.listType).length) {
183
+ previousItem[0].appendChild(newList);
184
+ }
185
+ // If this item is being moved from the top, add it to the top of the list.
186
+ if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
187
+ previousItem.children(o.listType).prepend(this.placeholder);
188
+ }
189
+ // Otherwise, add it to the bottom of the list.
190
+ else {
191
+ previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
192
+ }
193
+ this._trigger("change", event, this._uiHash());
194
+ }
195
+ else {
196
+ this._isAllowed(parentItem, level, level+childLevels);
197
+ }
198
+
199
+ //Post events to containers
200
+ this._contactContainers(event);
201
+
202
+ //Interconnect with droppables
203
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
204
+
205
+ //Call callbacks
206
+ this._trigger('sort', event, this._uiHash());
207
+
208
+ this.lastPositionAbs = this.positionAbs;
209
+ return false;
210
+
211
+ },
212
+
213
+ _mouseStop: function(event, noPropagation) {
214
+
215
+ // If the item is in a position not allowed, send it back
216
+ if (this.beyondMaxLevels) {
217
+
218
+ this.placeholder.removeClass(this.options.errorClass);
219
+
220
+ if (this.domPosition.prev) {
221
+ $(this.domPosition.prev).after(this.placeholder);
222
+ } else {
223
+ $(this.domPosition.parent).prepend(this.placeholder);
224
+ }
225
+
226
+ this._trigger("revert", event, this._uiHash());
227
+
228
+ }
229
+
230
+ // Clean last empty ul/ol
231
+ for (var i = this.items.length - 1; i >= 0; i--) {
232
+ var item = this.items[i].item[0];
233
+ this._clearEmpty(item);
234
+ }
235
+
236
+ $.ui.sortable.prototype._mouseStop.apply(this, arguments);
237
+
238
+ },
239
+
240
+ serialize: function(options) {
241
+
242
+ var o = $.extend({}, this.options, options),
243
+ items = this._getItemsAsjQuery(o && o.connected),
244
+ str = [];
245
+
246
+ $(items).each(function() {
247
+ var res = ($(o.item || this).attr(o.attribute || 'id') || '')
248
+ .match(o.expression || (/(.+)[-=_](.+)/)),
249
+ pid = ($(o.item || this).parent(o.listType)
250
+ .parent(o.items)
251
+ .attr(o.attribute || 'id') || '')
252
+ .match(o.expression || (/(.+)[-=_](.+)/));
253
+
254
+ if (res) {
255
+ str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
256
+ + '='
257
+ + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
258
+ }
259
+ });
260
+
261
+ if(!str.length && o.key) {
262
+ str.push(o.key + '=');
263
+ }
264
+
265
+ return str.join('&');
266
+
267
+ },
268
+
269
+ toHierarchy: function(options) {
270
+
271
+ var o = $.extend({}, this.options, options),
272
+ sDepth = o.startDepthCount || 0,
273
+ ret = [];
274
+
275
+ $(this.element).children(o.items).each(function () {
276
+ var level = _recursiveItems(this);
277
+ ret.push(level);
278
+ });
279
+
280
+ return ret;
281
+
282
+ function _recursiveItems(item) {
283
+ var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
284
+ if (id) {
285
+ var currentItem = {"id" : id[2]};
286
+ if ($(item).children(o.listType).children(o.items).length > 0) {
287
+ currentItem.children = [];
288
+ $(item).children(o.listType).children(o.items).each(function() {
289
+ var level = _recursiveItems(this);
290
+ currentItem.children.push(level);
291
+ });
292
+ }
293
+ return currentItem;
294
+ }
295
+ }
296
+ },
297
+
298
+ toArray: function(options) {
299
+
300
+ var o = $.extend({}, this.options, options),
301
+ sDepth = o.startDepthCount || 0,
302
+ ret = [],
303
+ left = 2;
304
+
305
+ /*ret.push({
306
+ "item_id": o.rootID,
307
+ "parent_id": 'none',
308
+ "depth": sDepth,
309
+ "left": '1',
310
+ "right": ($(o.items, this.element).length + 1) * 2
311
+ });*/
312
+
313
+ $(this.element).children(o.items).each(function () {
314
+ left = _recursiveArray(this, sDepth + 1, left);
315
+ });
316
+
317
+ ret = ret.sort(function(a,b){ return (a.left - b.left); });
318
+
319
+ return ret;
320
+
321
+ function _recursiveArray(item, depth, left) {
322
+
323
+ var right = left + 1,
324
+ id,
325
+ pid;
326
+
327
+ if ($(item).children(o.listType).children(o.items).length > 0) {
328
+ depth ++;
329
+ $(item).children(o.listType).children(o.items).each(function () {
330
+ right = _recursiveArray($(this), depth, right);
331
+ });
332
+ depth --;
333
+ }
334
+
335
+ id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
336
+
337
+ if (depth === sDepth + 1) {
338
+ pid = o.rootID;
339
+ } else {
340
+ var parentItem = ($(item).parent(o.listType)
341
+ .parent(o.items)
342
+ .attr(o.attribute || 'id'))
343
+ .match(o.expression || (/(.+)[-=_](.+)/));
344
+ pid = parentItem[2];
345
+ }
346
+
347
+ if (id) {
348
+ ret.push({"item_id": id[2], "parent_id": pid, "delim": $(item).parents('.post_taxonomy:first').find('input.tax_delim').val(), "left": left, "right": right, "xpath":$(item).find('input.widefat').val(), "assign":$(item).find('input.assign_post:first').is(':checked'), "auto_nested":$(item).parents('.post_taxonomy:first').find('input.taxonomy_auto_nested').is(':checked')});
349
+ }
350
+
351
+ left = right + 1;
352
+ return left;
353
+ }
354
+
355
+ },
356
+
357
+ _clearEmpty: function(item) {
358
+
359
+ var emptyList = $(item).children(this.options.listType);
360
+ if (emptyList.length && !emptyList.children().length) {
361
+ emptyList.remove();
362
+ }
363
+
364
+ },
365
+
366
+ _getLevel: function(item) {
367
+
368
+ var level = 1;
369
+
370
+ if (this.options.listType) {
371
+ var list = item.closest(this.options.listType);
372
+ while (list && list.length > 0 &&
373
+ !list.is('.ui-sortable')) {
374
+ level++;
375
+ list = list.parent().closest(this.options.listType);
376
+ }
377
+ }
378
+
379
+ return level;
380
+ },
381
+
382
+ _getChildLevels: function(parent, depth) {
383
+ var self = this,
384
+ o = this.options,
385
+ result = 0;
386
+ depth = depth || 0;
387
+
388
+ $(parent).children(o.listType).children(o.items).each(function (index, child) {
389
+ result = Math.max(self._getChildLevels(child, depth + 1), result);
390
+ });
391
+
392
+ return depth ? result + 1 : result;
393
+ },
394
+
395
+ _isAllowed: function(parentItem, level, levels) {
396
+ var o = this.options,
397
+ isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
398
+ maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
399
+
400
+ // Is the root protected?
401
+ // Are we trying to nest under a no-nest?
402
+ // Are we nesting too deep?
403
+ if (!o.isAllowed(parentItem, this.placeholder) ||
404
+ parentItem && parentItem.hasClass(o.disableNesting) ||
405
+ o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
406
+ this.placeholder.addClass(o.errorClass);
407
+ if (maxLevels < levels && maxLevels != 0) {
408
+ this.beyondMaxLevels = levels - maxLevels;
409
+ } else {
410
+ this.beyondMaxLevels = 1;
411
+ }
412
+ } else {
413
+ if (maxLevels < levels && maxLevels != 0) {
414
+ this.placeholder.addClass(o.errorClass);
415
+ this.beyondMaxLevels = levels - maxLevels;
416
+ } else {
417
+ this.placeholder.removeClass(o.errorClass);
418
+ this.beyondMaxLevels = 0;
419
+ }
420
+ }
421
+ }
422
+
423
+ }));
424
+
425
+ $.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
426
  })(jQuery);
static/js/jquery/jquery.tipsy.js CHANGED
@@ -1,198 +1,198 @@
1
- // tipsy, facebook style tooltips for jquery
2
- // version 1.0.0a
3
- // (c) 2008-2010 jason frame [jason@onehackoranother.com]
4
- // releated under the MIT license
5
-
6
- (function($) {
7
-
8
- function fixTitle($ele) {
9
- if ($ele.attr('title') || typeof($ele.attr('original-title')) != 'string') {
10
- $ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
11
- }
12
- }
13
-
14
- function Tipsy(element, options) {
15
- this.$element = $(element);
16
- this.options = options;
17
- this.enabled = true;
18
- fixTitle(this.$element);
19
- }
20
-
21
- Tipsy.prototype = {
22
- show: function() {
23
- var title = this.getTitle();
24
- if (title && this.enabled) {
25
- var $tip = this.tip();
26
-
27
- $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
28
- $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
29
- $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
30
-
31
- var pos = $.extend({}, this.$element.offset(), {
32
- width: this.$element[0].offsetWidth,
33
- height: this.$element[0].offsetHeight
34
- });
35
-
36
- var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
37
- var gravity = (typeof this.options.gravity == 'function')
38
- ? this.options.gravity.call(this.$element[0])
39
- : this.options.gravity;
40
-
41
- var tp;
42
- switch (gravity.charAt(0)) {
43
- case 'n':
44
- tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
45
- break;
46
- case 's':
47
- tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
48
- break;
49
- case 'e':
50
- tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
51
- break;
52
- case 'w':
53
- tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
54
- break;
55
- }
56
-
57
- if (gravity.length == 2) {
58
- if (gravity.charAt(1) == 'w') {
59
- tp.left = pos.left + pos.width / 2 - 15;
60
- } else {
61
- tp.left = pos.left + pos.width / 2 - actualWidth + 15;
62
- }
63
- }
64
-
65
- $tip.css(tp).addClass('tipsy-' + gravity);
66
-
67
- if (this.options.fade) {
68
- $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
69
- } else {
70
- $tip.css({visibility: 'visible', opacity: this.options.opacity});
71
- }
72
- }
73
- },
74
-
75
- hide: function() {
76
- if (this.options.fade) {
77
- this.tip().stop().fadeOut(function() { $(this).remove(); });
78
- } else {
79
- this.tip().remove();
80
- }
81
- },
82
-
83
- getTitle: function() {
84
- var title, $e = this.$element, o = this.options;
85
- fixTitle($e);
86
- var title, o = this.options;
87
- if (typeof o.title == 'string') {
88
- title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
89
- } else if (typeof o.title == 'function') {
90
- title = o.title.call($e[0]);
91
- }
92
- title = ('' + title).replace(/(^\s*|\s*$)/, "");
93
- return title || o.fallback;
94
- },
95
-
96
- tip: function() {
97
- if (!this.$tip) {
98
- this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
99
- }
100
- return this.$tip;
101
- },
102
-
103
- validate: function() {
104
- if (!this.$element[0].parentNode) {
105
- this.hide();
106
- this.$element = null;
107
- this.options = null;
108
- }
109
- },
110
-
111
- enable: function() { this.enabled = true; },
112
- disable: function() { this.enabled = false; },
113
- toggleEnabled: function() { this.enabled = !this.enabled; }
114
- };
115
-
116
- $.fn.tipsy = function(options) {
117
-
118
- if (options === true) {
119
- return this.data('tipsy');
120
- } else if (typeof options == 'string') {
121
- return this.data('tipsy')[options]();
122
- }
123
-
124
- options = $.extend({}, $.fn.tipsy.defaults, options);
125
-
126
- function get(ele) {
127
- var tipsy = $.data(ele, 'tipsy');
128
- if (!tipsy) {
129
- tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
130
- $.data(ele, 'tipsy', tipsy);
131
- }
132
- return tipsy;
133
- }
134
-
135
- function enter() {
136
- var tipsy = get(this);
137
- tipsy.hoverState = 'in';
138
- if (options.delayIn == 0) {
139
- tipsy.show();
140
- } else {
141
- setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
142
- }
143
- };
144
-
145
- function leave() {
146
- var tipsy = get(this);
147
- tipsy.hoverState = 'out';
148
- if (options.delayOut == 0) {
149
- tipsy.hide();
150
- } else {
151
- setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
152
- }
153
- };
154
-
155
- if (!options.live) this.each(function() { get(this); });
156
-
157
- if (options.trigger != 'manual') {
158
- var binder = options.live ? 'live' : 'bind',
159
- eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
160
- eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
161
- this[binder](eventIn, enter)[binder](eventOut, leave);
162
- }
163
-
164
- return this;
165
-
166
- };
167
-
168
- $.fn.tipsy.defaults = {
169
- delayIn: 0,
170
- delayOut: 0,
171
- fade: false,
172
- fallback: '',
173
- gravity: 'n',
174
- html: false,
175
- live: false,
176
- offset: 0,
177
- opacity: 0.8,
178
- title: 'title',
179
- trigger: 'hover'
180
- };
181
-
182
- // Overwrite this method to provide options on a per-element basis.
183
- // For example, you could store the gravity in a 'tipsy-gravity' attribute:
184
- // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
185
- // (remember - do not modify 'options' in place!)
186
- $.fn.tipsy.elementOptions = function(ele, options) {
187
- return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
188
- };
189
-
190
- $.fn.tipsy.autoNS = function() {
191
- return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
192
- };
193
-
194
- $.fn.tipsy.autoWE = function() {
195
- return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
196
- };
197
-
198
- })(jQuery);
1
+ // tipsy, facebook style tooltips for jquery
2
+ // version 1.0.0a
3
+ // (c) 2008-2010 jason frame [jason@onehackoranother.com]
4
+ // releated under the MIT license
5
+
6
+ (function($) {
7
+
8
+ function fixTitle($ele) {
9
+ if ($ele.attr('title') || typeof($ele.attr('original-title')) != 'string') {
10
+ $ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
11
+ }
12
+ }
13
+
14
+ function Tipsy(element, options) {
15
+ this.$element = $(element);
16
+ this.options = options;
17
+ this.enabled = true;
18
+ fixTitle(this.$element);
19
+ }
20
+
21
+ Tipsy.prototype = {
22
+ show: function() {
23
+ var title = this.getTitle();
24
+ if (title && this.enabled) {
25
+ var $tip = this.tip();
26
+
27
+ $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
28
+ $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
29
+ $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
30
+
31
+ var pos = $.extend({}, this.$element.offset(), {
32
+ width: this.$element[0].offsetWidth,
33
+ height: this.$element[0].offsetHeight
34
+ });
35
+
36
+ var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
37
+ var gravity = (typeof this.options.gravity == 'function')
38
+ ? this.options.gravity.call(this.$element[0])
39
+ : this.options.gravity;
40
+
41
+ var tp;
42
+ switch (gravity.charAt(0)) {
43
+ case 'n':
44
+ tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
45
+ break;
46
+ case 's':
47
+ tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
48
+ break;
49
+ case 'e':
50
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
51
+ break;
52
+ case 'w':
53
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
54
+ break;
55
+ }
56
+
57
+ if (gravity.length == 2) {
58
+ if (gravity.charAt(1) == 'w') {
59
+ tp.left = pos.left + pos.width / 2 - 15;
60
+ } else {
61
+ tp.left = pos.left + pos.width / 2 - actualWidth + 15;
62
+ }
63
+ }
64
+
65
+ $tip.css(tp).addClass('tipsy-' + gravity);
66
+
67
+ if (this.options.fade) {
68
+ $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
69
+ } else {
70
+ $tip.css({visibility: 'visible', opacity: this.options.opacity});
71
+ }
72
+ }
73
+ },
74
+
75
+ hide: function() {
76
+ if (this.options.fade) {
77
+ this.tip().stop().fadeOut(function() { $(this).remove(); });
78
+ } else {
79
+ this.tip().remove();
80
+ }
81
+ },
82
+
83
+ getTitle: function() {
84
+ var title, $e = this.$element, o = this.options;
85
+ fixTitle($e);
86
+ var title, o = this.options;
87
+ if (typeof o.title == 'string') {
88
+ title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
89
+ } else if (typeof o.title == 'function') {
90
+ title = o.title.call($e[0]);
91
+ }
92
+ title = ('' + title).replace(/(^\s*|\s*$)/, "");
93
+ return title || o.fallback;
94
+ },
95
+
96
+ tip: function() {
97
+ if (!this.$tip) {
98
+ this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
99
+ }
100
+ return this.$tip;
101
+ },
102
+
103
+ validate: function() {
104
+ if (!this.$element[0].parentNode) {
105
+ this.hide();
106
+ this.$element = null;
107
+ this.options = null;
108
+ }
109
+ },
110
+
111
+ enable: function() { this.enabled = true; },
112
+ disable: function() { this.enabled = false; },
113
+ toggleEnabled: function() { this.enabled = !this.enabled; }
114
+ };
115
+
116
+ $.fn.tipsy = function(options) {
117
+
118
+ if (options === true) {
119
+ return this.data('tipsy');
120
+ } else if (typeof options == 'string') {
121
+ return this.data('tipsy')[options]();
122
+ }
123
+
124
+ options = $.extend({}, $.fn.tipsy.defaults, options);
125
+
126
+ function get(ele) {
127
+ var tipsy = $.data(ele, 'tipsy');
128
+ if (!tipsy) {
129
+ tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
130
+ $.data(ele, 'tipsy', tipsy);
131
+ }
132
+ return tipsy;
133
+ }
134
+
135
+ function enter() {
136
+ var tipsy = get(this);
137
+ tipsy.hoverState = 'in';
138
+ if (options.delayIn == 0) {
139
+ tipsy.show();
140
+ } else {
141
+ setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
142
+ }
143
+ };
144
+
145
+ function leave() {
146
+ var tipsy = get(this);
147
+ tipsy.hoverState = 'out';
148
+ if (options.delayOut == 0) {
149
+ tipsy.hide();
150
+ } else {
151
+ setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
152
+ }
153
+ };
154
+
155
+ if (!options.live) this.each(function() { get(this); });
156
+
157
+ if (options.trigger != 'manual') {
158
+ var binder = options.live ? 'live' : 'bind',
159
+ eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
160
+ eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
161
+ this[binder](eventIn, enter)[binder](eventOut, leave);
162
+ }
163
+
164
+ return this;
165
+
166
+ };
167
+
168
+ $.fn.tipsy.defaults = {
169
+ delayIn: 0,
170
+ delayOut: 0,
171
+ fade: false,
172
+ fallback: '',
173
+ gravity: 'n',
174
+ html: false,
175
+ live: false,
176
+ offset: 0,
177
+ opacity: 0.8,
178
+ title: 'title',
179
+ trigger: 'hover'
180
+ };
181
+
182
+ // Overwrite this method to provide options on a per-element basis.
183
+ // For example, you could store the gravity in a 'tipsy-gravity' attribute:
184
+ // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
185
+ // (remember - do not modify 'options' in place!)
186
+ $.fn.tipsy.elementOptions = function(ele, options) {
187
+ return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
188
+ };
189
+
190
+ $.fn.tipsy.autoNS = function() {
191
+ return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
192
+ };
193
+
194
+ $.fn.tipsy.autoWE = function() {
195
+ return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
196
+ };
197
+
198
+ })(jQuery);
static/js/jquery/moment.js CHANGED
@@ -1,6 +1,6 @@
1
- // moment.js
2
- // version : 1.7.2
3
- // author : Tim Wood
4
- // license : MIT
5
- // momentjs.com
6
  (function(a){function E(a,b,c,d){var e=c.lang();return e[a].call?e[a](c,d):e[a][b]}function F(a,b){return function(c){return K(a.call(this,c),b)}}function G(a){return function(b){var c=a.call(this,b);return c+this.lang().ordinal(c)}}function H(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,this._lang=c||!1}function I(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=J(j/1e3),b.seconds=i%60,h+=J(i/60),b.minutes=h%60,g+=J(h/60),b.hours=g%24,f+=J(g/24),f+=e*7,b.days=f%30,d+=J(f/30),b.months=d%12,c+=J(d/12),b.years=c,this._lang=!1}function J(a){return a<0?Math.ceil(a):Math.floor(a)}function K(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function L(a,b,c){var d=b._milliseconds,e=b._days,f=b._months,g;d&&a._d.setTime(+a+d*c),e&&a.date(a.date()+e*c),f&&(g=a.date(),a.date(1).month(a.month()+f*c).date(Math.min(g,a.daysInMonth())))}function M(a){return Object.prototype.toString.call(a)==="[object Array]"}function N(a,b){var c=Math.min(a.length,b.length),d=Math.abs(a.length-b.length),e=0,f;for(f=0;f<c;f++)~~a[f]!==~~b[f]&&e++;return e+d}function O(a,b,c,d){var e,f,g=[];for(e=0;e<7;e++)g[e]=a[e]=a[e]==null?e===2?1:0:a[e];return a[7]=g[7]=b,a[8]!=null&&(g[8]=a[8]),a[3]+=c||0,a[4]+=d||0,f=new Date(0),b?(f.setUTCFullYear(a[0],a[1],a[2]),f.setUTCHours(a[3],a[4],a[5],a[6])):(f.setFullYear(a[0],a[1],a[2]),f.setHours(a[3],a[4],a[5],a[6])),f._a=g,f}function P(a,c){var d,e,g=[];!c&&h&&(c=require("./lang/"+a));for(d=0;d<i.length;d++)c[i[d]]=c[i[d]]||f.en[i[d]];for(d=0;d<12;d++)e=b([2e3,d]),g[d]=new RegExp("^"+(c.months[d]||c.months(e,""))+"|^"+(c.monthsShort[d]||c.monthsShort(e,"")).replace(".",""),"i");return c.monthsParse=c.monthsParse||g,f[a]=c,c}function Q(a){var c=typeof a=="string"&&a||a&&a._lang||null;return c?f[c]||P(c):b}function R(a){return a.match(/\[.*\]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function S(a){var b=a.match(k),c,d;for(c=0,d=b.length;c<d;c++)D[b[c]]?b[c]=D[b[c]]:b[c]=R(b[c]);return function(e){var f="";for(c=0;c<d;c++)f+=typeof b[c].call=="function"?b[c].call(e,a):b[c];return f}}function T(a,b){function d(b){return a.lang().longDateFormat[b]||b}var c=5;while(c--&&l.test(b))b=b.replace(l,d);return A[b]||(A[b]=S(b)),A[b](a)}function U(a){switch(a){case"DDDD":return p;case"YYYY":return q;case"S":case"SS":case"SSS":case"DDD":return o;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return r;case"Z":case"ZZ":return s;case"T":return t;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return n;default:return new RegExp(a.replace("\\",""))}}function V(a,b,c,d){var e,f;switch(a){case"M":case"MM":c[1]=b==null?0:~~b-1;break;case"MMM":case"MMMM":for(e=0;e<12;e++)if(Q().monthsParse[e].test(b)){c[1]=e,f=!0;break}f||(c[8]=!1);break;case"D":case"DD":case"DDD":case"DDDD":b!=null&&(c[2]=~~b);break;case"YY":c[0]=~~b+(~~b>70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f<e.length;f++)g=(U(e[f]).exec(a)||[])[0],g&&(a=a.slice(a.indexOf(g)+g.length)),D[e[f]]&&V(e[f],g,c,d);return d.isPm&&c[3]<12&&(c[3]+=12),d.isPm===!1&&c[3]===12&&(c[3]=0),O(c,d.isUTC,d.tzh,d.tzm)}function X(a,b){var c,d=a.match(m)||[],e,f=99,g,h,i;for(g=0;g<b.length;g++)h=W(a,b[g]),e=T(new H(h),b[g]).match(m)||[],i=N(d,e),i<f&&(f=i,c=h);return c}function Y(a){var b="YYYY-MM-DDT",c;if(u.exec(a)){for(c=0;c<4;c++)if(w[c][1].exec(a)){b+=w[c][0];break}return s.exec(a)?W(a,b+" Z"):W(a,b)}return new Date(a)}function Z(a,b,c,d,e){var f=e.relativeTime[a];return typeof f=="function"?f(b||1,!!c,a,d):f.replace(/%d/i,b||1)}function $(a,b,c){var e=d(Math.abs(a)/1e3),f=d(e/60),g=d(f/60),h=d(g/24),i=d(h/365),j=e<45&&["s",e]||f===1&&["m"]||f<45&&["mm",f]||g===1&&["h"]||g<22&&["hh",g]||h===1&&["d"]||h<=25&&["dd",h]||h<=45&&["M"]||h<345&&["MM",d(h/30)]||i===1&&["y"]||["yy",i];return j[2]=b,j[3]=a>0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d<i.length;d++)b[i[d]]=f[a][i[d]];b.monthsParse=f[a].monthsParse,g=a}},b.langData=Q,b.isMoment=function(a){return a instanceof H},b.isDuration=function(a){return a instanceof I},b.lang("en",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()<b([this.year()]).zone()||this.zone()<b([this.year(),5]).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return a==null?b:this.add({d:a-b})},startOf:function(a){switch(a.replace(/s$/,"")){case"year":this.month(0);case"month":this.date(1);case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return this},endOf:function(a){return this.startOf(a).add(a.replace(/s?$/,"s"),1).subtract("ms",1)},sod:function(){return this.clone().startOf("day")},eod:function(){return this.clone().endOf("day")},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return b.utc([this.year(),this.month()+1,0]).date()},lang:function(b){return b===a?Q(this):(this._lang=b,this)}};for(e=0;e<y.length;e++)_(y[e].toLowerCase(),y[e]);_("year","FullYear"),b.duration.fn=I.prototype={weeks:function(){return J(this.days()/7)},valueOf:function(){return this._milliseconds+this._days*864e5+this._months*2592e6},humanize:function(a){var b=+this,c=this.lang().relativeTime,d=$(b,!a,this.lang()),e=b<=0?c.past:c.future;return a&&(typeof e=="function"?d=e(d):d=e.replace(/%s/i,d)),d},lang:b.fn.lang};for(e in z)z.hasOwnProperty(e)&&(bb(e,z[e]),ab(e.toLowerCase()));bb("Weeks",6048e5),h&&(module.exports=b),typeof ender=="undefined"&&(this.moment=b),typeof define=="function"&&define.amd&&define("moment",[],function(){return b})}).call(this);
1
+ // moment.js
2
+ // version : 1.7.2
3
+ // author : Tim Wood
4
+ // license : MIT
5
+ // momentjs.com
6
  (function(a){function E(a,b,c,d){var e=c.lang();return e[a].call?e[a](c,d):e[a][b]}function F(a,b){return function(c){return K(a.call(this,c),b)}}function G(a){return function(b){var c=a.call(this,b);return c+this.lang().ordinal(c)}}function H(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,this._lang=c||!1}function I(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=J(j/1e3),b.seconds=i%60,h+=J(i/60),b.minutes=h%60,g+=J(h/60),b.hours=g%24,f+=J(g/24),f+=e*7,b.days=f%30,d+=J(f/30),b.months=d%12,c+=J(d/12),b.years=c,this._lang=!1}function J(a){return a<0?Math.ceil(a):Math.floor(a)}function K(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function L(a,b,c){var d=b._milliseconds,e=b._days,f=b._months,g;d&&a._d.setTime(+a+d*c),e&&a.date(a.date()+e*c),f&&(g=a.date(),a.date(1).month(a.month()+f*c).date(Math.min(g,a.daysInMonth())))}function M(a){return Object.prototype.toString.call(a)==="[object Array]"}function N(a,b){var c=Math.min(a.length,b.length),d=Math.abs(a.length-b.length),e=0,f;for(f=0;f<c;f++)~~a[f]!==~~b[f]&&e++;return e+d}function O(a,b,c,d){var e,f,g=[];for(e=0;e<7;e++)g[e]=a[e]=a[e]==null?e===2?1:0:a[e];return a[7]=g[7]=b,a[8]!=null&&(g[8]=a[8]),a[3]+=c||0,a[4]+=d||0,f=new Date(0),b?(f.setUTCFullYear(a[0],a[1],a[2]),f.setUTCHours(a[3],a[4],a[5],a[6])):(f.setFullYear(a[0],a[1],a[2]),f.setHours(a[3],a[4],a[5],a[6])),f._a=g,f}function P(a,c){var d,e,g=[];!c&&h&&(c=require("./lang/"+a));for(d=0;d<i.length;d++)c[i[d]]=c[i[d]]||f.en[i[d]];for(d=0;d<12;d++)e=b([2e3,d]),g[d]=new RegExp("^"+(c.months[d]||c.months(e,""))+"|^"+(c.monthsShort[d]||c.monthsShort(e,"")).replace(".",""),"i");return c.monthsParse=c.monthsParse||g,f[a]=c,c}function Q(a){var c=typeof a=="string"&&a||a&&a._lang||null;return c?f[c]||P(c):b}function R(a){return a.match(/\[.*\]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function S(a){var b=a.match(k),c,d;for(c=0,d=b.length;c<d;c++)D[b[c]]?b[c]=D[b[c]]:b[c]=R(b[c]);return function(e){var f="";for(c=0;c<d;c++)f+=typeof b[c].call=="function"?b[c].call(e,a):b[c];return f}}function T(a,b){function d(b){return a.lang().longDateFormat[b]||b}var c=5;while(c--&&l.test(b))b=b.replace(l,d);return A[b]||(A[b]=S(b)),A[b](a)}function U(a){switch(a){case"DDDD":return p;case"YYYY":return q;case"S":case"SS":case"SSS":case"DDD":return o;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return r;case"Z":case"ZZ":return s;case"T":return t;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return n;default:return new RegExp(a.replace("\\",""))}}function V(a,b,c,d){var e,f;switch(a){case"M":case"MM":c[1]=b==null?0:~~b-1;break;case"MMM":case"MMMM":for(e=0;e<12;e++)if(Q().monthsParse[e].test(b)){c[1]=e,f=!0;break}f||(c[8]=!1);break;case"D":case"DD":case"DDD":case"DDDD":b!=null&&(c[2]=~~b);break;case"YY":c[0]=~~b+(~~b>70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f<e.length;f++)g=(U(e[f]).exec(a)||[])[0],g&&(a=a.slice(a.indexOf(g)+g.length)),D[e[f]]&&V(e[f],g,c,d);return d.isPm&&c[3]<12&&(c[3]+=12),d.isPm===!1&&c[3]===12&&(c[3]=0),O(c,d.isUTC,d.tzh,d.tzm)}function X(a,b){var c,d=a.match(m)||[],e,f=99,g,h,i;for(g=0;g<b.length;g++)h=W(a,b[g]),e=T(new H(h),b[g]).match(m)||[],i=N(d,e),i<f&&(f=i,c=h);return c}function Y(a){var b="YYYY-MM-DDT",c;if(u.exec(a)){for(c=0;c<4;c++)if(w[c][1].exec(a)){b+=w[c][0];break}return s.exec(a)?W(a,b+" Z"):W(a,b)}return new Date(a)}function Z(a,b,c,d,e){var f=e.relativeTime[a];return typeof f=="function"?f(b||1,!!c,a,d):f.replace(/%d/i,b||1)}function $(a,b,c){var e=d(Math.abs(a)/1e3),f=d(e/60),g=d(f/60),h=d(g/24),i=d(h/365),j=e<45&&["s",e]||f===1&&["m"]||f<45&&["mm",f]||g===1&&["h"]||g<22&&["hh",g]||h===1&&["d"]||h<=25&&["dd",h]||h<=45&&["M"]||h<345&&["MM",d(h/30)]||i===1&&["y"]||["yy",i];return j[2]=b,j[3]=a>0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d<i.length;d++)b[i[d]]=f[a][i[d]];b.monthsParse=f[a].monthsParse,g=a}},b.langData=Q,b.isMoment=function(a){return a instanceof H},b.isDuration=function(a){return a instanceof I},b.lang("en",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()<b([this.year()]).zone()||this.zone()<b([this.year(),5]).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return a==null?b:this.add({d:a-b})},startOf:function(a){switch(a.replace(/s$/,"")){case"year":this.month(0);case"month":this.date(1);case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return this},endOf:function(a){return this.startOf(a).add(a.replace(/s?$/,"s"),1).subtract("ms",1)},sod:function(){return this.clone().startOf("day")},eod:function(){return this.clone().endOf("day")},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return b.utc([this.year(),this.month()+1,0]).date()},lang:function(b){return b===a?Q(this):(this._lang=b,this)}};for(e=0;e<y.length;e++)_(y[e].toLowerCase(),y[e]);_("year","FullYear"),b.duration.fn=I.prototype={weeks:function(){return J(this.days()/7)},valueOf:function(){return this._milliseconds+this._days*864e5+this._months*2592e6},humanize:function(a){var b=+this,c=this.lang().relativeTime,d=$(b,!a,this.lang()),e=b<=0?c.past:c.future;return a&&(typeof e=="function"?d=e(d):d=e.replace(/%s/i,d)),d},lang:b.fn.lang};for(e in z)z.hasOwnProperty(e)&&(bb(e,z[e]),ab(e.toLowerCase()));bb("Weeks",6048e5),h&&(module.exports=b),typeof ender=="undefined"&&(this.moment=b),typeof define=="function"&&define.amd&&define("moment",[],function(){return b})}).call(this);
static/js/jquery/ui.autocomplete.js CHANGED
@@ -1,606 +1,606 @@
1
- /*
2
- * jQuery UI Autocomplete 1.8.10
3
- *
4
- * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
- * Dual licensed under the MIT or GPL Version 2 licenses.
6
- * http://jquery.org/license
7
- *
8
- * http://docs.jquery.com/UI/Autocomplete
9
- *
10
- * Depends:
11
- * jquery.ui.core.js
12
- * jquery.ui.widget.js
13
- * jquery.ui.position.js
14
- */
15
- (function( $, undefined ) {
16
-
17
- // used to prevent race conditions with remote data sources
18
- var requestIndex = 0;
19
-
20
- $.widget( "ui.autocomplete", {
21
- options: {
22
- appendTo: "body",
23
- delay: 300,
24
- minLength: 1,
25
- position: {
26
- my: "left top",
27
- at: "left bottom",
28
- collision: "none"
29
- },
30
- source: null
31
- },
32
-
33
- pending: 0,
34
-
35
- _create: function() {
36
- var self = this,
37
- doc = this.element[ 0 ].ownerDocument,
38
- suppressKeyPress;
39
-
40
- this.element
41
- .addClass( "ui-autocomplete-input" )
42
- .attr( "autocomplete", "off" )
43
- // TODO verify these actually work as intended
44
- .attr({
45
- role: "textbox",
46
- "aria-autocomplete": "list",
47
- "aria-haspopup": "true"
48
- })
49
- .bind( "keydown.autocomplete", function( event ) {
50
- if ( self.options.disabled || self.element.attr( "readonly" ) ) {
51
- return;
52
- }
53
-
54
- suppressKeyPress = false;
55
- var keyCode = $.ui.keyCode;
56
- switch( event.keyCode ) {
57
- case keyCode.PAGE_UP:
58
- self._move( "previousPage", event );
59
- break;
60
- case keyCode.PAGE_DOWN:
61
- self._move( "nextPage", event );
62
- break;
63
- case keyCode.UP:
64
- self._move( "previous", event );
65
- // prevent moving cursor to beginning of text field in some browsers
66
- event.preventDefault();
67
- break;
68
- case keyCode.DOWN:
69
- self._move( "next", event );
70
- // prevent moving cursor to end of text field in some browsers
71
- event.preventDefault();
72
- break;
73
- case keyCode.ENTER:
74
- case keyCode.NUMPAD_ENTER:
75
- // when menu is open and has focus
76
- if ( self.menu.active ) {
77
- // #6055 - Opera still allows the keypress to occur
78
- // which causes forms to submit
79
- suppressKeyPress = true;
80
- event.preventDefault();
81
- }
82
- //passthrough - ENTER and TAB both select the current element
83
- case keyCode.TAB:
84
- if ( !self.menu.active ) {
85
- return;
86
- }
87
- self.menu.select( event );
88
- break;
89
- case keyCode.ESCAPE:
90
- self.element.val( self.term );
91
- self.close( event );
92
- break;
93
- default:
94
- // keypress is triggered before the input value is changed
95
- clearTimeout( self.searching );
96
- self.searching = setTimeout(function() {
97
- // only search if the value has changed
98
- if ( self.term != self.element.val() ) {
99
- self.selectedItem = null;
100
- self.search( null, event );
101
- }
102
- }, self.options.delay );
103
- break;
104
- }
105
- })
106
- .bind( "keypress.autocomplete", function( event ) {
107
- if ( suppressKeyPress ) {
108
- suppressKeyPress = false;
109
- event.preventDefault();
110
- }
111
- })
112
- .bind( "focus.autocomplete", function() {
113
- if ( self.options.disabled ) {
114
- return;
115
- }
116
-
117
- self.selectedItem = null;
118
- self.previous = self.element.val();
119
- })
120
- .bind( "blur.autocomplete", function( event ) {
121
- if ( self.options.disabled ) {
122
- return;
123
- }
124
-
125
- clearTimeout( self.searching );
126
- // clicks on the menu (or a button to trigger a search) will cause a blur event
127
- self.closing = setTimeout(function() {
128
- self.close( event );
129
- self._change( event );
130
- }, 150 );
131
- });
132
- this._initSource();
133
- this.response = function() {
134
- return self._response.apply( self, arguments );
135
- };
136
- this.menu = $( "<ul></ul>" )
137
- .addClass( "ui-autocomplete" )
138
- .appendTo( $( this.options.appendTo || "body", doc )[0] )
139
- // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
140
- .mousedown(function( event ) {
141
- // clicking on the scrollbar causes focus to shift to the body
142
- // but we can't detect a mouseup or a click immediately afterward
143
- // so we have to track the next mousedown and close the menu if
144
- // the user clicks somewhere outside of the autocomplete
145
- var menuElement = self.menu.element[ 0 ];
146
- if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
147
- setTimeout(function() {
148
- $( document ).one( 'mousedown', function( event ) {
149
- if ( event.target !== self.element[ 0 ] &&
150
- event.target !== menuElement &&
151
- !$.ui.contains( menuElement, event.target ) ) {
152
- self.close();
153
- }
154
- });
155
- }, 1 );
156
- }
157
-
158
- // use another timeout to make sure the blur-event-handler on the input was already triggered
159
- setTimeout(function() {
160
- clearTimeout( self.closing );
161
- }, 13);
162
- })
163
- .menu({
164
- focus: function( event, ui ) {
165
- var item = ui.item.data( "item.autocomplete" );
166
- if ( false !== self._trigger( "focus", event, { item: item } ) ) {
167
- // use value to match what will end up in the input, if it was a key event
168
- if ( /^key/.test(event.originalEvent.type) ) {
169
- self.element.val( item.value );
170
- }
171
- }
172
- },
173
- selected: function( event, ui ) {
174
- var item = ui.item.data( "item.autocomplete" ),
175
- previous = self.previous;
176
-
177
- // only trigger when focus was lost (click on menu)
178
- if ( self.element[0] !== doc.activeElement ) {
179
- self.element.focus();
180
- self.previous = previous;
181
- // #6109 - IE triggers two focus events and the second
182
- // is asynchronous, so we need to reset the previous
183
- // term synchronously and asynchronously :-(
184
- setTimeout(function() {
185
- self.previous = previous;
186
- self.selectedItem = item;
187
- }, 1);
188
- }
189
-
190
- if ( false !== self._trigger( "select", event, { item: item } ) ) {
191
- self.element.val( item.value );
192
- }
193
- // reset the term after the select event
194
- // this allows custom select handling to work properly
195
- self.term = self.element.val();
196
-
197
- self.close( event );
198
- self.selectedItem = item;
199
- },
200
- blur: function( event, ui ) {
201
- // don't set the value of the text field if it's already correct
202
- // this prevents moving the cursor unnecessarily
203
- if ( self.menu.element.is(":visible") &&
204
- ( self.element.val() !== self.term ) ) {
205
- self.element.val( self.term );
206
- }
207
- }
208
- })
209
- .zIndex( this.element.zIndex() + 1 )
210
- // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
211
- .css({ top: 0, left: 0 })
212
- .data( "menu" );
213
- if ( $.fn.bgiframe ) {
214
- this.menu.element.bgiframe();
215
- }
216
- },
217
-
218
- destroy: function() {
219
- this.element
220
- .removeClass( "ui-autocomplete-input" )
221
- .removeAttr( "autocomplete" )
222
- .removeAttr( "role" )
223
- .removeAttr( "aria-autocomplete" )
224
- .removeAttr( "aria-haspopup" );
225
- this.menu.element.remove();
226
- $.Widget.prototype.destroy.call( this );
227
- },
228
-
229
- _setOption: function( key, value ) {
230
- $.Widget.prototype._setOption.apply( this, arguments );
231
- if ( key === "source" ) {
232
- this._initSource();
233
- }
234
- if ( key === "appendTo" ) {
235
- this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
236
- }
237
- if ( key === "disabled" && value && this.xhr ) {
238
- this.xhr.abort();
239
- }
240
- },
241
-
242
- _initSource: function() {
243
- var self = this,
244
- array,
245
- url;
246
- if ( $.isArray(this.options.source) ) {
247
- array = this.options.source;
248
- this.source = function( request, response ) {
249
- response( $.ui.autocomplete.filter(array, request.term) );
250
- };
251
- } else if ( typeof this.options.source === "string" ) {
252
- url = this.options.source;
253
- this.source = function( request, response ) {
254
- if ( self.xhr ) {
255
- self.xhr.abort();
256
- }
257
- self.xhr = $.ajax({
258
- url: url,
259
- data: request,
260
- dataType: "json",
261
- autocompleteRequest: ++requestIndex,
262
- success: function( data, status ) {
263
- if ( this.autocompleteRequest === requestIndex ) {
264
- response( data );
265
- }
266
- },
267
- error: function() {
268
- if ( this.autocompleteRequest === requestIndex ) {
269
- response( [] );
270
- }
271
- }
272
- });
273
- };
274
- } else {
275
- this.source = this.options.source;
276
- }
277
- },
278
-
279
- search: function( value, event ) {
280
- value = value != null ? value : this.element.val();
281
-
282
- // always save the actual value, not the one passed as an argument
283
- this.term = this.element.val();
284
-
285
- if ( value.length < this.options.minLength ) {
286
- return this.close( event );
287
- }
288
-
289
- clearTimeout( this.closing );
290
- if ( this._trigger( "search", event ) === false ) {
291
- return;
292
- }
293
-
294
- return this._search( value );
295
- },
296
-
297
- _search: function( value ) {
298
- this.pending++;
299
- this.element.addClass( "ui-autocomplete-loading" );
300
-
301
- this.source( { term: value }, this.response );
302
- },
303
-
304
- _response: function( content ) {
305
- if ( !this.options.disabled && content && content.length ) {
306
- content = this._normalize( content );
307
- this._suggest( content );
308
- this._trigger( "open" );
309
- } else {
310
- this.close();
311
- }
312
- this.pending--;
313
- if ( !this.pending ) {
314
- this.element.removeClass( "ui-autocomplete-loading" );
315
- }
316
- },
317
-
318
- close: function( event ) {
319
- clearTimeout( this.closing );
320
- if ( this.menu.element.is(":visible") ) {
321
- this.menu.element.hide();
322
- this.menu.deactivate();
323
- this._trigger( "close", event );
324
- }
325
- },
326
-
327
- _change: function( event ) {
328
- if ( this.previous !== this.element.val() ) {
329
- this._trigger( "change", event, { item: this.selectedItem } );
330
- }
331
- },
332
-
333
- _normalize: function( items ) {
334
- // assume all items have the right format when the first item is complete
335
- if ( items.length && items[0].label && items[0].value ) {
336
- return items;
337
- }
338
- return $.map( items, function(item) {
339
- if ( typeof item === "string" ) {
340
- return {
341
- label: item,
342
- value: item
343
- };
344
- }
345
- return $.extend({
346
- label: item.label || item.value,
347
- value: item.value || item.label
348
- }, item );
349
- });
350
- },
351
-
352
- _suggest: function( items ) {
353
- var ul = this.menu.element
354
- .empty()
355
- .zIndex( this.element.zIndex() + 1 );
356
- this._renderMenu( ul, items );
357
- // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
358
- this.menu.deactivate();
359
- this.menu.refresh();
360
-
361
- // size and position menu
362
- ul.show();
363
- this._resizeMenu();
364
- ul.position( $.extend({
365
- of: this.element
366
- }, this.options.position ));
367
- },
368
-
369
- _resizeMenu: function() {
370
- var ul = this.menu.element;
371
- ul.outerWidth( Math.max(
372
- ul.width( "" ).outerWidth(),
373
- this.element.outerWidth()
374
- ) );
375
- },
376
-
377
- _renderMenu: function( ul, items ) {
378
- var self = this;
379
- $.each( items, function( index, item ) {
380
- self._renderItem( ul, item );
381
- });
382
- },
383
-
384
- _renderItem: function( ul, item) {
385
- return $( "<li></li>" )
386
- .data( "item.autocomplete", item )
387
- .append( $( "<a></a>" ).text( item.label ) )
388
- .appendTo( ul );
389
- },
390
-
391
- _move: function( direction, event ) {
392
- if ( !this.menu.element.is(":visible") ) {
393
- this.search( null, event );
394
- return;
395
- }
396
- if ( this.menu.first() && /^previous/.test(direction) ||
397
- this.menu.last() && /^next/.test(direction) ) {
398
- this.element.val( this.term );
399
- this.menu.deactivate();
400
- return;
401
- }
402
- this.menu[ direction ]( event );
403
- },
404
-
405
- widget: function() {
406
- return this.menu.element;
407
- }
408
- });
409
-
410
- $.extend( $.ui.autocomplete, {
411
- escapeRegex: function( value ) {
412
- return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
413
- },
414
- filter: function(array, term) {
415
- var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
416
- return $.grep( array, function(value) {
417
- return matcher.test( value.label || value.value || value );
418
- });
419
- }
420
- });
421
-
422
- }( jQuery ));
423
-
424
- /*
425
- * jQuery UI Menu (not officially released)
426
- *
427
- * This widget isn't yet finished and the API is subject to change. We plan to finish
428
- * it for the next release. You're welcome to give it a try anyway and give us feedback,
429
- * as long as you're okay with migrating your code later on. We can help with that, too.
430
- *
431
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
432
- * Dual licensed under the MIT or GPL Version 2 licenses.
433
- * http://jquery.org/license
434
- *
435
- * http://docs.jquery.com/UI/Menu
436
- *
437
- * Depends:
438
- * jquery.ui.core.js
439
- * jquery.ui.widget.js
440
- */
441
- (function($) {
442
-
443
- $.widget("ui.menu", {
444
- _create: function() {
445
- var self = this;
446
- this.element
447
- .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
448
- .attr({
449
- role: "listbox",
450
- "aria-activedescendant": "ui-active-menuitem"
451
- })
452
- .click(function( event ) {
453
- if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
454
- return;
455
- }
456
- // temporary
457
- event.preventDefault();
458
- self.select( event );
459
- });
460
- this.refresh();
461
- },
462
-
463
- refresh: function() {
464
- var self = this;
465
-
466
- // don't refresh list items that are already adapted
467
- var items = this.element.children("li:not(.ui-menu-item):has(a)")
468
- .addClass("ui-menu-item")
469
- .attr("role", "menuitem");
470
-
471
- items.children("a")
472
- .addClass("ui-corner-all")
473
- .attr("tabindex", -1)
474
- // mouseenter doesn't work with event delegation
475
- .mouseenter(function( event ) {
476
- self.activate( event, $(this).parent() );
477
- })
478
- .mouseleave(function() {
479
- self.deactivate();
480
- });
481
- },
482
-
483
- activate: function( event, item ) {
484
- this.deactivate();
485
- if (this.hasScroll()) {
486
- var offset = item.offset().top - this.element.offset().top,
487
- scroll = this.element.attr("scrollTop"),
488
- elementHeight = this.element.height();
489
- if (offset < 0) {
490
- this.element.attr("scrollTop", scroll + offset);
491
- } else if (offset >= elementHeight) {
492
- this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
493
- }
494
- }
495
- this.active = item.eq(0)
496
- .children("a")
497
- .addClass("ui-state-hover")
498
- .attr("id", "ui-active-menuitem")
499
- .end();
500
- this._trigger("focus", event, { item: item });
501
- },
502
-
503
- deactivate: function() {
504
- if (!this.active) { return; }
505
-
506
- this.active.children("a")
507
- .removeClass("ui-state-hover")
508
- .removeAttr("id");
509
- this._trigger("blur");
510
- this.active = null;
511
- },
512
-
513
- next: function(event) {
514
- this.move("next", ".ui-menu-item:first", event);
515
- },
516
-
517
- previous: function(event) {
518
- this.move("prev", ".ui-menu-item:last", event);
519
- },
520
-
521
- first: function() {
522
- return this.active && !this.active.prevAll(".ui-menu-item").length;
523
- },
524
-
525
- last: function() {
526
- return this.active && !this.active.nextAll(".ui-menu-item").length;
527
- },
528
-
529
- move: function(direction, edge, event) {
530
- if (!this.active) {
531
- this.activate(event, this.element.children(edge));
532
- return;
533
- }
534
- var next = this.active[direction + "All"](".ui-menu-item").eq(0);
535
- if (next.length) {
536
- this.activate(event, next);
537
- } else {
538
- this.activate(event, this.element.children(edge));
539
- }
540
- },
541
-
542
- // TODO merge with previousPage
543
- nextPage: function(event) {
544
- if (this.hasScroll()) {
545
- // TODO merge with no-scroll-else
546
- if (!this.active || this.last()) {
547
- this.activate(event, this.element.children(".ui-menu-item:first"));
548
- return;
549
- }
550
- var base = this.active.offset().top,
551
- height = this.element.height(),
552
- result = this.element.children(".ui-menu-item").filter(function() {
553
- var close = $(this).offset().top - base - height + $(this).height();
554
- // TODO improve approximation
555
- return close < 10 && close > -10;
556
- });
557
-
558
- // TODO try to catch this earlier when scrollTop indicates the last page anyway
559
- if (!result.length) {
560
- result = this.element.children(".ui-menu-item:last");
561
- }
562
- this.activate(event, result);
563
- } else {
564
- this.activate(event, this.element.children(".ui-menu-item")
565
- .filter(!this.active || this.last() ? ":first" : ":last"));
566
- }
567
- },
568
-
569
- // TODO merge with nextPage
570
- previousPage: function(event) {
571
- if (this.hasScroll()) {
572
- // TODO merge with no-scroll-else
573
- if (!this.active || this.first()) {
574
- this.activate(event, this.element.children(".ui-menu-item:last"));
575
- return;
576
- }
577
-
578
- var base = this.active.offset().top,
579
- height = this.element.height();
580
- result = this.element.children(".ui-menu-item").filter(function() {
581
- var close = $(this).offset().top - base + height - $(this).height();
582
- // TODO improve approximation
583
- return close < 10 && close > -10;
584
- });
585
-
586
- // TODO try to catch this earlier when scrollTop indicates the last page anyway
587
- if (!result.length) {
588
- result = this.element.children(".ui-menu-item:first");
589
- }
590
- this.activate(event, result);
591
- } else {
592
- this.activate(event, this.element.children(".ui-menu-item")
593
- .filter(!this.active || this.first() ? ":last" : ":first"));
594
- }
595
- },
596
-
597
- hasScroll: function() {
598
- return this.element.height() < this.element.attr("scrollHeight");
599
- },
600
-
601
- select: function( event ) {
602
- this._trigger("selected", event, { item: this.active });
603
- }
604
- });
605
-
606
- }(jQuery));
1
+ /*
2
+ * jQuery UI Autocomplete 1.8.10
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI/Autocomplete
9
+ *
10
+ * Depends:
11
+ * jquery.ui.core.js
12
+ * jquery.ui.widget.js
13
+ * jquery.ui.position.js
14
+ */
15
+ (function( $, undefined ) {
16
+
17
+ // used to prevent race conditions with remote data sources
18
+ var requestIndex = 0;
19
+
20
+ $.widget( "ui.autocomplete", {
21
+ options: {
22
+ appendTo: "body",
23
+ delay: 300,
24
+ minLength: 1,
25
+ position: {
26
+ my: "left top",
27
+ at: "left bottom",
28
+ collision: "none"
29
+ },
30
+ source: null
31
+ },
32
+
33
+ pending: 0,
34
+
35
+ _create: function() {
36
+ var self = this,
37
+ doc = this.element[ 0 ].ownerDocument,
38
+ suppressKeyPress;
39
+
40
+ this.element
41
+ .addClass( "ui-autocomplete-input" )
42
+ .attr( "autocomplete", "off" )
43
+ // TODO verify these actually work as intended
44
+ .attr({
45
+ role: "textbox",
46
+ "aria-autocomplete": "list",
47
+ "aria-haspopup": "true"
48
+ })
49
+ .bind( "keydown.autocomplete", function( event ) {
50
+ if ( self.options.disabled || self.element.attr( "readonly" ) ) {
51
+ return;
52
+ }
53
+
54
+ suppressKeyPress = false;
55
+ var keyCode = $.ui.keyCode;
56
+ switch( event.keyCode ) {
57
+ case keyCode.PAGE_UP:
58
+ self._move( "previousPage", event );
59
+ break;
60
+ case keyCode.PAGE_DOWN:
61
+ self._move( "nextPage", event );
62
+ break;
63
+ case keyCode.UP:
64
+ self._move( "previous", event );
65
+ // prevent moving cursor to beginning of text field in some browsers
66
+ event.preventDefault();
67
+ break;
68
+ case keyCode.DOWN:
69
+ self._move( "next", event );
70
+ // prevent moving cursor to end of text field in some browsers
71
+ event.preventDefault();
72
+ break;
73
+ case keyCode.ENTER:
74
+ case keyCode.NUMPAD_ENTER:
75
+ // when menu is open and has focus
76
+ if ( self.menu.active ) {
77
+ // #6055 - Opera still allows the keypress to occur
78
+ // which causes forms to submit
79
+ suppressKeyPress = true;
80
+ event.preventDefault();
81
+ }
82
+ //passthrough - ENTER and TAB both select the current element
83
+ case keyCode.TAB:
84
+ if ( !self.menu.active ) {
85
+ return;
86
+ }
87
+ self.menu.select( event );
88
+ break;
89
+ case keyCode.ESCAPE:
90
+ self.element.val( self.term );
91
+ self.close( event );
92
+ break;
93
+ default:
94
+ // keypress is triggered before the input value is changed
95
+ clearTimeout( self.searching );
96
+ self.searching = setTimeout(function() {
97
+ // only search if the value has changed
98
+ if ( self.term != self.element.val() ) {
99
+ self.selectedItem = null;
100
+ self.search( null, event );
101
+ }
102
+ }, self.options.delay );
103
+ break;
104
+ }
105
+ })
106
+ .bind( "keypress.autocomplete", function( event ) {
107
+ if ( suppressKeyPress ) {
108
+ suppressKeyPress = false;
109
+ event.preventDefault();
110
+ }
111
+ })
112
+ .bind( "focus.autocomplete", function() {
113
+ if ( self.options.disabled ) {
114
+ return;
115
+ }
116
+
117
+ self.selectedItem = null;
118
+ self.previous = self.element.val();
119
+ })
120
+ .bind( "blur.autocomplete", function( event ) {
121
+ if ( self.options.disabled ) {
122
+ return;
123
+ }
124
+
125
+ clearTimeout( self.searching );
126
+ // clicks on the menu (or a button to trigger a search) will cause a blur event
127
+ self.closing = setTimeout(function() {
128
+ self.close( event );
129
+ self._change( event );
130
+ }, 150 );
131
+ });
132
+ this._initSource();
133
+ this.response = function() {
134
+ return self._response.apply( self, arguments );
135
+ };
136
+ this.menu = $( "<ul></ul>" )
137
+ .addClass( "ui-autocomplete" )
138
+ .appendTo( $( this.options.appendTo || "body", doc )[0] )
139
+ // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
140
+ .mousedown(function( event ) {
141
+ // clicking on the scrollbar causes focus to shift to the body
142
+ // but we can't detect a mouseup or a click immediately afterward
143
+ // so we have to track the next mousedown and close the menu if
144
+ // the user clicks somewhere outside of the autocomplete
145
+ var menuElement = self.menu.element[ 0 ];
146
+ if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
147
+ setTimeout(function() {
148
+ $( document ).one( 'mousedown', function( event ) {
149
+ if ( event.target !== self.element[ 0 ] &&
150
+ event.target !== menuElement &&
151
+ !$.ui.contains( menuElement, event.target ) ) {
152
+ self.close();
153
+ }
154
+ });
155
+ }, 1 );
156
+ }
157
+
158
+ // use another timeout to make sure the blur-event-handler on the input was already triggered
159
+ setTimeout(function() {
160
+ clearTimeout( self.closing );
161
+ }, 13);
162
+ })
163
+ .menu({
164
+ focus: function( event, ui ) {
165
+ var item = ui.item.data( "item.autocomplete" );
166
+ if ( false !== self._trigger( "focus", event, { item: item } ) ) {
167
+ // use value to match what will end up in the input, if it was a key event
168
+ if ( /^key/.test(event.originalEvent.type) ) {
169
+ self.element.val( item.value );
170
+ }
171
+ }
172
+ },
173
+ selected: function( event, ui ) {
174
+ var item = ui.item.data( "item.autocomplete" ),
175
+ previous = self.previous;
176
+
177
+ // only trigger when focus was lost (click on menu)
178
+ if ( self.element[0] !== doc.activeElement ) {
179
+ self.element.focus();
180
+ self.previous = previous;
181
+ // #6109 - IE triggers two focus events and the second
182
+ // is asynchronous, so we need to reset the previous
183
+ // term synchronously and asynchronously :-(
184
+ setTimeout(function() {
185
+ self.previous = previous;
186
+ self.selectedItem = item;
187
+ }, 1);
188
+ }
189
+
190
+ if ( false !== self._trigger( "select", event, { item: item } ) ) {
191
+ self.element.val( item.value );
192
+ }
193
+ // reset the term after the select event
194
+ // this allows custom select handling to work properly
195
+ self.term = self.element.val();
196
+
197
+ self.close( event );
198
+ self.selectedItem = item;
199
+ },
200
+ blur: function( event, ui ) {
201
+ // don't set the value of the text field if it's already correct
202
+ // this prevents moving the cursor unnecessarily
203
+ if ( self.menu.element.is(":visible") &&
204
+ ( self.element.val() !== self.term ) ) {
205
+ self.element.val( self.term );
206
+ }
207
+ }
208
+ })
209
+ .zIndex( this.element.zIndex() + 1 )
210
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
211
+ .css({ top: 0, left: 0 })
212
+ .data( "menu" );
213
+ if ( $.fn.bgiframe ) {
214
+ this.menu.element.bgiframe();
215
+ }
216
+ },
217
+
218
+ destroy: function() {
219
+ this.element
220
+ .removeClass( "ui-autocomplete-input" )
221
+ .removeAttr( "autocomplete" )
222
+ .removeAttr( "role" )
223
+ .removeAttr( "aria-autocomplete" )
224
+ .removeAttr( "aria-haspopup" );
225
+ this.menu.element.remove();
226
+ $.Widget.prototype.destroy.call( this );
227
+ },
228
+
229
+ _setOption: function( key, value ) {
230
+ $.Widget.prototype._setOption.apply( this, arguments );
231
+ if ( key === "source" ) {
232
+ this._initSource();
233
+ }
234
+ if ( key === "appendTo" ) {
235
+ this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
236
+ }
237
+ if ( key === "disabled" && value && this.xhr ) {
238
+ this.xhr.abort();
239
+ }
240
+ },
241
+
242
+ _initSource: function() {
243
+ var self = this,
244
+ array,
245
+ url;
246
+ if ( $.isArray(this.options.source) ) {
247
+ array = this.options.source;
248
+ this.source = function( request, response ) {
249
+ response( $.ui.autocomplete.filter(array, request.term) );
250
+ };
251
+ } else if ( typeof this.options.source === "string" ) {
252
+ url = this.options.source;
253
+ this.source = function( request, response ) {
254
+ if ( self.xhr ) {
255
+ self.xhr.abort();
256
+ }
257
+ self.xhr = $.ajax({
258
+ url: url,
259
+ data: request,
260
+ dataType: "json",
261
+ autocompleteRequest: ++requestIndex,
262
+ success: function( data, status ) {
263
+ if ( this.autocompleteRequest === requestIndex ) {
264
+ response( data );
265
+ }
266
+ },
267
+ error: function() {
268
+ if ( this.autocompleteRequest === requestIndex ) {
269
+ response( [] );
270
+ }
271
+ }
272
+ });
273
+ };
274
+ } else {
275
+ this.source = this.options.source;
276
+ }
277
+ },
278
+
279
+ search: function( value, event ) {
280
+ value = value != null ? value : this.element.val();
281
+
282
+ // always save the actual value, not the one passed as an argument
283
+ this.term = this.element.val();
284
+
285
+ if ( value.length < this.options.minLength ) {
286
+ return this.close( event );
287
+ }
288
+
289
+ clearTimeout( this.closing );
290
+ if ( this._trigger( "search", event ) === false ) {
291
+ return;
292
+ }
293
+
294
+ return this._search( value );
295
+ },
296
+
297
+ _search: function( value ) {
298
+ this.pending++;
299
+ this.element.addClass( "ui-autocomplete-loading" );
300
+
301
+ this.source( { term: value }, this.response );
302
+ },
303
+
304
+ _response: function( content ) {
305
+ if ( !this.options.disabled && content && content.length ) {
306
+ content = this._normalize( content );
307
+ this._suggest( content );
308
+ this._trigger( "open" );
309
+ } else {
310
+ this.close();
311
+ }
312
+ this.pending--;
313
+ if ( !this.pending ) {
314
+ this.element.removeClass( "ui-autocomplete-loading" );
315
+ }
316
+ },
317
+
318
+ close: function( event ) {
319
+ clearTimeout( this.closing );
320
+ if ( this.menu.element.is(":visible") ) {
321
+ this.menu.element.hide();
322
+ this.menu.deactivate();
323
+ this._trigger( "close", event );
324
+ }
325
+ },
326
+
327
+ _change: function( event ) {
328
+ if ( this.previous !== this.element.val() ) {
329
+ this._trigger( "change", event, { item: this.selectedItem } );
330
+ }
331
+ },
332
+
333
+ _normalize: function( items ) {
334
+ // assume all items have the right format when the first item is complete
335
+ if ( items.length && items[0].label && items[0].value ) {
336
+ return items;
337
+ }
338
+ return $.map( items, function(item) {
339
+ if ( typeof item === "string" ) {
340
+ return {
341
+ label: item,
342
+ value: item
343
+ };
344
+ }
345
+ return $.extend({
346
+ label: item.label || item.value,
347
+ value: item.value || item.label
348
+ }, item );
349
+ });
350
+ },
351
+
352
+ _suggest: function( items ) {
353
+ var ul = this.menu.element
354
+ .empty()
355
+ .zIndex( this.element.zIndex() + 1 );
356
+ this._renderMenu( ul, items );
357
+ // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
358
+ this.menu.deactivate();
359
+ this.menu.refresh();
360
+
361
+ // size and position menu
362
+ ul.show();
363
+ this._resizeMenu();
364
+ ul.position( $.extend({
365
+ of: this.element
366
+ }, this.options.position ));
367
+ },
368
+
369
+ _resizeMenu: function() {
370
+ var ul = this.menu.element;
371
+ ul.outerWidth( Math.max(
372
+ ul.width( "" ).outerWidth(),
373
+ this.element.outerWidth()
374
+ ) );
375
+ },
376
+
377
+ _renderMenu: function( ul, items ) {
378
+ var self = this;
379
+ $.each( items, function( index, item ) {
380
+ self._renderItem( ul, item );
381
+ });
382
+ },
383
+
384
+ _renderItem: function( ul, item) {
385
+ return $( "<li></li>" )
386
+ .data( "item.autocomplete", item )
387
+ .append( $( "<a></a>" ).text( item.label ) )
388
+ .appendTo( ul );
389
+ },
390
+
391
+ _move: function( direction, event ) {
392
+ if ( !this.menu.element.is(":visible") ) {
393
+ this.search( null, event );
394
+ return;
395
+ }
396
+ if ( this.menu.first() && /^previous/.test(direction) ||
397
+ this.menu.last() && /^next/.test(direction) ) {
398
+ this.element.val( this.term );
399
+ this.menu.deactivate();
400
+ return;
401
+ }
402
+ this.menu[ direction ]( event );
403
+ },
404
+
405
+ widget: function() {
406
+ return this.menu.element;
407
+ }
408
+ });
409
+
410
+ $.extend( $.ui.autocomplete, {
411
+ escapeRegex: function( value ) {
412
+ return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
413
+ },
414
+ filter: function(array, term) {
415
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
416
+ return $.grep( array, function(value) {
417
+ return matcher.test( value.label || value.value || value );
418
+ });
419
+ }
420
+ });
421
+
422
+ }( jQuery ));
423
+
424
+ /*
425
+ * jQuery UI Menu (not officially released)
426
+ *
427
+ * This widget isn't yet finished and the API is subject to change. We plan to finish
428
+ * it for the next release. You're welcome to give it a try anyway and give us feedback,
429
+ * as long as you're okay with migrating your code later on. We can help with that, too.
430
+ *
431
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
432
+ * Dual licensed under the MIT or GPL Version 2 licenses.
433
+ * http://jquery.org/license
434
+ *
435
+ * http://docs.jquery.com/UI/Menu
436
+ *
437
+ * Depends:
438
+ * jquery.ui.core.js
439
+ * jquery.ui.widget.js
440
+ */
441
+ (function($) {
442
+
443
+ $.widget("ui.menu", {
444
+ _create: function() {
445
+ var self = this;
446
+ this.element
447
+ .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
448
+ .attr({
449
+ role: "listbox",
450
+ "aria-activedescendant": "ui-active-menuitem"
451
+ })
452
+ .click(function( event ) {
453
+ if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
454
+ return;
455
+ }
456
+ // temporary
457
+ event.preventDefault();
458
+ self.select( event );
459
+ });
460
+ this.refresh();
461
+ },
462
+
463
+ refresh: function() {
464
+ var self = this;
465
+
466
+ // don't refresh list items that are already adapted
467
+ var items = this.element.children("li:not(.ui-menu-item):has(a)")
468
+ .addClass("ui-menu-item")
469
+ .attr("role", "menuitem");
470
+
471
+ items.children("a")
472
+ .addClass("ui-corner-all")
473
+ .attr("tabindex", -1)
474
+ // mouseenter doesn't work with event delegation
475
+ .mouseenter(function( event ) {
476
+ self.activate( event, $(this).parent() );
477
+ })
478
+ .mouseleave(function() {
479
+ self.deactivate();
480
+ });
481
+ },
482
+
483
+ activate: function( event, item ) {
484
+ this.deactivate();
485
+ if (this.hasScroll()) {
486
+ var offset = item.offset().top - this.element.offset().top,
487
+ scroll = this.element.attr("scrollTop"),
488
+ elementHeight = this.element.height();
489
+ if (offset < 0) {
490
+ this.element.attr("scrollTop", scroll + offset);
491
+ } else if (offset >= elementHeight) {
492
+ this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
493
+ }
494
+ }
495
+ this.active = item.eq(0)
496
+ .children("a")
497
+ .addClass("ui-state-hover")
498
+ .attr("id", "ui-active-menuitem")
499
+ .end();
500
+ this._trigger("focus", event, { item: item });
501
+ },
502
+
503
+ deactivate: function() {
504
+ if (!this.active) { return; }
505
+
506
+ this.active.children("a")
507
+ .removeClass("ui-state-hover")
508
+ .removeAttr("id");
509
+ this._trigger("blur");
510
+ this.active = null;
511
+ },
512
+
513
+ next: function(event) {
514
+ this.move("next", ".ui-menu-item:first", event);
515
+ },
516
+
517
+ previous: function(event) {
518
+ this.move("prev", ".ui-menu-item:last", event);
519
+ },
520
+
521
+ first: function() {
522
+ return this.active && !this.active.prevAll(".ui-menu-item").length;
523
+ },
524
+
525
+ last: function() {
526
+ return this.active && !this.active.nextAll(".ui-menu-item").length;
527
+ },
528
+
529
+ move: function(direction, edge, event) {
530
+ if (!this.active) {
531
+ this.activate(event, this.element.children(edge));
532
+ return;
533
+ }
534
+ var next = this.active[direction + "All"](".ui-menu-item").eq(0);
535
+ if (next.length) {
536
+ this.activate(event, next);
537
+ } else {
538
+ this.activate(event, this.element.children(edge));
539
+ }
540
+ },
541
+
542
+ // TODO merge with previousPage
543
+ nextPage: function(event) {
544
+ if (this.hasScroll()) {
545
+ // TODO merge with no-scroll-else
546
+ if (!this.active || this.last()) {
547
+ this.activate(event, this.element.children(".ui-menu-item:first"));
548
+ return;
549
+ }
550
+ var base = this.active.offset().top,
551
+ height = this.element.height(),
552
+ result = this.element.children(".ui-menu-item").filter(function() {
553
+ var close = $(this).offset().top - base - height + $(this).height();
554
+ // TODO improve approximation
555
+ return close < 10 && close > -10;
556
+ });
557
+
558
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
559
+ if (!result.length) {
560
+ result = this.element.children(".ui-menu-item:last");
561
+ }
562
+ this.activate(event, result);
563
+ } else {
564
+ this.activate(event, this.element.children(".ui-menu-item")
565
+ .filter(!this.active || this.last() ? ":first" : ":last"));
566
+ }
567
+ },
568
+
569
+ // TODO merge with nextPage
570
+ previousPage: function(event) {
571
+ if (this.hasScroll()) {
572
+ // TODO merge with no-scroll-else
573
+ if (!this.active || this.first()) {
574
+ this.activate(event, this.element.children(".ui-menu-item:last"));
575
+ return;
576
+ }
577
+
578
+ var base = this.active.offset().top,
579
+ height = this.element.height();
580
+ result = this.element.children(".ui-menu-item").filter(function() {
581
+ var close = $(this).offset().top - base + height - $(this).height();
582
+ // TODO improve approximation
583
+ return close < 10 && close > -10;
584
+ });
585
+
586
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
587
+ if (!result.length) {
588
+ result = this.element.children(".ui-menu-item:first");
589
+ }
590
+ this.activate(event, result);
591
+ } else {
592
+ this.activate(event, this.element.children(".ui-menu-item")
593
+ .filter(!this.active || this.first() ? ":last" : ":first"));
594
+ }
595
+ },
596
+
597
+ hasScroll: function() {
598
+ return this.element.height() < this.element.attr("scrollHeight");
599
+ },
600
+
601
+ select: function( event ) {
602
+ this._trigger("selected", event, { item: this.active });
603
+ }
604
+ });
605
+
606
+ }(jQuery));
static/js/jquery/ui.datepicker.js CHANGED
@@ -1,1636 +1,1636 @@
1
- /*
2
- * jQuery UI Datepicker 1.7.3
3
- *
4
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5
- * Dual licensed under the MIT (MIT-LICENSE.txt)
6
- * and GPL (GPL-LICENSE.txt) licenses.
7
- *
8
- * http://docs.jquery.com/UI/Datepicker
9
- *
10
- * Depends:
11
- * ui.core.js
12
- */
13
-
14
- (function($) { // hide the namespace
15
-
16
- $.extend($.ui, { datepicker: { version: "1.7.3" } });
17
-
18
- var PROP_NAME = 'datepicker';
19
-
20
- /* Date picker manager.
21
- Use the singleton instance of this class, $.datepicker, to interact with the date picker.
22
- Settings for (groups of) date pickers are maintained in an instance object,
23
- allowing multiple different settings on the same page. */
24
-
25
- function Datepicker() {
26
- this.debug = false; // Change this to true to start debugging
27
- this._curInst = null; // The current instance in use
28
- this._keyEvent = false; // If the last event was a key event
29
- this._disabledInputs = []; // List of date picker inputs that have been disabled
30
- this._datepickerShowing = false; // True if the popup picker is showing , false if not
31
- this._inDialog = false; // True if showing within a "dialog", false if not
32
- this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
33
- this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
34
- this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
35
- this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
36
- this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
37
- this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
38
- this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
39
- this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
40
- this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
41
- this.regional = []; // Available regional settings, indexed by language code
42
- this.regional[''] = { // Default regional settings
43
- closeText: 'Done', // Display text for close link
44
- prevText: 'Prev', // Display text for previous month link
45
- nextText: 'Next', // Display text for next month link
46
- currentText: 'Today', // Display text for current month link
47
- monthNames: ['January','February','March','April','May','June',
48
- 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
49
- monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
50
- dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
51
- dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
52
- dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
53
- dateFormat: 'mm/dd/yy', // See format options on parseDate
54
- firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
55
- isRTL: false // True if right-to-left language, false if left-to-right
56
- };
57
- this._defaults = { // Global defaults for all the date picker instances
58
- showOn: 'focus', // 'focus' for popup on focus,
59
- // 'button' for trigger button, or 'both' for either
60
- showAnim: 'show', // Name of jQuery animation for popup
61
- showOptions: {}, // Options for enhanced animations
62
- defaultDate: null, // Used when field is blank: actual date,
63
- // +/-number for offset from today, null for today
64
- appendText: '', // Display text following the input box, e.g. showing the format
65
- buttonText: '...', // Text for trigger button
66
- buttonImage: '', // URL for trigger button image
67
- buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
68
- hideIfNoPrevNext: false, // True to hide next/previous month links
69
- // if not applicable, false to just disable them
70
- navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
71
- gotoCurrent: false, // True if today link goes back to current selection instead
72
- changeMonth: false, // True if month can be selected directly, false if only prev/next
73
- changeYear: false, // True if year can be selected directly, false if only prev/next
74
- showMonthAfterYear: false, // True if the year select precedes month, false for month then year
75
- yearRange: '-10:+10', // Range of years to display in drop-down,
76
- // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
77
- showOtherMonths: false, // True to show dates in other months, false to leave blank
78
- calculateWeek: this.iso8601Week, // How to calculate the week of the year,
79
- // takes a Date and returns the number of the week for it
80
- shortYearCutoff: '+10', // Short year values < this are in the current century,
81
- // > this are in the previous century,
82
- // string value starting with '+' for current year + value
83
- minDate: null, // The earliest selectable date, or null for no limit
84
- maxDate: null, // The latest selectable date, or null for no limit
85
- duration: 'normal', // Duration of display/closure
86
- beforeShowDay: null, // Function that takes a date and returns an array with
87
- // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
88
- // [2] = cell title (optional), e.g. $.datepicker.noWeekends
89
- beforeShow: null, // Function that takes an input field and
90
- // returns a set of custom settings for the date picker
91
- onSelect: null, // Define a callback function when a date is selected
92
- onChangeMonthYear: null, // Define a callback function when the month or year is changed
93
- onClose: null, // Define a callback function when the datepicker is closed
94
- numberOfMonths: 1, // Number of months to show at a time
95
- showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
96
- stepMonths: 1, // Number of months to step back/forward
97
- stepBigMonths: 12, // Number of months to step back/forward for the big links
98
- altField: '', // Selector for an alternate field to store selected dates into
99
- altFormat: '', // The date format to use for the alternate field
100
- constrainInput: true, // The input is constrained by the current date format
101
- showButtonPanel: false // True to show button panel, false to not show it
102
- };
103
- $.extend(this._defaults, this.regional['']);
104
- this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
105
- }
106
-
107
- $.extend(Datepicker.prototype, {
108
- /* Class name added to elements to indicate already configured with a date picker. */
109
- markerClassName: 'hasDatepicker',
110
-
111
- /* Debug logging (if enabled). */
112
- log: function () {
113
- if (this.debug)
114
- console.log.apply('', arguments);
115
- },
116
-
117
- /* Override the default settings for all instances of the date picker.
118
- @param settings object - the new settings to use as defaults (anonymous object)
119
- @return the manager object */
120
- setDefaults: function(settings) {
121
- extendRemove(this._defaults, settings || {});
122
- return this;
123
- },
124
-
125
- /* Attach the date picker to a jQuery selection.
126
- @param target element - the target input field or division or span
127
- @param settings object - the new settings to use for this date picker instance (anonymous) */
128
- _attachDatepicker: function(target, settings) {
129
- // check for settings on the control itself - in namespace 'date:'
130
- var inlineSettings = null;
131
- for (var attrName in this._defaults) {
132
- var attrValue = target.getAttribute('date:' + attrName);
133
- if (attrValue) {
134
- inlineSettings = inlineSettings || {};
135
- try {
136
- inlineSettings[attrName] = eval(attrValue);
137
- } catch (err) {
138
- inlineSettings[attrName] = attrValue;
139
- }
140
- }
141
- }
142
- var nodeName = target.nodeName.toLowerCase();
143
- var inline = (nodeName == 'div' || nodeName == 'span');
144
- if (!target.id)
145
- target.id = 'dp' + (++this.uuid);
146
- var inst = this._newInst($(target), inline);
147
- inst.settings = $.extend({}, settings || {}, inlineSettings || {});
148
- if (nodeName == 'input') {
149
- this._connectDatepicker(target, inst);
150
- } else if (inline) {
151
- this._inlineDatepicker(target, inst);
152
- }
153
- },
154
-
155
- /* Create a new instance object. */
156
- _newInst: function(target, inline) {
157
- var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
158
- return {id: id, input: target, // associated target
159
- selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
160
- drawMonth: 0, drawYear: 0, // month being drawn
161
- inline: inline, // is datepicker inline or not
162
- dpDiv: (!inline ? this.dpDiv : // presentation div
163
- $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
164
- },
165
-
166
- /* Attach the date picker to an input field. */
167
- _connectDatepicker: function(target, inst) {
168
- var input = $(target);
169
- inst.append = $([]);
170
- inst.trigger = $([]);
171
- if (input.hasClass(this.markerClassName))
172
- return;
173
- var appendText = this._get(inst, 'appendText');
174
- var isRTL = this._get(inst, 'isRTL');
175
- if (appendText) {
176
- inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
177
- input[isRTL ? 'before' : 'after'](inst.append);
178
- }
179
- var showOn = this._get(inst, 'showOn');
180
- if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
181
- input.focus(this._showDatepicker);
182
- if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
183
- var buttonText = this._get(inst, 'buttonText');
184
- var buttonImage = this._get(inst, 'buttonImage');
185
- inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
186
- $('<img/>').addClass(this._triggerClass).
187
- attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
188
- $('<button type="button"></button>').addClass(this._triggerClass).
189
- html(buttonImage == '' ? buttonText : $('<img/>').attr(
190
- { src:buttonImage, alt:buttonText, title:buttonText })));
191
- input[isRTL ? 'before' : 'after'](inst.trigger);
192
- inst.trigger.click(function() {
193
- if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
194
- $.datepicker._hideDatepicker();
195
- else
196
- $.datepicker._showDatepicker(target);
197
- return false;
198
- });
199
- }
200
- input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
201
- bind("setData.datepicker", function(event, key, value) {
202
- inst.settings[key] = value;
203
- }).bind("getData.datepicker", function(event, key) {
204
- return this._get(inst, key);
205
- });
206
- $.data(target, PROP_NAME, inst);
207
- },
208
-
209
- /* Attach an inline date picker to a div. */
210
- _inlineDatepicker: function(target, inst) {
211
- var divSpan = $(target);
212
- if (divSpan.hasClass(this.markerClassName))
213
- return;
214
- divSpan.addClass(this.markerClassName).append(inst.dpDiv).
215
- bind("setData.datepicker", function(event, key, value){
216
- inst.settings[key] = value;
217
- }).bind("getData.datepicker", function(event, key){
218
- return this._get(inst, key);
219
- });
220
- $.data(target, PROP_NAME, inst);
221
- this._setDate(inst, this._getDefaultDate(inst));
222
- this._updateDatepicker(inst);
223
- this._updateAlternate(inst);
224
- },
225
-
226
- /* Pop-up the date picker in a "dialog" box.
227
- @param input element - ignored
228
- @param dateText string - the initial date to display (in the current format)
229
- @param onSelect function - the function(dateText) to call when a date is selected
230
- @param settings object - update the dialog date picker instance's settings (anonymous object)
231
- @param pos int[2] - coordinates for the dialog's position within the screen or
232
- event - with x/y coordinates or
233
- leave empty for default (screen centre)
234
- @return the manager object */
235
- _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
236
- var inst = this._dialogInst; // internal instance
237
- if (!inst) {
238
- var id = 'dp' + (++this.uuid);
239
- this._dialogInput = $('<input type="text" id="' + id +
240
- '" size="1" style="position: absolute; top: -100px;"/>');
241
- this._dialogInput.keydown(this._doKeyDown);
242
- $('body').append(this._dialogInput);
243
- inst = this._dialogInst = this._newInst(this._dialogInput, false);
244
- inst.settings = {};
245
- $.data(this._dialogInput[0], PROP_NAME, inst);
246
- }
247
- extendRemove(inst.settings, settings || {});
248
- this._dialogInput.val(dateText);
249
-
250
- this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
251
- if (!this._pos) {
252
- var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
253
- var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
254
- var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
255
- var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
256
- this._pos = // should use actual width/height below
257
- [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
258
- }
259
-
260
- // move input on screen for focus, but hidden behind dialog
261
- this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
262
- inst.settings.onSelect = onSelect;
263
- this._inDialog = true;
264
- this.dpDiv.addClass(this._dialogClass);
265
- this._showDatepicker(this._dialogInput[0]);
266
- if ($.blockUI)
267
- $.blockUI(this.dpDiv);
268
- $.data(this._dialogInput[0], PROP_NAME, inst);
269
- return this;
270
- },
271
-
272
- /* Detach a datepicker from its control.
273
- @param target element - the target input field or division or span */
274
- _destroyDatepicker: function(target) {
275
- var $target = $(target);
276
- var inst = $.data(target, PROP_NAME);
277
- if (!$target.hasClass(this.markerClassName)) {
278
- return;
279
- }
280
- var nodeName = target.nodeName.toLowerCase();
281
- $.removeData(target, PROP_NAME);
282
- if (nodeName == 'input') {
283
- inst.append.remove();
284
- inst.trigger.remove();
285
- $target.removeClass(this.markerClassName).
286
- unbind('focus', this._showDatepicker).
287
- unbind('keydown', this._doKeyDown).
288
- unbind('keypress', this._doKeyPress);
289
- } else if (nodeName == 'div' || nodeName == 'span')
290
- $target.removeClass(this.markerClassName).empty();
291
- },
292
-
293
- /* Enable the date picker to a jQuery selection.
294
- @param target element - the target input field or division or span */
295
- _enableDatepicker: function(target) {
296
- var $target = $(target);
297
- var inst = $.data(target, PROP_NAME);
298
- if (!$target.hasClass(this.markerClassName)) {
299
- return;
300
- }
301
- var nodeName = target.nodeName.toLowerCase();
302
- if (nodeName == 'input') {
303
- target.disabled = false;
304
- inst.trigger.filter('button').
305
- each(function() { this.disabled = false; }).end().
306
- filter('img').css({opacity: '1.0', cursor: ''});
307
- }
308
- else if (nodeName == 'div' || nodeName == 'span') {
309
- var inline = $target.children('.' + this._inlineClass);
310
- inline.children().removeClass('ui-state-disabled');
311
- }
312
- this._disabledInputs = $.map(this._disabledInputs,
313
- function(value) { return (value == target ? null : value); }); // delete entry
314
- },
315
-
316
- /* Disable the date picker to a jQuery selection.
317
- @param target element - the target input field or division or span */
318
- _disableDatepicker: function(target) {
319
- var $target = $(target);
320
- var inst = $.data(target, PROP_NAME);
321
- if (!$target.hasClass(this.markerClassName)) {
322
- return;
323
- }
324
- var nodeName = target.nodeName.toLowerCase();
325
- if (nodeName == 'input') {
326
- target.disabled = true;
327
- inst.trigger.filter('button').
328
- each(function() { this.disabled = true; }).end().
329
- filter('img').css({opacity: '0.5', cursor: 'default'});
330
- }
331
- else if (nodeName == 'div' || nodeName == 'span') {
332
- var inline = $target.children('.' + this._inlineClass);
333
- inline.children().addClass('ui-state-disabled');
334
- }
335
- this._disabledInputs = $.map(this._disabledInputs,
336
- function(value) { return (value == target ? null : value); }); // delete entry
337
- this._disabledInputs[this._disabledInputs.length] = target;
338
- },
339
-
340
- /* Is the first field in a jQuery collection disabled as a datepicker?
341
- @param target element - the target input field or division or span
342
- @return boolean - true if disabled, false if enabled */
343
- _isDisabledDatepicker: function(target) {
344
- if (!target) {
345
- return false;
346
- }
347
- for (var i = 0; i < this._disabledInputs.length; i++) {
348
- if (this._disabledInputs[i] == target)
349
- return true;
350
- }
351
- return false;
352
- },
353
-
354
- /* Retrieve the instance data for the target control.
355
- @param target element - the target input field or division or span
356
- @return object - the associated instance data
357
- @throws error if a jQuery problem getting data */
358
- _getInst: function(target) {
359
- try {
360
- return $.data(target, PROP_NAME);
361
- }
362
- catch (err) {
363
- throw 'Missing instance data for this datepicker';
364
- }
365
- },
366
-
367
- /* Update or retrieve the settings for a date picker attached to an input field or division.
368
- @param target element - the target input field or division or span
369
- @param name object - the new settings to update or
370
- string - the name of the setting to change or retrieve,
371
- when retrieving also 'all' for all instance settings or
372
- 'defaults' for all global defaults
373
- @param value any - the new value for the setting
374
- (omit if above is an object or to retrieve a value) */
375
- _optionDatepicker: function(target, name, value) {
376
- var inst = this._getInst(target);
377
- if (arguments.length == 2 && typeof name == 'string') {
378
- return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
379
- (inst ? (name == 'all' ? $.extend({}, inst.settings) :
380
- this._get(inst, name)) : null));
381
- }
382
- var settings = name || {};
383
- if (typeof name == 'string') {
384
- settings = {};
385
- settings[name] = value;
386
- }
387
- if (inst) {
388
- if (this._curInst == inst) {
389
- this._hideDatepicker(null);
390
- }
391
- var date = this._getDateDatepicker(target);
392
- extendRemove(inst.settings, settings);
393
- this._setDateDatepicker(target, date);
394
- this._updateDatepicker(inst);
395
- }
396
- },
397
-
398
- // change method deprecated
399
- _changeDatepicker: function(target, name, value) {
400
- this._optionDatepicker(target, name, value);
401
- },
402
-
403
- /* Redraw the date picker attached to an input field or division.
404
- @param target element - the target input field or division or span */
405
- _refreshDatepicker: function(target) {
406
- var inst = this._getInst(target);
407
- if (inst) {
408
- this._updateDatepicker(inst);
409
- }
410
- },
411
-
412
- /* Set the dates for a jQuery selection.
413
- @param target element - the target input field or division or span
414
- @param date Date - the new date
415
- @param endDate Date - the new end date for a range (optional) */
416
- _setDateDatepicker: function(target, date, endDate) {
417
- var inst = this._getInst(target);
418
- if (inst) {
419
- this._setDate(inst, date, endDate);
420
- this._updateDatepicker(inst);
421
- this._updateAlternate(inst);
422
- }
423
- },
424
-
425
- /* Get the date(s) for the first entry in a jQuery selection.
426
- @param target element - the target input field or division or span
427
- @return Date - the current date or
428
- Date[2] - the current dates for a range */
429
- _getDateDatepicker: function(target) {
430
- var inst = this._getInst(target);
431
- if (inst && !inst.inline)
432
- this._setDateFromField(inst);
433
- return (inst ? this._getDate(inst) : null);
434
- },
435
-
436
- /* Handle keystrokes. */
437
- _doKeyDown: function(event) {
438
- var inst = $.datepicker._getInst(event.target);
439
- var handled = true;
440
- var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
441
- inst._keyEvent = true;
442
- if ($.datepicker._datepickerShowing)
443
- switch (event.keyCode) {
444
- case 9: $.datepicker._hideDatepicker(null, '');
445
- break; // hide on tab out
446
- case 13: var sel = $('td.' + $.datepicker._dayOverClass +
447
- ', td.' + $.datepicker._currentClass, inst.dpDiv);
448
- if (sel[0])
449
- $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
450
- else
451
- $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
452
- return false; // don't submit the form
453
- break; // select the value on enter
454
- case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
455
- break; // hide on escape
456
- case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
457
- -$.datepicker._get(inst, 'stepBigMonths') :
458
- -$.datepicker._get(inst, 'stepMonths')), 'M');
459
- break; // previous month/year on page up/+ ctrl
460
- case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
461
- +$.datepicker._get(inst, 'stepBigMonths') :
462
- +$.datepicker._get(inst, 'stepMonths')), 'M');
463
- break; // next month/year on page down/+ ctrl
464
- case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
465
- handled = event.ctrlKey || event.metaKey;
466
- break; // clear on ctrl or command +end
467
- case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
468
- handled = event.ctrlKey || event.metaKey;
469
- break; // current on ctrl or command +home
470
- case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
471
- handled = event.ctrlKey || event.metaKey;
472
- // -1 day on ctrl or command +left
473
- if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
474
- -$.datepicker._get(inst, 'stepBigMonths') :
475
- -$.datepicker._get(inst, 'stepMonths')), 'M');
476
- // next month/year on alt +left on Mac
477
- break;
478
- case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
479
- handled = event.ctrlKey || event.metaKey;
480
- break; // -1 week on ctrl or command +up
481
- case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
482
- handled = event.ctrlKey || event.metaKey;
483
- // +1 day on ctrl or command +right
484
- if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
485
- +$.datepicker._get(inst, 'stepBigMonths') :
486
- +$.datepicker._get(inst, 'stepMonths')), 'M');
487
- // next month/year on alt +right
488
- break;
489
- case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
490
- handled = event.ctrlKey || event.metaKey;
491
- break; // +1 week on ctrl or command +down
492
- default: handled = false;
493
- }
494
- else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
495
- $.datepicker._showDatepicker(this);
496
- else {
497
- handled = false;
498
- }
499
- if (handled) {
500
- event.preventDefault();
501
- event.stopPropagation();
502
- }
503
- },
504
-
505
- /* Filter entered characters - based on date format. */
506
- _doKeyPress: function(event) {
507
- var inst = $.datepicker._getInst(event.target);
508
- if ($.datepicker._get(inst, 'constrainInput')) {
509
- var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
510
- var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
511
- return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
512
- }
513
- },
514
-
515
- /* Pop-up the date picker for a given input field.
516
- @param input element - the input field attached to the date picker or
517
- event - if triggered by focus */
518
- _showDatepicker: function(input) {
519
- input = input.target || input;
520
- if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
521
- input = $('input', input.parentNode)[0];
522
- if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
523
- return;
524
- var inst = $.datepicker._getInst(input);
525
- var beforeShow = $.datepicker._get(inst, 'beforeShow');
526
- extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
527
- $.datepicker._hideDatepicker(null, '');
528
- $.datepicker._lastInput = input;
529
- $.datepicker._setDateFromField(inst);
530
- if ($.datepicker._inDialog) // hide cursor
531
- input.value = '';
532
- if (!$.datepicker._pos) { // position below input
533
- $.datepicker._pos = $.datepicker._findPos(input);
534
- $.datepicker._pos[1] += input.offsetHeight; // add the height
535
- }
536
- var isFixed = false;
537
- $(input).parents().each(function() {
538
- isFixed |= $(this).css('position') == 'fixed';
539
- return !isFixed;
540
- });
541
- if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
542
- $.datepicker._pos[0] -= document.documentElement.scrollLeft;
543
- $.datepicker._pos[1] -= document.documentElement.scrollTop;
544
- }
545
- var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
546
- $.datepicker._pos = null;
547
- inst.rangeStart = null;
548
- // determine sizing offscreen
549
- inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
550
- $.datepicker._updateDatepicker(inst);
551
- // fix width for dynamic number of date pickers
552
- // and adjust position before showing
553
- offset = $.datepicker._checkOffset(inst, offset, isFixed);
554
- inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
555
- 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
556
- left: offset.left + 'px', top: offset.top + 'px'});
557
- if (!inst.inline) {
558
- var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
559
- var duration = $.datepicker._get(inst, 'duration');
560
- var postProcess = function() {
561
- $.datepicker._datepickerShowing = true;
562
- if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
563
- $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
564
- height: inst.dpDiv.height() + 4});
565
- };
566
- if ($.effects && $.effects[showAnim])
567
- inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
568
- else
569
- inst.dpDiv[showAnim](duration, postProcess);
570
- if (duration == '')
571
- postProcess();
572
- if (inst.input[0].type != 'hidden')
573
- inst.input[0].focus();
574
- $.datepicker._curInst = inst;
575
- }
576
- },
577
-
578
- /* Generate the date picker content. */
579
- _updateDatepicker: function(inst) {
580
- var dims = {width: inst.dpDiv.width() + 4,
581
- height: inst.dpDiv.height() + 4};
582
- var self = this;
583
- inst.dpDiv.empty().append(this._generateHTML(inst))
584
- .find('iframe.ui-datepicker-cover').
585
- css({width: dims.width, height: dims.height})
586
- .end()
587
- .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
588
- .bind('mouseout', function(){
589
- $(this).removeClass('ui-state-hover');
590
- if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
591
- if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
592
- })
593
- .bind('mouseover', function(){
594
- if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
595
- $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
596
- $(this).addClass('ui-state-hover');
597
- if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
598
- if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
599
- }
600
- })
601
- .end()
602
- .find('.' + this._dayOverClass + ' a')
603
- .trigger('mouseover')
604
- .end();
605
- var numMonths = this._getNumberOfMonths(inst);
606
- var cols = numMonths[1];
607
- var width = 17;
608
- if (cols > 1) {
609
- inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
610
- } else {
611
- inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
612
- }
613
- inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
614
- 'Class']('ui-datepicker-multi');
615
- inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
616
- 'Class']('ui-datepicker-rtl');
617
- if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
618
- $(inst.input[0]).focus();
619
- },
620
-
621
- /* Check positioning to remain on screen. */
622
- _checkOffset: function(inst, offset, isFixed) {
623
- var dpWidth = inst.dpDiv.outerWidth();
624
- var dpHeight = inst.dpDiv.outerHeight();
625
- var inputWidth = inst.input ? inst.input.outerWidth() : 0;
626
- var inputHeight = inst.input ? inst.input.outerHeight() : 0;
627
- var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
628
- var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
629
-
630
- offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
631
- offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
632
- offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
633
-
634
- // now check if datepicker is showing outside window viewport - move to a better place if so.
635
- offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
636
- offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
637
-
638
- return offset;
639
- },
640
-
641
- /* Find an object's position on the screen. */
642
- _findPos: function(obj) {
643
- while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
644
- obj = obj.nextSibling;
645
- }
646
- var position = $(obj).offset();
647
- return [position.left, position.top];
648
- },
649
-
650
- /* Hide the date picker from view.
651
- @param input element - the input field attached to the date picker
652
- @param duration string - the duration over which to close the date picker */
653
- _hideDatepicker: function(input, duration) {
654
- var inst = this._curInst;
655
- if (!inst || (input && inst != $.data(input, PROP_NAME)))
656
- return;
657
- if (inst.stayOpen)
658
- this._selectDate('#' + inst.id, this._formatDate(inst,
659
- inst.currentDay, inst.currentMonth, inst.currentYear));
660
- inst.stayOpen = false;
661
- if (this._datepickerShowing) {
662
- duration = (duration != null ? duration : this._get(inst, 'duration'));
663
- var showAnim = this._get(inst, 'showAnim');
664
- var postProcess = function() {
665
- $.datepicker._tidyDialog(inst);
666
- };
667
- if (duration != '' && $.effects && $.effects[showAnim])
668
- inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
669
- duration, postProcess);
670
- else
671
- inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
672
- (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
673
- if (duration == '')
674
- this._tidyDialog(inst);
675
- var onClose = this._get(inst, 'onClose');
676
- if (onClose)
677
- onClose.apply((inst.input ? inst.input[0] : null),
678
- [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
679
- this._datepickerShowing = false;
680
- this._lastInput = null;
681
- if (this._inDialog) {
682
- this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
683
- if ($.blockUI) {
684
- $.unblockUI();
685
- $('body').append(this.dpDiv);
686
- }
687
- }
688
- this._inDialog = false;
689
- }
690
- this._curInst = null;
691
- },
692
-
693
- /* Tidy up after a dialog display. */
694
- _tidyDialog: function(inst) {
695
- inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
696
- },
697
-
698
- /* Close date picker if clicked elsewhere. */
699
- _checkExternalClick: function(event) {
700
- if (!$.datepicker._curInst)
701
- return;
702
- var $target = $(event.target);
703
- if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
704
- !$target.hasClass($.datepicker.markerClassName) &&
705
- !$target.hasClass($.datepicker._triggerClass) &&
706
- $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
707
- $.datepicker._hideDatepicker(null, '');
708
- },
709
-
710
- /* Adjust one of the date sub-fields. */
711
- _adjustDate: function(id, offset, period) {
712
- var target = $(id);
713
- var inst = this._getInst(target[0]);
714
- if (this._isDisabledDatepicker(target[0])) {
715
- return;
716
- }
717
- this._adjustInstDate(inst, offset +
718
- (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
719
- period);
720
- this._updateDatepicker(inst);
721
- },
722
-
723
- /* Action for current link. */
724
- _gotoToday: function(id) {
725
- var target = $(id);
726
- var inst = this._getInst(target[0]);
727
- if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
728
- inst.selectedDay = inst.currentDay;
729
- inst.drawMonth = inst.selectedMonth = inst.currentMonth;
730
- inst.drawYear = inst.selectedYear = inst.currentYear;
731
- }
732
- else {
733
- var date = new Date();
734
- inst.selectedDay = date.getDate();
735
- inst.drawMonth = inst.selectedMonth = date.getMonth();
736
- inst.drawYear = inst.selectedYear = date.getFullYear();
737
- }
738
- this._notifyChange(inst);
739
- this._adjustDate(target);
740
- },
741
-
742
- /* Action for selecting a new month/year. */
743
- _selectMonthYear: function(id, select, period) {
744
- var target = $(id);
745
- var inst = this._getInst(target[0]);
746
- inst._selectingMonthYear = false;
747
- inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
748
- inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
749
- parseInt(select.options[select.selectedIndex].value,10);
750
- this._notifyChange(inst);
751
- this._adjustDate(target);
752
- },
753
-
754
- /* Restore input focus after not changing month/year. */
755
- _clickMonthYear: function(id) {
756
- var target = $(id);
757
- var inst = this._getInst(target[0]);
758
- if (inst.input && inst._selectingMonthYear && !$.browser.msie)
759
- inst.input[0].focus();
760
- inst._selectingMonthYear = !inst._selectingMonthYear;
761
- },
762
-
763
- /* Action for selecting a day. */
764
- _selectDay: function(id, month, year, td) {
765
- var target = $(id);
766
- if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
767
- return;
768
- }
769
- var inst = this._getInst(target[0]);
770
- inst.selectedDay = inst.currentDay = $('a', td).html();
771
- inst.selectedMonth = inst.currentMonth = month;
772
- inst.selectedYear = inst.currentYear = year;
773
- if (inst.stayOpen) {
774
- inst.endDay = inst.endMonth = inst.endYear = null;
775
- }
776
- this._selectDate(id, this._formatDate(inst,
777
- inst.currentDay, inst.currentMonth, inst.currentYear));
778
- if (inst.stayOpen) {
779
- inst.rangeStart = this._daylightSavingAdjust(
780
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
781
- this._updateDatepicker(inst);
782
- }
783
- },
784
-
785
- /* Erase the input field and hide the date picker. */
786
- _clearDate: function(id) {
787
- var target = $(id);
788
- var inst = this._getInst(target[0]);
789
- inst.stayOpen = false;
790
- inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
791
- this._selectDate(target, '');
792
- },
793
-
794
- /* Update the input field with the selected date. */
795
- _selectDate: function(id, dateStr) {
796
- var target = $(id);
797
- var inst = this._getInst(target[0]);
798
- dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
799
- if (inst.input)
800
- inst.input.val(dateStr);
801
- this._updateAlternate(inst);
802
- var onSelect = this._get(inst, 'onSelect');
803
- if (onSelect)
804
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
805
- else if (inst.input)
806
- inst.input.trigger('change'); // fire the change event
807
- if (inst.inline)
808
- this._updateDatepicker(inst);
809
- else if (!inst.stayOpen) {
810
- this._hideDatepicker(null, this._get(inst, 'duration'));
811
- this._lastInput = inst.input[0];
812
- if (typeof(inst.input[0]) != 'object')
813
- inst.input[0].focus(); // restore focus
814
- this._lastInput = null;
815
- }
816
- },
817
-
818
- /* Update any alternate field to synchronise with the main field. */
819
- _updateAlternate: function(inst) {
820
- var altField = this._get(inst, 'altField');
821
- if (altField) { // update alternate field too
822
- var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
823
- var date = this._getDate(inst);
824
- dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
825
- $(altField).each(function() { $(this).val(dateStr); });
826
- }
827
- },
828
-
829
- /* Set as beforeShowDay function to prevent selection of weekends.
830
- @param date Date - the date to customise
831
- @return [boolean, string] - is this date selectable?, what is its CSS class? */
832
- noWeekends: function(date) {
833
- var day = date.getDay();
834
- return [(day > 0 && day < 6), ''];
835
- },
836
-
837
- /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
838
- @param date Date - the date to get the week for
839
- @return number - the number of the week within the year that contains this date */
840
- iso8601Week: function(date) {
841
- var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
842
- var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
843
- var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
844
- firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
845
- if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
846
- checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
847
- return $.datepicker.iso8601Week(checkDate);
848
- } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
849
- firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
850
- if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
851
- return 1;
852
- }
853
- }
854
- return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
855
- },
856
-
857
- /* Parse a string value into a date object.
858
- See formatDate below for the possible formats.
859
-
860
- @param format string - the expected format of the date
861
- @param value string - the date in the above format
862
- @param settings Object - attributes include:
863
- shortYearCutoff number - the cutoff year for determining the century (optional)
864
- dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
865
- dayNames string[7] - names of the days from Sunday (optional)
866
- monthNamesShort string[12] - abbreviated names of the months (optional)
867
- monthNames string[12] - names of the months (optional)
868
- @return Date - the extracted date value or null if value is blank */
869
- parseDate: function (format, value, settings) {
870
- if (format == null || value == null)
871
- throw 'Invalid arguments';
872
- value = (typeof value == 'object' ? value.toString() : value + '');
873
- if (value == '')
874
- return null;
875
- var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
876
- var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
877
- var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
878
- var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
879
- var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
880
- var year = -1;
881
- var month = -1;
882
- var day = -1;
883
- var doy = -1;
884
- var literal = false;
885
- // Check whether a format character is doubled
886
- var lookAhead = function(match) {
887
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
888
- if (matches)
889
- iFormat++;
890
- return matches;
891
- };
892
- // Extract a number from the string value
893
- var getNumber = function(match) {
894
- lookAhead(match);
895
- var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
896
- var size = origSize;
897
- var num = 0;
898
- while (size > 0 && iValue < value.length &&
899
- value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
900
- num = num * 10 + parseInt(value.charAt(iValue++),10);
901
- size--;
902
- }
903
- if (size == origSize)
904
- throw 'Missing number at position ' + iValue;
905
- return num;
906
- };
907
- // Extract a name from the string value and convert to an index
908
- var getName = function(match, shortNames, longNames) {
909
- var names = (lookAhead(match) ? longNames : shortNames);
910
- var size = 0;
911
- for (var j = 0; j < names.length; j++)
912
- size = Math.max(size, names[j].length);
913
- var name = '';
914
- var iInit = iValue;
915
- while (size > 0 && iValue < value.length) {
916
- name += value.charAt(iValue++);
917
- for (var i = 0; i < names.length; i++)
918
- if (name == names[i])
919
- return i + 1;
920
- size--;
921
- }
922
- throw 'Unknown name at position ' + iInit;
923
- };
924
- // Confirm that a literal character matches the string value
925
- var checkLiteral = function() {
926
- if (value.charAt(iValue) != format.charAt(iFormat))
927
- throw 'Unexpected literal at position ' + iValue;
928
- iValue++;
929
- };
930
- var iValue = 0;
931
- for (var iFormat = 0; iFormat < format.length; iFormat++) {
932
- if (literal)
933
- if (format.charAt(iFormat) == "'" && !lookAhead("'"))
934
- literal = false;
935
- else
936
- checkLiteral();
937
- else
938
- switch (format.charAt(iFormat)) {
939
- case 'd':
940
- day = getNumber('d');
941
- break;
942
- case 'D':
943
- getName('D', dayNamesShort, dayNames);
944
- break;
945
- case 'o':
946
- doy = getNumber('o');
947
- break;
948
- case 'm':
949
- month = getNumber('m');
950
- break;
951
- case 'M':
952
- month = getName('M', monthNamesShort, monthNames);
953
- break;
954
- case 'y':
955
- year = getNumber('y');
956
- break;
957
- case '@':
958
- var date = new Date(getNumber('@'));
959
- year = date.getFullYear();
960
- month = date.getMonth() + 1;
961
- day = date.getDate();
962
- break;
963
- case "'":
964
- if (lookAhead("'"))
965
- checkLiteral();
966
- else
967
- literal = true;
968
- break;
969
- default:
970
- checkLiteral();
971
- }
972
- }
973
- if (year == -1)
974
- year = new Date().getFullYear();
975
- else if (year < 100)
976
- year += new Date().getFullYear() - new Date().getFullYear() % 100 +
977
- (year <= shortYearCutoff ? 0 : -100);
978
- if (doy > -1) {
979
- month = 1;
980
- day = doy;
981
- do {
982
- var dim = this._getDaysInMonth(year, month - 1);
983
- if (day <= dim)
984
- break;
985
- month++;
986
- day -= dim;
987
- } while (true);
988
- }
989
- var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
990
- if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
991
- throw 'Invalid date'; // E.g. 31/02/*
992
- return date;
993
- },
994
-
995
- /* Standard date formats. */
996
- ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
997
- COOKIE: 'D, dd M yy',
998
- ISO_8601: 'yy-mm-dd',
999
- RFC_822: 'D, d M y',
1000
- RFC_850: 'DD, dd-M-y',
1001
- RFC_1036: 'D, d M y',
1002
- RFC_1123: 'D, d M yy',
1003
- RFC_2822: 'D, d M yy',
1004
- RSS: 'D, d M y', // RFC 822
1005
- TIMESTAMP: '@',
1006
- W3C: 'yy-mm-dd', // ISO 8601
1007
-
1008
- /* Format a date object into a string value.
1009
- The format can be combinations of the following:
1010
- d - day of month (no leading zero)
1011
- dd - day of month (two digit)
1012
- o - day of year (no leading zeros)
1013
- oo - day of year (three digit)
1014
- D - day name short
1015
- DD - day name long
1016
- m - month of year (no leading zero)
1017
- mm - month of year (two digit)
1018
- M - month name short
1019
- MM - month name long
1020
- y - year (two digit)
1021
- yy - year (four digit)
1022
- @ - Unix timestamp (ms since 01/01/1970)
1023
- '...' - literal text
1024
- '' - single quote
1025
-
1026
- @param format string - the desired format of the date
1027
- @param date Date - the date value to format
1028
- @param settings Object - attributes include:
1029
- dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1030
- dayNames string[7] - names of the days from Sunday (optional)
1031
- monthNamesShort string[12] - abbreviated names of the months (optional)
1032
- monthNames string[12] - names of the months (optional)
1033
- @return string - the date in the above format */
1034
- formatDate: function (format, date, settings) {
1035
- if (!date)
1036
- return '';
1037
- var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1038
- var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1039
- var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1040
- var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1041
- // Check whether a format character is doubled
1042
- var lookAhead = function(match) {
1043
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1044
- if (matches)
1045
- iFormat++;
1046
- return matches;
1047
- };
1048
- // Format a number, with leading zero if necessary
1049
- var formatNumber = function(match, value, len) {
1050
- var num = '' + value;
1051
- if (lookAhead(match))
1052
- while (num.length < len)
1053
- num = '0' + num;
1054
- return num;
1055
- };
1056
- // Format a name, short or long as requested
1057
- var formatName = function(match, value, shortNames, longNames) {
1058
- return (lookAhead(match) ? longNames[value] : shortNames[value]);
1059
- };
1060
- var output = '';
1061
- var literal = false;
1062
- if (date)
1063
- for (var iFormat = 0; iFormat < format.length; iFormat++) {
1064
- if (literal)
1065
- if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1066
- literal = false;
1067
- else
1068
- output += format.charAt(iFormat);
1069
- else
1070
- switch (format.charAt(iFormat)) {
1071
- case 'd':
1072
- output += formatNumber('d', date.getDate(), 2);
1073
- break;
1074
- case 'D':
1075
- output += formatName('D', date.getDay(), dayNamesShort, dayNames);
1076
- break;
1077
- case 'o':
1078
- var doy = date.getDate();
1079
- for (var m = date.getMonth() - 1; m >= 0; m--)
1080
- doy += this._getDaysInMonth(date.getFullYear(), m);
1081
- output += formatNumber('o', doy, 3);
1082
- break;
1083
- case 'm':
1084
- output += formatNumber('m', date.getMonth() + 1, 2);
1085
- break;
1086
- case 'M':
1087
- output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
1088
- break;
1089
- case 'y':
1090
- output += (lookAhead('y') ? date.getFullYear() :
1091
- (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
1092
- break;
1093
- case '@':
1094
- output += date.getTime();
1095
- break;
1096
- case "'":
1097
- if (lookAhead("'"))
1098
- output += "'";
1099
- else
1100
- literal = true;
1101
- break;
1102
- default:
1103
- output += format.charAt(iFormat);
1104
- }
1105
- }
1106
- return output;
1107
- },
1108
-
1109
- /* Extract all possible characters from the date format. */
1110
- _possibleChars: function (format) {
1111
- var chars = '';
1112
- var literal = false;
1113
- for (var iFormat = 0; iFormat < format.length; iFormat++)
1114
- if (literal)
1115
- if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1116
- literal = false;
1117
- else
1118
- chars += format.charAt(iFormat);
1119
- else
1120
- switch (format.charAt(iFormat)) {
1121
- case 'd': case 'm': case 'y': case '@':
1122
- chars += '0123456789';
1123
- break;
1124
- case 'D': case 'M':
1125
- return null; // Accept anything
1126
- case "'":
1127
- if (lookAhead("'"))
1128
- chars += "'";
1129
- else
1130
- literal = true;
1131
- break;
1132
- default:
1133
- chars += format.charAt(iFormat);
1134
- }
1135
- return chars;
1136
- },
1137
-
1138
- /* Get a setting value, defaulting if necessary. */
1139
- _get: function(inst, name) {
1140
- return inst.settings[name] !== undefined ?
1141
- inst.settings[name] : this._defaults[name];
1142
- },
1143
-
1144
- /* Parse existing date and initialise date picker. */
1145
- _setDateFromField: function(inst) {
1146
- var dateFormat = this._get(inst, 'dateFormat');
1147
- var dates = inst.input ? inst.input.val() : null;
1148
- inst.endDay = inst.endMonth = inst.endYear = null;
1149
- var date = defaultDate = this._getDefaultDate(inst);
1150
- var settings = this._getFormatConfig(inst);
1151
- try {
1152
- date = this.parseDate(dateFormat, dates, settings) || defaultDate;
1153
- } catch (event) {
1154
- this.log(event);
1155
- date = defaultDate;
1156
- }
1157
- inst.selectedDay = date.getDate();
1158
- inst.drawMonth = inst.selectedMonth = date.getMonth();
1159
- inst.drawYear = inst.selectedYear = date.getFullYear();
1160
- inst.currentDay = (dates ? date.getDate() : 0);
1161
- inst.currentMonth = (dates ? date.getMonth() : 0);
1162
- inst.currentYear = (dates ? date.getFullYear() : 0);
1163
- this._adjustInstDate(inst);
1164
- },
1165
-
1166
- /* Retrieve the default date shown on opening. */
1167
- _getDefaultDate: function(inst) {
1168
- var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
1169
- var minDate = this._getMinMaxDate(inst, 'min', true);
1170
- var maxDate = this._getMinMaxDate(inst, 'max');
1171
- date = (minDate && date < minDate ? minDate : date);
1172
- date = (maxDate && date > maxDate ? maxDate : date);
1173
- return date;
1174
- },
1175
-
1176
- /* A date may be specified as an exact value or a relative one. */
1177
- _determineDate: function(date, defaultDate) {
1178
- var offsetNumeric = function(offset) {
1179
- var date = new Date();
1180
- date.setDate(date.getDate() + offset);
1181
- return date;
1182
- };
1183
- var offsetString = function(offset, getDaysInMonth) {
1184
- var date = new Date();
1185
- var year = date.getFullYear();
1186
- var month = date.getMonth();
1187
- var day = date.getDate();
1188
- var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
1189
- var matches = pattern.exec(offset);
1190
- while (matches) {
1191
- switch (matches[2] || 'd') {
1192
- case 'd' : case 'D' :
1193
- day += parseInt(matches[1],10); break;
1194
- case 'w' : case 'W' :
1195
- day += parseInt(matches[1],10) * 7; break;
1196
- case 'm' : case 'M' :
1197
- month += parseInt(matches[1],10);
1198
- day = Math.min(day, getDaysInMonth(year, month));
1199
- break;
1200
- case 'y': case 'Y' :
1201
- year += parseInt(matches[1],10);
1202
- day = Math.min(day, getDaysInMonth(year, month));
1203
- break;
1204
- }
1205
- matches = pattern.exec(offset);
1206
- }
1207
- return new Date(year, month, day);
1208
- };
1209
- date = (date == null ? defaultDate :
1210
- (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
1211
- (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
1212
- date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
1213
- if (date) {
1214
- date.setHours(0);
1215
- date.setMinutes(0);
1216
- date.setSeconds(0);
1217
- date.setMilliseconds(0);
1218
- }
1219
- return this._daylightSavingAdjust(date);
1220
- },
1221
-
1222
- /* Handle switch to/from daylight saving.
1223
- Hours may be non-zero on daylight saving cut-over:
1224
- > 12 when midnight changeover, but then cannot generate
1225
- midnight datetime, so jump to 1AM, otherwise reset.
1226
- @param date (Date) the date to check
1227
- @return (Date) the corrected date */
1228
- _daylightSavingAdjust: function(date) {
1229
- if (!date) return null;
1230
- date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
1231
- return date;
1232
- },
1233
-
1234
- /* Set the date(s) directly. */
1235
- _setDate: function(inst, date, endDate) {
1236
- var clear = !(date);
1237
- var origMonth = inst.selectedMonth;
1238
- var origYear = inst.selectedYear;
1239
- date = this._determineDate(date, new Date());
1240
- inst.selectedDay = inst.currentDay = date.getDate();
1241
- inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
1242
- inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
1243
- if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
1244
- this._notifyChange(inst);
1245
- this._adjustInstDate(inst);
1246
- if (inst.input) {
1247
- inst.input.val(clear ? '' : this._formatDate(inst));
1248
- }
1249
- },
1250
-
1251
- /* Retrieve the date(s) directly. */
1252
- _getDate: function(inst) {
1253
- var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
1254
- this._daylightSavingAdjust(new Date(
1255
- inst.currentYear, inst.currentMonth, inst.currentDay)));
1256
- return startDate;
1257
- },
1258
-
1259
- /* Generate the HTML for the current state of the date picker. */
1260
- _generateHTML: function(inst) {
1261
- var today = new Date();
1262
- today = this._daylightSavingAdjust(
1263
- new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
1264
- var isRTL = this._get(inst, 'isRTL');
1265
- var showButtonPanel = this._get(inst, 'showButtonPanel');
1266
- var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
1267
- var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
1268
- var numMonths = this._getNumberOfMonths(inst);
1269
- var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
1270
- var stepMonths = this._get(inst, 'stepMonths');
1271
- var stepBigMonths = this._get(inst, 'stepBigMonths');
1272
- var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
1273
- var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
1274
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1275
- var minDate = this._getMinMaxDate(inst, 'min', true);
1276
- var maxDate = this._getMinMaxDate(inst, 'max');
1277
- var drawMonth = inst.drawMonth - showCurrentAtPos;
1278
- var drawYear = inst.drawYear;
1279
- if (drawMonth < 0) {
1280
- drawMonth += 12;
1281
- drawYear--;
1282
- }
1283
- if (maxDate) {
1284
- var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
1285
- maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
1286
- maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1287
- while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
1288
- drawMonth--;
1289
- if (drawMonth < 0) {
1290
- drawMonth = 11;
1291
- drawYear--;
1292
- }
1293
- }
1294
- }
1295
- inst.drawMonth = drawMonth;
1296
- inst.drawYear = drawYear;
1297
- var prevText = this._get(inst, 'prevText');
1298
- prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
1299
- this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
1300
- this._getFormatConfig(inst)));
1301
- var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1302
- '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
1303
- ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
1304
- (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
1305
- var nextText = this._get(inst, 'nextText');
1306
- nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
1307
- this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
1308
- this._getFormatConfig(inst)));
1309
- var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1310
- '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
1311
- ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
1312
- (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
1313
- var currentText = this._get(inst, 'currentText');
1314
- var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
1315
- currentText = (!navigationAsDateFormat ? currentText :
1316
- this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
1317
- var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
1318
- var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
1319
- (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
1320
- '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
1321
- var firstDay = parseInt(this._get(inst, 'firstDay'),10);
1322
- firstDay = (isNaN(firstDay) ? 0 : firstDay);
1323
- var dayNames = this._get(inst, 'dayNames');
1324
- var dayNamesShort = this._get(inst, 'dayNamesShort');
1325
- var dayNamesMin = this._get(inst, 'dayNamesMin');
1326
- var monthNames = this._get(inst, 'monthNames');
1327
- var monthNamesShort = this._get(inst, 'monthNamesShort');
1328
- var beforeShowDay = this._get(inst, 'beforeShowDay');
1329
- var showOtherMonths = this._get(inst, 'showOtherMonths');
1330
- var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
1331
- var endDate = inst.endDay ? this._daylightSavingAdjust(
1332
- new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
1333
- var defaultDate = this._getDefaultDate(inst);
1334
- var html = '';
1335
- for (var row = 0; row < numMonths[0]; row++) {
1336
- var group = '';
1337
- for (var col = 0; col < numMonths[1]; col++) {
1338
- var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
1339
- var cornerClass = ' ui-corner-all';
1340
- var calender = '';
1341
- if (isMultiMonth) {
1342
- calender += '<div class="ui-datepicker-group ui-datepicker-group-';
1343
- switch (col) {
1344
- case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
1345
- case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
1346
- default: calender += 'middle'; cornerClass = ''; break;
1347
- }
1348
- calender += '">';
1349
- }
1350
- calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
1351
- (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
1352
- (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
1353
- this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
1354
- selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
1355
- '</div><table class="ui-datepicker-calendar"><thead>' +
1356
- '<tr>';
1357
- var thead = '';
1358
- for (var dow = 0; dow < 7; dow++) { // days of the week
1359
- var day = (dow + firstDay) % 7;
1360
- thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
1361
- '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
1362
- }
1363
- calender += thead + '</tr></thead><tbody>';
1364
- var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
1365
- if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
1366
- inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
1367
- var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
1368
- var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
1369
- var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
1370
- for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
1371
- calender += '<tr>';
1372
- var tbody = '';
1373
- for (var dow = 0; dow < 7; dow++) { // create date picker days
1374
- var daySettings = (beforeShowDay ?
1375
- beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
1376
- var otherMonth = (printDate.getMonth() != drawMonth);
1377
- var unselectable = otherMonth || !daySettings[0] ||
1378
- (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
1379
- tbody += '<td class="' +
1380
- ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
1381
- (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
1382
- ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
1383
- (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
1384
- // or defaultDate is current printedDate and defaultDate is selectedDate
1385
- ' ' + this._dayOverClass : '') + // highlight selected day
1386
- (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
1387
- (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
1388
- (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
1389
- ' ' + this._currentClass : '') + // highlight selected day
1390
- (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
1391
- ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
1392
- (unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
1393
- inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
1394
- (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
1395
- (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
1396
- (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
1397
- (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
1398
- ' ui-state-active' : '') + // highlight selected day
1399
- '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
1400
- printDate.setDate(printDate.getDate() + 1);
1401
- printDate = this._daylightSavingAdjust(printDate);
1402
- }
1403
- calender += tbody + '</tr>';
1404
- }
1405
- drawMonth++;
1406
- if (drawMonth > 11) {
1407
- drawMonth = 0;
1408
- drawYear++;
1409
- }
1410
- calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
1411
- ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
1412
- group += calender;
1413
- }
1414
- html += group;
1415
- }
1416
- html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
1417
- '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
1418
- inst._keyEvent = false;
1419
- return html;
1420
- },
1421
-
1422
- /* Generate the month and year header. */
1423
- _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
1424
- selectedDate, secondary, monthNames, monthNamesShort) {
1425
- minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
1426
- var changeMonth = this._get(inst, 'changeMonth');
1427
- var changeYear = this._get(inst, 'changeYear');
1428
- var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
1429
- var html = '<div class="ui-datepicker-title">';
1430
- var monthHtml = '';
1431
- // month selection
1432
- if (secondary || !changeMonth)
1433
- monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
1434
- else {
1435
- var inMinYear = (minDate && minDate.getFullYear() == drawYear);
1436
- var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
1437
- monthHtml += '<select class="ui-datepicker-month" ' +
1438
- 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
1439
- 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
1440
- '>';
1441
- for (var month = 0; month < 12; month++) {
1442
- if ((!inMinYear || month >= minDate.getMonth()) &&
1443
- (!inMaxYear || month <= maxDate.getMonth()))
1444
- monthHtml += '<option value="' + month + '"' +
1445
- (month == drawMonth ? ' selected="selected"' : '') +
1446
- '>' + monthNamesShort[month] + '</option>';
1447
- }
1448
- monthHtml += '</select>';
1449
- }
1450
- if (!showMonthAfterYear)
1451
- html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
1452
- // year selection
1453
- if (secondary || !changeYear)
1454
- html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
1455
- else {
1456
- // determine range of years to display
1457
- var years = this._get(inst, 'yearRange').split(':');
1458
- var year = 0;
1459
- var endYear = 0;
1460
- if (years.length != 2) {
1461
- year = drawYear - 10;
1462
- endYear = drawYear + 10;
1463
- } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
1464
- year = drawYear + parseInt(years[0], 10);
1465
- endYear = drawYear + parseInt(years[1], 10);
1466
- } else {
1467
- year = parseInt(years[0], 10);
1468
- endYear = parseInt(years[1], 10);
1469
- }
1470
- year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
1471
- endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
1472
- html += '<select class="ui-datepicker-year" ' +
1473
- 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
1474
- 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
1475
- '>';
1476
- for (; year <= endYear; year++) {
1477
- html += '<option value="' + year + '"' +
1478
- (year == drawYear ? ' selected="selected"' : '') +
1479
- '>' + year + '</option>';
1480
- }
1481
- html += '</select>';
1482
- }
1483
- if (showMonthAfterYear)
1484
- html += (secondary || changeMonth || changeYear ? '&#xa0;' : '') + monthHtml;
1485
- html += '</div>'; // Close datepicker_header
1486
- return html;
1487
- },
1488
-
1489
- /* Adjust one of the date sub-fields. */
1490
- _adjustInstDate: function(inst, offset, period) {
1491
- var year = inst.drawYear + (period == 'Y' ? offset : 0);
1492
- var month = inst.drawMonth + (period == 'M' ? offset : 0);
1493
- var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
1494
- (period == 'D' ? offset : 0);
1495
- var date = this._daylightSavingAdjust(new Date(year, month, day));
1496
- // ensure it is within the bounds set
1497
- var minDate = this._getMinMaxDate(inst, 'min', true);
1498
- var maxDate = this._getMinMaxDate(inst, 'max');
1499
- date = (minDate && date < minDate ? minDate : date);
1500
- date = (maxDate && date > maxDate ? maxDate : date);
1501
- inst.selectedDay = date.getDate();
1502
- inst.drawMonth = inst.selectedMonth = date.getMonth();
1503
- inst.drawYear = inst.selectedYear = date.getFullYear();
1504
- if (period == 'M' || period == 'Y')
1505
- this._notifyChange(inst);
1506
- },
1507
-
1508
- /* Notify change of month/year. */
1509
- _notifyChange: function(inst) {
1510
- var onChange = this._get(inst, 'onChangeMonthYear');
1511
- if (onChange)
1512
- onChange.apply((inst.input ? inst.input[0] : null),
1513
- [inst.selectedYear, inst.selectedMonth + 1, inst]);
1514
- },
1515
-
1516
- /* Determine the number of months to show. */
1517
- _getNumberOfMonths: function(inst) {
1518
- var numMonths = this._get(inst, 'numberOfMonths');
1519
- return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
1520
- },
1521
-
1522
- /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
1523
- _getMinMaxDate: function(inst, minMax, checkRange) {
1524
- var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
1525
- return (!checkRange || !inst.rangeStart ? date :
1526
- (!date || inst.rangeStart > date ? inst.rangeStart : date));
1527
- },
1528
-
1529
- /* Find the number of days in a given month. */
1530
- _getDaysInMonth: function(year, month) {
1531
- return 32 - new Date(year, month, 32).getDate();
1532
- },
1533
-
1534
- /* Find the day of the week of the first of a month. */
1535
- _getFirstDayOfMonth: function(year, month) {
1536
- return new Date(year, month, 1).getDay();
1537
- },
1538
-
1539
- /* Determines if we should allow a "next/prev" month display change. */
1540
- _canAdjustMonth: function(inst, offset, curYear, curMonth) {
1541
- var numMonths = this._getNumberOfMonths(inst);
1542
- var date = this._daylightSavingAdjust(new Date(
1543
- curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
1544
- if (offset < 0)
1545
- date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
1546
- return this._isInRange(inst, date);
1547
- },
1548
-
1549
- /* Is the given date in the accepted range? */
1550
- _isInRange: function(inst, date) {
1551
- // during range selection, use minimum of selected date and range start
1552
- var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
1553
- new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
1554
- newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
1555
- var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
1556
- var maxDate = this._getMinMaxDate(inst, 'max');
1557
- return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
1558
- },
1559
-
1560
- /* Provide the configuration settings for formatting/parsing. */
1561
- _getFormatConfig: function(inst) {
1562
- var shortYearCutoff = this._get(inst, 'shortYearCutoff');
1563
- shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
1564
- new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
1565
- return {shortYearCutoff: shortYearCutoff,
1566
- dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
1567
- monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
1568
- },
1569
-
1570
- /* Format the given date for display. */
1571
- _formatDate: function(inst, day, month, year) {
1572
- if (!day) {
1573
- inst.currentDay = inst.selectedDay;
1574
- inst.currentMonth = inst.selectedMonth;
1575
- inst.currentYear = inst.selectedYear;
1576
- }
1577
- var date = (day ? (typeof day == 'object' ? day :
1578
- this._daylightSavingAdjust(new Date(year, month, day))) :
1579
- this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1580
- return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
1581
- }
1582
- });
1583
-
1584
- /* jQuery extend now ignores nulls! */
1585
- function extendRemove(target, props) {
1586
- $.extend(target, props);
1587
- for (var name in props)
1588
- if (props[name] == null || props[name] == undefined)
1589
- target[name] = props[name];
1590
- return target;
1591
- };
1592
-
1593
- /* Determine whether an object is an array. */
1594
- function isArray(a) {
1595
- return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
1596
- (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
1597
- };
1598
-
1599
- /* Invoke the datepicker functionality.
1600
- @param options string - a command, optionally followed by additional parameters or
1601
- Object - settings for attaching new datepicker functionality
1602
- @return jQuery object */
1603
- $.fn.datepicker = function(options){
1604
-
1605
- /* Initialise the date picker. */
1606
- if (!$.datepicker.initialized) {
1607
- $(document).mousedown($.datepicker._checkExternalClick).
1608
- find('body').append($.datepicker.dpDiv);
1609
- $.datepicker.initialized = true;
1610
- }
1611
-
1612
- var otherArgs = Array.prototype.slice.call(arguments, 1);
1613
- if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
1614
- return $.datepicker['_' + options + 'Datepicker'].
1615
- apply($.datepicker, [this[0]].concat(otherArgs));
1616
- if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1617
- return $.datepicker['_' + options + 'Datepicker'].
1618
- apply($.datepicker, [this[0]].concat(otherArgs));
1619
- return this.each(function() {
1620
- typeof options == 'string' ?
1621
- $.datepicker['_' + options + 'Datepicker'].
1622
- apply($.datepicker, [this].concat(otherArgs)) :
1623
- $.datepicker._attachDatepicker(this, options);
1624
- });
1625
- };
1626
-
1627
- $.datepicker = new Datepicker(); // singleton instance
1628
- $.datepicker.initialized = false;
1629
- $.datepicker.uuid = new Date().getTime();
1630
- $.datepicker.version = "1.7.3";
1631
-
1632
- // Workaround for #4055
1633
- // Add another global to avoid noConflict issues with inline event handlers
1634
- window.DP_jQuery = $;
1635
-
1636
- })(jQuery);
1
+ /*
2
+ * jQuery UI Datepicker 1.7.3
3
+ *
4
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
6
+ * and GPL (GPL-LICENSE.txt) licenses.
7
+ *
8
+ * http://docs.jquery.com/UI/Datepicker
9
+ *
10
+ * Depends:
11
+ * ui.core.js
12
+ */
13
+
14
+ (function($) { // hide the namespace
15
+
16
+ $.extend($.ui, { datepicker: { version: "1.7.3" } });
17
+
18
+ var PROP_NAME = 'datepicker';
19
+
20
+ /* Date picker manager.
21
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
22
+ Settings for (groups of) date pickers are maintained in an instance object,
23
+ allowing multiple different settings on the same page. */
24
+
25
+ function Datepicker() {
26
+ this.debug = false; // Change this to true to start debugging
27
+ this._curInst = null; // The current instance in use
28
+ this._keyEvent = false; // If the last event was a key event
29
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
30
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
31
+ this._inDialog = false; // True if showing within a "dialog", false if not
32
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
33
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
34
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
35
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
36
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
37
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
38
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
39
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
40
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
41
+ this.regional = []; // Available regional settings, indexed by language code
42
+ this.regional[''] = { // Default regional settings
43
+ closeText: 'Done', // Display text for close link
44
+ prevText: 'Prev', // Display text for previous month link
45
+ nextText: 'Next', // Display text for next month link
46
+ currentText: 'Today', // Display text for current month link
47
+ monthNames: ['January','February','March','April','May','June',
48
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
49
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
50
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
51
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
52
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
53
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
54
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
55
+ isRTL: false // True if right-to-left language, false if left-to-right
56
+ };
57
+ this._defaults = { // Global defaults for all the date picker instances
58
+ showOn: 'focus', // 'focus' for popup on focus,
59
+ // 'button' for trigger button, or 'both' for either
60
+ showAnim: 'show', // Name of jQuery animation for popup
61
+ showOptions: {}, // Options for enhanced animations
62
+ defaultDate: null, // Used when field is blank: actual date,
63
+ // +/-number for offset from today, null for today
64
+ appendText: '', // Display text following the input box, e.g. showing the format
65
+ buttonText: '...', // Text for trigger button
66
+ buttonImage: '', // URL for trigger button image
67
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
68
+ hideIfNoPrevNext: false, // True to hide next/previous month links
69
+ // if not applicable, false to just disable them
70
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
71
+ gotoCurrent: false, // True if today link goes back to current selection instead
72
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
73
+ changeYear: false, // True if year can be selected directly, false if only prev/next
74
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
75
+ yearRange: '-10:+10', // Range of years to display in drop-down,
76
+ // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
77
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
78
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
79
+ // takes a Date and returns the number of the week for it
80
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
81
+ // > this are in the previous century,
82
+ // string value starting with '+' for current year + value
83
+ minDate: null, // The earliest selectable date, or null for no limit
84
+ maxDate: null, // The latest selectable date, or null for no limit
85
+ duration: 'normal', // Duration of display/closure
86
+ beforeShowDay: null, // Function that takes a date and returns an array with
87
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
88
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
89
+ beforeShow: null, // Function that takes an input field and
90
+ // returns a set of custom settings for the date picker
91
+ onSelect: null, // Define a callback function when a date is selected
92
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
93
+ onClose: null, // Define a callback function when the datepicker is closed
94
+ numberOfMonths: 1, // Number of months to show at a time
95
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
96
+ stepMonths: 1, // Number of months to step back/forward
97
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
98
+ altField: '', // Selector for an alternate field to store selected dates into
99
+ altFormat: '', // The date format to use for the alternate field
100
+ constrainInput: true, // The input is constrained by the current date format
101
+ showButtonPanel: false // True to show button panel, false to not show it
102
+ };
103
+ $.extend(this._defaults, this.regional['']);
104
+ this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
105
+ }
106
+
107
+ $.extend(Datepicker.prototype, {
108
+ /* Class name added to elements to indicate already configured with a date picker. */
109
+ markerClassName: 'hasDatepicker',
110
+
111
+ /* Debug logging (if enabled). */
112
+ log: function () {
113
+ if (this.debug)
114
+ console.log.apply('', arguments);
115
+ },
116
+
117
+ /* Override the default settings for all instances of the date picker.
118
+ @param settings object - the new settings to use as defaults (anonymous object)
119
+ @return the manager object */
120
+ setDefaults: function(settings) {
121
+ extendRemove(this._defaults, settings || {});
122
+ return this;
123
+ },
124
+
125
+ /* Attach the date picker to a jQuery selection.
126
+ @param target element - the target input field or division or span
127
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
128
+ _attachDatepicker: function(target, settings) {
129
+ // check for settings on the control itself - in namespace 'date:'
130
+ var inlineSettings = null;
131
+ for (var attrName in this._defaults) {
132
+ var attrValue = target.getAttribute('date:' + attrName);
133
+ if (attrValue) {
134
+ inlineSettings = inlineSettings || {};
135
+ try {
136
+ inlineSettings[attrName] = eval(attrValue);
137
+ } catch (err) {
138
+ inlineSettings[attrName] = attrValue;
139
+ }
140
+ }
141
+ }
142
+ var nodeName = target.nodeName.toLowerCase();
143
+ var inline = (nodeName == 'div' || nodeName == 'span');
144
+ if (!target.id)
145
+ target.id = 'dp' + (++this.uuid);
146
+ var inst = this._newInst($(target), inline);
147
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
148
+ if (nodeName == 'input') {
149
+ this._connectDatepicker(target, inst);
150
+ } else if (inline) {
151
+ this._inlineDatepicker(target, inst);
152
+ }
153
+ },
154
+
155
+ /* Create a new instance object. */
156
+ _newInst: function(target, inline) {
157
+ var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
158
+ return {id: id, input: target, // associated target
159
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
160
+ drawMonth: 0, drawYear: 0, // month being drawn
161
+ inline: inline, // is datepicker inline or not
162
+ dpDiv: (!inline ? this.dpDiv : // presentation div
163
+ $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
164
+ },
165
+
166
+ /* Attach the date picker to an input field. */
167
+ _connectDatepicker: function(target, inst) {
168
+ var input = $(target);
169
+ inst.append = $([]);
170
+ inst.trigger = $([]);
171
+ if (input.hasClass(this.markerClassName))
172
+ return;
173
+ var appendText = this._get(inst, 'appendText');
174
+ var isRTL = this._get(inst, 'isRTL');
175
+ if (appendText) {
176
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
177
+ input[isRTL ? 'before' : 'after'](inst.append);
178
+ }
179
+ var showOn = this._get(inst, 'showOn');
180
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
181
+ input.focus(this._showDatepicker);
182
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
183
+ var buttonText = this._get(inst, 'buttonText');
184
+ var buttonImage = this._get(inst, 'buttonImage');
185
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
186
+ $('<img/>').addClass(this._triggerClass).
187
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
188
+ $('<button type="button"></button>').addClass(this._triggerClass).
189
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
190
+ { src:buttonImage, alt:buttonText, title:buttonText })));
191
+ input[isRTL ? 'before' : 'after'](inst.trigger);
192
+ inst.trigger.click(function() {
193
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
194
+ $.datepicker._hideDatepicker();
195
+ else
196
+ $.datepicker._showDatepicker(target);
197
+ return false;
198
+ });
199
+ }
200
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
201
+ bind("setData.datepicker", function(event, key, value) {
202
+ inst.settings[key] = value;
203
+ }).bind("getData.datepicker", function(event, key) {
204
+ return this._get(inst, key);
205
+ });
206
+ $.data(target, PROP_NAME, inst);
207
+ },
208
+
209
+ /* Attach an inline date picker to a div. */
210
+ _inlineDatepicker: function(target, inst) {
211
+ var divSpan = $(target);
212
+ if (divSpan.hasClass(this.markerClassName))
213
+ return;
214
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
215
+ bind("setData.datepicker", function(event, key, value){
216
+ inst.settings[key] = value;
217
+ }).bind("getData.datepicker", function(event, key){
218
+ return this._get(inst, key);
219
+ });
220
+ $.data(target, PROP_NAME, inst);
221
+ this._setDate(inst, this._getDefaultDate(inst));
222
+ this._updateDatepicker(inst);
223
+ this._updateAlternate(inst);
224
+ },
225
+
226
+ /* Pop-up the date picker in a "dialog" box.
227
+ @param input element - ignored
228
+ @param dateText string - the initial date to display (in the current format)
229
+ @param onSelect function - the function(dateText) to call when a date is selected
230
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
231
+ @param pos int[2] - coordinates for the dialog's position within the screen or
232
+ event - with x/y coordinates or
233
+ leave empty for default (screen centre)
234
+ @return the manager object */
235
+ _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
236
+ var inst = this._dialogInst; // internal instance
237
+ if (!inst) {
238
+ var id = 'dp' + (++this.uuid);
239
+ this._dialogInput = $('<input type="text" id="' + id +
240
+ '" size="1" style="position: absolute; top: -100px;"/>');
241
+ this._dialogInput.keydown(this._doKeyDown);
242
+ $('body').append(this._dialogInput);
243
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
244
+ inst.settings = {};
245
+ $.data(this._dialogInput[0], PROP_NAME, inst);
246
+ }
247
+ extendRemove(inst.settings, settings || {});
248
+ this._dialogInput.val(dateText);
249
+
250
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
251
+ if (!this._pos) {
252
+ var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
253
+ var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
254
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
255
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
256
+ this._pos = // should use actual width/height below
257
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
258
+ }
259
+
260
+ // move input on screen for focus, but hidden behind dialog
261
+ this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
262
+ inst.settings.onSelect = onSelect;
263
+ this._inDialog = true;
264
+ this.dpDiv.addClass(this._dialogClass);
265
+ this._showDatepicker(this._dialogInput[0]);
266
+ if ($.blockUI)
267
+ $.blockUI(this.dpDiv);
268
+ $.data(this._dialogInput[0], PROP_NAME, inst);
269
+ return this;
270
+ },
271
+
272
+ /* Detach a datepicker from its control.
273
+ @param target element - the target input field or division or span */
274
+ _destroyDatepicker: function(target) {
275
+ var $target = $(target);
276
+ var inst = $.data(target, PROP_NAME);
277
+ if (!$target.hasClass(this.markerClassName)) {
278
+ return;
279
+ }
280
+ var nodeName = target.nodeName.toLowerCase();
281
+ $.removeData(target, PROP_NAME);
282
+ if (nodeName == 'input') {
283
+ inst.append.remove();
284
+ inst.trigger.remove();
285
+ $target.removeClass(this.markerClassName).
286
+ unbind('focus', this._showDatepicker).
287
+ unbind('keydown', this._doKeyDown).
288
+ unbind('keypress', this._doKeyPress);
289
+ } else if (nodeName == 'div' || nodeName == 'span')
290
+ $target.removeClass(this.markerClassName).empty();
291
+ },
292
+
293
+ /* Enable the date picker to a jQuery selection.
294
+ @param target element - the target input field or division or span */
295
+ _enableDatepicker: function(target) {
296
+ var $target = $(target);
297
+ var inst = $.data(target, PROP_NAME);
298
+ if (!$target.hasClass(this.markerClassName)) {
299
+ return;
300
+ }
301
+ var nodeName = target.nodeName.toLowerCase();
302
+ if (nodeName == 'input') {
303
+ target.disabled = false;
304
+ inst.trigger.filter('button').
305
+ each(function() { this.disabled = false; }).end().
306
+ filter('img').css({opacity: '1.0', cursor: ''});
307
+ }
308
+ else if (nodeName == 'div' || nodeName == 'span') {
309
+ var inline = $target.children('.' + this._inlineClass);
310
+ inline.children().removeClass('ui-state-disabled');
311
+ }
312
+ this._disabledInputs = $.map(this._disabledInputs,
313
+ function(value) { return (value == target ? null : value); }); // delete entry
314
+ },
315
+
316
+ /* Disable the date picker to a jQuery selection.
317
+ @param target element - the target input field or division or span */
318
+ _disableDatepicker: function(target) {
319
+ var $target = $(target);
320
+ var inst = $.data(target, PROP_NAME);
321
+ if (!$target.hasClass(this.markerClassName)) {
322
+ return;
323
+ }
324
+ var nodeName = target.nodeName.toLowerCase();
325
+ if (nodeName == 'input') {
326
+ target.disabled = true;
327
+ inst.trigger.filter('button').
328
+ each(function() { this.disabled = true; }).end().
329
+ filter('img').css({opacity: '0.5', cursor: 'default'});
330
+ }
331
+ else if (nodeName == 'div' || nodeName == 'span') {
332
+ var inline = $target.children('.' + this._inlineClass);
333
+ inline.children().addClass('ui-state-disabled');
334
+ }
335
+ this._disabledInputs = $.map(this._disabledInputs,
336
+ function(value) { return (value == target ? null : value); }); // delete entry
337
+ this._disabledInputs[this._disabledInputs.length] = target;
338
+ },
339
+
340
+ /* Is the first field in a jQuery collection disabled as a datepicker?
341
+ @param target element - the target input field or division or span
342
+ @return boolean - true if disabled, false if enabled */
343
+ _isDisabledDatepicker: function(target) {
344
+ if (!target) {
345
+ return false;
346
+ }
347
+ for (var i = 0; i < this._disabledInputs.length; i++) {
348
+ if (this._disabledInputs[i] == target)
349
+ return true;
350
+ }
351
+ return false;
352
+ },
353
+
354
+ /* Retrieve the instance data for the target control.
355
+ @param target element - the target input field or division or span
356
+ @return object - the associated instance data
357
+ @throws error if a jQuery problem getting data */
358
+ _getInst: function(target) {
359
+ try {
360
+ return $.data(target, PROP_NAME);
361
+ }
362
+ catch (err) {
363
+ throw 'Missing instance data for this datepicker';
364
+ }
365
+ },
366
+
367
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
368
+ @param target element - the target input field or division or span
369
+ @param name object - the new settings to update or
370
+ string - the name of the setting to change or retrieve,
371
+ when retrieving also 'all' for all instance settings or
372
+ 'defaults' for all global defaults
373
+ @param value any - the new value for the setting
374
+ (omit if above is an object or to retrieve a value) */
375
+ _optionDatepicker: function(target, name, value) {
376
+ var inst = this._getInst(target);
377
+ if (arguments.length == 2 && typeof name == 'string') {
378
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
379
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
380
+ this._get(inst, name)) : null));
381
+ }
382
+ var settings = name || {};
383
+ if (typeof name == 'string') {
384
+ settings = {};
385
+ settings[name] = value;
386
+ }
387
+ if (inst) {
388
+ if (this._curInst == inst) {
389
+ this._hideDatepicker(null);
390
+ }
391
+ var date = this._getDateDatepicker(target);
392
+ extendRemove(inst.settings, settings);
393
+ this._setDateDatepicker(target, date);
394
+ this._updateDatepicker(inst);
395
+ }
396
+ },
397
+
398
+ // change method deprecated
399
+ _changeDatepicker: function(target, name, value) {
400
+ this._optionDatepicker(target, name, value);
401
+ },
402
+
403
+ /* Redraw the date picker attached to an input field or division.
404
+ @param target element - the target input field or division or span */
405
+ _refreshDatepicker: function(target) {
406
+ var inst = this._getInst(target);
407
+ if (inst) {
408
+ this._updateDatepicker(inst);
409
+ }
410
+ },
411
+
412
+ /* Set the dates for a jQuery selection.
413
+ @param target element - the target input field or division or span
414
+ @param date Date - the new date
415
+ @param endDate Date - the new end date for a range (optional) */
416
+ _setDateDatepicker: function(target, date, endDate) {
417
+ var inst = this._getInst(target);
418
+ if (inst) {
419
+ this._setDate(inst, date, endDate);
420
+ this._updateDatepicker(inst);
421
+ this._updateAlternate(inst);
422
+ }
423
+ },
424
+
425
+ /* Get the date(s) for the first entry in a jQuery selection.
426
+ @param target element - the target input field or division or span
427
+ @return Date - the current date or
428
+ Date[2] - the current dates for a range */
429
+ _getDateDatepicker: function(target) {
430
+ var inst = this._getInst(target);
431
+ if (inst && !inst.inline)
432
+ this._setDateFromField(inst);
433
+ return (inst ? this._getDate(inst) : null);
434
+ },
435
+
436
+ /* Handle keystrokes. */
437
+ _doKeyDown: function(event) {
438
+ var inst = $.datepicker._getInst(event.target);
439
+ var handled = true;
440
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
441
+ inst._keyEvent = true;
442
+ if ($.datepicker._datepickerShowing)
443
+ switch (event.keyCode) {
444
+ case 9: $.datepicker._hideDatepicker(null, '');
445
+ break; // hide on tab out
446
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass +
447
+ ', td.' + $.datepicker._currentClass, inst.dpDiv);
448
+ if (sel[0])
449
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
450
+ else
451
+ $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
452
+ return false; // don't submit the form
453
+ break; // select the value on enter
454
+ case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
455
+ break; // hide on escape
456
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
457
+ -$.datepicker._get(inst, 'stepBigMonths') :
458
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
459
+ break; // previous month/year on page up/+ ctrl
460
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
461
+ +$.datepicker._get(inst, 'stepBigMonths') :
462
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
463
+ break; // next month/year on page down/+ ctrl
464
+ case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
465
+ handled = event.ctrlKey || event.metaKey;
466
+ break; // clear on ctrl or command +end
467
+ case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
468
+ handled = event.ctrlKey || event.metaKey;
469
+ break; // current on ctrl or command +home
470
+ case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
471
+ handled = event.ctrlKey || event.metaKey;
472
+ // -1 day on ctrl or command +left
473
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
474
+ -$.datepicker._get(inst, 'stepBigMonths') :
475
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
476
+ // next month/year on alt +left on Mac
477
+ break;
478
+ case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
479
+ handled = event.ctrlKey || event.metaKey;
480
+ break; // -1 week on ctrl or command +up
481
+ case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
482
+ handled = event.ctrlKey || event.metaKey;
483
+ // +1 day on ctrl or command +right
484
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
485
+ +$.datepicker._get(inst, 'stepBigMonths') :
486
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
487
+ // next month/year on alt +right
488
+ break;
489
+ case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
490
+ handled = event.ctrlKey || event.metaKey;
491
+ break; // +1 week on ctrl or command +down
492
+ default: handled = false;
493
+ }
494
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
495
+ $.datepicker._showDatepicker(this);
496
+ else {
497
+ handled = false;
498
+ }
499
+ if (handled) {
500
+ event.preventDefault();
501
+ event.stopPropagation();
502
+ }
503
+ },
504
+
505
+ /* Filter entered characters - based on date format. */
506
+ _doKeyPress: function(event) {
507
+ var inst = $.datepicker._getInst(event.target);
508
+ if ($.datepicker._get(inst, 'constrainInput')) {
509
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
510
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
511
+ return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
512
+ }
513
+ },
514
+
515
+ /* Pop-up the date picker for a given input field.
516
+ @param input element - the input field attached to the date picker or
517
+ event - if triggered by focus */
518
+ _showDatepicker: function(input) {
519
+ input = input.target || input;
520
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
521
+ input = $('input', input.parentNode)[0];
522
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
523
+ return;
524
+ var inst = $.datepicker._getInst(input);
525
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
526
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
527
+ $.datepicker._hideDatepicker(null, '');
528
+ $.datepicker._lastInput = input;
529
+ $.datepicker._setDateFromField(inst);
530
+ if ($.datepicker._inDialog) // hide cursor
531
+ input.value = '';
532
+ if (!$.datepicker._pos) { // position below input
533
+ $.datepicker._pos = $.datepicker._findPos(input);
534
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
535
+ }
536
+ var isFixed = false;
537
+ $(input).parents().each(function() {
538
+ isFixed |= $(this).css('position') == 'fixed';
539
+ return !isFixed;
540
+ });
541
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
542
+ $.datepicker._pos[0] -= document.documentElement.scrollLeft;
543
+ $.datepicker._pos[1] -= document.documentElement.scrollTop;
544
+ }
545
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
546
+ $.datepicker._pos = null;
547
+ inst.rangeStart = null;
548
+ // determine sizing offscreen
549
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
550
+ $.datepicker._updateDatepicker(inst);
551
+ // fix width for dynamic number of date pickers
552
+ // and adjust position before showing
553
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
554
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
555
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
556
+ left: offset.left + 'px', top: offset.top + 'px'});
557
+ if (!inst.inline) {
558
+ var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
559
+ var duration = $.datepicker._get(inst, 'duration');
560
+ var postProcess = function() {
561
+ $.datepicker._datepickerShowing = true;
562
+ if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
563
+ $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
564
+ height: inst.dpDiv.height() + 4});
565
+ };
566
+ if ($.effects && $.effects[showAnim])
567
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
568
+ else
569
+ inst.dpDiv[showAnim](duration, postProcess);
570
+ if (duration == '')
571
+ postProcess();
572
+ if (inst.input[0].type != 'hidden')
573
+ inst.input[0].focus();
574
+ $.datepicker._curInst = inst;
575
+ }
576
+ },
577
+
578
+ /* Generate the date picker content. */
579
+ _updateDatepicker: function(inst) {
580
+ var dims = {width: inst.dpDiv.width() + 4,
581
+ height: inst.dpDiv.height() + 4};
582
+ var self = this;
583
+ inst.dpDiv.empty().append(this._generateHTML(inst))
584
+ .find('iframe.ui-datepicker-cover').
585
+ css({width: dims.width, height: dims.height})
586
+ .end()
587
+ .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
588
+ .bind('mouseout', function(){
589
+ $(this).removeClass('ui-state-hover');
590
+ if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
591
+ if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
592
+ })
593
+ .bind('mouseover', function(){
594
+ if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
595
+ $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
596
+ $(this).addClass('ui-state-hover');
597
+ if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
598
+ if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
599
+ }
600
+ })
601
+ .end()
602
+ .find('.' + this._dayOverClass + ' a')
603
+ .trigger('mouseover')
604
+ .end();
605
+ var numMonths = this._getNumberOfMonths(inst);
606
+ var cols = numMonths[1];
607
+ var width = 17;
608
+ if (cols > 1) {
609
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
610
+ } else {
611
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
612
+ }
613
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
614
+ 'Class']('ui-datepicker-multi');
615
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
616
+ 'Class']('ui-datepicker-rtl');
617
+ if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
618
+ $(inst.input[0]).focus();
619
+ },
620
+
621
+ /* Check positioning to remain on screen. */
622
+ _checkOffset: function(inst, offset, isFixed) {
623
+ var dpWidth = inst.dpDiv.outerWidth();
624
+ var dpHeight = inst.dpDiv.outerHeight();
625
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
626
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
627
+ var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
628
+ var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
629
+
630
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
631
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
632
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
633
+
634
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
635
+ offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
636
+ offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
637
+
638
+ return offset;
639
+ },
640
+
641
+ /* Find an object's position on the screen. */
642
+ _findPos: function(obj) {
643
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
644
+ obj = obj.nextSibling;
645
+ }
646
+ var position = $(obj).offset();
647
+ return [position.left, position.top];
648
+ },
649
+
650
+ /* Hide the date picker from view.
651
+ @param input element - the input field attached to the date picker
652
+ @param duration string - the duration over which to close the date picker */
653
+ _hideDatepicker: function(input, duration) {
654
+ var inst = this._curInst;
655
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
656
+ return;
657
+ if (inst.stayOpen)
658
+ this._selectDate('#' + inst.id, this._formatDate(inst,
659
+ inst.currentDay, inst.currentMonth, inst.currentYear));
660
+ inst.stayOpen = false;
661
+ if (this._datepickerShowing) {
662
+ duration = (duration != null ? duration : this._get(inst, 'duration'));
663
+ var showAnim = this._get(inst, 'showAnim');
664
+ var postProcess = function() {
665
+ $.datepicker._tidyDialog(inst);
666
+ };
667
+ if (duration != '' && $.effects && $.effects[showAnim])
668
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
669
+ duration, postProcess);
670
+ else
671
+ inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
672
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
673
+ if (duration == '')
674
+ this._tidyDialog(inst);
675
+ var onClose = this._get(inst, 'onClose');
676
+ if (onClose)
677
+ onClose.apply((inst.input ? inst.input[0] : null),
678
+ [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
679
+ this._datepickerShowing = false;
680
+ this._lastInput = null;
681
+ if (this._inDialog) {
682
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
683
+ if ($.blockUI) {
684
+ $.unblockUI();
685
+ $('body').append(this.dpDiv);
686
+ }
687
+ }
688
+ this._inDialog = false;
689
+ }
690
+ this._curInst = null;
691
+ },
692
+
693
+ /* Tidy up after a dialog display. */
694
+ _tidyDialog: function(inst) {
695
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
696
+ },
697
+
698
+ /* Close date picker if clicked elsewhere. */
699
+ _checkExternalClick: function(event) {
700
+ if (!$.datepicker._curInst)
701
+ return;
702
+ var $target = $(event.target);
703
+ if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
704
+ !$target.hasClass($.datepicker.markerClassName) &&
705
+ !$target.hasClass($.datepicker._triggerClass) &&
706
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
707
+ $.datepicker._hideDatepicker(null, '');
708
+ },
709
+
710
+ /* Adjust one of the date sub-fields. */
711
+ _adjustDate: function(id, offset, period) {
712
+ var target = $(id);
713
+ var inst = this._getInst(target[0]);
714
+ if (this._isDisabledDatepicker(target[0])) {
715
+ return;
716
+ }
717
+ this._adjustInstDate(inst, offset +
718
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
719
+ period);
720
+ this._updateDatepicker(inst);
721
+ },
722
+
723
+ /* Action for current link. */
724
+ _gotoToday: function(id) {
725
+ var target = $(id);
726
+ var inst = this._getInst(target[0]);
727
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
728
+ inst.selectedDay = inst.currentDay;
729
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
730
+ inst.drawYear = inst.selectedYear = inst.currentYear;
731
+ }
732
+ else {
733
+ var date = new Date();
734
+ inst.selectedDay = date.getDate();
735
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
736
+ inst.drawYear = inst.selectedYear = date.getFullYear();
737
+ }
738
+ this._notifyChange(inst);
739
+ this._adjustDate(target);
740
+ },
741
+
742
+ /* Action for selecting a new month/year. */
743
+ _selectMonthYear: function(id, select, period) {
744
+ var target = $(id);
745
+ var inst = this._getInst(target[0]);
746
+ inst._selectingMonthYear = false;
747
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
748
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
749
+ parseInt(select.options[select.selectedIndex].value,10);
750
+ this._notifyChange(inst);
751
+ this._adjustDate(target);
752
+ },
753
+
754
+ /* Restore input focus after not changing month/year. */
755
+ _clickMonthYear: function(id) {
756
+ var target = $(id);
757
+ var inst = this._getInst(target[0]);
758
+ if (inst.input && inst._selectingMonthYear && !$.browser.msie)
759
+ inst.input[0].focus();
760
+ inst._selectingMonthYear = !inst._selectingMonthYear;
761
+ },
762
+
763
+ /* Action for selecting a day. */
764
+ _selectDay: function(id, month, year, td) {
765
+ var target = $(id);
766
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
767
+ return;
768
+ }
769
+ var inst = this._getInst(target[0]);
770
+ inst.selectedDay = inst.currentDay = $('a', td).html();
771
+ inst.selectedMonth = inst.currentMonth = month;
772
+ inst.selectedYear = inst.currentYear = year;
773
+ if (inst.stayOpen) {
774
+ inst.endDay = inst.endMonth = inst.endYear = null;
775
+ }
776
+ this._selectDate(id, this._formatDate(inst,
777
+ inst.currentDay, inst.currentMonth, inst.currentYear));
778
+ if (inst.stayOpen) {
779
+ inst.rangeStart = this._daylightSavingAdjust(
780
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
781
+ this._updateDatepicker(inst);
782
+ }
783
+ },
784
+
785
+ /* Erase the input field and hide the date picker. */
786
+ _clearDate: function(id) {
787
+ var target = $(id);
788
+ var inst = this._getInst(target[0]);
789
+ inst.stayOpen = false;
790
+ inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
791
+ this._selectDate(target, '');
792
+ },
793
+
794
+ /* Update the input field with the selected date. */
795
+ _selectDate: function(id, dateStr) {
796
+ var target = $(id);
797
+ var inst = this._getInst(target[0]);
798
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
799
+ if (inst.input)
800
+ inst.input.val(dateStr);
801
+ this._updateAlternate(inst);
802
+ var onSelect = this._get(inst, 'onSelect');
803
+ if (onSelect)
804
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
805
+ else if (inst.input)
806
+ inst.input.trigger('change'); // fire the change event
807
+ if (inst.inline)
808
+ this._updateDatepicker(inst);
809
+ else if (!inst.stayOpen) {
810
+ this._hideDatepicker(null, this._get(inst, 'duration'));
811
+ this._lastInput = inst.input[0];
812
+ if (typeof(inst.input[0]) != 'object')
813
+ inst.input[0].focus(); // restore focus
814
+ this._lastInput = null;
815
+ }
816
+ },
817
+
818
+ /* Update any alternate field to synchronise with the main field. */
819
+ _updateAlternate: function(inst) {
820
+ var altField = this._get(inst, 'altField');
821
+ if (altField) { // update alternate field too
822
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
823
+ var date = this._getDate(inst);
824
+ dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
825
+ $(altField).each(function() { $(this).val(dateStr); });
826
+ }
827
+ },
828
+
829
+ /* Set as beforeShowDay function to prevent selection of weekends.
830
+ @param date Date - the date to customise
831
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
832
+ noWeekends: function(date) {
833
+ var day = date.getDay();
834
+ return [(day > 0 && day < 6), ''];
835
+ },
836
+
837
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
838
+ @param date Date - the date to get the week for
839
+ @return number - the number of the week within the year that contains this date */
840
+ iso8601Week: function(date) {
841
+ var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
842
+ var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
843
+ var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
844
+ firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
845
+ if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
846
+ checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
847
+ return $.datepicker.iso8601Week(checkDate);
848
+ } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
849
+ firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
850
+ if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
851
+ return 1;
852
+ }
853
+ }
854
+ return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
855
+ },
856
+
857
+ /* Parse a string value into a date object.
858
+ See formatDate below for the possible formats.
859
+
860
+ @param format string - the expected format of the date
861
+ @param value string - the date in the above format
862
+ @param settings Object - attributes include:
863
+ shortYearCutoff number - the cutoff year for determining the century (optional)
864
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
865
+ dayNames string[7] - names of the days from Sunday (optional)
866
+ monthNamesShort string[12] - abbreviated names of the months (optional)
867
+ monthNames string[12] - names of the months (optional)
868
+ @return Date - the extracted date value or null if value is blank */
869
+ parseDate: function (format, value, settings) {
870
+ if (format == null || value == null)
871
+ throw 'Invalid arguments';
872
+ value = (typeof value == 'object' ? value.toString() : value + '');
873
+ if (value == '')
874
+ return null;
875
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
876
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
877
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
878
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
879
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
880
+ var year = -1;
881
+ var month = -1;
882
+ var day = -1;
883
+ var doy = -1;
884
+ var literal = false;
885
+ // Check whether a format character is doubled
886
+ var lookAhead = function(match) {
887
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
888
+ if (matches)
889
+ iFormat++;
890
+ return matches;
891
+ };
892
+ // Extract a number from the string value
893
+ var getNumber = function(match) {
894
+ lookAhead(match);
895
+ var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
896
+ var size = origSize;
897
+ var num = 0;
898
+ while (size > 0 && iValue < value.length &&
899
+ value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
900
+ num = num * 10 + parseInt(value.charAt(iValue++),10);
901
+ size--;
902
+ }
903
+ if (size == origSize)
904
+ throw 'Missing number at position ' + iValue;
905
+ return num;
906
+ };
907
+ // Extract a name from the string value and convert to an index
908
+ var getName = function(match, shortNames, longNames) {
909
+ var names = (lookAhead(match) ? longNames : shortNames);
910
+ var size = 0;
911
+ for (var j = 0; j < names.length; j++)
912
+ size = Math.max(size, names[j].length);
913
+ var name = '';
914
+ var iInit = iValue;
915
+ while (size > 0 && iValue < value.length) {
916
+ name += value.charAt(iValue++);
917
+ for (var i = 0; i < names.length; i++)
918
+ if (name == names[i])
919
+ return i + 1;
920
+ size--;
921
+ }
922
+ throw 'Unknown name at position ' + iInit;
923
+ };
924
+ // Confirm that a literal character matches the string value
925
+ var checkLiteral = function() {
926
+ if (value.charAt(iValue) != format.charAt(iFormat))
927
+ throw 'Unexpected literal at position ' + iValue;
928
+ iValue++;
929
+ };
930
+ var iValue = 0;
931
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
932
+ if (literal)
933
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
934
+ literal = false;
935
+ else
936
+ checkLiteral();
937
+ else
938
+ switch (format.charAt(iFormat)) {
939
+ case 'd':
940
+ day = getNumber('d');
941
+ break;
942
+ case 'D':
943
+ getName('D', dayNamesShort, dayNames);
944
+ break;
945
+ case 'o':
946
+ doy = getNumber('o');
947
+ break;
948
+ case 'm':
949
+ month = getNumber('m');
950
+ break;
951
+ case 'M':
952
+ month = getName('M', monthNamesShort, monthNames);
953
+ break;
954
+ case 'y':
955
+ year = getNumber('y');
956
+ break;
957
+ case '@':
958
+ var date = new Date(getNumber('@'));
959
+ year = date.getFullYear();
960
+ month = date.getMonth() + 1;
961
+ day = date.getDate();
962
+ break;
963
+ case "'":
964
+ if (lookAhead("'"))
965
+ checkLiteral();
966
+ else
967
+ literal = true;
968
+ break;
969
+ default:
970
+ checkLiteral();
971
+ }
972
+ }
973
+ if (year == -1)
974
+ year = new Date().getFullYear();
975
+ else if (year < 100)
976
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
977
+ (year <= shortYearCutoff ? 0 : -100);
978
+ if (doy > -1) {
979
+ month = 1;
980
+ day = doy;
981
+ do {
982
+ var dim = this._getDaysInMonth(year, month - 1);
983
+ if (day <= dim)
984
+ break;
985
+ month++;
986
+ day -= dim;
987
+ } while (true);
988
+ }
989
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
990
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
991
+ throw 'Invalid date'; // E.g. 31/02/*
992
+ return date;
993
+ },
994
+
995
+ /* Standard date formats. */
996
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
997
+ COOKIE: 'D, dd M yy',
998
+ ISO_8601: 'yy-mm-dd',
999
+ RFC_822: 'D, d M y',
1000
+ RFC_850: 'DD, dd-M-y',
1001
+ RFC_1036: 'D, d M y',
1002
+ RFC_1123: 'D, d M yy',
1003
+ RFC_2822: 'D, d M yy',
1004
+ RSS: 'D, d M y', // RFC 822
1005
+ TIMESTAMP: '@',
1006
+ W3C: 'yy-mm-dd', // ISO 8601
1007
+
1008
+ /* Format a date object into a string value.
1009
+ The format can be combinations of the following:
1010
+ d - day of month (no leading zero)
1011
+ dd - day of month (two digit)
1012
+ o - day of year (no leading zeros)
1013
+ oo - day of year (three digit)
1014
+ D - day name short
1015
+ DD - day name long
1016
+ m - month of year (no leading zero)
1017
+ mm - month of year (two digit)
1018
+ M - month name short
1019
+ MM - month name long
1020
+ y - year (two digit)
1021
+ yy - year (four digit)
1022
+ @ - Unix timestamp (ms since 01/01/1970)
1023
+ '...' - literal text
1024
+ '' - single quote
1025
+
1026
+ @param format string - the desired format of the date
1027
+ @param date Date - the date value to format
1028
+ @param settings Object - attributes include:
1029
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1030
+ dayNames string[7] - names of the days from Sunday (optional)
1031
+ monthNamesShort string[12] - abbreviated names of the months (optional)
1032
+ monthNames string[12] - names of the months (optional)
1033
+ @return string - the date in the above format */
1034
+ formatDate: function (format, date, settings) {
1035
+ if (!date)
1036
+ return '';
1037
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1038
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1039
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1040
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1041
+ // Check whether a format character is doubled
1042
+ var lookAhead = function(match) {
1043
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1044
+ if (matches)
1045
+ iFormat++;
1046
+ return matches;
1047
+ };
1048
+ // Format a number, with leading zero if necessary
1049
+ var formatNumber = function(match, value, len) {
1050
+ var num = '' + value;
1051
+ if (lookAhead(match))
1052
+ while (num.length < len)
1053
+ num = '0' + num;
1054
+ return num;
1055
+ };
1056
+ // Format a name, short or long as requested
1057
+ var formatName = function(match, value, shortNames, longNames) {
1058
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
1059
+ };
1060
+ var output = '';
1061
+ var literal = false;
1062
+ if (date)
1063
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1064
+ if (literal)
1065
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1066
+ literal = false;
1067
+ else
1068
+ output += format.charAt(iFormat);
1069
+ else
1070
+ switch (format.charAt(iFormat)) {
1071
+ case 'd':
1072
+ output += formatNumber('d', date.getDate(), 2);
1073
+ break;
1074
+ case 'D':
1075
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
1076
+ break;
1077
+ case 'o':
1078
+ var doy = date.getDate();
1079
+ for (var m = date.getMonth() - 1; m >= 0; m--)
1080
+ doy += this._getDaysInMonth(date.getFullYear(), m);
1081
+ output += formatNumber('o', doy, 3);
1082
+ break;
1083
+ case 'm':
1084
+ output += formatNumber('m', date.getMonth() + 1, 2);
1085
+ break;
1086
+ case 'M':
1087
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
1088
+ break;
1089
+ case 'y':
1090
+ output += (lookAhead('y') ? date.getFullYear() :
1091
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
1092
+ break;
1093
+ case '@':
1094
+ output += date.getTime();
1095
+ break;
1096
+ case "'":
1097
+ if (lookAhead("'"))
1098
+ output += "'";
1099
+ else
1100
+ literal = true;
1101
+ break;
1102
+ default:
1103
+ output += format.charAt(iFormat);
1104
+ }
1105
+ }
1106
+ return output;
1107
+ },
1108
+
1109
+ /* Extract all possible characters from the date format. */
1110
+ _possibleChars: function (format) {
1111
+ var chars = '';
1112
+ var literal = false;
1113
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
1114
+ if (literal)
1115
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1116
+ literal = false;
1117
+ else
1118
+ chars += format.charAt(iFormat);
1119
+ else
1120
+ switch (format.charAt(iFormat)) {
1121
+ case 'd': case 'm': case 'y': case '@':
1122
+ chars += '0123456789';
1123
+ break;
1124
+ case 'D': case 'M':
1125
+ return null; // Accept anything
1126
+ case "'":
1127
+ if (lookAhead("'"))
1128
+ chars += "'";
1129
+ else
1130
+ literal = true;
1131
+ break;
1132
+ default:
1133
+ chars += format.charAt(iFormat);
1134
+ }
1135
+ return chars;
1136
+ },
1137
+
1138
+ /* Get a setting value, defaulting if necessary. */
1139
+ _get: function(inst, name) {
1140
+ return inst.settings[name] !== undefined ?
1141
+ inst.settings[name] : this._defaults[name];
1142
+ },
1143
+
1144
+ /* Parse existing date and initialise date picker. */
1145
+ _setDateFromField: function(inst) {
1146
+ var dateFormat = this._get(inst, 'dateFormat');
1147
+ var dates = inst.input ? inst.input.val() : null;
1148
+ inst.endDay = inst.endMonth = inst.endYear = null;
1149
+ var date = defaultDate = this._getDefaultDate(inst);
1150
+ var settings = this._getFormatConfig(inst);
1151
+ try {
1152
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
1153
+ } catch (event) {
1154
+ this.log(event);
1155
+ date = defaultDate;
1156
+ }
1157
+ inst.selectedDay = date.getDate();
1158
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1159
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1160
+ inst.currentDay = (dates ? date.getDate() : 0);
1161
+ inst.currentMonth = (dates ? date.getMonth() : 0);
1162
+ inst.currentYear = (dates ? date.getFullYear() : 0);
1163
+ this._adjustInstDate(inst);
1164
+ },
1165
+
1166
+ /* Retrieve the default date shown on opening. */
1167
+ _getDefaultDate: function(inst) {
1168
+ var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
1169
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1170
+ var maxDate = this._getMinMaxDate(inst, 'max');
1171
+ date = (minDate && date < minDate ? minDate : date);
1172
+ date = (maxDate && date > maxDate ? maxDate : date);
1173
+ return date;
1174
+ },
1175
+
1176
+ /* A date may be specified as an exact value or a relative one. */
1177
+ _determineDate: function(date, defaultDate) {
1178
+ var offsetNumeric = function(offset) {
1179
+ var date = new Date();
1180
+ date.setDate(date.getDate() + offset);
1181
+ return date;
1182
+ };
1183
+ var offsetString = function(offset, getDaysInMonth) {
1184
+ var date = new Date();
1185
+ var year = date.getFullYear();
1186
+ var month = date.getMonth();
1187
+ var day = date.getDate();
1188
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
1189
+ var matches = pattern.exec(offset);
1190
+ while (matches) {
1191
+ switch (matches[2] || 'd') {
1192
+ case 'd' : case 'D' :
1193
+ day += parseInt(matches[1],10); break;
1194
+ case 'w' : case 'W' :
1195
+ day += parseInt(matches[1],10) * 7; break;
1196
+ case 'm' : case 'M' :
1197
+ month += parseInt(matches[1],10);
1198
+ day = Math.min(day, getDaysInMonth(year, month));
1199
+ break;
1200
+ case 'y': case 'Y' :
1201
+ year += parseInt(matches[1],10);
1202
+ day = Math.min(day, getDaysInMonth(year, month));
1203
+ break;
1204
+ }
1205
+ matches = pattern.exec(offset);
1206
+ }
1207
+ return new Date(year, month, day);
1208
+ };
1209
+ date = (date == null ? defaultDate :
1210
+ (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
1211
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
1212
+ date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
1213
+ if (date) {
1214
+ date.setHours(0);
1215
+ date.setMinutes(0);
1216
+ date.setSeconds(0);
1217
+ date.setMilliseconds(0);
1218
+ }
1219
+ return this._daylightSavingAdjust(date);
1220
+ },
1221
+
1222
+ /* Handle switch to/from daylight saving.
1223
+ Hours may be non-zero on daylight saving cut-over:
1224
+ > 12 when midnight changeover, but then cannot generate
1225
+ midnight datetime, so jump to 1AM, otherwise reset.
1226
+ @param date (Date) the date to check
1227
+ @return (Date) the corrected date */
1228
+ _daylightSavingAdjust: function(date) {
1229
+ if (!date) return null;
1230
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
1231
+ return date;
1232
+ },
1233
+
1234
+ /* Set the date(s) directly. */
1235
+ _setDate: function(inst, date, endDate) {
1236
+ var clear = !(date);
1237
+ var origMonth = inst.selectedMonth;
1238
+ var origYear = inst.selectedYear;
1239
+ date = this._determineDate(date, new Date());
1240
+ inst.selectedDay = inst.currentDay = date.getDate();
1241
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
1242
+ inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
1243
+ if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
1244
+ this._notifyChange(inst);
1245
+ this._adjustInstDate(inst);
1246
+ if (inst.input) {
1247
+ inst.input.val(clear ? '' : this._formatDate(inst));
1248
+ }
1249
+ },
1250
+
1251
+ /* Retrieve the date(s) directly. */
1252
+ _getDate: function(inst) {
1253
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
1254
+ this._daylightSavingAdjust(new Date(
1255
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
1256
+ return startDate;
1257
+ },
1258
+
1259
+ /* Generate the HTML for the current state of the date picker. */
1260
+ _generateHTML: function(inst) {
1261
+ var today = new Date();
1262
+ today = this._daylightSavingAdjust(
1263
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
1264
+ var isRTL = this._get(inst, 'isRTL');
1265
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
1266
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
1267
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
1268
+ var numMonths = this._getNumberOfMonths(inst);
1269
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
1270
+ var stepMonths = this._get(inst, 'stepMonths');
1271
+ var stepBigMonths = this._get(inst, 'stepBigMonths');
1272
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
1273
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
1274
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1275
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1276
+ var maxDate = this._getMinMaxDate(inst, 'max');
1277
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
1278
+ var drawYear = inst.drawYear;
1279
+ if (drawMonth < 0) {
1280
+ drawMonth += 12;
1281
+ drawYear--;
1282
+ }
1283
+ if (maxDate) {
1284
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
1285
+ maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
1286
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1287
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
1288
+ drawMonth--;
1289
+ if (drawMonth < 0) {
1290
+ drawMonth = 11;
1291
+ drawYear--;
1292
+ }
1293
+ }
1294
+ }
1295
+ inst.drawMonth = drawMonth;
1296
+ inst.drawYear = drawYear;
1297
+ var prevText = this._get(inst, 'prevText');
1298
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
1299
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
1300
+ this._getFormatConfig(inst)));
1301
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1302
+ '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
1303
+ ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
1304
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
1305
+ var nextText = this._get(inst, 'nextText');
1306
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
1307
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
1308
+ this._getFormatConfig(inst)));
1309
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1310
+ '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
1311
+ ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
1312
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
1313
+ var currentText = this._get(inst, 'currentText');
1314
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
1315
+ currentText = (!navigationAsDateFormat ? currentText :
1316
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
1317
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
1318
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
1319
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
1320
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
1321
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
1322
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
1323
+ var dayNames = this._get(inst, 'dayNames');
1324
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
1325
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
1326
+ var monthNames = this._get(inst, 'monthNames');
1327
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
1328
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
1329
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
1330
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
1331
+ var endDate = inst.endDay ? this._daylightSavingAdjust(
1332
+ new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
1333
+ var defaultDate = this._getDefaultDate(inst);
1334
+ var html = '';
1335
+ for (var row = 0; row < numMonths[0]; row++) {
1336
+ var group = '';
1337
+ for (var col = 0; col < numMonths[1]; col++) {
1338
+ var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
1339
+ var cornerClass = ' ui-corner-all';
1340
+ var calender = '';
1341
+ if (isMultiMonth) {
1342
+ calender += '<div class="ui-datepicker-group ui-datepicker-group-';
1343
+ switch (col) {
1344
+ case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
1345
+ case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
1346
+ default: calender += 'middle'; cornerClass = ''; break;
1347
+ }
1348
+ calender += '">';
1349
+ }
1350
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
1351
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
1352
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
1353
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
1354
+ selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
1355
+ '</div><table class="ui-datepicker-calendar"><thead>' +
1356
+ '<tr>';
1357
+ var thead = '';
1358
+ for (var dow = 0; dow < 7; dow++) { // days of the week
1359
+ var day = (dow + firstDay) % 7;
1360
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
1361
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
1362
+ }
1363
+ calender += thead + '</tr></thead><tbody>';
1364
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
1365
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
1366
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
1367
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
1368
+ var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
1369
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
1370
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
1371
+ calender += '<tr>';
1372
+ var tbody = '';
1373
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
1374
+ var daySettings = (beforeShowDay ?
1375
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
1376
+ var otherMonth = (printDate.getMonth() != drawMonth);
1377
+ var unselectable = otherMonth || !daySettings[0] ||
1378
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
1379
+ tbody += '<td class="' +
1380
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
1381
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
1382
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
1383
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
1384
+ // or defaultDate is current printedDate and defaultDate is selectedDate
1385
+ ' ' + this._dayOverClass : '') + // highlight selected day
1386
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
1387
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
1388
+ (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
1389
+ ' ' + this._currentClass : '') + // highlight selected day
1390
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
1391
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
1392
+ (unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
1393
+ inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
1394
+ (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
1395
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
1396
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
1397
+ (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
1398
+ ' ui-state-active' : '') + // highlight selected day
1399
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
1400
+ printDate.setDate(printDate.getDate() + 1);
1401
+ printDate = this._daylightSavingAdjust(printDate);
1402
+ }
1403
+ calender += tbody + '</tr>';
1404
+ }
1405
+ drawMonth++;
1406
+ if (drawMonth > 11) {
1407
+ drawMonth = 0;
1408
+ drawYear++;
1409
+ }
1410
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
1411
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
1412
+ group += calender;
1413
+ }
1414
+ html += group;
1415
+ }
1416
+ html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
1417
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
1418
+ inst._keyEvent = false;
1419
+ return html;
1420
+ },
1421
+
1422
+ /* Generate the month and year header. */
1423
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
1424
+ selectedDate, secondary, monthNames, monthNamesShort) {
1425
+ minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
1426
+ var changeMonth = this._get(inst, 'changeMonth');
1427
+ var changeYear = this._get(inst, 'changeYear');
1428
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
1429
+ var html = '<div class="ui-datepicker-title">';
1430
+ var monthHtml = '';
1431
+ // month selection
1432
+ if (secondary || !changeMonth)
1433
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
1434
+ else {
1435
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
1436
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
1437
+ monthHtml += '<select class="ui-datepicker-month" ' +
1438
+ 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
1439
+ 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
1440
+ '>';
1441
+ for (var month = 0; month < 12; month++) {
1442
+ if ((!inMinYear || month >= minDate.getMonth()) &&
1443
+ (!inMaxYear || month <= maxDate.getMonth()))
1444
+ monthHtml += '<option value="' + month + '"' +
1445
+ (month == drawMonth ? ' selected="selected"' : '') +
1446
+ '>' + monthNamesShort[month] + '</option>';
1447
+ }
1448
+ monthHtml += '</select>';
1449
+ }
1450
+ if (!showMonthAfterYear)
1451
+ html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
1452
+ // year selection
1453
+ if (secondary || !changeYear)
1454
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
1455
+ else {
1456
+ // determine range of years to display
1457
+ var years = this._get(inst, 'yearRange').split(':');
1458
+ var year = 0;
1459
+ var endYear = 0;
1460
+ if (years.length != 2) {
1461
+ year = drawYear - 10;
1462
+ endYear = drawYear + 10;
1463
+ } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
1464
+ year = drawYear + parseInt(years[0], 10);
1465
+ endYear = drawYear + parseInt(years[1], 10);
1466
+ } else {
1467
+ year = parseInt(years[0], 10);
1468
+ endYear = parseInt(years[1], 10);
1469
+ }
1470
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
1471
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
1472
+ html += '<select class="ui-datepicker-year" ' +
1473
+ 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
1474
+ 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
1475
+ '>';
1476
+ for (; year <= endYear; year++) {
1477
+ html += '<option value="' + year + '"' +
1478
+ (year == drawYear ? ' selected="selected"' : '') +
1479
+ '>' + year + '</option>';
1480
+ }
1481
+ html += '</select>';
1482
+ }
1483
+ if (showMonthAfterYear)
1484
+ html += (secondary || changeMonth || changeYear ? '&#xa0;' : '') + monthHtml;
1485
+ html += '</div>'; // Close datepicker_header
1486
+ return html;
1487
+ },
1488
+
1489
+ /* Adjust one of the date sub-fields. */
1490
+ _adjustInstDate: function(inst, offset, period) {
1491
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
1492
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
1493
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
1494
+ (period == 'D' ? offset : 0);
1495
+ var date = this._daylightSavingAdjust(new Date(year, month, day));
1496
+ // ensure it is within the bounds set
1497
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1498
+ var maxDate = this._getMinMaxDate(inst, 'max');
1499
+ date = (minDate && date < minDate ? minDate : date);
1500
+ date = (maxDate && date > maxDate ? maxDate : date);
1501
+ inst.selectedDay = date.getDate();
1502
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1503
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1504
+ if (period == 'M' || period == 'Y')
1505
+ this._notifyChange(inst);
1506
+ },
1507
+
1508
+ /* Notify change of month/year. */
1509
+ _notifyChange: function(inst) {
1510
+ var onChange = this._get(inst, 'onChangeMonthYear');
1511
+ if (onChange)
1512
+ onChange.apply((inst.input ? inst.input[0] : null),
1513
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
1514
+ },
1515
+
1516
+ /* Determine the number of months to show. */
1517
+ _getNumberOfMonths: function(inst) {
1518
+ var numMonths = this._get(inst, 'numberOfMonths');
1519
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
1520
+ },
1521
+
1522
+ /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
1523
+ _getMinMaxDate: function(inst, minMax, checkRange) {
1524
+ var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
1525
+ return (!checkRange || !inst.rangeStart ? date :
1526
+ (!date || inst.rangeStart > date ? inst.rangeStart : date));
1527
+ },
1528
+
1529
+ /* Find the number of days in a given month. */
1530
+ _getDaysInMonth: function(year, month) {
1531
+ return 32 - new Date(year, month, 32).getDate();
1532
+ },
1533
+
1534
+ /* Find the day of the week of the first of a month. */
1535
+ _getFirstDayOfMonth: function(year, month) {
1536
+ return new Date(year, month, 1).getDay();
1537
+ },
1538
+
1539
+ /* Determines if we should allow a "next/prev" month display change. */
1540
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
1541
+ var numMonths = this._getNumberOfMonths(inst);
1542
+ var date = this._daylightSavingAdjust(new Date(
1543
+ curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
1544
+ if (offset < 0)
1545
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
1546
+ return this._isInRange(inst, date);
1547
+ },
1548
+
1549
+ /* Is the given date in the accepted range? */
1550
+ _isInRange: function(inst, date) {
1551
+ // during range selection, use minimum of selected date and range start
1552
+ var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
1553
+ new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
1554
+ newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
1555
+ var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
1556
+ var maxDate = this._getMinMaxDate(inst, 'max');
1557
+ return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
1558
+ },
1559
+
1560
+ /* Provide the configuration settings for formatting/parsing. */
1561
+ _getFormatConfig: function(inst) {
1562
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
1563
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
1564
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
1565
+ return {shortYearCutoff: shortYearCutoff,
1566
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
1567
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
1568
+ },
1569
+
1570
+ /* Format the given date for display. */
1571
+ _formatDate: function(inst, day, month, year) {
1572
+ if (!day) {
1573
+ inst.currentDay = inst.selectedDay;
1574
+ inst.currentMonth = inst.selectedMonth;
1575
+ inst.currentYear = inst.selectedYear;
1576
+ }
1577
+ var date = (day ? (typeof day == 'object' ? day :
1578
+ this._daylightSavingAdjust(new Date(year, month, day))) :
1579
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1580
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
1581
+ }
1582
+ });
1583
+
1584
+ /* jQuery extend now ignores nulls! */
1585
+ function extendRemove(target, props) {
1586
+ $.extend(target, props);
1587
+ for (var name in props)
1588
+ if (props[name] == null || props[name] == undefined)
1589
+ target[name] = props[name];
1590
+ return target;
1591
+ };
1592
+
1593
+ /* Determine whether an object is an array. */
1594
+ function isArray(a) {
1595
+ return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
1596
+ (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
1597
+ };
1598
+
1599
+ /* Invoke the datepicker functionality.
1600
+ @param options string - a command, optionally followed by additional parameters or
1601
+ Object - settings for attaching new datepicker functionality
1602
+ @return jQuery object */
1603
+ $.fn.datepicker = function(options){
1604
+
1605
+ /* Initialise the date picker. */
1606
+ if (!$.datepicker.initialized) {
1607
+ $(document).mousedown($.datepicker._checkExternalClick).
1608
+ find('body').append($.datepicker.dpDiv);
1609
+ $.datepicker.initialized = true;
1610
+ }
1611
+
1612
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
1613
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
1614
+ return $.datepicker['_' + options + 'Datepicker'].
1615
+ apply($.datepicker, [this[0]].concat(otherArgs));
1616
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1617
+ return $.datepicker['_' + options + 'Datepicker'].
1618
+ apply($.datepicker, [this[0]].concat(otherArgs));
1619
+ return this.each(function() {
1620
+ typeof options == 'string' ?
1621
+ $.datepicker['_' + options + 'Datepicker'].
1622
+ apply($.datepicker, [this].concat(otherArgs)) :
1623
+ $.datepicker._attachDatepicker(this, options);
1624
+ });
1625
+ };
1626
+
1627
+ $.datepicker = new Datepicker(); // singleton instance
1628
+ $.datepicker.initialized = false;
1629
+ $.datepicker.uuid = new Date().getTime();
1630
+ $.datepicker.version = "1.7.3";
1631
+
1632
+ // Workaround for #4055
1633
+ // Add another global to avoid noConflict issues with inline event handlers
1634
+ window.DP_jQuery = $;
1635
+
1636
+ })(jQuery);
static/js/plupload/plupload.full.js CHANGED
@@ -1,2 +1,2 @@
1
- /*1.5b*/
2
  (function(){var f=0,l=[],n={},j={},a={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},m=/[<>&\"\']/g,b,c=window.setTimeout,d={},e;function h(){this.returnValue=false}function k(){this.cancelBubble=true}(function(o){var p=o.split(/,/),q,s,r;for(q=0;q<p.length;q+=2){r=p[q+1].split(/ /);for(s=0;s<r.length;s++){j[r[s]]=p[q]}}})("application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats,docx pptx xlsx,audio/mpeg,mpga mpega mp2 mp3,audio/x-wav,wav,audio/mp4,m4a,image/bmp,bmp,image/gif,gif,image/jpeg,jpeg jpg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/html,htm html xhtml,text/rtf,rtf,video/mpeg,mpeg mpg mpe,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/vnd.rn-realvideo,rv,text/csv,csv,text/plain,asc txt text diff log,application/octet-stream,exe");var g={VERSION:"1.5b",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,IMAGE_FORMAT_ERROR:-700,IMAGE_MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:j,extend:function(o){g.each(arguments,function(p,q){if(q>0){g.each(p,function(s,r){o[r]=s})}});return o},cleanName:function(o){var p,q;q=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(p=0;p<q.length;p+=2){o=o.replace(q[p],q[p+1])}o=o.replace(/\s+/g,"_");o=o.replace(/[^a-z0-9_\-\.]+/gi,"");return o},addRuntime:function(o,p){p.name=o;l[o]=p;l.push(p);return p},guid:function(){var o=new Date().getTime().toString(32),p;for(p=0;p<5;p++){o+=Math.floor(Math.random()*65535).toString(32)}return(g.guidPrefix||"p")+o+(f++).toString(32)},buildUrl:function(p,o){var q="";g.each(o,function(s,r){q+=(q?"&":"")+encodeURIComponent(r)+"="+encodeURIComponent(s)});if(q){p+=(p.indexOf("?")>0?"&":"?")+q}return p},each:function(r,s){var q,p,o;if(r){q=r.length;if(q===b){for(p in r){if(r.hasOwnProperty(p)){if(s(r[p],p)===false){return}}}}else{for(o=0;o<q;o++){if(s(r[o],o)===false){return}}}}},formatSize:function(o){if(o===b||/\D/.test(o)){return g.translate("N/A")}if(o>1073741824){return Math.round(o/1073741824,1)+" GB"}if(o>1048576){return Math.round(o/1048576,1)+" MB"}if(o>1024){return Math.round(o/1024,1)+" KB"}return o+" b"},getPos:function(p,t){var u=0,s=0,w,v=document,q,r;p=p;t=t||v.body;function o(C){var A,B,z=0,D=0;if(C){B=C.getBoundingClientRect();A=v.compatMode==="CSS1Compat"?v.documentElement:v.body;z=B.left+A.scrollLeft;D=B.top+A.scrollTop}return{x:z,y:D}}if(p&&p.getBoundingClientRect&&(navigator.userAgent.indexOf("MSIE")>0&&v.documentMode!==8)){q=o(p);r=o(t);return{x:q.x-r.x,y:q.y-r.y}}w=p;while(w&&w!=t&&w.nodeType){u+=w.offsetLeft||0;s+=w.offsetTop||0;w=w.offsetParent}w=p.parentNode;while(w&&w!=t&&w.nodeType){u-=w.scrollLeft||0;s-=w.scrollTop||0;w=w.parentNode}return{x:u,y:s}},getSize:function(o){return{w:o.offsetWidth||o.clientWidth,h:o.offsetHeight||o.clientHeight}},parseSize:function(o){var p;if(typeof(o)=="string"){o=/^([0-9]+)([mgk]?)$/.exec(o.toLowerCase().replace(/[^0-9mkg]/g,""));p=o[2];o=+o[1];if(p=="g"){o*=1073741824}if(p=="m"){o*=1048576}if(p=="k"){o*=1024}}return o},xmlEncode:function(o){return o?(""+o).replace(m,function(p){return a[p]?"&"+a[p]+";":p}):o},toArray:function(q){var p,o=[];for(p=0;p<q.length;p++){o[p]=q[p]}return o},addI18n:function(o){return g.extend(n,o)},translate:function(o){return n[o]||o},isEmptyObj:function(o){if(o===b){return true}for(var p in o){return false}return true},hasClass:function(q,p){var o;if(q.className==""){return false}o=new RegExp("(^|\\s+)"+p+"(\\s+|$)");return o.test(q.className)},addClass:function(p,o){if(!g.hasClass(p,o)){p.className=p.className==""?o:p.className.replace(/\s+$/,"")+" "+o}},removeClass:function(q,p){var o=new RegExp("(^|\\s+)"+p+"(\\s+|$)");q.className=q.className.replace(o,function(s,r,t){return r===" "&&t===" "?" ":""})},getStyle:function(p,o){if(p.currentStyle){return p.currentStyle[o]}else{if(window.getComputedStyle){return window.getComputedStyle(p,null)[o]}}},addEvent:function(t,o,u){var s,r,q,p;p=arguments[3];o=o.toLowerCase();if(e===b){e="Plupload_"+g.guid()}if(t.addEventListener){s=u;t.addEventListener(o,s,false)}else{if(t.attachEvent){s=function(){var v=window.event;if(!v.target){v.target=v.srcElement}v.preventDefault=h;v.stopPropagation=k;u(v)};t.attachEvent("on"+o,s)}}if(t[e]===b){t[e]=g.guid()}if(!d.hasOwnProperty(t[e])){d[t[e]]={}}r=d[t[e]];if(!r.hasOwnProperty(o)){r[o]=[]}r[o].push({func:s,orig:u,key:p})},removeEvent:function(t,o){var r,u,q;if(typeof(arguments[2])=="function"){u=arguments[2]}else{q=arguments[2]}o=o.toLowerCase();if(t[e]&&d[t[e]]&&d[t[e]][o]){r=d[t[e]][o]}else{return}for(var p=r.length-1;p>=0;p--){if(r[p].key===q||r[p].orig===u){if(t.detachEvent){t.detachEvent("on"+o,r[p].func)}else{if(t.removeEventListener){t.removeEventListener(o,r[p].func,false)}}r[p].orig=null;r[p].func=null;r.splice(p,1);if(u!==b){break}}}if(!r.length){delete d[t[e]][o]}if(g.isEmptyObj(d[t[e]])){delete d[t[e]];try{delete t[e]}catch(s){t[e]=b}}},removeAllEvents:function(p){var o=arguments[1];if(p[e]===b||!p[e]){return}g.each(d[p[e]],function(r,q){g.removeEvent(p,q,o)})}};g.Uploader=function(r){var p={},u,t=[],q;u=new g.QueueProgress();r=g.extend({chunk_size:0,multipart:true,multi_selection:true,file_data_name:"file",filters:[]},r);function s(){var w,x=0,v;if(this.state==g.STARTED){for(v=0;v<t.length;v++){if(!w&&t[v].status==g.QUEUED){w=t[v];w.status=g.UPLOADING;if(this.trigger("BeforeUpload",w)){this.trigger("UploadFile",w)}}else{x++}}if(x==t.length){this.trigger("UploadComplete",t);this.stop()}}}function o(){var w,v;u.reset();for(w=0;w<t.length;w++){v=t[w];if(v.size!==b){u.size+=v.size;u.loaded+=v.loaded}else{u.size=b}if(v.status==g.DONE){u.uploaded++}else{if(v.status==g.FAILED){u.failed++}else{u.queued++}}}if(u.size===b){u.percent=t.length>0?Math.ceil(u.uploaded/t.length*100):0}else{u.bytesPerSec=Math.ceil(u.loaded/((+new Date()-q||1)/1000));u.percent=u.size>0?Math.ceil(u.loaded/u.size*100):0}}g.extend(this,{state:g.STOPPED,runtime:"",features:{},files:t,settings:r,total:u,id:g.guid(),init:function(){var A=this,B,x,w,z=0,y;if(typeof(r.preinit)=="function"){r.preinit(A)}else{g.each(r.preinit,function(D,C){A.bind(C,D)})}r.page_url=r.page_url||document.location.pathname.replace(/\/[^\/]+$/g,"/");if(!/^(\w+:\/\/|\/)/.test(r.url)){r.url=r.page_url+r.url}r.chunk_size=g.parseSize(r.chunk_size);r.max_file_size=g.parseSize(r.max_file_size);A.bind("FilesAdded",function(C,F){var E,D,H=0,I,G=r.filters;if(G&&G.length){I=[];g.each(G,function(J){g.each(J.extensions.split(/,/),function(K){if(/^\s*\*\s*$/.test(K)){I.push("\\.*")}else{I.push("\\."+K.replace(new RegExp("["+("/^$.*+?|()[]{}\\".replace(/./g,"\\$&"))+"]","g"),"\\$&"))}})});I=new RegExp(I.join("|")+"$","i")}for(E=0;E<F.length;E++){D=F[E];D.loaded=0;D.percent=0;D.status=g.QUEUED;if(I&&!I.test(D.name)){C.trigger("Error",{code:g.FILE_EXTENSION_ERROR,message:g.translate("File extension error."),file:D});continue}if(D.size!==b&&D.size>r.max_file_size){C.trigger("Error",{code:g.FILE_SIZE_ERROR,message:g.translate("File size error."),file:D});continue}t.push(D);H++}if(H){c(function(){A.trigger("QueueChanged");A.refresh()},1)}else{return false}});if(r.unique_names){A.bind("UploadFile",function(C,D){var F=D.name.match(/\.([^.]+)$/),E="tmp";if(F){E=F[1]}D.target_name=D.id+"."+E})}A.bind("UploadProgress",function(C,D){D.percent=D.size>0?Math.ceil(D.loaded/D.size*100):100;o()});A.bind("StateChanged",function(C){if(C.state==g.STARTED){q=(+new Date())}else{if(C.state==g.STOPPED){for(B=C.files.length-1;B>=0;B--){if(C.files[B].status==g.UPLOADING){C.files[B].status=g.QUEUED;o()}}}}});A.bind("QueueChanged",o);A.bind("Error",function(C,D){if(D.file){D.file.status=g.FAILED;o();if(C.state==g.STARTED){c(function(){s.call(A)},1)}}});A.bind("FileUploaded",function(C,D){D.status=g.DONE;D.loaded=D.size;C.trigger("UploadProgress",D);c(function(){s.call(A)},1)});if(r.runtimes){x=[];y=r.runtimes.split(/\s?,\s?/);for(B=0;B<y.length;B++){if(l[y[B]]){x.push(l[y[B]])}}}else{x=l}function v(){var F=x[z++],E,C,D;if(F){E=F.getFeatures();C=A.settings.required_features;if(C){C=C.split(",");for(D=0;D<C.length;D++){if(!E[C[D]]){v();return}}}F.init(A,function(G){if(G&&G.success){A.features=E;A.runtime=F.name;A.trigger("Init",{runtime:F.name});A.trigger("PostInit");A.refresh()}else{v()}})}else{A.trigger("Error",{code:g.INIT_ERROR,message:g.translate("Init error.")})}}v();if(typeof(r.init)=="function"){r.init(A)}else{g.each(r.init,function(D,C){A.bind(C,D)})}},refresh:function(){this.trigger("Refresh")},start:function(){if(this.state!=g.STARTED){this.state=g.STARTED;this.trigger("StateChanged");s.call(this)}},stop:function(){if(this.state!=g.STOPPED){this.state=g.STOPPED;this.trigger("StateChanged")}},getFile:function(w){var v;for(v=t.length-1;v>=0;v--){if(t[v].id===w){return t[v]}}},removeFile:function(w){var v;for(v=t.length-1;v>=0;v--){if(t[v].id===w.id){return this.splice(v,1)[0]}}},splice:function(x,v){var w;w=t.splice(x===b?0:x,v===b?t.length:v);this.trigger("FilesRemoved",w);this.trigger("QueueChanged");return w},trigger:function(w){var y=p[w.toLowerCase()],x,v;if(y){v=Array.prototype.slice.call(arguments);v[0]=this;for(x=0;x<y.length;x++){if(y[x].func.apply(y[x].scope,v)===false){return false}}}return true},hasEventListener:function(v){return !!p[v.toLowerCase()]},bind:function(v,x,w){var y;v=v.toLowerCase();y=p[v]||[];y.push({func:x,scope:w||this});p[v]=y},unbind:function(v){v=v.toLowerCase();var y=p[v],w,x=arguments[1];if(y){if(x!==b){for(w=y.length-1;w>=0;w--){if(y[w].func===x){y.splice(w,1);break}}}else{y=[]}if(!y.length){delete p[v]}}},unbindAll:function(){var v=this;g.each(p,function(x,w){v.unbind(w)})},destroy:function(){this.trigger("Destroy");this.unbindAll()}})};g.File=function(r,p,q){var o=this;o.id=r;o.name=p;o.size=q;o.loaded=0;o.percent=0;o.status=0};g.Runtime=function(){this.getFeatures=function(){};this.init=function(o,p){}};g.QueueProgress=function(){var o=this;o.size=0;o.loaded=0;o.uploaded=0;o.failed=0;o.queued=0;o.percent=0;o.bytesPerSec=0;o.reset=function(){o.size=o.loaded=o.uploaded=o.failed=o.queued=o.percent=o.bytesPerSec=0}};g.runtimes={};window.plupload=g})();(function(){if(window.google&&google.gears){return}var a=null;if(typeof GearsFactory!="undefined"){a=new GearsFactory()}else{try{a=new ActiveXObject("Gears.Factory");if(a.getBuildInfo().indexOf("ie_mobile")!=-1){a.privateSetGlobalObject(this)}}catch(b){if((typeof navigator.mimeTypes!="undefined")&&navigator.mimeTypes["application/x-googlegears"]){a=document.createElement("object");a.style.display="none";a.width=0;a.height=0;a.type="application/x-googlegears";document.documentElement.appendChild(a)}}}if(!a){return}if(!window.google){window.google={}}if(!google.gears){google.gears={factory:a}}})();(function(e,b,c,d){var f={};function a(h,k,m){var g,j,l,o;j=google.gears.factory.create("beta.canvas");try{j.decode(h);if(!k.width){k.width=j.width}if(!k.height){k.height=j.height}o=Math.min(width/j.width,height/j.height);if(o<1||(o===1&&m==="image/jpeg")){j.resize(Math.round(j.width*o),Math.round(j.height*o));if(k.quality){return j.encode(m,{quality:k.quality/100})}return j.encode(m)}}catch(n){}return h}c.runtimes.Gears=c.addRuntime("gears",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(j,l){var k;if(!e.google||!google.gears){return l({success:false})}try{k=google.gears.factory.create("beta.desktop")}catch(h){return l({success:false})}function g(o){var n,m,p=[],q;for(m=0;m<o.length;m++){n=o[m];q=c.guid();f[q]=n.blob;p.push(new c.File(q,n.name,n.blob.length))}j.trigger("FilesAdded",p)}j.bind("PostInit",function(){var n=j.settings,m=b.getElementById(n.drop_element);if(m){c.addEvent(m,"dragover",function(o){k.setDropEffect(o,"copy");o.preventDefault()},j.id);c.addEvent(m,"drop",function(p){var o=k.getDragData(p,"application/x-gears-files");if(o){g(o.files)}p.preventDefault()},j.id);m=0}c.addEvent(b.getElementById(n.browse_button),"click",function(s){var r=[],p,o,q;s.preventDefault();no_type_restriction:for(p=0;p<n.filters.length;p++){q=n.filters[p].extensions.split(",");for(o=0;o<q.length;o++){if(q[o]==="*"){r=[];break no_type_restriction}r.push("."+q[o])}}k.openFiles(g,{singleFile:!n.multi_selection,filter:r})},j.id)});j.bind("UploadFile",function(s,p){var u=0,t,q,r=0,o=s.settings.resize,m;if(o&&/\.(png|jpg|jpeg)$/i.test(p.name)){f[p.id]=a(f[p.id],o,/\.png$/i.test(p.name)?"image/png":"image/jpeg")}p.size=f[p.id].length;q=s.settings.chunk_size;m=q>0;t=Math.ceil(p.size/q);if(!m){q=p.size;t=1}function n(){var z,B,w=s.settings.multipart,v=0,A={name:p.target_name||p.name},x=s.settings.url;function y(D){var C,I="----pluploadboundary"+c.guid(),F="--",H="\r\n",E,G;if(w){z.setRequestHeader("Content-Type","multipart/form-data; boundary="+I);C=google.gears.factory.create("beta.blobbuilder");c.each(c.extend(A,s.settings.multipart_params),function(K,J){C.append(F+I+H+'Content-Disposition: form-data; name="'+J+'"'+H+H);C.append(K+H)});G=c.mimeTypes[p.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";C.append(F+I+H+'Content-Disposition: form-data; name="'+s.settings.file_data_name+'"; filename="'+p.name+'"'+H+"Content-Type: "+G+H+H);C.append(D);C.append(H+F+I+F+H);E=C.getAsBlob();v=E.length-D.length;D=E}z.send(D)}if(p.status==c.DONE||p.status==c.FAILED||s.state==c.STOPPED){return}if(m){A.chunk=u;A.chunks=t}B=Math.min(q,p.size-(u*q));if(!w){x=c.buildUrl(s.settings.url,A)}z=google.gears.factory.create("beta.httprequest");z.open("POST",x);if(!w){z.setRequestHeader("Content-Disposition",'attachment; filename="'+p.name+'"');z.setRequestHeader("Content-Type","application/octet-stream")}c.each(s.settings.headers,function(D,C){z.setRequestHeader(C,D)});z.upload.onprogress=function(C){p.loaded=r+C.loaded-v;s.trigger("UploadProgress",p)};z.onreadystatechange=function(){var C;if(z.readyState==4){if(z.status==200){C={chunk:u,chunks:t,response:z.responseText,status:z.status};s.trigger("ChunkUploaded",p,C);if(C.cancelled){p.status=c.FAILED;return}r+=B;if(++u>=t){p.status=c.DONE;s.trigger("FileUploaded",p,{response:z.responseText,status:z.status})}else{n()}}else{s.trigger("Error",{code:c.HTTP_ERROR,message:c.translate("HTTP Error."),file:p,chunk:u,chunks:t,status:z.status})}}};if(u<t){y(f[p.id].slice(u*q,B))}}n()});j.bind("Destroy",function(m){var n,o,p={browseButton:m.settings.browse_button,dropElm:m.settings.drop_element};for(n in p){o=b.getElementById(p[n]);if(o){c.removeAllEvents(o,m.id)}}});l({success:true})}})})(window,document,plupload);(function(g,b,d,e){var a={},h={};function c(o){var n,m=typeof o,j,l,k;if(o===e||o===null){return"null"}if(m==="string"){n="\bb\tt\nn\ff\rr\"\"''\\\\";return'"'+o.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g,function(r,q){var p=n.indexOf(q);if(p+1){return"\\"+n.charAt(p+1)}r=q.charCodeAt().toString(16);return"\\u"+"0000".substring(r.length)+r})+'"'}if(m=="object"){j=o.length!==e;n="";if(j){for(l=0;l<o.length;l++){if(n){n+=","}n+=c(o[l])}n="["+n+"]"}else{for(k in o){if(o.hasOwnProperty(k)){if(n){n+=","}n+=c(k)+":"+c(o[k])}}n="{"+n+"}"}return n}return""+o}function f(s){var v=false,j=null,o=null,k,l,m,u,n,q=0;try{try{o=new ActiveXObject("AgControl.AgControl");if(o.IsVersionSupported(s)){v=true}o=null}catch(r){var p=navigator.plugins["Silverlight Plug-In"];if(p){k=p.description;if(k==="1.0.30226.2"){k="2.0.30226.2"}l=k.split(".");while(l.length>3){l.pop()}while(l.length<4){l.push(0)}m=s.split(".");while(m.length>4){m.pop()}do{u=parseInt(m[q],10);n=parseInt(l[q],10);q++}while(q<m.length&&u===n);if(u<=n&&!isNaN(u)){v=true}}}}catch(t){v=false}return v}d.silverlight={trigger:function(n,k){var m=a[n],l,j;if(m){j=d.toArray(arguments).slice(1);j[0]="Silverlight:"+k;setTimeout(function(){m.trigger.apply(m,j)},0)}}};d.runtimes.Silverlight=d.addRuntime("silverlight",{getFeatures:function(){return{jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(p,q){var o,m="",n=p.settings.filters,l,k=b.body;if(!f("2.0.31005.0")||(g.opera&&g.opera.buildNumber)){q({success:false});return}h[p.id]=false;a[p.id]=p;o=b.createElement("div");o.id=p.id+"_silverlight_container";d.extend(o.style,{position:"absolute",top:"0px",background:p.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100px",height:"100px",overflow:"hidden",opacity:p.settings.shim_bgcolor||b.documentMode>8?"":0.01});o.className="plupload silverlight";if(p.settings.container){k=b.getElementById(p.settings.container);if(d.getStyle(k,"position")==="static"){k.style.position="relative"}}k.appendChild(o);for(l=0;l<n.length;l++){m+=(m!=""?"|":"")+n[l].title+" | *."+n[l].extensions.replace(/,/g,";*.")}o.innerHTML='<object id="'+p.id+'_silverlight" data="data:application/x-silverlight," type="application/x-silverlight-2" style="outline:none;" width="1024" height="1024"><param name="source" value="'+p.settings.silverlight_xap_url+'"/><param name="background" value="Transparent"/><param name="windowless" value="true"/><param name="enablehtmlaccess" value="true"/><param name="initParams" value="id='+p.id+",filter="+m+",multiselect="+p.settings.multi_selection+'"/></object>';function j(){return b.getElementById(p.id+"_silverlight").content.Upload}p.bind("Silverlight:Init",function(){var r,s={};if(h[p.id]){return}h[p.id]=true;p.bind("Silverlight:StartSelectFiles",function(t){r=[]});p.bind("Silverlight:SelectFile",function(t,w,u,v){var x;x=d.guid();s[x]=w;s[w]=x;r.push(new d.File(x,u,v))});p.bind("Silverlight:SelectSuccessful",function(){if(r.length){p.trigger("FilesAdded",r)}});p.bind("Silverlight:UploadChunkError",function(t,w,u,x,v){p.trigger("Error",{code:d.IO_ERROR,message:"IO Error.",details:v,file:t.getFile(s[w])})});p.bind("Silverlight:UploadFileProgress",function(t,x,u,w){var v=t.getFile(s[x]);if(v.status!=d.FAILED){v.size=w;v.loaded=u;t.trigger("UploadProgress",v)}});p.bind("Refresh",function(t){var u,v,w;u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_silverlight_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});p.bind("Silverlight:UploadChunkSuccessful",function(t,w,u,z,y){var x,v=t.getFile(s[w]);x={chunk:u,chunks:z,response:y};t.trigger("ChunkUploaded",v,x);if(v.status!=d.FAILED){j().UploadNextChunk()}if(u==z-1){v.status=d.DONE;t.trigger("FileUploaded",v,{response:y})}});p.bind("Silverlight:UploadSuccessful",function(t,w,u){var v=t.getFile(s[w]);v.status=d.DONE;t.trigger("FileUploaded",v,{response:u})});p.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){j().RemoveFile(s[v[u].id])}});p.bind("UploadFile",function(t,v){var w=t.settings,u=w.resize||{};j().UploadFile(s[v.id],t.settings.url,c({name:v.target_name||v.name,mime:d.mimeTypes[v.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:w.chunk_size,image_width:u.width,image_height:u.height,image_quality:u.quality||90,multipart:!!w.multipart,multipart_params:w.multipart_params||{},file_data_name:w.file_data_name,headers:w.headers}))});p.bind("Silverlight:MouseEnter",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});p.bind("Silverlight:MouseLeave",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});p.bind("Silverlight:MouseLeftButtonDown",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)})}});p.bind("Sliverlight:StartSelectFiles",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});p.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete h[t.id];delete a[t.id];u=b.getElementById(t.id+"_silverlight_container");if(u){k.removeChild(u)}});q({success:true})})}})})(window,document,plupload);(function(f,b,d,e){var a={},g={};function c(){var h;try{h=navigator.plugins["Shockwave Flash"];h=h.description}catch(k){try{h=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(j){h="0.0"}}h=h.match(/\d+/g);return parseFloat(h[0]+"."+h[1])}d.flash={trigger:function(k,h,j){setTimeout(function(){var n=a[k],m,l;if(n){n.trigger("Flash:"+h,j)}},0)}};d.runtimes.Flash=d.addRuntime("flash",{getFeatures:function(){return{jpgresize:true,pngresize:true,maxWidth:8091,maxHeight:8091,chunks:true,progress:true,multipart:true}},init:function(k,p){var o,j,l,q=0,h=b.body;if(c()<10){p({success:false});return}g[k.id]=false;a[k.id]=k;o=b.getElementById(k.settings.browse_button);j=b.createElement("div");j.id=k.id+"_flash_container";d.extend(j.style,{position:"absolute",top:"0px",background:k.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100%",height:"100%"});j.className="plupload flash";if(k.settings.container){h=b.getElementById(k.settings.container);if(d.getStyle(h,"position")==="static"){h.style.position="relative"}}h.appendChild(j);l="id="+escape(k.id);j.innerHTML='<object id="'+k.id+'_flash" width="100%" height="100%" style="outline:0" type="application/x-shockwave-flash" data="'+k.settings.flash_swf_url+'"><param name="movie" value="'+k.settings.flash_swf_url+'" /><param name="flashvars" value="'+l+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>';function n(){return b.getElementById(k.id+"_flash")}function m(){if(q++>5000){p({success:false});return}if(!g[k.id]){setTimeout(m,1)}}m();o=j=null;k.bind("Flash:Init",function(){var s={},r;n().setFileFilters(k.settings.filters,k.settings.multi_selection);if(g[k.id]){return}g[k.id]=true;k.bind("UploadFile",function(t,v){var w=t.settings,u=k.settings.resize||{};n().uploadFile(s[v.id],w.url,{name:v.target_name||v.name,mime:d.mimeTypes[v.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:w.chunk_size,width:u.width,height:u.height,quality:u.quality,multipart:w.multipart,multipart_params:w.multipart_params||{},file_data_name:w.file_data_name,format:/\.(jpg|jpeg)$/i.test(v.name)?"jpg":"png",headers:w.headers,urlstream_upload:w.urlstream_upload})});k.bind("Flash:UploadProcess",function(u,t){var v=u.getFile(s[t.id]);if(v.status!=d.FAILED){v.loaded=t.loaded;v.size=t.size;u.trigger("UploadProgress",v)}});k.bind("Flash:UploadChunkComplete",function(t,v){var w,u=t.getFile(s[v.id]);w={chunk:v.chunk,chunks:v.chunks,response:v.text};t.trigger("ChunkUploaded",u,w);if(u.status!=d.FAILED){n().uploadNextChunk()}if(v.chunk==v.chunks-1){u.status=d.DONE;t.trigger("FileUploaded",u,{response:v.text})}});k.bind("Flash:SelectFiles",function(t,w){var v,u,x=[],y;for(u=0;u<w.length;u++){v=w[u];y=d.guid();s[y]=v.id;s[v.id]=y;x.push(new d.File(y,v.name,v.size))}if(x.length){k.trigger("FilesAdded",x)}});k.bind("Flash:SecurityError",function(t,u){k.trigger("Error",{code:d.SECURITY_ERROR,message:d.translate("Security error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:GenericError",function(t,u){k.trigger("Error",{code:d.GENERIC_ERROR,message:d.translate("Generic error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:IOError",function(t,u){k.trigger("Error",{code:d.IO_ERROR,message:d.translate("IO error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:ImageError",function(t,u){k.trigger("Error",{code:parseInt(u.code,10),message:d.translate("Image error."),file:k.getFile(s[u.id])})});k.bind("Flash:StageEvent:rollOver",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});k.bind("Flash:StageEvent:rollOut",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});k.bind("Flash:StageEvent:mouseDown",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)},t.id)}});k.bind("Flash:StageEvent:mouseUp",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});k.bind("Flash:ExifData",function(t,u){k.trigger("ExifData",k.getFile(s[u.id]),u.data)});k.bind("Flash:GpsData",function(t,u){k.trigger("GpsData",k.getFile(s[u.id]),u.data)});k.bind("QueueChanged",function(t){k.refresh()});k.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){n().removeFile(s[v[u].id])}});k.bind("StateChanged",function(t){k.refresh()});k.bind("Refresh",function(t){var u,v,w;n().setFileFilters(k.settings.filters,k.settings.multi_selection);u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_flash_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});k.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete g[t.id];delete a[t.id];u=b.getElementById(t.id+"_flash_container");if(u){h.removeChild(u)}});p({success:true})})}})})(window,document,plupload);(function(a){a.runtimes.BrowserPlus=a.addRuntime("browserplus",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(g,j){var e=window.BrowserPlus,h={},d=g.settings,c=d.resize;function f(o){var n,m,k=[],l,p;for(m=0;m<o.length;m++){l=o[m];p=a.guid();h[p]=l;k.push(new a.File(p,l.name,l.size))}if(m){g.trigger("FilesAdded",k)}}function b(){g.bind("PostInit",function(){var n,l=d.drop_element,p=g.id+"_droptarget",k=document.getElementById(l),m;function q(s,r){e.DragAndDrop.AddDropTarget({id:s},function(t){e.DragAndDrop.AttachCallbacks({id:s,hover:function(u){if(!u&&r){r()}},drop:function(u){if(r){r()}f(u)}},function(){})})}function o(){document.getElementById(p).style.top="-1000px"}if(k){if(document.attachEvent&&(/MSIE/gi).test(navigator.userAgent)){n=document.createElement("div");n.setAttribute("id",p);a.extend(n.style,{position:"absolute",top:"-1000px",background:"red",filter:"alpha(opacity=0)",opacity:0});document.body.appendChild(n);a.addEvent(k,"dragenter",function(s){var r,t;r=document.getElementById(l);t=a.getPos(r);a.extend(document.getElementById(p).style,{top:t.y+"px",left:t.x+"px",width:r.offsetWidth+"px",height:r.offsetHeight+"px"})});q(p,o)}else{q(l)}}a.addEvent(document.getElementById(d.browse_button),"click",function(w){var u=[],s,r,v=d.filters,t;w.preventDefault();no_type_restriction:for(s=0;s<v.length;s++){t=v[s].extensions.split(",");for(r=0;r<t.length;r++){if(t[r]==="*"){u=[];break no_type_restriction}u.push(a.mimeTypes[t[r]])}}e.FileBrowse.OpenBrowseDialog({mimeTypes:u},function(x){if(x.success){f(x.value)}})});k=n=null});g.bind("UploadFile",function(n,k){var m=h[k.id],s={},l=n.settings.chunk_size,o,p=[];function r(t,v){var u;if(k.status==a.FAILED){return}s.name=k.target_name||k.name;if(l){s.chunk=""+t;s.chunks=""+v}u=p.shift();e.Uploader.upload({url:n.settings.url,files:{file:u},cookies:document.cookies,postvars:a.extend(s,n.settings.multipart_params),progressCallback:function(y){var x,w=0;o[t]=parseInt(y.filePercent*u.size/100,10);for(x=0;x<o.length;x++){w+=o[x]}k.loaded=w;n.trigger("UploadProgress",k)}},function(x){var w,y;if(x.success){w=x.value.statusCode;if(l){n.trigger("ChunkUploaded",k,{chunk:t,chunks:v,response:x.value.body,status:w})}if(p.length>0){r(++t,v)}else{k.status=a.DONE;n.trigger("FileUploaded",k,{response:x.value.body,status:w});if(w>=400){n.trigger("Error",{code:a.HTTP_ERROR,message:a.translate("HTTP Error."),file:k,status:w})}}}else{n.trigger("Error",{code:a.GENERIC_ERROR,message:a.translate("Generic Error."),file:k,details:x.error})}})}function q(t){k.size=t.size;if(l){e.FileAccess.chunk({file:t,chunkSize:l},function(w){if(w.success){var x=w.value,u=x.length;o=Array(u);for(var v=0;v<u;v++){o[v]=0;p.push(x[v])}r(0,u)}})}else{o=Array(1);p.push(t);r(0,1)}}if(c&&/\.(png|jpg|jpeg)$/i.test(k.name)){BrowserPlus.ImageAlter.transform({file:m,quality:c.quality||90,actions:[{scale:{maxwidth:c.width,maxheight:c.height}}]},function(t){if(t.success){q(t.value.file)}})}else{q(m)}});j({success:true})}if(e){e.init(function(l){var k=[{service:"Uploader",version:"3"},{service:"DragAndDrop",version:"1"},{service:"FileBrowse",version:"1"},{service:"FileAccess",version:"2"}];if(c){k.push({service:"ImageAlter",version:"4"})}if(l.success){e.require({services:k},function(m){if(m.success){b()}else{j()}})}else{j()}})}else{j()}}})})(plupload);(function(h,k,j,e){var c={},g;function m(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsDataURL(o);n.onload=function(){p(n.result)}}else{return p(o.getAsDataURL())}}function l(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsBinaryString(o);n.onload=function(){p(n.result)}}else{return p(o.getAsBinary())}}function d(r,p,n,v){var q,o,u,s,t=this;m(c[r.id],function(w){q=k.createElement("canvas");q.style.display="none";k.body.appendChild(q);o=q.getContext("2d");u=new Image();u.onerror=u.onabort=function(){v({success:false})};u.onload=function(){var B,x,z,y,A;if(!p.width){p.width=u.width}if(!p.height){p.height=u.height}s=Math.min(p.width/u.width,p.height/u.height);if(s<1||(s===1&&n==="image/jpeg")){B=Math.round(u.width*s);x=Math.round(u.height*s);q.width=B;q.height=x;o.drawImage(u,0,0,B,x);if(n==="image/jpeg"){y=new f(atob(w.substring(w.indexOf("base64,")+7)));if(y.headers&&y.headers.length){A=new a();if(A.init(y.get("exif")[0])){A.setExif("PixelXDimension",B);A.setExif("PixelYDimension",x);y.set("exif",A.getBinary());if(t.hasEventListener("ExifData")){t.trigger("ExifData",r,A.EXIF())}if(t.hasEventListener("GpsData")){t.trigger("GpsData",r,A.GPS())}}}if(p.quality){try{w=q.toDataURL(n,p.quality/100)}catch(C){w=q.toDataURL(n)}}}else{w=q.toDataURL(n)}w=w.substring(w.indexOf("base64,")+7);w=atob(w);if(y&&y.headers&&y.headers.length){w=y.restore(w);y.purge()}q.parentNode.removeChild(q);v({success:true,data:w})}else{v({success:false})}};u.src=w})}j.runtimes.Html5=j.addRuntime("html5",{getFeatures:function(){var t,o,s,r,q,n,p;p=(function(){var y=navigator,x=y.userAgent,z=y.vendor,v,u,w;v=/WebKit/.test(x);w=v&&z.indexOf("Apple")!==-1;u=h.opera&&h.opera.buildNumber;return{ie:!v&&!u&&(/MSIE/gi).test(x)&&(/Explorer/gi).test(y.appName),webkit:v,gecko:!v&&/Gecko/.test(x),safari:w,safariwin:w&&navigator.platform.indexOf("Win")!==-1,opera:!!u}}());o=s=q=n=false;if(h.XMLHttpRequest){t=new XMLHttpRequest();s=!!t.upload;o=!!(t.sendAsBinary||t.upload)}if(o){r=!!(t.sendAsBinary||(h.Uint8Array&&h.ArrayBuffer));q=!!(File&&(File.prototype.getAsDataURL||h.FileReader)&&r);n=!!(File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice))}g=p.safariwin;return{html5:o,dragdrop:(function(){var u=k.createElement("div");return("draggable" in u)||("ondragstart" in u&&"ondrop" in u)}()),jpgresize:q,pngresize:q,multipart:q||!!h.FileReader||!!h.FormData,canSendBinary:r,cantSendBlobInFormData:!!(p.gecko&&h.FormData&&h.FileReader&&!FileReader.prototype.readAsArrayBuffer),progress:s,chunks:n,triggerDialog:(p.gecko&&h.FormData||p.webkit)}},init:function(p,q){var n;function o(v){var t,s,u=[],w,r={};for(s=0;s<v.length;s++){t=v[s];if(r[t.name]){continue}r[t.name]=true;w=j.guid();c[w]=t;u.push(new j.File(w,t.fileName||t.name,t.fileSize||t.size))}if(u.length){p.trigger("FilesAdded",u)}}n=this.getFeatures();if(!n.html5){q({success:false});return}p.bind("Init",function(v){var F,E,B=[],u,C,s=v.settings.filters,t,A,r=k.body,D;F=k.createElement("div");F.id=v.id+"_html5_container";j.extend(F.style,{position:"absolute",background:p.settings.shim_bgcolor||"transparent",width:"100px",height:"100px",overflow:"hidden",zIndex:99999,opacity:p.settings.shim_bgcolor?"":0});F.className="plupload html5";if(p.settings.container){r=k.getElementById(p.settings.container);if(j.getStyle(r,"position")==="static"){r.style.position="relative"}}r.appendChild(F);no_type_restriction:for(u=0;u<s.length;u++){t=s[u].extensions.split(/,/);for(C=0;C<t.length;C++){if(t[C]==="*"){B=[];break no_type_restriction}A=j.mimeTypes[t[C]];if(A){B.push(A)}}}F.innerHTML='<input id="'+p.id+'_html5" style="font-size:999px" type="file" accept="'+B.join(",")+'" '+(p.settings.multi_selection?'multiple="multiple"':"")+" />";F.scrollTop=100;D=k.getElementById(p.id+"_html5");if(v.features.triggerDialog){j.extend(D.style,{position:"absolute",width:"100%",height:"100%"})}else{j.extend(D.style,{cssFloat:"right",styleFloat:"right"})}D.onchange=function(){o(this.files);this.value=""};E=k.getElementById(v.settings.browse_button);if(E){var x=v.settings.browse_button_hover,z=v.settings.browse_button_active,w=v.features.triggerDialog?E:F;if(x){j.addEvent(w,"mouseover",function(){j.addClass(E,x)},v.id);j.addEvent(w,"mouseout",function(){j.removeClass(E,x)},v.id)}if(z){j.addEvent(w,"mousedown",function(){j.addClass(E,z)},v.id);j.addEvent(k.body,"mouseup",function(){j.removeClass(E,z)},v.id)}if(v.features.triggerDialog){j.addEvent(E,"click",function(y){k.getElementById(v.id+"_html5").click();y.preventDefault()},v.id)}}});p.bind("PostInit",function(){var r=k.getElementById(p.settings.drop_element);if(r){if(g){j.addEvent(r,"dragenter",function(v){var u,s,t;u=k.getElementById(p.id+"_drop");if(!u){u=k.createElement("input");u.setAttribute("type","file");u.setAttribute("id",p.id+"_drop");u.setAttribute("multiple","multiple");j.addEvent(u,"change",function(){o(this.files);j.removeEvent(u,"change",p.id);u.parentNode.removeChild(u)},p.id);r.appendChild(u)}s=j.getPos(r,k.getElementById(p.settings.container));t=j.getSize(r);if(j.getStyle(r,"position")==="static"){j.extend(r.style,{position:"relative"})}j.extend(u.style,{position:"absolute",display:"block",top:0,left:0,width:t.w+"px",height:t.h+"px",opacity:0})},p.id);return}j.addEvent(r,"dragover",function(s){s.preventDefault()},p.id);j.addEvent(r,"drop",function(t){var s=t.dataTransfer;if(s&&s.files){o(s.files)}t.preventDefault()},p.id)}});p.bind("Refresh",function(r){var s,t,u,w,v;s=k.getElementById(p.settings.browse_button);if(s){t=j.getPos(s,k.getElementById(r.settings.container));u=j.getSize(s);w=k.getElementById(p.id+"_html5_container");j.extend(w.style,{top:t.y+"px",left:t.x+"px",width:u.w+"px",height:u.h+"px"});if(p.features.triggerDialog){if(j.getStyle(s,"position")==="static"){j.extend(s.style,{position:"relative"})}v=parseInt(j.getStyle(s,"z-index"),10);if(isNaN(v)){v=0}j.extend(s.style,{zIndex:v});j.extend(w.style,{zIndex:v-1})}}});p.bind("UploadFile",function(r,t){var u=r.settings,x,s;function w(z,C,y){var A;if(File.prototype.slice){try{z.slice();return z.slice(C,y)}catch(B){return z.slice(C,y-C)}}else{if(A=File.prototype.webkitSlice||File.prototype.mozSlice){return A.call(z,C,y)}else{return null}}}function v(z){var C=0,B=0,y=("FileReader" in h)?new FileReader:null,D=typeof(z)==="string";function A(){var I,M,K,L,H,J,F,E=r.settings.url;function G(W){var T=0,U=new XMLHttpRequest,X=U.upload,N="----pluploadboundary"+j.guid(),O,P="--",V="\r\n",R="";if(X){X.onprogress=function(Y){t.loaded=Math.min(t.size,B+Y.loaded-T);r.trigger("UploadProgress",t)}}U.onreadystatechange=function(){var Y,aa;if(U.readyState==4){try{Y=U.status}catch(Z){Y=0}if(Y>=400){r.trigger("Error",{code:j.HTTP_ERROR,message:j.translate("HTTP Error."),file:t,status:Y})}else{if(K){aa={chunk:C,chunks:K,response:U.responseText,status:Y};r.trigger("ChunkUploaded",t,aa);B+=J;if(aa.cancelled){t.status=j.FAILED;return}t.loaded=Math.min(t.size,(C+1)*H)}else{t.loaded=t.size}r.trigger("UploadProgress",t);W=I=O=R=null;if(!K||++C>=K){t.status=j.DONE;r.trigger("FileUploaded",t,{response:U.responseText,status:Y})}else{A()}}U=null}};if(r.settings.multipart&&n.multipart){L.name=t.target_name||t.name;U.open("post",E,true);j.each(r.settings.headers,function(Z,Y){U.setRequestHeader(Y,Z)});if(!D&&!!h.FormData){O=new FormData();j.each(j.extend(L,r.settings.multipart_params),function(Z,Y){O.append(Y,Z)});O.append(r.settings.file_data_name,W);U.send(O);return}if(D){U.setRequestHeader("Content-Type","multipart/form-data; boundary="+N);j.each(j.extend(L,r.settings.multipart_params),function(Z,Y){R+=P+N+V+'Content-Disposition: form-data; name="'+Y+'"'+V+V;R+=unescape(encodeURIComponent(Z))+V});F=j.mimeTypes[t.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";R+=P+N+V+'Content-Disposition: form-data; name="'+r.settings.file_data_name+'"; filename="'+unescape(encodeURIComponent(t.name))+'"'+V+"Content-Type: "+F+V+V+W+V+P+N+P+V;T=R.length-W.length;W=R;if(U.sendAsBinary){U.sendAsBinary(W)}else{if(n.canSendBinary){var S=new Uint8Array(W.length);for(var Q=0;Q<W.length;Q++){S[Q]=(W.charCodeAt(Q)&255)}U.send(S.buffer)}}return}}E=j.buildUrl(r.settings.url,j.extend(L,r.settings.multipart_params));U.open("post",E,true);U.setRequestHeader("Content-Type","application/octet-stream");j.each(r.settings.headers,function(Z,Y){U.setRequestHeader(Y,Z)});U.send(W)}if(t.status==j.DONE||t.status==j.FAILED||r.state==j.STOPPED){return}L={name:t.target_name||t.name};if(u.chunk_size&&t.size>u.chunk_size&&(n.chunks||typeof(z)=="string")){H=u.chunk_size;K=Math.ceil(t.size/H);J=Math.min(H,t.size-(C*H));if(typeof(z)=="string"){I=z.substring(C*H,C*H+J)}else{I=w(z,C*H,C*H+J)}L.chunk=C;L.chunks=K}else{J=t.size;I=z}if(y&&n.cantSendBlobInFormData&&n.chunks&&r.settings.chunk_size){y.onload=function(){D=true;G(y.result)};y.readAsBinaryString(I)}else{G(I)}}A()}x=c[t.id];if(n.jpgresize&&r.settings.resize&&/\.(png|jpg|jpeg)$/i.test(t.name)){d.call(r,t,r.settings.resize,/\.png$/i.test(t.name)?"image/png":"image/jpeg",function(y){if(y.success){t.size=y.data.length;v(y.data)}else{v(x)}})}else{if(!n.chunks&&n.jpgresize){l(x,v)}else{v(x)}}});p.bind("Destroy",function(r){var t,u,s=k.body,v={inputContainer:r.id+"_html5_container",inputFile:r.id+"_html5",browseButton:r.settings.browse_button,dropElm:r.settings.drop_element};for(t in v){u=k.getElementById(v[t]);if(u){j.removeAllEvents(u,r.id)}}j.removeAllEvents(k.body,r.id);if(r.settings.container){s=k.getElementById(r.settings.container)}s.removeChild(k.getElementById(v.inputContainer))});q({success:true})}});function b(){var q=false,o;function r(t,v){var s=q?0:-8*(v-1),w=0,u;for(u=0;u<v;u++){w|=(o.charCodeAt(t+u)<<Math.abs(s+u*8))}return w}function n(u,s,t){var t=arguments.length===3?t:o.length-s-1;o=o.substr(0,s)+u+o.substr(t+s)}function p(t,u,w){var x="",s=q?0:-8*(w-1),v;for(v=0;v<w;v++){x+=String.fromCharCode((u>>Math.abs(s+v*8))&255)}n(x,t,w)}return{II:function(s){if(s===e){return q}else{q=s}},init:function(s){q=false;o=s},SEGMENT:function(s,u,t){switch(arguments.length){case 1:return o.substr(s,o.length-s-1);case 2:return o.substr(s,u);case 3:n(t,s,u);break;default:return o}},BYTE:function(s){return r(s,1)},SHORT:function(s){return r(s,2)},LONG:function(s,t){if(t===e){return r(s,4)}else{p(s,t,4)}},SLONG:function(s){var t=r(s,4);return(t>2147483647?t-4294967296:t)},STRING:function(s,t){var u="";for(t+=s;s<t;s++){u+=String.fromCharCode(r(s,1))}return u}}}function f(s){var u={65505:{app:"EXIF",name:"APP1",signature:"Exif\0"},65506:{app:"ICC",name:"APP2",signature:"ICC_PROFILE\0"},65517:{app:"IPTC",name:"APP13",signature:"Photoshop 3.0\0"}},t=[],r,n,p=e,q=0,o;r=new b();r.init(s);if(r.SHORT(0)!==65496){return}n=2;o=Math.min(1048576,s.length);while(n<=o){p=r.SHORT(n);if(p>=65488&&p<=65495){n+=2;continue}if(p===65498||p===65497){break}q=r.SHORT(n+2)+2;if(u[p]&&r.STRING(n+4,u[p].signature.length)===u[p].signature){t.push({hex:p,app:u[p].app.toUpperCase(),name:u[p].name.toUpperCase(),start:n,length:q,segment:r.SEGMENT(n,q)})}n+=q}r.init(null);return{headers:t,restore:function(y){r.init(y);var w=new f(y);if(!w.headers){return false}for(var x=w.headers.length;x>0;x--){var z=w.headers[x-1];r.SEGMENT(z.start,z.length,"")}w.purge();n=r.SHORT(2)==65504?4+r.SHORT(4):2;for(var x=0,v=t.length;x<v;x++){r.SEGMENT(n,0,t[x].segment);n+=t[x].length}return r.SEGMENT()},get:function(x){var y=[];for(var w=0,v=t.length;w<v;w++){if(t[w].app===x.toUpperCase()){y.push(t[w].segment)}}return y},set:function(y,x){var z=[];if(typeof(x)==="string"){z.push(x)}else{z=x}for(var w=ii=0,v=t.length;w<v;w++){if(t[w].app===y.toUpperCase()){t[w].segment=z[ii];t[w].length=z[ii].length;ii++}if(ii>=z.length){break}}},purge:function(){t=[];r.init(null)}}}function a(){var q,n,o={},t;q=new b();n={tiff:{274:"Orientation",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}};t={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}};function p(u,C){var w=q.SHORT(u),z,F,G,B,A,v,x,D,E=[],y={};for(z=0;z<w;z++){x=v=u+12*z+2;G=C[q.SHORT(x)];if(G===e){continue}B=q.SHORT(x+=2);A=q.LONG(x+=2);x+=4;E=[];switch(B){case 1:case 7:if(A>4){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.BYTE(x+F)}break;case 2:if(A>4){x=q.LONG(x)+o.tiffHeader}y[G]=q.STRING(x,A-1);continue;case 3:if(A>2){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.SHORT(x+F*2)}break;case 4:if(A>1){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)}break;case 5:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)/q.LONG(x+F*4+4)}break;case 9:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)}break;case 10:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)/q.SLONG(x+F*4+4)}break;default:continue}D=(A==1?E[0]:E);if(t.hasOwnProperty(G)&&typeof D!="object"){y[G]=t[G][D]}else{y[G]=D}}return y}function s(){var v=e,u=o.tiffHeader;q.II(q.SHORT(u)==18761);if(q.SHORT(u+=2)!==42){return false}o.IFD0=o.tiffHeader+q.LONG(u+=2);v=p(o.IFD0,n.tiff);o.exifIFD=("ExifIFDPointer" in v?o.tiffHeader+v.ExifIFDPointer:e);o.gpsIFD=("GPSInfoIFDPointer" in v?o.tiffHeader+v.GPSInfoIFDPointer:e);return true}function r(w,u,z){var B,y,x,A=0;if(typeof(u)==="string"){var v=n[w.toLowerCase()];for(hex in v){if(v[hex]===u){u=hex;break}}}B=o[w.toLowerCase()+"IFD"];y=q.SHORT(B);for(i=0;i<y;i++){x=B+12*i+2;if(q.SHORT(x)==u){A=x+8;break}}if(!A){return false}q.LONG(A,z);return true}return{init:function(u){o={tiffHeader:10};if(u===e||!u.length){return false}q.init(u);if(q.SHORT(0)===65505&&q.STRING(4,5).toUpperCase()==="EXIF\0"){return s()}return false},EXIF:function(){var u;u=p(o.exifIFD,n.exif);if(u.ExifVersion){u.ExifVersion=String.fromCharCode(u.ExifVersion[0],u.ExifVersion[1],u.ExifVersion[2],u.ExifVersion[3])}return u},GPS:function(){var u;u=p(o.gpsIFD,n.gps);if(u.GPSVersionID){u.GPSVersionID=u.GPSVersionID.join(".")}return u},setExif:function(u,v){if(u!=="PixelXDimension"&&u!=="PixelYDimension"){return false}return r("exif",u,v)},getBinary:function(){return q.SEGMENT()}}}})(window,document,plupload);(function(d,a,b,c){function e(f){return a.getElementById(f)}b.runtimes.Html4=b.addRuntime("html4",{getFeatures:function(){var f=(function(){var l=navigator,k=l.userAgent,m=l.vendor,h,g,j;h=/WebKit/.test(k);j=h&&m.indexOf("Apple")!==-1;g=d.opera&&d.opera.buildNumber;return{ie:!h&&!g&&(/MSIE/gi).test(k)&&(/Explorer/gi).test(l.appName),webkit:h,gecko:!h&&/Gecko/.test(k),safari:j,safariwin:j&&navigator.platform.indexOf("Win")!==-1,opera:!!g}}());return{multipart:true,triggerDialog:(f.gecko&&d.FormData||f.webkit)}},init:function(f,g){f.bind("Init",function(p){var j=a.body,n,h="javascript",k,x,q,z=[],r=/MSIE/.test(navigator.userAgent),t=[],m=p.settings.filters,o,l,s,w;no_type_restriction:for(o=0;o<m.length;o++){l=m[o].extensions.split(/,/);for(w=0;w<l.length;w++){if(l[w]==="*"){t=[];break no_type_restriction}s=b.mimeTypes[l[w]];if(s){t.push(s)}}}t=t.join(",");function v(){var C,A,y,B;q=b.guid();z.push(q);C=a.createElement("form");C.setAttribute("id","form_"+q);C.setAttribute("method","post");C.setAttribute("enctype","multipart/form-data");C.setAttribute("encoding","multipart/form-data");C.setAttribute("target",p.id+"_iframe");C.style.position="absolute";A=a.createElement("input");A.setAttribute("id","input_"+q);A.setAttribute("type","file");A.setAttribute("accept",t);A.setAttribute("size",1);B=e(p.settings.browse_button);if(p.features.triggerDialog&&B){b.addEvent(e(p.settings.browse_button),"click",function(D){A.click();D.preventDefault()},p.id)}b.extend(A.style,{width:"100%",height:"100%",opacity:0,fontSize:"999px"});b.extend(C.style,{overflow:"hidden"});y=p.settings.shim_bgcolor;if(y){C.style.background=y}if(r){b.extend(A.style,{filter:"alpha(opacity=0)"})}b.addEvent(A,"change",function(G){var E=G.target,D,F=[],H;if(E.value){e("form_"+q).style.top=-1048575+"px";D=E.value.replace(/\\/g,"/");D=D.substring(D.length,D.lastIndexOf("/")+1);F.push(new b.File(q,D));if(!p.features.triggerDialog){b.removeAllEvents(C,p.id)}else{b.removeEvent(B,"click",p.id)}b.removeEvent(A,"change",p.id);v();if(F.length){f.trigger("FilesAdded",F)}}},p.id);C.appendChild(A);j.appendChild(C);p.refresh()}function u(){var y=a.createElement("div");y.innerHTML='<iframe id="'+p.id+'_iframe" name="'+p.id+'_iframe" src="'+h+':&quot;&quot;" style="display:none"></iframe>';n=y.firstChild;j.appendChild(n);b.addEvent(n,"load",function(D){var E=D.target,C,A;if(!k){return}try{C=E.contentWindow.document||E.contentDocument||d.frames[E.id].document}catch(B){p.trigger("Error",{code:b.SECURITY_ERROR,message:b.translate("Security error."),file:k});return}A=C.documentElement.innerText||C.documentElement.textContent;if(A){k.status=b.DONE;k.loaded=1025;k.percent=100;p.trigger("UploadProgress",k);p.trigger("FileUploaded",k,{response:A})}},p.id)}if(p.settings.container){j=e(p.settings.container);if(b.getStyle(j,"position")==="static"){j.style.position="relative"}}p.bind("UploadFile",function(y,B){var C,A;if(B.status==b.DONE||B.status==b.FAILED||y.state==b.STOPPED){return}C=e("form_"+B.id);A=e("input_"+B.id);A.setAttribute("name",y.settings.file_data_name);C.setAttribute("action",y.settings.url);b.each(b.extend({name:B.target_name||B.name},y.settings.multipart_params),function(F,D){var E=a.createElement("input");b.extend(E,{type:"hidden",name:D,value:F});C.insertBefore(E,C.firstChild)});k=B;e("form_"+q).style.top=-1048575+"px";C.submit();C.parentNode.removeChild(C)});p.bind("FileUploaded",function(y){y.refresh()});p.bind("StateChanged",function(y){if(y.state==b.STARTED){u()}if(y.state==b.STOPPED){d.setTimeout(function(){b.removeEvent(n,"load",y.id);n.parentNode.removeChild(n)},0)}});p.bind("Refresh",function(A){var G,B,C,D,y,H,I,F,E;G=e(A.settings.browse_button);if(G){y=b.getPos(G,e(A.settings.container));H=b.getSize(G);I=e("form_"+q);F=e("input_"+q);b.extend(I.style,{top:y.y+"px",left:y.x+"px",width:H.w+"px",height:H.h+"px"});if(A.features.triggerDialog){if(b.getStyle(G,"position")==="static"){b.extend(G.style,{position:"relative"})}E=parseInt(G.style.zIndex,10);if(isNaN(E)){E=0}b.extend(G.style,{zIndex:E});b.extend(I.style,{zIndex:E-1})}C=A.settings.browse_button_hover;D=A.settings.browse_button_active;B=A.features.triggerDialog?G:I;if(C){b.addEvent(B,"mouseover",function(){b.addClass(G,C)},A.id);b.addEvent(B,"mouseout",function(){b.removeClass(G,C)},A.id)}if(D){b.addEvent(B,"mousedown",function(){b.addClass(G,D)},A.id);b.addEvent(a.body,"mouseup",function(){b.removeClass(G,D)},A.id)}}});f.bind("FilesRemoved",function(y,B){var A,C;for(A=0;A<B.length;A++){C=e("form_"+B[A].id);if(C){C.parentNode.removeChild(C)}}});f.bind("Destroy",function(y){var A,B,C,D={inputContainer:"form_"+q,inputFile:"input_"+q,browseButton:y.settings.browse_button};for(A in D){B=e(D[A]);if(B){b.removeAllEvents(B,y.id)}}b.removeAllEvents(a.body,y.id);b.each(z,function(F,E){C=e("form_"+F);if(C){j.removeChild(C)}})});v()});g({success:true})}})})(window,document,plupload);
1
+ /*1.5b*/
2
  (function(){var f=0,l=[],n={},j={},a={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},m=/[<>&\"\']/g,b,c=window.setTimeout,d={},e;function h(){this.returnValue=false}function k(){this.cancelBubble=true}(function(o){var p=o.split(/,/),q,s,r;for(q=0;q<p.length;q+=2){r=p[q+1].split(/ /);for(s=0;s<r.length;s++){j[r[s]]=p[q]}}})("application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats,docx pptx xlsx,audio/mpeg,mpga mpega mp2 mp3,audio/x-wav,wav,audio/mp4,m4a,image/bmp,bmp,image/gif,gif,image/jpeg,jpeg jpg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/html,htm html xhtml,text/rtf,rtf,video/mpeg,mpeg mpg mpe,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/vnd.rn-realvideo,rv,text/csv,csv,text/plain,asc txt text diff log,application/octet-stream,exe");var g={VERSION:"1.5b",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,IMAGE_FORMAT_ERROR:-700,IMAGE_MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:j,extend:function(o){g.each(arguments,function(p,q){if(q>0){g.each(p,function(s,r){o[r]=s})}});return o},cleanName:function(o){var p,q;q=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(p=0;p<q.length;p+=2){o=o.replace(q[p],q[p+1])}o=o.replace(/\s+/g,"_");o=o.replace(/[^a-z0-9_\-\.]+/gi,"");return o},addRuntime:function(o,p){p.name=o;l[o]=p;l.push(p);return p},guid:function(){var o=new Date().getTime().toString(32),p;for(p=0;p<5;p++){o+=Math.floor(Math.random()*65535).toString(32)}return(g.guidPrefix||"p")+o+(f++).toString(32)},buildUrl:function(p,o){var q="";g.each(o,function(s,r){q+=(q?"&":"")+encodeURIComponent(r)+"="+encodeURIComponent(s)});if(q){p+=(p.indexOf("?")>0?"&":"?")+q}return p},each:function(r,s){var q,p,o;if(r){q=r.length;if(q===b){for(p in r){if(r.hasOwnProperty(p)){if(s(r[p],p)===false){return}}}}else{for(o=0;o<q;o++){if(s(r[o],o)===false){return}}}}},formatSize:function(o){if(o===b||/\D/.test(o)){return g.translate("N/A")}if(o>1073741824){return Math.round(o/1073741824,1)+" GB"}if(o>1048576){return Math.round(o/1048576,1)+" MB"}if(o>1024){return Math.round(o/1024,1)+" KB"}return o+" b"},getPos:function(p,t){var u=0,s=0,w,v=document,q,r;p=p;t=t||v.body;function o(C){var A,B,z=0,D=0;if(C){B=C.getBoundingClientRect();A=v.compatMode==="CSS1Compat"?v.documentElement:v.body;z=B.left+A.scrollLeft;D=B.top+A.scrollTop}return{x:z,y:D}}if(p&&p.getBoundingClientRect&&(navigator.userAgent.indexOf("MSIE")>0&&v.documentMode!==8)){q=o(p);r=o(t);return{x:q.x-r.x,y:q.y-r.y}}w=p;while(w&&w!=t&&w.nodeType){u+=w.offsetLeft||0;s+=w.offsetTop||0;w=w.offsetParent}w=p.parentNode;while(w&&w!=t&&w.nodeType){u-=w.scrollLeft||0;s-=w.scrollTop||0;w=w.parentNode}return{x:u,y:s}},getSize:function(o){return{w:o.offsetWidth||o.clientWidth,h:o.offsetHeight||o.clientHeight}},parseSize:function(o){var p;if(typeof(o)=="string"){o=/^([0-9]+)([mgk]?)$/.exec(o.toLowerCase().replace(/[^0-9mkg]/g,""));p=o[2];o=+o[1];if(p=="g"){o*=1073741824}if(p=="m"){o*=1048576}if(p=="k"){o*=1024}}return o},xmlEncode:function(o){return o?(""+o).replace(m,function(p){return a[p]?"&"+a[p]+";":p}):o},toArray:function(q){var p,o=[];for(p=0;p<q.length;p++){o[p]=q[p]}return o},addI18n:function(o){return g.extend(n,o)},translate:function(o){return n[o]||o},isEmptyObj:function(o){if(o===b){return true}for(var p in o){return false}return true},hasClass:function(q,p){var o;if(q.className==""){return false}o=new RegExp("(^|\\s+)"+p+"(\\s+|$)");return o.test(q.className)},addClass:function(p,o){if(!g.hasClass(p,o)){p.className=p.className==""?o:p.className.replace(/\s+$/,"")+" "+o}},removeClass:function(q,p){var o=new RegExp("(^|\\s+)"+p+"(\\s+|$)");q.className=q.className.replace(o,function(s,r,t){return r===" "&&t===" "?" ":""})},getStyle:function(p,o){if(p.currentStyle){return p.currentStyle[o]}else{if(window.getComputedStyle){return window.getComputedStyle(p,null)[o]}}},addEvent:function(t,o,u){var s,r,q,p;p=arguments[3];o=o.toLowerCase();if(e===b){e="Plupload_"+g.guid()}if(t.addEventListener){s=u;t.addEventListener(o,s,false)}else{if(t.attachEvent){s=function(){var v=window.event;if(!v.target){v.target=v.srcElement}v.preventDefault=h;v.stopPropagation=k;u(v)};t.attachEvent("on"+o,s)}}if(t[e]===b){t[e]=g.guid()}if(!d.hasOwnProperty(t[e])){d[t[e]]={}}r=d[t[e]];if(!r.hasOwnProperty(o)){r[o]=[]}r[o].push({func:s,orig:u,key:p})},removeEvent:function(t,o){var r,u,q;if(typeof(arguments[2])=="function"){u=arguments[2]}else{q=arguments[2]}o=o.toLowerCase();if(t[e]&&d[t[e]]&&d[t[e]][o]){r=d[t[e]][o]}else{return}for(var p=r.length-1;p>=0;p--){if(r[p].key===q||r[p].orig===u){if(t.detachEvent){t.detachEvent("on"+o,r[p].func)}else{if(t.removeEventListener){t.removeEventListener(o,r[p].func,false)}}r[p].orig=null;r[p].func=null;r.splice(p,1);if(u!==b){break}}}if(!r.length){delete d[t[e]][o]}if(g.isEmptyObj(d[t[e]])){delete d[t[e]];try{delete t[e]}catch(s){t[e]=b}}},removeAllEvents:function(p){var o=arguments[1];if(p[e]===b||!p[e]){return}g.each(d[p[e]],function(r,q){g.removeEvent(p,q,o)})}};g.Uploader=function(r){var p={},u,t=[],q;u=new g.QueueProgress();r=g.extend({chunk_size:0,multipart:true,multi_selection:true,file_data_name:"file",filters:[]},r);function s(){var w,x=0,v;if(this.state==g.STARTED){for(v=0;v<t.length;v++){if(!w&&t[v].status==g.QUEUED){w=t[v];w.status=g.UPLOADING;if(this.trigger("BeforeUpload",w)){this.trigger("UploadFile",w)}}else{x++}}if(x==t.length){this.trigger("UploadComplete",t);this.stop()}}}function o(){var w,v;u.reset();for(w=0;w<t.length;w++){v=t[w];if(v.size!==b){u.size+=v.size;u.loaded+=v.loaded}else{u.size=b}if(v.status==g.DONE){u.uploaded++}else{if(v.status==g.FAILED){u.failed++}else{u.queued++}}}if(u.size===b){u.percent=t.length>0?Math.ceil(u.uploaded/t.length*100):0}else{u.bytesPerSec=Math.ceil(u.loaded/((+new Date()-q||1)/1000));u.percent=u.size>0?Math.ceil(u.loaded/u.size*100):0}}g.extend(this,{state:g.STOPPED,runtime:"",features:{},files:t,settings:r,total:u,id:g.guid(),init:function(){var A=this,B,x,w,z=0,y;if(typeof(r.preinit)=="function"){r.preinit(A)}else{g.each(r.preinit,function(D,C){A.bind(C,D)})}r.page_url=r.page_url||document.location.pathname.replace(/\/[^\/]+$/g,"/");if(!/^(\w+:\/\/|\/)/.test(r.url)){r.url=r.page_url+r.url}r.chunk_size=g.parseSize(r.chunk_size);r.max_file_size=g.parseSize(r.max_file_size);A.bind("FilesAdded",function(C,F){var E,D,H=0,I,G=r.filters;if(G&&G.length){I=[];g.each(G,function(J){g.each(J.extensions.split(/,/),function(K){if(/^\s*\*\s*$/.test(K)){I.push("\\.*")}else{I.push("\\."+K.replace(new RegExp("["+("/^$.*+?|()[]{}\\".replace(/./g,"\\$&"))+"]","g"),"\\$&"))}})});I=new RegExp(I.join("|")+"$","i")}for(E=0;E<F.length;E++){D=F[E];D.loaded=0;D.percent=0;D.status=g.QUEUED;if(I&&!I.test(D.name)){C.trigger("Error",{code:g.FILE_EXTENSION_ERROR,message:g.translate("File extension error."),file:D});continue}if(D.size!==b&&D.size>r.max_file_size){C.trigger("Error",{code:g.FILE_SIZE_ERROR,message:g.translate("File size error."),file:D});continue}t.push(D);H++}if(H){c(function(){A.trigger("QueueChanged");A.refresh()},1)}else{return false}});if(r.unique_names){A.bind("UploadFile",function(C,D){var F=D.name.match(/\.([^.]+)$/),E="tmp";if(F){E=F[1]}D.target_name=D.id+"."+E})}A.bind("UploadProgress",function(C,D){D.percent=D.size>0?Math.ceil(D.loaded/D.size*100):100;o()});A.bind("StateChanged",function(C){if(C.state==g.STARTED){q=(+new Date())}else{if(C.state==g.STOPPED){for(B=C.files.length-1;B>=0;B--){if(C.files[B].status==g.UPLOADING){C.files[B].status=g.QUEUED;o()}}}}});A.bind("QueueChanged",o);A.bind("Error",function(C,D){if(D.file){D.file.status=g.FAILED;o();if(C.state==g.STARTED){c(function(){s.call(A)},1)}}});A.bind("FileUploaded",function(C,D){D.status=g.DONE;D.loaded=D.size;C.trigger("UploadProgress",D);c(function(){s.call(A)},1)});if(r.runtimes){x=[];y=r.runtimes.split(/\s?,\s?/);for(B=0;B<y.length;B++){if(l[y[B]]){x.push(l[y[B]])}}}else{x=l}function v(){var F=x[z++],E,C,D;if(F){E=F.getFeatures();C=A.settings.required_features;if(C){C=C.split(",");for(D=0;D<C.length;D++){if(!E[C[D]]){v();return}}}F.init(A,function(G){if(G&&G.success){A.features=E;A.runtime=F.name;A.trigger("Init",{runtime:F.name});A.trigger("PostInit");A.refresh()}else{v()}})}else{A.trigger("Error",{code:g.INIT_ERROR,message:g.translate("Init error.")})}}v();if(typeof(r.init)=="function"){r.init(A)}else{g.each(r.init,function(D,C){A.bind(C,D)})}},refresh:function(){this.trigger("Refresh")},start:function(){if(this.state!=g.STARTED){this.state=g.STARTED;this.trigger("StateChanged");s.call(this)}},stop:function(){if(this.state!=g.STOPPED){this.state=g.STOPPED;this.trigger("StateChanged")}},getFile:function(w){var v;for(v=t.length-1;v>=0;v--){if(t[v].id===w){return t[v]}}},removeFile:function(w){var v;for(v=t.length-1;v>=0;v--){if(t[v].id===w.id){return this.splice(v,1)[0]}}},splice:function(x,v){var w;w=t.splice(x===b?0:x,v===b?t.length:v);this.trigger("FilesRemoved",w);this.trigger("QueueChanged");return w},trigger:function(w){var y=p[w.toLowerCase()],x,v;if(y){v=Array.prototype.slice.call(arguments);v[0]=this;for(x=0;x<y.length;x++){if(y[x].func.apply(y[x].scope,v)===false){return false}}}return true},hasEventListener:function(v){return !!p[v.toLowerCase()]},bind:function(v,x,w){var y;v=v.toLowerCase();y=p[v]||[];y.push({func:x,scope:w||this});p[v]=y},unbind:function(v){v=v.toLowerCase();var y=p[v],w,x=arguments[1];if(y){if(x!==b){for(w=y.length-1;w>=0;w--){if(y[w].func===x){y.splice(w,1);break}}}else{y=[]}if(!y.length){delete p[v]}}},unbindAll:function(){var v=this;g.each(p,function(x,w){v.unbind(w)})},destroy:function(){this.trigger("Destroy");this.unbindAll()}})};g.File=function(r,p,q){var o=this;o.id=r;o.name=p;o.size=q;o.loaded=0;o.percent=0;o.status=0};g.Runtime=function(){this.getFeatures=function(){};this.init=function(o,p){}};g.QueueProgress=function(){var o=this;o.size=0;o.loaded=0;o.uploaded=0;o.failed=0;o.queued=0;o.percent=0;o.bytesPerSec=0;o.reset=function(){o.size=o.loaded=o.uploaded=o.failed=o.queued=o.percent=o.bytesPerSec=0}};g.runtimes={};window.plupload=g})();(function(){if(window.google&&google.gears){return}var a=null;if(typeof GearsFactory!="undefined"){a=new GearsFactory()}else{try{a=new ActiveXObject("Gears.Factory");if(a.getBuildInfo().indexOf("ie_mobile")!=-1){a.privateSetGlobalObject(this)}}catch(b){if((typeof navigator.mimeTypes!="undefined")&&navigator.mimeTypes["application/x-googlegears"]){a=document.createElement("object");a.style.display="none";a.width=0;a.height=0;a.type="application/x-googlegears";document.documentElement.appendChild(a)}}}if(!a){return}if(!window.google){window.google={}}if(!google.gears){google.gears={factory:a}}})();(function(e,b,c,d){var f={};function a(h,k,m){var g,j,l,o;j=google.gears.factory.create("beta.canvas");try{j.decode(h);if(!k.width){k.width=j.width}if(!k.height){k.height=j.height}o=Math.min(width/j.width,height/j.height);if(o<1||(o===1&&m==="image/jpeg")){j.resize(Math.round(j.width*o),Math.round(j.height*o));if(k.quality){return j.encode(m,{quality:k.quality/100})}return j.encode(m)}}catch(n){}return h}c.runtimes.Gears=c.addRuntime("gears",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(j,l){var k;if(!e.google||!google.gears){return l({success:false})}try{k=google.gears.factory.create("beta.desktop")}catch(h){return l({success:false})}function g(o){var n,m,p=[],q;for(m=0;m<o.length;m++){n=o[m];q=c.guid();f[q]=n.blob;p.push(new c.File(q,n.name,n.blob.length))}j.trigger("FilesAdded",p)}j.bind("PostInit",function(){var n=j.settings,m=b.getElementById(n.drop_element);if(m){c.addEvent(m,"dragover",function(o){k.setDropEffect(o,"copy");o.preventDefault()},j.id);c.addEvent(m,"drop",function(p){var o=k.getDragData(p,"application/x-gears-files");if(o){g(o.files)}p.preventDefault()},j.id);m=0}c.addEvent(b.getElementById(n.browse_button),"click",function(s){var r=[],p,o,q;s.preventDefault();no_type_restriction:for(p=0;p<n.filters.length;p++){q=n.filters[p].extensions.split(",");for(o=0;o<q.length;o++){if(q[o]==="*"){r=[];break no_type_restriction}r.push("."+q[o])}}k.openFiles(g,{singleFile:!n.multi_selection,filter:r})},j.id)});j.bind("UploadFile",function(s,p){var u=0,t,q,r=0,o=s.settings.resize,m;if(o&&/\.(png|jpg|jpeg)$/i.test(p.name)){f[p.id]=a(f[p.id],o,/\.png$/i.test(p.name)?"image/png":"image/jpeg")}p.size=f[p.id].length;q=s.settings.chunk_size;m=q>0;t=Math.ceil(p.size/q);if(!m){q=p.size;t=1}function n(){var z,B,w=s.settings.multipart,v=0,A={name:p.target_name||p.name},x=s.settings.url;function y(D){var C,I="----pluploadboundary"+c.guid(),F="--",H="\r\n",E,G;if(w){z.setRequestHeader("Content-Type","multipart/form-data; boundary="+I);C=google.gears.factory.create("beta.blobbuilder");c.each(c.extend(A,s.settings.multipart_params),function(K,J){C.append(F+I+H+'Content-Disposition: form-data; name="'+J+'"'+H+H);C.append(K+H)});G=c.mimeTypes[p.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";C.append(F+I+H+'Content-Disposition: form-data; name="'+s.settings.file_data_name+'"; filename="'+p.name+'"'+H+"Content-Type: "+G+H+H);C.append(D);C.append(H+F+I+F+H);E=C.getAsBlob();v=E.length-D.length;D=E}z.send(D)}if(p.status==c.DONE||p.status==c.FAILED||s.state==c.STOPPED){return}if(m){A.chunk=u;A.chunks=t}B=Math.min(q,p.size-(u*q));if(!w){x=c.buildUrl(s.settings.url,A)}z=google.gears.factory.create("beta.httprequest");z.open("POST",x);if(!w){z.setRequestHeader("Content-Disposition",'attachment; filename="'+p.name+'"');z.setRequestHeader("Content-Type","application/octet-stream")}c.each(s.settings.headers,function(D,C){z.setRequestHeader(C,D)});z.upload.onprogress=function(C){p.loaded=r+C.loaded-v;s.trigger("UploadProgress",p)};z.onreadystatechange=function(){var C;if(z.readyState==4){if(z.status==200){C={chunk:u,chunks:t,response:z.responseText,status:z.status};s.trigger("ChunkUploaded",p,C);if(C.cancelled){p.status=c.FAILED;return}r+=B;if(++u>=t){p.status=c.DONE;s.trigger("FileUploaded",p,{response:z.responseText,status:z.status})}else{n()}}else{s.trigger("Error",{code:c.HTTP_ERROR,message:c.translate("HTTP Error."),file:p,chunk:u,chunks:t,status:z.status})}}};if(u<t){y(f[p.id].slice(u*q,B))}}n()});j.bind("Destroy",function(m){var n,o,p={browseButton:m.settings.browse_button,dropElm:m.settings.drop_element};for(n in p){o=b.getElementById(p[n]);if(o){c.removeAllEvents(o,m.id)}}});l({success:true})}})})(window,document,plupload);(function(g,b,d,e){var a={},h={};function c(o){var n,m=typeof o,j,l,k;if(o===e||o===null){return"null"}if(m==="string"){n="\bb\tt\nn\ff\rr\"\"''\\\\";return'"'+o.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g,function(r,q){var p=n.indexOf(q);if(p+1){return"\\"+n.charAt(p+1)}r=q.charCodeAt().toString(16);return"\\u"+"0000".substring(r.length)+r})+'"'}if(m=="object"){j=o.length!==e;n="";if(j){for(l=0;l<o.length;l++){if(n){n+=","}n+=c(o[l])}n="["+n+"]"}else{for(k in o){if(o.hasOwnProperty(k)){if(n){n+=","}n+=c(k)+":"+c(o[k])}}n="{"+n+"}"}return n}return""+o}function f(s){var v=false,j=null,o=null,k,l,m,u,n,q=0;try{try{o=new ActiveXObject("AgControl.AgControl");if(o.IsVersionSupported(s)){v=true}o=null}catch(r){var p=navigator.plugins["Silverlight Plug-In"];if(p){k=p.description;if(k==="1.0.30226.2"){k="2.0.30226.2"}l=k.split(".");while(l.length>3){l.pop()}while(l.length<4){l.push(0)}m=s.split(".");while(m.length>4){m.pop()}do{u=parseInt(m[q],10);n=parseInt(l[q],10);q++}while(q<m.length&&u===n);if(u<=n&&!isNaN(u)){v=true}}}}catch(t){v=false}return v}d.silverlight={trigger:function(n,k){var m=a[n],l,j;if(m){j=d.toArray(arguments).slice(1);j[0]="Silverlight:"+k;setTimeout(function(){m.trigger.apply(m,j)},0)}}};d.runtimes.Silverlight=d.addRuntime("silverlight",{getFeatures:function(){return{jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(p,q){var o,m="",n=p.settings.filters,l,k=b.body;if(!f("2.0.31005.0")||(g.opera&&g.opera.buildNumber)){q({success:false});return}h[p.id]=false;a[p.id]=p;o=b.createElement("div");o.id=p.id+"_silverlight_container";d.extend(o.style,{position:"absolute",top:"0px",background:p.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100px",height:"100px",overflow:"hidden",opacity:p.settings.shim_bgcolor||b.documentMode>8?"":0.01});o.className="plupload silverlight";if(p.settings.container){k=b.getElementById(p.settings.container);if(d.getStyle(k,"position")==="static"){k.style.position="relative"}}k.appendChild(o);for(l=0;l<n.length;l++){m+=(m!=""?"|":"")+n[l].title+" | *."+n[l].extensions.replace(/,/g,";*.")}o.innerHTML='<object id="'+p.id+'_silverlight" data="data:application/x-silverlight," type="application/x-silverlight-2" style="outline:none;" width="1024" height="1024"><param name="source" value="'+p.settings.silverlight_xap_url+'"/><param name="background" value="Transparent"/><param name="windowless" value="true"/><param name="enablehtmlaccess" value="true"/><param name="initParams" value="id='+p.id+",filter="+m+",multiselect="+p.settings.multi_selection+'"/></object>';function j(){return b.getElementById(p.id+"_silverlight").content.Upload}p.bind("Silverlight:Init",function(){var r,s={};if(h[p.id]){return}h[p.id]=true;p.bind("Silverlight:StartSelectFiles",function(t){r=[]});p.bind("Silverlight:SelectFile",function(t,w,u,v){var x;x=d.guid();s[x]=w;s[w]=x;r.push(new d.File(x,u,v))});p.bind("Silverlight:SelectSuccessful",function(){if(r.length){p.trigger("FilesAdded",r)}});p.bind("Silverlight:UploadChunkError",function(t,w,u,x,v){p.trigger("Error",{code:d.IO_ERROR,message:"IO Error.",details:v,file:t.getFile(s[w])})});p.bind("Silverlight:UploadFileProgress",function(t,x,u,w){var v=t.getFile(s[x]);if(v.status!=d.FAILED){v.size=w;v.loaded=u;t.trigger("UploadProgress",v)}});p.bind("Refresh",function(t){var u,v,w;u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_silverlight_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});p.bind("Silverlight:UploadChunkSuccessful",function(t,w,u,z,y){var x,v=t.getFile(s[w]);x={chunk:u,chunks:z,response:y};t.trigger("ChunkUploaded",v,x);if(v.status!=d.FAILED){j().UploadNextChunk()}if(u==z-1){v.status=d.DONE;t.trigger("FileUploaded",v,{response:y})}});p.bind("Silverlight:UploadSuccessful",function(t,w,u){var v=t.getFile(s[w]);v.status=d.DONE;t.trigger("FileUploaded",v,{response:u})});p.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){j().RemoveFile(s[v[u].id])}});p.bind("UploadFile",function(t,v){var w=t.settings,u=w.resize||{};j().UploadFile(s[v.id],t.settings.url,c({name:v.target_name||v.name,mime:d.mimeTypes[v.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:w.chunk_size,image_width:u.width,image_height:u.height,image_quality:u.quality||90,multipart:!!w.multipart,multipart_params:w.multipart_params||{},file_data_name:w.file_data_name,headers:w.headers}))});p.bind("Silverlight:MouseEnter",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});p.bind("Silverlight:MouseLeave",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});p.bind("Silverlight:MouseLeftButtonDown",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)})}});p.bind("Sliverlight:StartSelectFiles",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});p.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete h[t.id];delete a[t.id];u=b.getElementById(t.id+"_silverlight_container");if(u){k.removeChild(u)}});q({success:true})})}})})(window,document,plupload);(function(f,b,d,e){var a={},g={};function c(){var h;try{h=navigator.plugins["Shockwave Flash"];h=h.description}catch(k){try{h=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(j){h="0.0"}}h=h.match(/\d+/g);return parseFloat(h[0]+"."+h[1])}d.flash={trigger:function(k,h,j){setTimeout(function(){var n=a[k],m,l;if(n){n.trigger("Flash:"+h,j)}},0)}};d.runtimes.Flash=d.addRuntime("flash",{getFeatures:function(){return{jpgresize:true,pngresize:true,maxWidth:8091,maxHeight:8091,chunks:true,progress:true,multipart:true}},init:function(k,p){var o,j,l,q=0,h=b.body;if(c()<10){p({success:false});return}g[k.id]=false;a[k.id]=k;o=b.getElementById(k.settings.browse_button);j=b.createElement("div");j.id=k.id+"_flash_container";d.extend(j.style,{position:"absolute",top:"0px",background:k.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100%",height:"100%"});j.className="plupload flash";if(k.settings.container){h=b.getElementById(k.settings.container);if(d.getStyle(h,"position")==="static"){h.style.position="relative"}}h.appendChild(j);l="id="+escape(k.id);j.innerHTML='<object id="'+k.id+'_flash" width="100%" height="100%" style="outline:0" type="application/x-shockwave-flash" data="'+k.settings.flash_swf_url+'"><param name="movie" value="'+k.settings.flash_swf_url+'" /><param name="flashvars" value="'+l+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>';function n(){return b.getElementById(k.id+"_flash")}function m(){if(q++>5000){p({success:false});return}if(!g[k.id]){setTimeout(m,1)}}m();o=j=null;k.bind("Flash:Init",function(){var s={},r;n().setFileFilters(k.settings.filters,k.settings.multi_selection);if(g[k.id]){return}g[k.id]=true;k.bind("UploadFile",function(t,v){var w=t.settings,u=k.settings.resize||{};n().uploadFile(s[v.id],w.url,{name:v.target_name||v.name,mime:d.mimeTypes[v.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:w.chunk_size,width:u.width,height:u.height,quality:u.quality,multipart:w.multipart,multipart_params:w.multipart_params||{},file_data_name:w.file_data_name,format:/\.(jpg|jpeg)$/i.test(v.name)?"jpg":"png",headers:w.headers,urlstream_upload:w.urlstream_upload})});k.bind("Flash:UploadProcess",function(u,t){var v=u.getFile(s[t.id]);if(v.status!=d.FAILED){v.loaded=t.loaded;v.size=t.size;u.trigger("UploadProgress",v)}});k.bind("Flash:UploadChunkComplete",function(t,v){var w,u=t.getFile(s[v.id]);w={chunk:v.chunk,chunks:v.chunks,response:v.text};t.trigger("ChunkUploaded",u,w);if(u.status!=d.FAILED){n().uploadNextChunk()}if(v.chunk==v.chunks-1){u.status=d.DONE;t.trigger("FileUploaded",u,{response:v.text})}});k.bind("Flash:SelectFiles",function(t,w){var v,u,x=[],y;for(u=0;u<w.length;u++){v=w[u];y=d.guid();s[y]=v.id;s[v.id]=y;x.push(new d.File(y,v.name,v.size))}if(x.length){k.trigger("FilesAdded",x)}});k.bind("Flash:SecurityError",function(t,u){k.trigger("Error",{code:d.SECURITY_ERROR,message:d.translate("Security error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:GenericError",function(t,u){k.trigger("Error",{code:d.GENERIC_ERROR,message:d.translate("Generic error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:IOError",function(t,u){k.trigger("Error",{code:d.IO_ERROR,message:d.translate("IO error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:ImageError",function(t,u){k.trigger("Error",{code:parseInt(u.code,10),message:d.translate("Image error."),file:k.getFile(s[u.id])})});k.bind("Flash:StageEvent:rollOver",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});k.bind("Flash:StageEvent:rollOut",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});k.bind("Flash:StageEvent:mouseDown",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)},t.id)}});k.bind("Flash:StageEvent:mouseUp",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});k.bind("Flash:ExifData",function(t,u){k.trigger("ExifData",k.getFile(s[u.id]),u.data)});k.bind("Flash:GpsData",function(t,u){k.trigger("GpsData",k.getFile(s[u.id]),u.data)});k.bind("QueueChanged",function(t){k.refresh()});k.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){n().removeFile(s[v[u].id])}});k.bind("StateChanged",function(t){k.refresh()});k.bind("Refresh",function(t){var u,v,w;n().setFileFilters(k.settings.filters,k.settings.multi_selection);u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_flash_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});k.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete g[t.id];delete a[t.id];u=b.getElementById(t.id+"_flash_container");if(u){h.removeChild(u)}});p({success:true})})}})})(window,document,plupload);(function(a){a.runtimes.BrowserPlus=a.addRuntime("browserplus",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(g,j){var e=window.BrowserPlus,h={},d=g.settings,c=d.resize;function f(o){var n,m,k=[],l,p;for(m=0;m<o.length;m++){l=o[m];p=a.guid();h[p]=l;k.push(new a.File(p,l.name,l.size))}if(m){g.trigger("FilesAdded",k)}}function b(){g.bind("PostInit",function(){var n,l=d.drop_element,p=g.id+"_droptarget",k=document.getElementById(l),m;function q(s,r){e.DragAndDrop.AddDropTarget({id:s},function(t){e.DragAndDrop.AttachCallbacks({id:s,hover:function(u){if(!u&&r){r()}},drop:function(u){if(r){r()}f(u)}},function(){})})}function o(){document.getElementById(p).style.top="-1000px"}if(k){if(document.attachEvent&&(/MSIE/gi).test(navigator.userAgent)){n=document.createElement("div");n.setAttribute("id",p);a.extend(n.style,{position:"absolute",top:"-1000px",background:"red",filter:"alpha(opacity=0)",opacity:0});document.body.appendChild(n);a.addEvent(k,"dragenter",function(s){var r,t;r=document.getElementById(l);t=a.getPos(r);a.extend(document.getElementById(p).style,{top:t.y+"px",left:t.x+"px",width:r.offsetWidth+"px",height:r.offsetHeight+"px"})});q(p,o)}else{q(l)}}a.addEvent(document.getElementById(d.browse_button),"click",function(w){var u=[],s,r,v=d.filters,t;w.preventDefault();no_type_restriction:for(s=0;s<v.length;s++){t=v[s].extensions.split(",");for(r=0;r<t.length;r++){if(t[r]==="*"){u=[];break no_type_restriction}u.push(a.mimeTypes[t[r]])}}e.FileBrowse.OpenBrowseDialog({mimeTypes:u},function(x){if(x.success){f(x.value)}})});k=n=null});g.bind("UploadFile",function(n,k){var m=h[k.id],s={},l=n.settings.chunk_size,o,p=[];function r(t,v){var u;if(k.status==a.FAILED){return}s.name=k.target_name||k.name;if(l){s.chunk=""+t;s.chunks=""+v}u=p.shift();e.Uploader.upload({url:n.settings.url,files:{file:u},cookies:document.cookies,postvars:a.extend(s,n.settings.multipart_params),progressCallback:function(y){var x,w=0;o[t]=parseInt(y.filePercent*u.size/100,10);for(x=0;x<o.length;x++){w+=o[x]}k.loaded=w;n.trigger("UploadProgress",k)}},function(x){var w,y;if(x.success){w=x.value.statusCode;if(l){n.trigger("ChunkUploaded",k,{chunk:t,chunks:v,response:x.value.body,status:w})}if(p.length>0){r(++t,v)}else{k.status=a.DONE;n.trigger("FileUploaded",k,{response:x.value.body,status:w});if(w>=400){n.trigger("Error",{code:a.HTTP_ERROR,message:a.translate("HTTP Error."),file:k,status:w})}}}else{n.trigger("Error",{code:a.GENERIC_ERROR,message:a.translate("Generic Error."),file:k,details:x.error})}})}function q(t){k.size=t.size;if(l){e.FileAccess.chunk({file:t,chunkSize:l},function(w){if(w.success){var x=w.value,u=x.length;o=Array(u);for(var v=0;v<u;v++){o[v]=0;p.push(x[v])}r(0,u)}})}else{o=Array(1);p.push(t);r(0,1)}}if(c&&/\.(png|jpg|jpeg)$/i.test(k.name)){BrowserPlus.ImageAlter.transform({file:m,quality:c.quality||90,actions:[{scale:{maxwidth:c.width,maxheight:c.height}}]},function(t){if(t.success){q(t.value.file)}})}else{q(m)}});j({success:true})}if(e){e.init(function(l){var k=[{service:"Uploader",version:"3"},{service:"DragAndDrop",version:"1"},{service:"FileBrowse",version:"1"},{service:"FileAccess",version:"2"}];if(c){k.push({service:"ImageAlter",version:"4"})}if(l.success){e.require({services:k},function(m){if(m.success){b()}else{j()}})}else{j()}})}else{j()}}})})(plupload);(function(h,k,j,e){var c={},g;function m(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsDataURL(o);n.onload=function(){p(n.result)}}else{return p(o.getAsDataURL())}}function l(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsBinaryString(o);n.onload=function(){p(n.result)}}else{return p(o.getAsBinary())}}function d(r,p,n,v){var q,o,u,s,t=this;m(c[r.id],function(w){q=k.createElement("canvas");q.style.display="none";k.body.appendChild(q);o=q.getContext("2d");u=new Image();u.onerror=u.onabort=function(){v({success:false})};u.onload=function(){var B,x,z,y,A;if(!p.width){p.width=u.width}if(!p.height){p.height=u.height}s=Math.min(p.width/u.width,p.height/u.height);if(s<1||(s===1&&n==="image/jpeg")){B=Math.round(u.width*s);x=Math.round(u.height*s);q.width=B;q.height=x;o.drawImage(u,0,0,B,x);if(n==="image/jpeg"){y=new f(atob(w.substring(w.indexOf("base64,")+7)));if(y.headers&&y.headers.length){A=new a();if(A.init(y.get("exif")[0])){A.setExif("PixelXDimension",B);A.setExif("PixelYDimension",x);y.set("exif",A.getBinary());if(t.hasEventListener("ExifData")){t.trigger("ExifData",r,A.EXIF())}if(t.hasEventListener("GpsData")){t.trigger("GpsData",r,A.GPS())}}}if(p.quality){try{w=q.toDataURL(n,p.quality/100)}catch(C){w=q.toDataURL(n)}}}else{w=q.toDataURL(n)}w=w.substring(w.indexOf("base64,")+7);w=atob(w);if(y&&y.headers&&y.headers.length){w=y.restore(w);y.purge()}q.parentNode.removeChild(q);v({success:true,data:w})}else{v({success:false})}};u.src=w})}j.runtimes.Html5=j.addRuntime("html5",{getFeatures:function(){var t,o,s,r,q,n,p;p=(function(){var y=navigator,x=y.userAgent,z=y.vendor,v,u,w;v=/WebKit/.test(x);w=v&&z.indexOf("Apple")!==-1;u=h.opera&&h.opera.buildNumber;return{ie:!v&&!u&&(/MSIE/gi).test(x)&&(/Explorer/gi).test(y.appName),webkit:v,gecko:!v&&/Gecko/.test(x),safari:w,safariwin:w&&navigator.platform.indexOf("Win")!==-1,opera:!!u}}());o=s=q=n=false;if(h.XMLHttpRequest){t=new XMLHttpRequest();s=!!t.upload;o=!!(t.sendAsBinary||t.upload)}if(o){r=!!(t.sendAsBinary||(h.Uint8Array&&h.ArrayBuffer));q=!!(File&&(File.prototype.getAsDataURL||h.FileReader)&&r);n=!!(File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice))}g=p.safariwin;return{html5:o,dragdrop:(function(){var u=k.createElement("div");return("draggable" in u)||("ondragstart" in u&&"ondrop" in u)}()),jpgresize:q,pngresize:q,multipart:q||!!h.FileReader||!!h.FormData,canSendBinary:r,cantSendBlobInFormData:!!(p.gecko&&h.FormData&&h.FileReader&&!FileReader.prototype.readAsArrayBuffer),progress:s,chunks:n,triggerDialog:(p.gecko&&h.FormData||p.webkit)}},init:function(p,q){var n;function o(v){var t,s,u=[],w,r={};for(s=0;s<v.length;s++){t=v[s];if(r[t.name]){continue}r[t.name]=true;w=j.guid();c[w]=t;u.push(new j.File(w,t.fileName||t.name,t.fileSize||t.size))}if(u.length){p.trigger("FilesAdded",u)}}n=this.getFeatures();if(!n.html5){q({success:false});return}p.bind("Init",function(v){var F,E,B=[],u,C,s=v.settings.filters,t,A,r=k.body,D;F=k.createElement("div");F.id=v.id+"_html5_container";j.extend(F.style,{position:"absolute",background:p.settings.shim_bgcolor||"transparent",width:"100px",height:"100px",overflow:"hidden",zIndex:99999,opacity:p.settings.shim_bgcolor?"":0});F.className="plupload html5";if(p.settings.container){r=k.getElementById(p.settings.container);if(j.getStyle(r,"position")==="static"){r.style.position="relative"}}r.appendChild(F);no_type_restriction:for(u=0;u<s.length;u++){t=s[u].extensions.split(/,/);for(C=0;C<t.length;C++){if(t[C]==="*"){B=[];break no_type_restriction}A=j.mimeTypes[t[C]];if(A){B.push(A)}}}F.innerHTML='<input id="'+p.id+'_html5" style="font-size:999px" type="file" accept="'+B.join(",")+'" '+(p.settings.multi_selection?'multiple="multiple"':"")+" />";F.scrollTop=100;D=k.getElementById(p.id+"_html5");if(v.features.triggerDialog){j.extend(D.style,{position:"absolute",width:"100%",height:"100%"})}else{j.extend(D.style,{cssFloat:"right",styleFloat:"right"})}D.onchange=function(){o(this.files);this.value=""};E=k.getElementById(v.settings.browse_button);if(E){var x=v.settings.browse_button_hover,z=v.settings.browse_button_active,w=v.features.triggerDialog?E:F;if(x){j.addEvent(w,"mouseover",function(){j.addClass(E,x)},v.id);j.addEvent(w,"mouseout",function(){j.removeClass(E,x)},v.id)}if(z){j.addEvent(w,"mousedown",function(){j.addClass(E,z)},v.id);j.addEvent(k.body,"mouseup",function(){j.removeClass(E,z)},v.id)}if(v.features.triggerDialog){j.addEvent(E,"click",function(y){k.getElementById(v.id+"_html5").click();y.preventDefault()},v.id)}}});p.bind("PostInit",function(){var r=k.getElementById(p.settings.drop_element);if(r){if(g){j.addEvent(r,"dragenter",function(v){var u,s,t;u=k.getElementById(p.id+"_drop");if(!u){u=k.createElement("input");u.setAttribute("type","file");u.setAttribute("id",p.id+"_drop");u.setAttribute("multiple","multiple");j.addEvent(u,"change",function(){o(this.files);j.removeEvent(u,"change",p.id);u.parentNode.removeChild(u)},p.id);r.appendChild(u)}s=j.getPos(r,k.getElementById(p.settings.container));t=j.getSize(r);if(j.getStyle(r,"position")==="static"){j.extend(r.style,{position:"relative"})}j.extend(u.style,{position:"absolute",display:"block",top:0,left:0,width:t.w+"px",height:t.h+"px",opacity:0})},p.id);return}j.addEvent(r,"dragover",function(s){s.preventDefault()},p.id);j.addEvent(r,"drop",function(t){var s=t.dataTransfer;if(s&&s.files){o(s.files)}t.preventDefault()},p.id)}});p.bind("Refresh",function(r){var s,t,u,w,v;s=k.getElementById(p.settings.browse_button);if(s){t=j.getPos(s,k.getElementById(r.settings.container));u=j.getSize(s);w=k.getElementById(p.id+"_html5_container");j.extend(w.style,{top:t.y+"px",left:t.x+"px",width:u.w+"px",height:u.h+"px"});if(p.features.triggerDialog){if(j.getStyle(s,"position")==="static"){j.extend(s.style,{position:"relative"})}v=parseInt(j.getStyle(s,"z-index"),10);if(isNaN(v)){v=0}j.extend(s.style,{zIndex:v});j.extend(w.style,{zIndex:v-1})}}});p.bind("UploadFile",function(r,t){var u=r.settings,x,s;function w(z,C,y){var A;if(File.prototype.slice){try{z.slice();return z.slice(C,y)}catch(B){return z.slice(C,y-C)}}else{if(A=File.prototype.webkitSlice||File.prototype.mozSlice){return A.call(z,C,y)}else{return null}}}function v(z){var C=0,B=0,y=("FileReader" in h)?new FileReader:null,D=typeof(z)==="string";function A(){var I,M,K,L,H,J,F,E=r.settings.url;function G(W){var T=0,U=new XMLHttpRequest,X=U.upload,N="----pluploadboundary"+j.guid(),O,P="--",V="\r\n",R="";if(X){X.onprogress=function(Y){t.loaded=Math.min(t.size,B+Y.loaded-T);r.trigger("UploadProgress",t)}}U.onreadystatechange=function(){var Y,aa;if(U.readyState==4){try{Y=U.status}catch(Z){Y=0}if(Y>=400){r.trigger("Error",{code:j.HTTP_ERROR,message:j.translate("HTTP Error."),file:t,status:Y})}else{if(K){aa={chunk:C,chunks:K,response:U.responseText,status:Y};r.trigger("ChunkUploaded",t,aa);B+=J;if(aa.cancelled){t.status=j.FAILED;return}t.loaded=Math.min(t.size,(C+1)*H)}else{t.loaded=t.size}r.trigger("UploadProgress",t);W=I=O=R=null;if(!K||++C>=K){t.status=j.DONE;r.trigger("FileUploaded",t,{response:U.responseText,status:Y})}else{A()}}U=null}};if(r.settings.multipart&&n.multipart){L.name=t.target_name||t.name;U.open("post",E,true);j.each(r.settings.headers,function(Z,Y){U.setRequestHeader(Y,Z)});if(!D&&!!h.FormData){O=new FormData();j.each(j.extend(L,r.settings.multipart_params),function(Z,Y){O.append(Y,Z)});O.append(r.settings.file_data_name,W);U.send(O);return}if(D){U.setRequestHeader("Content-Type","multipart/form-data; boundary="+N);j.each(j.extend(L,r.settings.multipart_params),function(Z,Y){R+=P+N+V+'Content-Disposition: form-data; name="'+Y+'"'+V+V;R+=unescape(encodeURIComponent(Z))+V});F=j.mimeTypes[t.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";R+=P+N+V+'Content-Disposition: form-data; name="'+r.settings.file_data_name+'"; filename="'+unescape(encodeURIComponent(t.name))+'"'+V+"Content-Type: "+F+V+V+W+V+P+N+P+V;T=R.length-W.length;W=R;if(U.sendAsBinary){U.sendAsBinary(W)}else{if(n.canSendBinary){var S=new Uint8Array(W.length);for(var Q=0;Q<W.length;Q++){S[Q]=(W.charCodeAt(Q)&255)}U.send(S.buffer)}}return}}E=j.buildUrl(r.settings.url,j.extend(L,r.settings.multipart_params));U.open("post",E,true);U.setRequestHeader("Content-Type","application/octet-stream");j.each(r.settings.headers,function(Z,Y){U.setRequestHeader(Y,Z)});U.send(W)}if(t.status==j.DONE||t.status==j.FAILED||r.state==j.STOPPED){return}L={name:t.target_name||t.name};if(u.chunk_size&&t.size>u.chunk_size&&(n.chunks||typeof(z)=="string")){H=u.chunk_size;K=Math.ceil(t.size/H);J=Math.min(H,t.size-(C*H));if(typeof(z)=="string"){I=z.substring(C*H,C*H+J)}else{I=w(z,C*H,C*H+J)}L.chunk=C;L.chunks=K}else{J=t.size;I=z}if(y&&n.cantSendBlobInFormData&&n.chunks&&r.settings.chunk_size){y.onload=function(){D=true;G(y.result)};y.readAsBinaryString(I)}else{G(I)}}A()}x=c[t.id];if(n.jpgresize&&r.settings.resize&&/\.(png|jpg|jpeg)$/i.test(t.name)){d.call(r,t,r.settings.resize,/\.png$/i.test(t.name)?"image/png":"image/jpeg",function(y){if(y.success){t.size=y.data.length;v(y.data)}else{v(x)}})}else{if(!n.chunks&&n.jpgresize){l(x,v)}else{v(x)}}});p.bind("Destroy",function(r){var t,u,s=k.body,v={inputContainer:r.id+"_html5_container",inputFile:r.id+"_html5",browseButton:r.settings.browse_button,dropElm:r.settings.drop_element};for(t in v){u=k.getElementById(v[t]);if(u){j.removeAllEvents(u,r.id)}}j.removeAllEvents(k.body,r.id);if(r.settings.container){s=k.getElementById(r.settings.container)}s.removeChild(k.getElementById(v.inputContainer))});q({success:true})}});function b(){var q=false,o;function r(t,v){var s=q?0:-8*(v-1),w=0,u;for(u=0;u<v;u++){w|=(o.charCodeAt(t+u)<<Math.abs(s+u*8))}return w}function n(u,s,t){var t=arguments.length===3?t:o.length-s-1;o=o.substr(0,s)+u+o.substr(t+s)}function p(t,u,w){var x="",s=q?0:-8*(w-1),v;for(v=0;v<w;v++){x+=String.fromCharCode((u>>Math.abs(s+v*8))&255)}n(x,t,w)}return{II:function(s){if(s===e){return q}else{q=s}},init:function(s){q=false;o=s},SEGMENT:function(s,u,t){switch(arguments.length){case 1:return o.substr(s,o.length-s-1);case 2:return o.substr(s,u);case 3:n(t,s,u);break;default:return o}},BYTE:function(s){return r(s,1)},SHORT:function(s){return r(s,2)},LONG:function(s,t){if(t===e){return r(s,4)}else{p(s,t,4)}},SLONG:function(s){var t=r(s,4);return(t>2147483647?t-4294967296:t)},STRING:function(s,t){var u="";for(t+=s;s<t;s++){u+=String.fromCharCode(r(s,1))}return u}}}function f(s){var u={65505:{app:"EXIF",name:"APP1",signature:"Exif\0"},65506:{app:"ICC",name:"APP2",signature:"ICC_PROFILE\0"},65517:{app:"IPTC",name:"APP13",signature:"Photoshop 3.0\0"}},t=[],r,n,p=e,q=0,o;r=new b();r.init(s);if(r.SHORT(0)!==65496){return}n=2;o=Math.min(1048576,s.length);while(n<=o){p=r.SHORT(n);if(p>=65488&&p<=65495){n+=2;continue}if(p===65498||p===65497){break}q=r.SHORT(n+2)+2;if(u[p]&&r.STRING(n+4,u[p].signature.length)===u[p].signature){t.push({hex:p,app:u[p].app.toUpperCase(),name:u[p].name.toUpperCase(),start:n,length:q,segment:r.SEGMENT(n,q)})}n+=q}r.init(null);return{headers:t,restore:function(y){r.init(y);var w=new f(y);if(!w.headers){return false}for(var x=w.headers.length;x>0;x--){var z=w.headers[x-1];r.SEGMENT(z.start,z.length,"")}w.purge();n=r.SHORT(2)==65504?4+r.SHORT(4):2;for(var x=0,v=t.length;x<v;x++){r.SEGMENT(n,0,t[x].segment);n+=t[x].length}return r.SEGMENT()},get:function(x){var y=[];for(var w=0,v=t.length;w<v;w++){if(t[w].app===x.toUpperCase()){y.push(t[w].segment)}}return y},set:function(y,x){var z=[];if(typeof(x)==="string"){z.push(x)}else{z=x}for(var w=ii=0,v=t.length;w<v;w++){if(t[w].app===y.toUpperCase()){t[w].segment=z[ii];t[w].length=z[ii].length;ii++}if(ii>=z.length){break}}},purge:function(){t=[];r.init(null)}}}function a(){var q,n,o={},t;q=new b();n={tiff:{274:"Orientation",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}};t={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}};function p(u,C){var w=q.SHORT(u),z,F,G,B,A,v,x,D,E=[],y={};for(z=0;z<w;z++){x=v=u+12*z+2;G=C[q.SHORT(x)];if(G===e){continue}B=q.SHORT(x+=2);A=q.LONG(x+=2);x+=4;E=[];switch(B){case 1:case 7:if(A>4){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.BYTE(x+F)}break;case 2:if(A>4){x=q.LONG(x)+o.tiffHeader}y[G]=q.STRING(x,A-1);continue;case 3:if(A>2){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.SHORT(x+F*2)}break;case 4:if(A>1){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)}break;case 5:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)/q.LONG(x+F*4+4)}break;case 9:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)}break;case 10:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)/q.SLONG(x+F*4+4)}break;default:continue}D=(A==1?E[0]:E);if(t.hasOwnProperty(G)&&typeof D!="object"){y[G]=t[G][D]}else{y[G]=D}}return y}function s(){var v=e,u=o.tiffHeader;q.II(q.SHORT(u)==18761);if(q.SHORT(u+=2)!==42){return false}o.IFD0=o.tiffHeader+q.LONG(u+=2);v=p(o.IFD0,n.tiff);o.exifIFD=("ExifIFDPointer" in v?o.tiffHeader+v.ExifIFDPointer:e);o.gpsIFD=("GPSInfoIFDPointer" in v?o.tiffHeader+v.GPSInfoIFDPointer:e);return true}function r(w,u,z){var B,y,x,A=0;if(typeof(u)==="string"){var v=n[w.toLowerCase()];for(hex in v){if(v[hex]===u){u=hex;break}}}B=o[w.toLowerCase()+"IFD"];y=q.SHORT(B);for(i=0;i<y;i++){x=B+12*i+2;if(q.SHORT(x)==u){A=x+8;break}}if(!A){return false}q.LONG(A,z);return true}return{init:function(u){o={tiffHeader:10};if(u===e||!u.length){return false}q.init(u);if(q.SHORT(0)===65505&&q.STRING(4,5).toUpperCase()==="EXIF\0"){return s()}return false},EXIF:function(){var u;u=p(o.exifIFD,n.exif);if(u.ExifVersion){u.ExifVersion=String.fromCharCode(u.ExifVersion[0],u.ExifVersion[1],u.ExifVersion[2],u.ExifVersion[3])}return u},GPS:function(){var u;u=p(o.gpsIFD,n.gps);if(u.GPSVersionID){u.GPSVersionID=u.GPSVersionID.join(".")}return u},setExif:function(u,v){if(u!=="PixelXDimension"&&u!=="PixelYDimension"){return false}return r("exif",u,v)},getBinary:function(){return q.SEGMENT()}}}})(window,document,plupload);(function(d,a,b,c){function e(f){return a.getElementById(f)}b.runtimes.Html4=b.addRuntime("html4",{getFeatures:function(){var f=(function(){var l=navigator,k=l.userAgent,m=l.vendor,h,g,j;h=/WebKit/.test(k);j=h&&m.indexOf("Apple")!==-1;g=d.opera&&d.opera.buildNumber;return{ie:!h&&!g&&(/MSIE/gi).test(k)&&(/Explorer/gi).test(l.appName),webkit:h,gecko:!h&&/Gecko/.test(k),safari:j,safariwin:j&&navigator.platform.indexOf("Win")!==-1,opera:!!g}}());return{multipart:true,triggerDialog:(f.gecko&&d.FormData||f.webkit)}},init:function(f,g){f.bind("Init",function(p){var j=a.body,n,h="javascript",k,x,q,z=[],r=/MSIE/.test(navigator.userAgent),t=[],m=p.settings.filters,o,l,s,w;no_type_restriction:for(o=0;o<m.length;o++){l=m[o].extensions.split(/,/);for(w=0;w<l.length;w++){if(l[w]==="*"){t=[];break no_type_restriction}s=b.mimeTypes[l[w]];if(s){t.push(s)}}}t=t.join(",");function v(){var C,A,y,B;q=b.guid();z.push(q);C=a.createElement("form");C.setAttribute("id","form_"+q);C.setAttribute("method","post");C.setAttribute("enctype","multipart/form-data");C.setAttribute("encoding","multipart/form-data");C.setAttribute("target",p.id+"_iframe");C.style.position="absolute";A=a.createElement("input");A.setAttribute("id","input_"+q);A.setAttribute("type","file");A.setAttribute("accept",t);A.setAttribute("size",1);B=e(p.settings.browse_button);if(p.features.triggerDialog&&B){b.addEvent(e(p.settings.browse_button),"click",function(D){A.click();D.preventDefault()},p.id)}b.extend(A.style,{width:"100%",height:"100%",opacity:0,fontSize:"999px"});b.extend(C.style,{overflow:"hidden"});y=p.settings.shim_bgcolor;if(y){C.style.background=y}if(r){b.extend(A.style,{filter:"alpha(opacity=0)"})}b.addEvent(A,"change",function(G){var E=G.target,D,F=[],H;if(E.value){e("form_"+q).style.top=-1048575+"px";D=E.value.replace(/\\/g,"/");D=D.substring(D.length,D.lastIndexOf("/")+1);F.push(new b.File(q,D));if(!p.features.triggerDialog){b.removeAllEvents(C,p.id)}else{b.removeEvent(B,"click",p.id)}b.removeEvent(A,"change",p.id);v();if(F.length){f.trigger("FilesAdded",F)}}},p.id);C.appendChild(A);j.appendChild(C);p.refresh()}function u(){var y=a.createElement("div");y.innerHTML='<iframe id="'+p.id+'_iframe" name="'+p.id+'_iframe" src="'+h+':&quot;&quot;" style="display:none"></iframe>';n=y.firstChild;j.appendChild(n);b.addEvent(n,"load",function(D){var E=D.target,C,A;if(!k){return}try{C=E.contentWindow.document||E.contentDocument||d.frames[E.id].document}catch(B){p.trigger("Error",{code:b.SECURITY_ERROR,message:b.translate("Security error."),file:k});return}A=C.documentElement.innerText||C.documentElement.textContent;if(A){k.status=b.DONE;k.loaded=1025;k.percent=100;p.trigger("UploadProgress",k);p.trigger("FileUploaded",k,{response:A})}},p.id)}if(p.settings.container){j=e(p.settings.container);if(b.getStyle(j,"position")==="static"){j.style.position="relative"}}p.bind("UploadFile",function(y,B){var C,A;if(B.status==b.DONE||B.status==b.FAILED||y.state==b.STOPPED){return}C=e("form_"+B.id);A=e("input_"+B.id);A.setAttribute("name",y.settings.file_data_name);C.setAttribute("action",y.settings.url);b.each(b.extend({name:B.target_name||B.name},y.settings.multipart_params),function(F,D){var E=a.createElement("input");b.extend(E,{type:"hidden",name:D,value:F});C.insertBefore(E,C.firstChild)});k=B;e("form_"+q).style.top=-1048575+"px";C.submit();C.parentNode.removeChild(C)});p.bind("FileUploaded",function(y){y.refresh()});p.bind("StateChanged",function(y){if(y.state==b.STARTED){u()}if(y.state==b.STOPPED){d.setTimeout(function(){b.removeEvent(n,"load",y.id);n.parentNode.removeChild(n)},0)}});p.bind("Refresh",function(A){var G,B,C,D,y,H,I,F,E;G=e(A.settings.browse_button);if(G){y=b.getPos(G,e(A.settings.container));H=b.getSize(G);I=e("form_"+q);F=e("input_"+q);b.extend(I.style,{top:y.y+"px",left:y.x+"px",width:H.w+"px",height:H.h+"px"});if(A.features.triggerDialog){if(b.getStyle(G,"position")==="static"){b.extend(G.style,{position:"relative"})}E=parseInt(G.style.zIndex,10);if(isNaN(E)){E=0}b.extend(G.style,{zIndex:E});b.extend(I.style,{zIndex:E-1})}C=A.settings.browse_button_hover;D=A.settings.browse_button_active;B=A.features.triggerDialog?G:I;if(C){b.addEvent(B,"mouseover",function(){b.addClass(G,C)},A.id);b.addEvent(B,"mouseout",function(){b.removeClass(G,C)},A.id)}if(D){b.addEvent(B,"mousedown",function(){b.addClass(G,D)},A.id);b.addEvent(a.body,"mouseup",function(){b.removeClass(G,D)},A.id)}}});f.bind("FilesRemoved",function(y,B){var A,C;for(A=0;A<B.length;A++){C=e("form_"+B[A].id);if(C){C.parentNode.removeChild(C)}}});f.bind("Destroy",function(y){var A,B,C,D={inputContainer:"form_"+q,inputFile:"input_"+q,browseButton:y.settings.browse_button};for(A in D){B=e(D[A]);if(B){b.removeAllEvents(B,y.id)}}b.removeAllEvents(a.body,y.id);b.each(z,function(F,E){C=e("form_"+F);if(C){j.removeChild(C)}})});v()});g({success:true})}})})(window,document,plupload);
static/js/plupload/wplupload.js CHANGED
@@ -1,116 +1,120 @@
1
- (function(window, $, undefined) {
2
-
3
- var _parent = window.dialogArguments || opener || parent || top;
4
-
5
- $.fn.wplupload = function($options) {
6
- var $up, $defaults = {
7
- runtimes : 'gears,browserplus,html5,flash,silverlight,html4',
8
- browse_button_hover: 'hover',
9
- browse_button_active: 'active'
10
- };
11
-
12
- $options = $.extend({}, $defaults, $options);
13
-
14
- return this.each(function() {
15
- var $this = $(this);
16
-
17
- $up = new plupload.Uploader($options);
18
-
19
-
20
- /*$up.bind('Init', function(up) {
21
- var dropElm = $('#' + up.settings.drop_element);
22
- if (dropElm.length && up.features.dragdrop) {
23
- dropElm.bind('dragenter', function() {
24
- $(this).css('border', '3px dashed #cccccc');
25
- });
26
- dropElm.bind('dragout drop', function() {
27
- $(this).css('border', 'none');
28
- });
29
- }
30
- });*/
31
-
32
- $up.bind('FilesAdded', function(up, files) {
33
- $.each(files, function(i, file) {
34
- // Create a progress bar containing the filename
35
- $('#basic').find('.submit-buttons').hide();
36
- $('#progress').css({'visibility':'visible'});
37
- })
38
- });
39
-
40
- $up.init();
41
-
42
- $up.bind('Error', function(up, err) {
43
- $('#upload_process').html(err.message);
44
- });
45
-
46
- $up.bind('FilesAdded', function(up, files) {
47
- // Disable submit and enable cancel
48
-
49
- $('#cancel-upload').removeAttr('disabled');
50
-
51
- $up.start();
52
- });
53
-
54
- $up.bind('UploadFile', function(up, file, r) {
55
-
56
- });
57
-
58
- $up.bind('UploadProgress', function(up, file) {
59
- // Lengthen the progress bar
60
- $('#progressbar').html('Uploading data feed ... ' + file.percent + '%');
61
- $('#upload_process').progressbar({value:file.percent});
62
-
63
- });
64
-
65
-
66
- $up.bind('FileUploaded', function(up, file, r) {
67
- var fetch = typeof(shortform) == 'undefined' ? 1 : 2;
68
-
69
- r = _parseJSON(r.response);
70
-
71
- $('#filepath').val(r.name);
72
-
73
- $('#progressbar').html('Upload Complete - ' + file.name + ' (' + ( (file.size / (1024*1024) >= 1) ? (file.size / (1024*1024)).toFixed(2) + 'mb' : (file.size / (1024)).toFixed(2) + 'kb') + ')');
74
-
75
- $('#basic').find('.submit-buttons').show();
76
-
77
- if (r.OK) {
78
-
79
- }
80
- });
81
-
82
- $up.bind('UploadComplete', function(up) {
83
- $('#cancel-upload').attr('disabled', 'disabled');
84
- });
85
-
86
- $('#cancel-upload').click(function() {
87
- var i, file;
88
-
89
- $up.stop();
90
-
91
- i = $up.files.length;
92
- for (i = $up.files.length - 1; i >= 0; i--) {
93
- file = $up.files[i];
94
- if ($.inArray(file.status, [plupload.QUEUED, plupload.UPLOADING]) !== -1) {
95
- $up.removeFile($up.getFile(file.id));
96
- }
97
- }
98
-
99
- $('#cancel-upload').attr('disabled', 'disabled');
100
-
101
- });
102
-
103
- });
104
- };
105
-
106
- function _parseJSON(r) {
107
- var obj;
108
- try {
109
- obj = $.parseJSON(r);
110
- } catch (e) {
111
- obj = { OK : 0 };
112
- }
113
- return obj;
114
- }
115
-
 
 
 
 
116
  }(window, jQuery));
1
+ (function(window, $, undefined) {
2
+
3
+ var _parent = window.dialogArguments || opener || parent || top;
4
+
5
+ $.fn.wplupload = function($options) {
6
+ var $up, $defaults = {
7
+ runtimes : 'gears,browserplus,html5,flash,silverlight,html4',
8
+ browse_button_hover: 'hover',
9
+ browse_button_active: 'active'
10
+ };
11
+
12
+ $options = $.extend({}, $defaults, $options);
13
+
14
+ return this.each(function() {
15
+ var $this = $(this);
16
+
17
+ $up = new plupload.Uploader($options);
18
+
19
+
20
+ /*$up.bind('Init', function(up) {
21
+ var dropElm = $('#' + up.settings.drop_element);
22
+ if (dropElm.length && up.features.dragdrop) {
23
+ dropElm.bind('dragenter', function() {
24
+ $(this).css('border', '3px dashed #cccccc');
25
+ });
26
+ dropElm.bind('dragout drop', function() {
27
+ $(this).css('border', 'none');
28
+ });
29
+ }
30
+ });*/
31
+
32
+ $up.bind('FilesAdded', function(up, files) {
33
+ $.each(files, function(i, file) {
34
+ // Create a progress bar containing the filename
35
+ $('#basic').find('.submit-buttons').hide();
36
+ $('#progress').css({'visibility':'visible'});
37
+ })
38
+ });
39
+
40
+ $up.init();
41
+
42
+ $up.bind('Error', function(up, err) {
43
+ $('#upload_process').html(err.message);
44
+ });
45
+
46
+ $up.bind('FilesAdded', function(up, files) {
47
+ // Disable submit and enable cancel
48
+
49
+ $('#cancel-upload').removeAttr('disabled');
50
+
51
+ $up.start();
52
+ });
53
+
54
+ $up.bind('UploadFile', function(up, file, r) {
55
+
56
+ });
57
+
58
+ $up.bind('UploadProgress', function(up, file) {
59
+ // Lengthen the progress bar
60
+ $('#progressbar').html('Uploading data feed ... ' + file.percent + '%');
61
+ $('#upload_process').progressbar({value:file.percent});
62
+
63
+ });
64
+
65
+
66
+ $up.bind('FileUploaded', function(up, file, r) {
67
+ var fetch = typeof(shortform) == 'undefined' ? 1 : 2;
68
+
69
+ r = _parseJSON(r.response);
70
+
71
+ $('#filepath').val(r.name);
72
+
73
+ $('#progressbar').html('Upload Complete - ' + file.name + ' (' + ( (file.size / (1024*1024) >= 1) ? (file.size / (1024*1024)).toFixed(2) + 'mb' : (file.size / (1024)).toFixed(2) + 'kb') + ')');
74
+
75
+ $('#basic').find('.submit-buttons').show();
76
+
77
+ if (r.OK) {
78
+
79
+ } else if (r.error != undefined && '' != r.error.message) {
80
+ $('#progressbar').html(r.error.message);
81
+ }
82
+
83
+ });
84
+
85
+ $up.bind('UploadComplete', function(up) {
86
+ $('#cancel-upload').attr('disabled', 'disabled');
87
+ });
88
+
89
+ $('#cancel-upload').click(function() {
90
+ var i, file;
91
+
92
+ $up.stop();
93
+
94
+ i = $up.files.length;
95
+ for (i = $up.files.length - 1; i >= 0; i--) {
96
+ file = $up.files[i];
97
+ if ($.inArray(file.status, [plupload.QUEUED, plupload.UPLOADING]) !== -1) {
98
+ $up.removeFile($up.getFile(file.id));
99
+ }
100
+ }
101
+
102
+ $('#cancel-upload').attr('disabled', 'disabled');
103
+
104
+ });
105
+
106
+ });
107
+ };
108
+
109
+ function _parseJSON(r) {
110
+ var obj;
111
+ try {
112
+ var matches = r.match(/{.*}/);
113
+ obj = $.parseJSON(matches[0]);
114
+ } catch (e) {
115
+ obj = { OK : 0 };
116
+ }
117
+ return obj;
118
+ }
119
+
120
  }(window, jQuery));
views/admin/help/index.php CHANGED
@@ -1,23 +1,23 @@
1
- <h2><?php _e('WP All Import Support', 'pmxi_plugin') ?></h2>
2
-
3
- <table class="layout">
4
- <tr>
5
- <td class="left">
6
- <p style='font-size: 1.3em;'>
7
- <b>E-mail</b> - <a href='mailto:support@soflyy.com'>support@soflyy.com</a><br />
8
- <b>Support page</b> - <a href='http://www.wpallimport.com/support?utm_source=wordpress.org&utm_medium=support&utm_campaign=free+plugin' target='_blank'>http://www.wpallimport.com/support</a>
9
- </p>
10
-
11
- <p style='font-size: 1.3em;'>Thanks for installing the free version of WP All Import.</p>
12
-
13
- <p style='font-size: 1.3em;'>We are able to provide limited technical support to free version users. Support is not guaranteed, and is based on availability</p>
14
-
15
- <p style='font-size: 1.3em;'><b>Please note we are unable to provide technical support via the WordPress.org community forums.</b></p>
16
-
17
- <p style='font-size: 1.3em;'><a href='http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=support&utm_campaign=free+plugin' target='_blank'>For premium support, please upgrade to the professional edition of WP All Import.</a></p>
18
-
19
-
20
- </td>
21
- <td class="right">&nbsp;</td>
22
- </tr>
23
  </table>
1
+ <h2><?php _e('WP All Import Support', 'pmxi_plugin') ?></h2>
2
+
3
+ <table class="layout">
4
+ <tr>
5
+ <td class="left">
6
+ <p style='font-size: 1.3em;'>
7
+ <b>E-mail</b> - <a href='mailto:support@soflyy.com'>support@soflyy.com</a><br />
8
+ <b>Support page</b> - <a href='http://www.wpallimport.com/support?utm_source=wordpress.org&utm_medium=support&utm_campaign=free+plugin' target='_blank'>http://www.wpallimport.com/support</a>
9
+ </p>
10
+
11
+ <p style='font-size: 1.3em;'>Thanks for installing the free version of WP All Import.</p>
12
+
13
+ <p style='font-size: 1.3em;'>We are able to provide limited technical support to free version users. Support is not guaranteed, and is based on availability</p>
14
+
15
+ <p style='font-size: 1.3em;'><b>Please note we are unable to provide technical support via the WordPress.org community forums.</b></p>
16
+
17
+ <p style='font-size: 1.3em;'><a href='http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=support&utm_campaign=free+plugin' target='_blank'>For premium support, please upgrade to the professional edition of WP All Import.</a></p>
18
+
19
+
20
+ </td>
21
+ <td class="right">&nbsp;</td>
22
+ </tr>
23
  </table>
views/admin/import/element_after.php CHANGED
@@ -31,7 +31,7 @@
31
  <p><?php _e('Current XPath:','pmxi_plugin');?></p>
32
  <div>
33
  <input type="text" name="xpath" value="<?php echo esc_attr($post['xpath']) ?>" style="max-width:none;" />
34
- <input type="hidden" id="root_element" name="root_element" value="<?php echo $_SESSION['pmxi_import']['source']['root_element']; ?>"/>
35
  <?php
36
  if (!empty($elements_cloud)){
37
  ?>
@@ -43,7 +43,7 @@
43
  echo implode(', ', $root_elements);
44
  }
45
  ?>
46
- &nbsp; <br/><br/>or <a href="javascript:void(0);" rel="<?php echo esc_attr($post['xpath']) ?>" root="<?php echo $_SESSION['pmxi_import']['source']['root_element']; ?>" id="get_default_xpath"><?php _e('get default xPath','pmxi_plugin');?></a>
47
  </div> <br><br>
48
  <a href="http://www.w3schools.com/xpath/default.asp" target='_blank'><?php _e('XPath Tutorial','pmxi_plugin');?></a> - <?php _e('For further help','pmxi_plugin');?>, <a href="http://www.wpallimport.com/support" target='_blank'><?php _e('contact us','pmxi_plugin');?></a>.
49
  </fieldset>
31
  <p><?php _e('Current XPath:','pmxi_plugin');?></p>
32
  <div>
33
  <input type="text" name="xpath" value="<?php echo esc_attr($post['xpath']) ?>" style="max-width:none;" />
34
+ <input type="hidden" id="root_element" name="root_element" value="<?php echo PMXI_Plugin::$session->data['pmxi_import']['source']['root_element']; ?>"/>
35
  <?php
36
  if (!empty($elements_cloud)){
37
  ?>
43
  echo implode(', ', $root_elements);
44
  }
45
  ?>
46
+ &nbsp; <br/><br/>or <a href="javascript:void(0);" rel="<?php echo esc_attr($post['xpath']) ?>" root="<?php echo PMXI_Plugin::$session->data['pmxi_import']['source']['root_element']; ?>" id="get_default_xpath"><?php _e('get default xPath','pmxi_plugin');?></a>
47
  </div> <br><br>
48
  <a href="http://www.w3schools.com/xpath/default.asp" target='_blank'><?php _e('XPath Tutorial','pmxi_plugin');?></a> - <?php _e('For further help','pmxi_plugin');?>, <a href="http://www.wpallimport.com/support" target='_blank'><?php _e('contact us','pmxi_plugin');?></a>.
49
  </fieldset>
views/admin/import/evaluate.php CHANGED
@@ -1,20 +1,20 @@
1
- <div class="updated">
2
- <p><?php printf(__('Current selection matches <span class="matches_count">%s</span> %s.', 'pmxi_plugin'), $node_list_count, _n('element', 'elements', $node_list_count, 'pmxi_plugin')) ?></p>
3
- <?php if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $elements->length > PMXI_Plugin::getInstance()->getOption('highlight_limit')): ?>
4
- <p><?php _e('<strong>Note</strong>: Highlighting is turned off since can be very slow on large sets of elements.', 'pmxi_plugin') ?></p>
5
- <?php endif ?>
6
- </div>
7
- <div id="current_xml">
8
- <?php $this->render_xml_element($elements->item( ($_POST['show_element'] and !$_SESSION['pmxi_import']['large_file']) ? $_POST['show_element'] - 1 : 0 ), false, '//'); ?>
9
- </div>
10
- <script type="text/javascript">
11
- (function($){
12
- var paths = <?php echo json_encode($paths) ?>;
13
- var $xml = $('.xml');
14
-
15
- $xml.html($('#current_xml').html()).css({'visibility':'visible'});
16
- for (var i = 0; i < paths.length; i++) {
17
- $xml.find('.xml-element[title="' + paths[i] + '"]').addClass('selected').parents('.xml-element').find('> .xml-content.collapsed').removeClass('collapsed').parent().find('> .xml-expander').html('-');
18
- }
19
- })(jQuery);
20
  </script>
1
+ <div class="updated">
2
+ <p><?php printf(__('Current selection matches <span class="matches_count">%s</span> %s.', 'pmxi_plugin'), $node_list_count, _n('element', 'elements', $node_list_count, 'pmxi_plugin')) ?></p>
3
+ <?php if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $elements->length > PMXI_Plugin::getInstance()->getOption('highlight_limit')): ?>
4
+ <p><?php _e('<strong>Note</strong>: Highlighting is turned off since can be very slow on large sets of elements.', 'pmxi_plugin') ?></p>
5
+ <?php endif ?>
6
+ </div>
7
+ <div id="current_xml">
8
+ <?php $this->render_xml_element($elements->item( ($_POST['show_element'] and !PMXI_Plugin::$session->data['pmxi_import']['large_file']) ? $_POST['show_element'] - 1 : 0 ), false, '//'); ?>
9
+ </div>
10
+ <script type="text/javascript">
11
+ (function($){
12
+ var paths = <?php echo json_encode($paths) ?>;
13
+ var $xml = $('.xml');
14
+
15
+ $xml.html($('#current_xml').html()).css({'visibility':'visible'});
16
+ for (var i = 0; i < paths.length; i++) {
17
+ $xml.find('.xml-element[title="' + paths[i] + '"]').addClass('selected').parents('.xml-element').find('> .xml-content.collapsed').removeClass('collapsed').parent().find('> .xml-expander').html('-');
18
+ }
19
+ })(jQuery);
20
  </script>
views/admin/import/evaluate_variations.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (!empty($variation_list_count)):?>
2
+ <div class="updated">
3
+ <p><?php printf(__('Current selection matches <span class="matches_count">%s</span> %s.', 'pmxi_plugin'), $variation_list_count, _n('element', 'elements', $variation_list_count, 'pmxi_plugin')) ?></p>
4
+ <?php if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $variation_list_count > PMXI_Plugin::getInstance()->getOption('highlight_limit')): ?>
5
+ <p><?php _e('<strong>Note</strong>: Highlighting is turned off since can be very slow on large sets of elements.', 'pmxi_plugin') ?></p>
6
+ <?php endif ?>
7
+ </div>
8
+ <div id="current_xml">
9
+ <div class="variations_tag">
10
+ <input type="hidden" name="variations_tagno" value="<?php echo $tagno + 1 ?>" />
11
+ <div class="title">
12
+ <?php printf(__('Variation Record #<strong>%s</strong> out of <strong>%s</strong>', 'pmxi_plugin'), $tagno + 1, $variation_list_count); ?>
13
+ <div class="navigation">
14
+ <?php if ($tagno > 0): ?><a href="#variation_prev">&lang;&lang;</a><?php else: ?><span>&lang;&lang;</span><?php endif ?>
15
+ <?php if ($tagno < $variation_list_count - 1): ?><a href="#variation_next">&rang;&rang;</a><?php else: ?><span>&rang;&rang;</span><?php endif ?>
16
+ </div>
17
+ </div>
18
+ <div class="clear"></div>
19
+ <div class="xml resetable"> <?php if (!empty($variation_list_count)) $this->render_xml_element($variation_elements->item($tagno), true); ?></div>
20
+ </div>
21
+ </div>
22
+ <?php endif; ?>
23
+ <script type="text/javascript">
24
+ (function($){
25
+ var paths = <?php echo json_encode($paths) ?>;
26
+ var $xml = $('#variations_xml');
27
+ $xml.html($('#current_xml').html()).css({'visibility':'visible'});
28
+ for (var i = 0; i < paths.length; i++) {
29
+ $xml.find('.xml-element[title="' + paths[i] + '"]').addClass('selected').parents('.xml-element').find('> .xml-content.collapsed').removeClass('collapsed').parent().find('> .xml-expander').html('-');
30
+ }
31
+ })(jQuery);
32
+ </script>
views/admin/import/options/_buttons_template.php CHANGED
@@ -3,7 +3,7 @@
3
  <label for="save_import_as"><?php _e('Friendly Name','pmxi_plugin');?></label> <input type="text" name="friendly_name" title="<?php _e('Save friendly name...', 'pmxi_plugin') ?>" style="vertical-align:middle; font-size:11px; background:#fff !important;" value="<?php echo esc_attr($post['friendly_name']) ?>" />
4
  </div>
5
  <br>
6
- <?php if ($_SESSION['pmxi_import']['large_file'] or (!empty($import) and $import->large_import == 'Yes')):?>
7
  <div class="input">
8
  <label for="records_per_request"><?php _e('Records Per Iteration', 'pmxi_plugin');?></label> <input type="text" name="records_per_request" style="vertical-align:middle; font-size:11px; background:#fff !important; width: 40px;" value="<?php echo esc_attr($post['records_per_request']) ?>" />
9
  <a href="#help" class="help" title="<?php _e('Your feed was detected as a &quot;large&quot; file. The import process will be executed via AJAX requests. To make import process faster you can increase the number of records imported per iteration. Higher numbers put more strain on your server but make the import process take less time. 10 is a very safe number. To speed up the process, try 100 or more, especially if your import settings are simple and you are not downloading images.', 'pmxi_plugin') ?>">?</a>
3
  <label for="save_import_as"><?php _e('Friendly Name','pmxi_plugin');?></label> <input type="text" name="friendly_name" title="<?php _e('Save friendly name...', 'pmxi_plugin') ?>" style="vertical-align:middle; font-size:11px; background:#fff !important;" value="<?php echo esc_attr($post['friendly_name']) ?>" />
4
  </div>
5
  <br>
6
+ <?php if (PMXI_Plugin::$session->data['pmxi_import']['large_file'] or (!empty($import) and $import->large_import == 'Yes')):?>
7
  <div class="input">
8
  <label for="records_per_request"><?php _e('Records Per Iteration', 'pmxi_plugin');?></label> <input type="text" name="records_per_request" style="vertical-align:middle; font-size:11px; background:#fff !important; width: 40px;" value="<?php echo esc_attr($post['records_per_request']) ?>" />
9
  <a href="#help" class="help" title="<?php _e('Your feed was detected as a &quot;large&quot; file. The import process will be executed via AJAX requests. To make import process faster you can increase the number of records imported per iteration. Higher numbers put more strain on your server but make the import process take less time. 10 is a very safe number. To speed up the process, try 100 or more, especially if your import settings are simple and you are not downloading images.', 'pmxi_plugin') ?>">?</a>
views/admin/import/options/_featured_template.php CHANGED
@@ -2,7 +2,7 @@
2
  <td colspan="3">
3
  <h3>
4
  <?php _e('Download & Import Images To The Post Media Gallery', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Specify URLs or XPath Template Tags to download and import images to the post media gallery. The first image will be set as the Featured Image. Example: <pre>{image[1]},{image[2]},{image[3]}</pre> Separate your URLs or XPath Template Tags with the comma. <i>Separated by</i> character will use if xPath value contains multiple URLs, for example: <br> \'http://test.com/first.jpg | http://test.com/second.png\'.', 'pmxi_plugin') ?>">?</a>
5
- <span class="separated_by">Separated by</span>
6
  </h3>
7
  <div>
8
  <input type="text" name="featured_image" style="width:92%;" value="<?php echo ($post_type == "product") ? esc_attr($post['featured_image']) : ""; ?>" <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
@@ -13,6 +13,25 @@
13
  <input type="checkbox" id="create_draft_<?php echo $entry; ?>" name="create_draft" value="yes" <?php echo ($post_type == "product" and "yes" == $post['create_draft']) ? 'checked="checked"' : '' ?> <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
14
  <label for="create_draft_<?php echo $entry; ?>"><?php _e('<small>If no images are downloaded successfully, create entry as Draft.</small>', 'pmxi_plugin') ?></label>
15
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  <?php if ($post_type != "product"):?>
17
  <center>
18
 
2
  <td colspan="3">
3
  <h3>
4
  <?php _e('Download & Import Images To The Post Media Gallery', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Specify URLs or XPath Template Tags to download and import images to the post media gallery. The first image will be set as the Featured Image. Example: <pre>{image[1]},{image[2]},{image[3]}</pre> Separate your URLs or XPath Template Tags with the comma. <i>Separated by</i> character will use if xPath value contains multiple URLs, for example: <br> \'http://test.com/first.jpg | http://test.com/second.png\'.', 'pmxi_plugin') ?>">?</a>
5
+ <span class="separated_by"><?php _e('Separated by','pmxi_plugin');?></span>
6
  </h3>
7
  <div>
8
  <input type="text" name="featured_image" style="width:92%;" value="<?php echo ($post_type == "product") ? esc_attr($post['featured_image']) : ""; ?>" <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
13
  <input type="checkbox" id="create_draft_<?php echo $entry; ?>" name="create_draft" value="yes" <?php echo ($post_type == "product" and "yes" == $post['create_draft']) ? 'checked="checked"' : '' ?> <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
14
  <label for="create_draft_<?php echo $entry; ?>"><?php _e('<small>If no images are downloaded successfully, create entry as Draft.</small>', 'pmxi_plugin') ?></label>
15
  </div>
16
+ <div class="input">
17
+ <input type="radio" id="use_filename_<?php echo $entry; ?>" name="images_name" value="filename" <?php echo ($post['images_name'] == "filename") ? 'checked="checked"' : '' ?> <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
18
+ <label for="use_filename_<?php echo $entry; ?>"><?php _e('<small>The image filenames should be generated based on URLs.</small>', 'pmxi_plugin') ?></label> <br>
19
+
20
+ <input type="radio" id="use_autoname_<?php echo $entry; ?>" name="images_name" value="auto" <?php echo ($post['images_name'] == "auto") ? 'checked="checked"' : '' ?> <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
21
+ <label for="use_autoname_<?php echo $entry; ?>"><?php _e('<small>The image filenames should be generated based on timestamp.</small>', 'pmxi_plugin') ?></label> <br>
22
+ </div>
23
+ <div class="input">
24
+ <input type="hidden" name="auto_rename_images" value="0" />
25
+ <input type="checkbox" id="auto_rename_images_<?php echo $entry; ?>" name="auto_rename_images" value="1" <?php echo $post['auto_rename_images'] ? 'checked="checked"' : '' ?> class="switcher" <?php if ($post_type != "product"):?>disabled="disabled"<?php endif; ?>/>
26
+ <label for="auto_rename_images_<?php echo $entry; ?>"><?php _e('<small>The image filenames should be generated based on provided suffix.</small>', 'pmxi_plugin') ?></label>
27
+ <a href="#help" class="help" title="<?php _e('Example <product_title>Acme Product</product>. Image filenames: acme_product-1.(ext), acme_product-2.(ext), acme_product-3.(ext), etc.', 'pmxi_plugin') ?>">?</a>
28
+ </div>
29
+ <div class="switcher-target-auto_rename_images_<?php echo $entry; ?>" style="padding-left:17px;">
30
+ <div class="input">
31
+ <?php _e('<small>Images suffix</small>', 'pmxi_plugin') ?>
32
+ <input type="text" name="auto_rename_images_suffix" value="<?php echo esc_attr($post['auto_rename_images_suffix']) ?>" />
33
+ </div>
34
+ </div>
35
  <?php if ($post_type != "product"):?>
36
  <center>
37
 
views/admin/import/options/_reimport_template.php CHANGED
@@ -1,7 +1,7 @@
1
  <tr>
2
  <td colspan="3">
3
  <fieldset class="optionsset">
4
- <legend>Record Matching</legend>
5
  <div class="input" style="margin-bottom:15px;">
6
  <input type="radio" id="auto_matching_<?php echo $entry; ?>" class="switcher" name="duplicate_matching" value="auto" <?php echo 'manual' != $post['duplicate_matching'] ? 'checked="checked"': '' ?> />
7
  <label for="auto_matching_<?php echo $entry; ?>"><?php _e('Automatic Record Matching', 'pmxi_plugin' )?></label><br>
@@ -24,7 +24,7 @@
24
  <label for="duplicate_indicator_content_<?php echo $entry; ?>"><?php _e('content', 'pmxi_plugin' )?></label><br>
25
  <input type="radio" id="duplicate_indicator_custom_field_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="custom field" <?php echo 'custom field' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?> />
26
  <label for="duplicate_indicator_custom_field_<?php echo $entry; ?>"><?php _e('custom field', 'pmxi_plugin' )?></label><br>
27
- <span class="switcher-target-duplicate_indicator_custom_field_<?php echo $entry; ?>" style="vertical-align:middle" style="padding-left:17px;">
28
  <?php _e('Name', 'pmxi_plugin') ?>
29
  <input type="text" name="custom_duplicate_name" value="<?php echo esc_attr($post['custom_duplicate_name']) ?>" /><br>
30
  <?php _e('Value', 'pmxi_plugin') ?>
@@ -53,6 +53,20 @@
53
  <a href="#help" class="help" title="<?php _e('Check this option if you want attachments like featured image to be kept in media library after parent post or page is removed or replaced during reimport operation.', 'pmxi_plugin') ?>">?</a>
54
  </div>
55
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  <div class="input">
57
  <input type="radio" id="is_keep_former_posts_<?php echo $entry; ?>" name="is_keep_former_posts" value="yes" <?php echo "yes" == $post['is_keep_former_posts'] ? 'checked="checked"': '' ?> class="switcher" />
58
  <label for="is_keep_former_posts_<?php echo $entry; ?>"><?php _e('Do not update already existing records', 'pmxi_plugin') ?></label> <br>
@@ -69,37 +83,49 @@
69
  <input type="hidden" name="is_keep_title" value="0" />
70
  <input type="checkbox" id="is_keep_title_<?php echo $entry; ?>" name="is_keep_title" value="1" <?php echo $post['is_keep_title'] ? 'checked="checked"': '' ?> />
71
  <label for="is_keep_title_<?php echo $entry; ?>"><?php _e('Keep title', 'pmxi_plugin') ?></label>
72
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their titles.', 'pmxi_plugin') ?>">?</a>
73
  </div>
74
  <div class="input">
75
  <input type="hidden" name="is_keep_excerpt" value="0" />
76
  <input type="checkbox" id="is_keep_excerpt_<?php echo $entry; ?>" name="is_keep_excerpt" value="1" <?php echo $post['is_keep_excerpt'] ? 'checked="checked"': '' ?> />
77
  <label for="is_keep_excerpt_<?php echo $entry; ?>"><?php _e('Keep excerpt', 'pmxi_plugin') ?></label>
78
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their excerpts.', 'pmxi_plugin') ?>">?</a>
79
  </div>
80
  <div class="input">
81
  <input type="hidden" name="is_keep_dates" value="0" />
82
  <input type="checkbox" id="is_keep_dates_<?php echo $entry; ?>" name="is_keep_dates" value="1" <?php echo $post['is_keep_dates'] ? 'checked="checked"': '' ?> />
83
  <label for="is_keep_dates_<?php echo $entry; ?>"><?php _e('Keep dates', 'pmxi_plugin') ?></label>
84
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their publish dates.', 'pmxi_plugin') ?>">?</a>
85
  </div>
86
  <div class="input">
87
  <input type="hidden" name="is_keep_menu_order" value="0" />
88
  <input type="checkbox" id="is_keep_menu_order_<?php echo $entry; ?>" name="is_keep_menu_order" value="1" <?php echo $post['is_keep_menu_order'] ? 'checked="checked"': '' ?> />
89
  <label for="is_keep_menu_order_<?php echo $entry; ?>"><?php _e('Keep menu order', 'pmxi_plugin') ?></label>
90
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their menu order.', 'pmxi_plugin') ?>">?</a>
 
 
 
 
91
  </div>
92
  <div class="input">
93
  <input type="hidden" name="is_keep_content" value="0" />
94
  <input type="checkbox" id="is_keep_content_<?php echo $entry; ?>" name="is_keep_content" value="1" <?php echo $post['is_keep_content'] ? 'checked="checked"': '' ?> />
95
  <label for="is_keep_content_<?php echo $entry; ?>"><?php _e('Keep content', 'pmxi_plugin') ?></label>
96
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their content.', 'pmxi_plugin') ?>">?</a>
97
  </div>
98
  <div class="input">
99
  <input type="hidden" name="is_keep_categories" value="0" />
100
- <input type="checkbox" id="is_keep_categories_<?php echo $entry; ?>" name="is_keep_categories" value="1" <?php echo $post['is_keep_categories'] ? 'checked="checked"': '' ?> />
101
  <label for="is_keep_categories_<?php echo $entry; ?>"><?php _e('Keep categories, tags and taxonomies', 'pmxi_plugin') ?></label>
102
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their category, tag and custom taxonomies associations upon reimport.', 'pmxi_plugin') ?>">?</a>
 
 
 
 
 
 
 
 
 
 
 
103
  </div>
104
  <div class="input">
105
  <input type="hidden" name="is_keep_images" value="0" />
@@ -115,7 +141,7 @@
115
  </div>
116
  <div class="input">
117
  <input type="hidden" name="keep_custom_fields" value="0" />
118
- <input type="checkbox" id="keep_custom_fields_<?php echo $entry; ?>" name="keep_custom_fields" value="1" <?php echo $post['keep_custom_fields'] ? 'checked="checked"': '' ?> class="switcher switcher-reversed" />
119
  <label for="keep_custom_fields_<?php echo $entry; ?>"><?php _e('Keep custom fields', 'pmxi_plugin') ?></label>
120
  <a href="#help" class="help" title="<?php _e('If Keep Custom Fields box is checked, it will keep all Custom Fields, and add any new Custom Fields specified in Custom Fields section, as long as they do not overwrite existing fields. If \'Only keep this Custom Fields\' is specified, it will only keep the specified fields.', 'pmxi_plugin') ?>">?</a>
121
  </div>
1
  <tr>
2
  <td colspan="3">
3
  <fieldset class="optionsset">
4
+ <legend><?php _e('Record Matching','pmxi_plugin');?></legend>
5
  <div class="input" style="margin-bottom:15px;">
6
  <input type="radio" id="auto_matching_<?php echo $entry; ?>" class="switcher" name="duplicate_matching" value="auto" <?php echo 'manual' != $post['duplicate_matching'] ? 'checked="checked"': '' ?> />
7
  <label for="auto_matching_<?php echo $entry; ?>"><?php _e('Automatic Record Matching', 'pmxi_plugin' )?></label><br>
24
  <label for="duplicate_indicator_content_<?php echo $entry; ?>"><?php _e('content', 'pmxi_plugin' )?></label><br>
25
  <input type="radio" id="duplicate_indicator_custom_field_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="custom field" <?php echo 'custom field' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?> />
26
  <label for="duplicate_indicator_custom_field_<?php echo $entry; ?>"><?php _e('custom field', 'pmxi_plugin' )?></label><br>
27
+ <span class="switcher-target-duplicate_indicator_custom_field_<?php echo $entry; ?>" style="vertical-align:middle; padding-left:17px;">
28
  <?php _e('Name', 'pmxi_plugin') ?>
29
  <input type="text" name="custom_duplicate_name" value="<?php echo esc_attr($post['custom_duplicate_name']) ?>" /><br>
30
  <?php _e('Value', 'pmxi_plugin') ?>
53
  <a href="#help" class="help" title="<?php _e('Check this option if you want attachments like featured image to be kept in media library after parent post or page is removed or replaced during reimport operation.', 'pmxi_plugin') ?>">?</a>
54
  </div>
55
  </div>
56
+ <div class="input">
57
+ <input type="hidden" name="is_update_missing_cf" value="0" />
58
+ <input type="checkbox" id="is_update_missing_cf_<?php echo $entry; ?>" name="is_update_missing_cf" value="1" <?php echo $post['is_update_missing_cf'] ? 'checked="checked"': '' ?> class="switcher"/>
59
+ <label for="is_update_missing_cf_<?php echo $entry; ?>"><?php _e('Instead of Deleting Missing Records, Set Custom Field', 'pmxi_plugin') ?></label>
60
+ <a href="#help" class="help" title="<?php _e('Check this option if you want to update posts custom fields from the previous import operation which are not found among newly imported set.', 'pmxi_plugin') ?>">?</a>
61
+ </div>
62
+ <div class="switcher-target-is_update_missing_cf_<?php echo $entry; ?>" style="padding-left:17px;">
63
+ <div class="input">
64
+ <?php _e('Name', 'pmxi_plugin') ?>
65
+ <input type="text" name="update_missing_cf_name" value="<?php echo esc_attr($post['update_missing_cf_name']) ?>" /><br>
66
+ <?php _e('Value', 'pmxi_plugin') ?>
67
+ <input type="text" name="update_missing_cf_value" value="<?php echo esc_attr($post['update_missing_cf_value']) ?>" />
68
+ </div>
69
+ </div>
70
  <div class="input">
71
  <input type="radio" id="is_keep_former_posts_<?php echo $entry; ?>" name="is_keep_former_posts" value="yes" <?php echo "yes" == $post['is_keep_former_posts'] ? 'checked="checked"': '' ?> class="switcher" />
72
  <label for="is_keep_former_posts_<?php echo $entry; ?>"><?php _e('Do not update already existing records', 'pmxi_plugin') ?></label> <br>
83
  <input type="hidden" name="is_keep_title" value="0" />
84
  <input type="checkbox" id="is_keep_title_<?php echo $entry; ?>" name="is_keep_title" value="1" <?php echo $post['is_keep_title'] ? 'checked="checked"': '' ?> />
85
  <label for="is_keep_title_<?php echo $entry; ?>"><?php _e('Keep title', 'pmxi_plugin') ?></label>
86
+
87
  </div>
88
  <div class="input">
89
  <input type="hidden" name="is_keep_excerpt" value="0" />
90
  <input type="checkbox" id="is_keep_excerpt_<?php echo $entry; ?>" name="is_keep_excerpt" value="1" <?php echo $post['is_keep_excerpt'] ? 'checked="checked"': '' ?> />
91
  <label for="is_keep_excerpt_<?php echo $entry; ?>"><?php _e('Keep excerpt', 'pmxi_plugin') ?></label>
 
92
  </div>
93
  <div class="input">
94
  <input type="hidden" name="is_keep_dates" value="0" />
95
  <input type="checkbox" id="is_keep_dates_<?php echo $entry; ?>" name="is_keep_dates" value="1" <?php echo $post['is_keep_dates'] ? 'checked="checked"': '' ?> />
96
  <label for="is_keep_dates_<?php echo $entry; ?>"><?php _e('Keep dates', 'pmxi_plugin') ?></label>
 
97
  </div>
98
  <div class="input">
99
  <input type="hidden" name="is_keep_menu_order" value="0" />
100
  <input type="checkbox" id="is_keep_menu_order_<?php echo $entry; ?>" name="is_keep_menu_order" value="1" <?php echo $post['is_keep_menu_order'] ? 'checked="checked"': '' ?> />
101
  <label for="is_keep_menu_order_<?php echo $entry; ?>"><?php _e('Keep menu order', 'pmxi_plugin') ?></label>
102
+ </div>
103
+ <div class="input">
104
+ <input type="hidden" name="is_keep_parent" value="0" />
105
+ <input type="checkbox" id="is_keep_parent_<?php echo $entry; ?>" name="is_keep_parent" value="1" <?php echo $post['is_keep_parent'] ? 'checked="checked"': '' ?> />
106
+ <label for="is_keep_parent_<?php echo $entry; ?>"><?php _e('Keep parent post', 'pmxi_plugin') ?></label>
107
  </div>
108
  <div class="input">
109
  <input type="hidden" name="is_keep_content" value="0" />
110
  <input type="checkbox" id="is_keep_content_<?php echo $entry; ?>" name="is_keep_content" value="1" <?php echo $post['is_keep_content'] ? 'checked="checked"': '' ?> />
111
  <label for="is_keep_content_<?php echo $entry; ?>"><?php _e('Keep content', 'pmxi_plugin') ?></label>
 
112
  </div>
113
  <div class="input">
114
  <input type="hidden" name="is_keep_categories" value="0" />
115
+ <input type="checkbox" id="is_keep_categories_<?php echo $entry; ?>" name="is_keep_categories" value="1" class="switcher" <?php echo $post['is_keep_categories'] ? 'checked="checked"': '' ?> />
116
  <label for="is_keep_categories_<?php echo $entry; ?>"><?php _e('Keep categories, tags and taxonomies', 'pmxi_plugin') ?></label>
117
+ <div class="switcher-target-is_keep_categories_<?php echo $entry; ?>" style="padding-left:17px;">
118
+ <div class="input" style="margin-bottom:3px;">
119
+ <input type="hidden" name="is_add_newest_categories" value="0" />
120
+ <input type="checkbox" id="is_add_newest_categories_<?php echo $entry; ?>" name="is_add_newest_categories" value="1" <?php echo $post['is_add_newest_categories'] ? 'checked="checked"': '' ?> />
121
+ <label for="is_add_newest_categories_<?php echo $entry; ?>" style="position:relative; top:1px;"><?php _e('Add new categories and taxonomies', 'pmxi_plugin') ?></label>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ <div class="input">
126
+ <input type="hidden" name="is_keep_attachments_on_update" value="0" />
127
+ <input type="checkbox" id="is_keep_attachments_on_update_<?php echo $entry; ?>" name="is_keep_attachments_on_update" value="1" <?php echo $post['is_keep_attachments_on_update'] ? 'checked="checked"': '' ?> />
128
+ <label for="is_keep_attachments_on_update_<?php echo $entry; ?>"><?php _e('Keep attachments', 'pmxi_plugin') ?></label>
129
  </div>
130
  <div class="input">
131
  <input type="hidden" name="is_keep_images" value="0" />
141
  </div>
142
  <div class="input">
143
  <input type="hidden" name="keep_custom_fields" value="0" />
144
+ <input type="checkbox" id="keep_custom_fields_<?php echo $entry; ?>" name="keep_custom_fields" value="1" <?php echo $post['keep_custom_fields'] ? 'checked="checked"': '' ?> class="switcher switcher-reversed"/>
145
  <label for="keep_custom_fields_<?php echo $entry; ?>"><?php _e('Keep custom fields', 'pmxi_plugin') ?></label>
146
  <a href="#help" class="help" title="<?php _e('If Keep Custom Fields box is checked, it will keep all Custom Fields, and add any new Custom Fields specified in Custom Fields section, as long as they do not overwrite existing fields. If \'Only keep this Custom Fields\' is specified, it will only keep the specified fields.', 'pmxi_plugin') ?>">?</a>
147
  </div>
views/admin/import/process.php CHANGED
@@ -7,7 +7,7 @@
7
  <a href="javascript:void(0);" id="view_log"><?php _e('View Log','pmxi_plugin');?></a><span id="download_log_separator"> | </span> <a href="javascript:void(0);" id="download_log"><?php _e('Download Log','pmxi_plugin');?></a>
8
  <p><?php _e('Warnings','pmxi_plugin');?> (<span id="warnings">0</span>), <?php _e('Errors','pmxi_plugin');?> (<span id="errors">0</span>)</p>
9
  </div>
10
- <fieldset id="logwrapper" <?php if ($_SESSION['pmxi_import']['large_file']): ?> style="display:none;" <?php endif; ?>>
11
  <legend><?php _e('Log','pmxi_plugin');?></legend>
12
  <div id="loglist">
13
 
@@ -69,7 +69,7 @@
69
  // fill log bar
70
  $('.progress-msg').each(function(i){
71
  if ( ! $(this).find('.import_process_bar').length){
72
- <?php if ($_SESSION['pmxi_import']['large_file']): ?>
73
  if ($('#loglist').find('p').length > 100) $('#loglist').html('');
74
  <?php endif; ?>
75
  $('#loglist').append('<p ' + ((odd) ? 'class="odd"' : 'class="even"') + '>' + $(this).html() + '</p>');
@@ -91,7 +91,7 @@
91
  //]]>
92
  </script>
93
 
94
- <?php if ($_SESSION['pmxi_import']['large_file']): ?>
95
 
96
  <script type="text/javascript">
97
  //<![CDATA[
7
  <a href="javascript:void(0);" id="view_log"><?php _e('View Log','pmxi_plugin');?></a><span id="download_log_separator"> | </span> <a href="javascript:void(0);" id="download_log"><?php _e('Download Log','pmxi_plugin');?></a>
8
  <p><?php _e('Warnings','pmxi_plugin');?> (<span id="warnings">0</span>), <?php _e('Errors','pmxi_plugin');?> (<span id="errors">0</span>)</p>
9
  </div>
10
+ <fieldset id="logwrapper" <?php if (PMXI_Plugin::$session->data['pmxi_import']['large_file']): ?> style="display:none;" <?php endif; ?>>
11
  <legend><?php _e('Log','pmxi_plugin');?></legend>
12
  <div id="loglist">
13
 
69
  // fill log bar
70
  $('.progress-msg').each(function(i){
71
  if ( ! $(this).find('.import_process_bar').length){
72
+ <?php if (PMXI_Plugin::$session->data['pmxi_import']['large_file']): ?>
73
  if ($('#loglist').find('p').length > 100) $('#loglist').html('');
74
  <?php endif; ?>
75
  $('#loglist').append('<p ' + ((odd) ? 'class="odd"' : 'class="even"') + '>' + $(this).html() + '</p>');
91
  //]]>
92
  </script>
93
 
94
+ <?php if (PMXI_Plugin::$session->data['pmxi_import']['large_file']): ?>
95
 
96
  <script type="text/javascript">
97
  //<![CDATA[
views/admin/import/tag.php CHANGED
@@ -2,14 +2,14 @@
2
  <div class="tag">
3
  <input type="hidden" name="tagno" value="<?php echo $tagno ?>" />
4
  <div class="title">
5
- <?php printf(__('Record #<strong>%s</strong> out of <strong>%s</strong>', 'pmxi_plugin'), $tagno, ( ! $_SESSION['pmxi_import']['large_file']) ? $elements->length : $_SESSION['pmxi_import']['count']); ?>
6
  <div class="navigation">
7
  <?php if ($tagno > 1): ?><a href="#prev">&lang;&lang;</a><?php else: ?><span>&lang;&lang;</span><?php endif ?>
8
- <?php if ($tagno < $elements->length or ($_SESSION['pmxi_import']['large_file'] and $tagno < $_SESSION['pmxi_import']['count'])): ?><a href="#next">&rang;&rang;</a><?php else: ?><span>&rang;&rang;</span><?php endif ?>
9
  </div>
10
  </div>
11
  <div class="clear"></div>
12
- <div class="xml resetable"> <?php if (!empty($elements->length)) $this->render_xml_element(( ! $_SESSION['pmxi_import']['large_file']) ? $elements->item($tagno - 1) : $elements->item(0), true); ?></div>
13
  <p class="xpath_help">
14
  <?php _e('Operate on elements using your own PHP functions, use FOREACH loops, and more.<br />Read the <a href="http://www.wpallimport.com/portal/" target="_blank">documentation</a> to learn how.', 'pmxi_plugin') ?>
15
  </p>
2
  <div class="tag">
3
  <input type="hidden" name="tagno" value="<?php echo $tagno ?>" />
4
  <div class="title">
5
+ <?php printf(__('Record #<strong>%s</strong> out of <strong>%s</strong>', 'pmxi_plugin'), $tagno, ( ! PMXI_Plugin::$session->data['pmxi_import']['large_file']) ? $elements->length : PMXI_Plugin::$session->data['pmxi_import']['count']); ?>
6
  <div class="navigation">
7
  <?php if ($tagno > 1): ?><a href="#prev">&lang;&lang;</a><?php else: ?><span>&lang;&lang;</span><?php endif ?>
8
+ <?php if ($tagno < $elements->length or (PMXI_Plugin::$session->data['pmxi_import']['large_file'] and $tagno < PMXI_Plugin::$session->data['pmxi_import']['count'])): ?><a href="#next">&rang;&rang;</a><?php else: ?><span>&rang;&rang;</span><?php endif ?>
9
  </div>
10
  </div>
11
  <div class="clear"></div>
12
+ <div class="xml resetable"> <?php if (!empty($elements->length)) $this->render_xml_element(( ! PMXI_Plugin::$session->data['pmxi_import']['large_file']) ? $elements->item($tagno - 1) : $elements->item(0), true); ?></div>
13
  <p class="xpath_help">
14
  <?php _e('Operate on elements using your own PHP functions, use FOREACH loops, and more.<br />Read the <a href="http://www.wpallimport.com/portal/" target="_blank">documentation</a> to learn how.', 'pmxi_plugin') ?>
15
  </p>
views/admin/import/template.php CHANGED
@@ -41,13 +41,14 @@
41
  </div>
42
  </div>
43
  <p>
 
44
  <span class="header-option">
45
  <input type="hidden" name="is_keep_linebreaks" value="0" />
46
  <input type="checkbox" id="is_keep_linebreaks" name="is_keep_linebreaks" value="1" <?php echo $post['is_keep_linebreaks'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;"/>
47
  <label for="is_keep_linebreaks"><?php _e('Keep line breaks from XML', 'pmxi_plugin') ?></label> <br>
48
  <input type="hidden" name="is_leave_html" value="0" />
49
  <input type="checkbox" id="is_leave_html" name="is_leave_html" value="1" <?php echo $post['is_leave_html'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;" class="switcher"/>
50
- <label for="is_leave_html"><?php _e('Decode HTML entities with <b>html_entity_decode</b>', 'pmxi_plugin') ?></label><a class="help" href="#help" original-title="If HTML code is showing up in your posts, use this option. You can also use <br /><br /><i>[html_entity_decode({my/xpath})]</i><br /><br /> or <br /><br /><i>[htmlentities({my/xpath})]</i><br /><br /> to decode or encode HTML in your file.">?</a>
51
  <div class="switcher-target-is_leave_html" style="padding-left:17px;">
52
  <input type="hidden" name="fix_characters" value="0" />
53
  <input type="checkbox" id="fix_characters" name="fix_characters" value="1" <?php echo $post['fix_characters'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;"/>
41
  </div>
42
  </div>
43
  <p>
44
+ <?php $legacy_handling = PMXI_Plugin::getInstance()->getOption('legacy_special_character_handling'); ?>
45
  <span class="header-option">
46
  <input type="hidden" name="is_keep_linebreaks" value="0" />
47
  <input type="checkbox" id="is_keep_linebreaks" name="is_keep_linebreaks" value="1" <?php echo $post['is_keep_linebreaks'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;"/>
48
  <label for="is_keep_linebreaks"><?php _e('Keep line breaks from XML', 'pmxi_plugin') ?></label> <br>
49
  <input type="hidden" name="is_leave_html" value="0" />
50
  <input type="checkbox" id="is_leave_html" name="is_leave_html" value="1" <?php echo $post['is_leave_html'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;" class="switcher"/>
51
+ <label for="is_leave_html"><?php _e('Decode HTML entities with <b>'.(($legacy_handling) ? 'htmlspecialchars_decode' : 'html_entity_decode').'</b>', 'pmxi_plugin') ?></label><a class="help" href="#help" original-title="If HTML code is showing up in your posts, use this option. You can also use <br /><br /><i>[html_entity_decode({my/xpath})]</i><br /><br /> or <br /><br /><i>[htmlentities({my/xpath})]</i><br /><br /> to decode or encode HTML in your file.">?</a>
52
  <div class="switcher-target-is_leave_html" style="padding-left:17px;">
53
  <input type="hidden" name="fix_characters" value="0" />
54
  <input type="checkbox" id="fix_characters" name="fix_characters" value="1" <?php echo $post['fix_characters'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;"/>
views/admin/settings/index.php CHANGED
@@ -58,6 +58,11 @@
58
 
59
  <h3><?php _e('Import Settings', 'pmxi_plugin') ?></h3>
60
  <div><?php printf(__('Chunk maximum size %s (Kb)', 'pmxi_plugin'), '<input type="text" name="chunk_size" value="' . esc_attr($post['chunk_size']) . '"/>') ?></div>
 
 
 
 
 
61
  <p>
62
  <input type="hidden" name="pingbacks" value="0"/>
63
  <?php printf(__('Enable WP_IMPORTING %s', 'pmxi_plugin'), '<input type="checkbox" name="pingbacks" value="1" style="position:relative; top:-2px;" '. (($post['pingbacks']) ? 'checked="checked"' : '') .'/>') ?>
58
 
59
  <h3><?php _e('Import Settings', 'pmxi_plugin') ?></h3>
60
  <div><?php printf(__('Chunk maximum size %s (Kb)', 'pmxi_plugin'), '<input type="text" name="chunk_size" value="' . esc_attr($post['chunk_size']) . '"/>') ?></div>
61
+ <p>
62
+ <input type="hidden" name="legacy_special_character_handling" value="0"/>
63
+ <?php printf(__('<label for="legacy_special_character_handling">Use legacy special character handling</label> %s', 'pmxi_plugin'), '<input type="checkbox" name="legacy_special_character_handling" id="legacy_special_character_handling" value="1" style="position:relative; top:-2px;" '. (($post['legacy_special_character_handling']) ? 'checked="checked"' : '') .'/>') ?>
64
+ <a href="#help" class="help" title="<?php _e('By default wpallimport uses htmlspecialchars() to encode html tags in csv feeds. If this option is enabled that wpallimport will use htmlentities() function.', 'pmxi_plugin') ?>">?</a>
65
+ </p>
66
  <p>
67
  <input type="hidden" name="pingbacks" value="0"/>
68
  <?php printf(__('Enable WP_IMPORTING %s', 'pmxi_plugin'), '<input type="checkbox" name="pingbacks" value="1" style="position:relative; top:-2px;" '. (($post['pingbacks']) ? 'checked="checked"' : '') .'/>') ?>