Simple Lightbox - Version 2.8.0

Version Description

Faster link processing & other optimizations (WordPress 5.3+ & PHP 7.2+ required).

Download this release

Release Info

Developer Archetyped
Plugin Icon wp plugin Simple Lightbox
Version 2.8.0
Comparing to
See all releases

Code changes from version 2.7.1 to 2.8.0

Files changed (53) hide show
  1. .gitignore +3 -1
  2. Gruntfile.js +5 -5
  3. changelog.txt +19 -0
  4. client/js/dev/lib.admin.js +1 -1
  5. client/js/dev/lib.core.js +71 -71
  6. client/js/dev/lib.view.js +486 -448
  7. client/js/prod/lib.admin.js +1 -1
  8. client/js/prod/lib.core.js +1 -1
  9. client/js/prod/lib.view.js +1 -1
  10. client/sass/admin.scss +3 -3
  11. content-handlers/image/js/dev/handler.image.js +1 -1
  12. content-handlers/image/js/prod/handler.image.js +1 -1
  13. controller.php +313 -262
  14. functions.php +1 -1
  15. grunt/phplint.js +2 -2
  16. grunt/sass.js +3 -0
  17. includes/class.admin.php +62 -62
  18. includes/class.admin_action.php +17 -17
  19. includes/class.admin_menu.php +5 -5
  20. includes/class.admin_page.php +18 -13
  21. includes/class.admin_section.php +5 -5
  22. includes/class.admin_view.php +65 -65
  23. includes/class.base.php +57 -57
  24. includes/class.base_collection.php +30 -30
  25. includes/class.base_object.php +29 -29
  26. includes/class.collection_controller.php +10 -10
  27. includes/class.component.php +15 -15
  28. includes/class.content_handler.php +10 -10
  29. includes/class.content_handlers.php +31 -31
  30. includes/class.field_base.php +170 -107
  31. includes/class.field_collection.php +69 -65
  32. includes/class.field_type.php +123 -83
  33. includes/class.fields.php +100 -66
  34. includes/class.option.php +21 -21
  35. includes/class.options.php +156 -118
  36. includes/class.template_tags.php +16 -16
  37. includes/class.theme.php +12 -12
  38. includes/class.themes.php +34 -34
  39. includes/class.utilities.php +168 -168
  40. main.php +14 -14
  41. package-lock.json +1164 -1187
  42. package.json +7 -6
  43. readme.txt +18 -17
  44. template-tags/item/js/dev/tag.item.js +1 -1
  45. template-tags/item/js/prod/tag.item.js +1 -1
  46. template-tags/ui/js/dev/tag.ui.js +6 -6
  47. template-tags/ui/js/prod/tag.ui.js +1 -1
  48. themes/baseline/js/prod/client.js +1 -1
  49. themes/baseline/sass/style.scss +17 -17
  50. themes/black/sass/style.scss +7 -7
  51. themes/default/js/dev/client.js +3 -3
  52. themes/default/js/prod/client.js +1 -1
  53. themes/default/sass/style.scss +31 -31
.gitignore CHANGED
@@ -1 +1,3 @@
1
- .vscode
 
 
1
+ .vscode
2
+ .sass-cache
3
+ node_modules/
Gruntfile.js CHANGED
@@ -11,13 +11,13 @@ module.exports = function(grunt) {
11
  paths : {
12
  // Base dir assets dir
13
  base : 'client',
14
-
15
  // PHP assets
16
  php : {
17
  files_std : ['*.php', '**/*.php', '!node_modules/**/*.php'], // Standard file match
18
  files : '<%= paths.php.files_std %>' // Dynamic file match
19
  },
20
-
21
  // JavaScript assets
22
  js : {
23
  base : 'js', // Base dir
@@ -26,7 +26,7 @@ module.exports = function(grunt) {
26
  files_std : '**/<%= paths.js.src %>/**/*.js', // Standard file match
27
  files : '<%= paths.js.files_std %>' // Dynamic file match
28
  },
29
-
30
  // Sass assets
31
  sass : {
32
  src : 'sass', // Source files dir
@@ -39,10 +39,10 @@ module.exports = function(grunt) {
39
  }
40
  },
41
  });
42
-
43
  // Load task configurations
44
  grunt.loadTasks('grunt');
45
-
46
  // Default Tasks
47
  grunt.registerTask('build', ['phplint', 'jshint:all', 'uglify', 'sass']);
48
  grunt.registerTask('watch_all', ['watch:js', 'watch:sass']);
11
  paths : {
12
  // Base dir assets dir
13
  base : 'client',
14
+
15
  // PHP assets
16
  php : {
17
  files_std : ['*.php', '**/*.php', '!node_modules/**/*.php'], // Standard file match
18
  files : '<%= paths.php.files_std %>' // Dynamic file match
19
  },
20
+
21
  // JavaScript assets
22
  js : {
23
  base : 'js', // Base dir
26
  files_std : '**/<%= paths.js.src %>/**/*.js', // Standard file match
27
  files : '<%= paths.js.files_std %>' // Dynamic file match
28
  },
29
+
30
  // Sass assets
31
  sass : {
32
  src : 'sass', // Source files dir
39
  }
40
  },
41
  });
42
+
43
  // Load task configurations
44
  grunt.loadTasks('grunt');
45
+
46
  // Default Tasks
47
  grunt.registerTask('build', ['phplint', 'jshint:all', 'uglify', 'sass']);
48
  grunt.registerTask('watch_all', ['watch:js', 'watch:sass']);
changelog.txt CHANGED
@@ -1,3 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 2.7.0 =
2
 
3
  * Fix: Remove reference to deprecated `screen_icon()` function (The Icon of Finnegan Island)
1
+ = 2.8.0 =
2
+
3
+ * Update: WordPress 5.3+ required.
4
+ * Update: PHP 7.2+ required.
5
+ * Optimize: Link detection up to 2x faster.
6
+ * Optimize: Options data handling.
7
+ * Optimize: Default title filtering.
8
+ * Optimize: Standardize media item data structure to avoid conflicts with third-party data.
9
+ * Optimize: Load only necessary media item properties in browser.
10
+ * Optimize: Filter all media items (instead of each individual item).
11
+ * Filter Removed: `media_item_properties` (single item).
12
+ * Filter Added: `media_items` (all items).
13
+ * Fix: `area` elements included in link detection (This is Jim's Area).
14
+
15
+ = 2.7.1 =
16
+
17
+ * Update: Confirm compatibility with WordPress 5.0+
18
+ * Optimize: Improved support for captions generated by Block Editor.
19
+
20
  = 2.7.0 =
21
 
22
  * Fix: Remove reference to deprecated `screen_icon()` function (The Icon of Finnegan Island)
client/js/dev/lib.admin.js CHANGED
@@ -11,7 +11,7 @@ if ( !!window.SLB && !!SLB.attach ) { (function ($) {
11
 
12
  SLB.attach('Admin', {
13
  /**
14
- * Initialization routines
15
  */
16
  init: function() {
17
  if ( postboxes ) {
11
 
12
  SLB.attach('Admin', {
13
  /**
14
+ * Initialization routines
15
  */
16
  init: function() {
17
  if ( postboxes ) {
client/js/dev/lib.core.js CHANGED
@@ -9,7 +9,7 @@ if ( window.jQuery ){(function($) {
9
  /**
10
  * Extendible class
11
  * Adapted from John Resig
12
- * @link http://ejohn.org/blog/simple-javascript-inheritance/
13
  */
14
  var c_init = false;
15
  var Class = function() {};
@@ -21,13 +21,13 @@ var Class = function() {};
21
  */
22
  Class.extend = function(members) {
23
  var _super = this.prototype;
24
-
25
  // Copy instance to prototype
26
  c_init = true;
27
  var proto = new this();
28
  c_init = false;
29
-
30
- var val, name;
31
  // Scrub prototype objects (Decouple from super class)
32
  for ( name in proto ) {
33
  if ( $.isPlainObject(proto[name]) ) {
@@ -35,7 +35,7 @@ Class.extend = function(members) {
35
  proto[name] = val;
36
  }
37
  }
38
-
39
  /**
40
  * Create class method with access to super class method
41
  * @param string nm Method name
@@ -67,7 +67,7 @@ Class.extend = function(members) {
67
  proto[name] = ( $.isPlainObject(members[name]) ) ? $.extend({}, members[name]) : members[name];
68
  }
69
  }
70
-
71
  /**
72
  * Class constructor
73
  * Supports pre-construction initilization (`Class._init()`)
@@ -85,17 +85,17 @@ Class.extend = function(members) {
85
  }
86
  }
87
  }
88
-
89
-
90
  // Populate new prototype
91
  Class.prototype = proto;
92
-
93
  // Set constructor
94
  Class.prototype.constructor = Class;
95
-
96
  // Set extender
97
  Class.extend = this.extend;
98
-
99
  // Return function
100
  return Class;
101
  };
@@ -105,7 +105,7 @@ Class.extend = function(members) {
105
  */
106
  var Base = {
107
  /* Properties */
108
-
109
  /**
110
  * Base object flag
111
  * @var bool
@@ -121,9 +121,9 @@ var Base = {
121
  * @var string
122
  */
123
  prefix: 'slb',
124
-
125
  /* Methods */
126
-
127
  /**
128
  * Constructor
129
  * Sets instance parent
@@ -131,7 +131,7 @@ var Base = {
131
  _init: function() {
132
  this._set_parent();
133
  },
134
-
135
  /**
136
  * Set instance parent
137
  * Set utilities parent to current instance
@@ -143,7 +143,7 @@ var Base = {
143
  }
144
  this.util._parent = this;
145
  },
146
-
147
  /**
148
  * Attach new member to instance
149
  * Member can be property (value) or method
@@ -172,11 +172,11 @@ var Base = {
172
  }
173
  return ret;
174
  },
175
-
176
  /**
177
  * Check for child object
178
  * Child object can be multi-level (e.g. Child.Level2child.Level3child)
179
- *
180
  * @param string child Name of child object
181
  */
182
  has_child: function(child) {
@@ -184,7 +184,7 @@ var Base = {
184
  if ( !this.util.is_string(child) ) {
185
  return false;
186
  }
187
-
188
  var children = child.split('.');
189
  child = null;
190
  var o = this;
@@ -202,7 +202,7 @@ var Base = {
202
  }
203
  return true;
204
  },
205
-
206
  /**
207
  * Check if instance is set as a base
208
  * @uses base
@@ -211,7 +211,7 @@ var Base = {
211
  is_base: function() {
212
  return !!this.base;
213
  },
214
-
215
  /**
216
  * Get parent instance
217
  * @uses `Base._parent` property
@@ -232,14 +232,14 @@ var Base = {
232
  */
233
  var Utilities = {
234
  /* Properties */
235
-
236
  _base: null,
237
  _parent: null,
238
-
239
  /* Methods */
240
-
241
  /* Connections */
242
-
243
  /**
244
  * Get base ancestor
245
  * @return obj Base ancestor
@@ -262,7 +262,7 @@ var Utilities = {
262
  }
263
  return this._base;
264
  },
265
-
266
  /**
267
  * Get parent object or parent property value
268
  * @param string prop (optional) Property to retrieve
@@ -281,9 +281,9 @@ var Utilities = {
281
  }
282
  return ret;
283
  },
284
-
285
  /* Prefix */
286
-
287
  /**
288
  * Retrieve valid separator
289
  * If supplied argument is not a valid separator, use default separator
@@ -294,7 +294,7 @@ var Utilities = {
294
  var sep_default = '_';
295
  return ( this.is_string(sep, false) ) ? sep : sep_default;
296
  },
297
-
298
  /**
299
  * Retrieve prefix
300
  * @return string Prefix
@@ -303,14 +303,14 @@ var Utilities = {
303
  var p = this.get_parent('prefix');
304
  return ( this.is_string(p, false) ) ? p : '';
305
  },
306
-
307
  /**
308
  * Check if string is prefixed
309
  */
310
  has_prefix: function(val, sep) {
311
  return ( this.is_string(val) && 0 === val.indexOf(this.get_prefix() + this.get_sep(sep)) );
312
  },
313
-
314
  /**
315
  * Add Prefix to a string
316
  * @param string val Value to add prefix to
@@ -327,10 +327,10 @@ var Utilities = {
327
  if ( !this.is_bool(once) ) {
328
  once = true;
329
  }
330
-
331
  return ( once && this.has_prefix(val, sep) ) ? val : [this.get_prefix(), val].join(sep);
332
  },
333
-
334
  /**
335
  * Remove Prefix from a string
336
  * @param string val Value to add prefix to
@@ -358,9 +358,9 @@ var Utilities = {
358
  }
359
  return val;
360
  },
361
-
362
  /* Attributes */
363
-
364
  /*
365
  * Get attribute name
366
  * @param string attr_base Attribute's base name
@@ -378,9 +378,9 @@ var Utilities = {
378
  }
379
  return attr;
380
  },
381
-
382
  /* Request */
383
-
384
  /**
385
  * Retrieve valid context
386
  * @return array Context
@@ -394,11 +394,11 @@ var Utilities = {
394
  // Return context
395
  return b.context;
396
  },
397
-
398
  /**
399
  * Check if a context exists in current request
400
  * If multiple contexts are supplied, result will be TRUE if at least ONE context exists
401
- *
402
  * @param string|array ctx Context to check for
403
  * @return bool TRUE if context exists, FALSE otherwise
404
  */
@@ -409,9 +409,9 @@ var Utilities = {
409
  }
410
  return ( this.is_array(ctx) && this.arr_intersect(this.get_context(), ctx).length > 0 );
411
  },
412
-
413
  /* Helpers */
414
-
415
  /**
416
  * Check if value is set/defined
417
  * @param mixed val Value to check
@@ -420,7 +420,7 @@ var Utilities = {
420
  is_set: function(val) {
421
  return ( typeof val !== 'undefined' );
422
  },
423
-
424
  /**
425
  * Validate data type
426
  * @param mixed val Value to validate
@@ -443,14 +443,14 @@ var Utilities = {
443
  break;
444
  }
445
  }
446
-
447
  // Validate empty values
448
  if ( ret && ( !this.is_set(nonempty) || !!nonempty ) ) {
449
  ret = !this.is_empty(val);
450
  }
451
  return ret;
452
  },
453
-
454
  /**
455
  * Check if value is a string
456
  * @uses is_type()
@@ -461,7 +461,7 @@ var Utilities = {
461
  is_string: function(value, nonempty) {
462
  return this.is_type(value, 'string', nonempty);
463
  },
464
-
465
  /**
466
  * Check if value is an array
467
  * @uses is_type()
@@ -472,7 +472,7 @@ var Utilities = {
472
  is_array: function(value, nonempty) {
473
  return ( this.is_type(value, 'array', nonempty) );
474
  },
475
-
476
  /**
477
  * Check if value is a boolean
478
  * @uses is_type()
@@ -482,7 +482,7 @@ var Utilities = {
482
  is_bool: function(value) {
483
  return this.is_type(value, 'boolean', false);
484
  },
485
-
486
  /**
487
  * Check if value is an object
488
  * @uses is_type()
@@ -493,7 +493,7 @@ var Utilities = {
493
  is_obj: function(value, nonempty) {
494
  return this.is_type(value, 'object', nonempty);
495
  },
496
-
497
  /**
498
  * Check if value is a function
499
  * @uses is_type()
@@ -503,7 +503,7 @@ var Utilities = {
503
  is_func: function(value) {
504
  return this.is_type(value, 'function', false);
505
  },
506
-
507
  /**
508
  * Checks if an object has a method
509
  * @param obj obj Object to check
@@ -525,7 +525,7 @@ var Utilities = {
525
  }
526
  return ret;
527
  },
528
-
529
  /**
530
  * Check if object is instance of a class
531
  * @param obj obj Instance object
@@ -538,7 +538,7 @@ var Utilities = {
538
  }
539
  return ( this.is_obj(obj) && ( obj instanceof parent ) );
540
  },
541
-
542
  /**
543
  * Check if object is class
544
  * Optionally check if class is sub-class of another class
@@ -555,7 +555,7 @@ var Utilities = {
555
  }
556
  return ret;
557
  },
558
-
559
  /**
560
  * Check if value is a number
561
  * @uses is_type()
@@ -570,7 +570,7 @@ var Utilities = {
570
  };
571
  return ( this.is_type(value, 'number', nonempty) && !f.nan(value) && f.finite(value) );
572
  },
573
-
574
  /**
575
  * Check if value is a integer
576
  * @uses is_type()
@@ -581,7 +581,7 @@ var Utilities = {
581
  is_int: function(value, nonempty) {
582
  return ( this.is_num(value, nonempty) && Math.floor(value) === value );
583
  },
584
-
585
  /**
586
  * Check if value is scalar (string, number, boolean)
587
  * @uses is_type()
@@ -592,7 +592,7 @@ var Utilities = {
592
  is_scalar: function(value, nonempty) {
593
  return ( this.is_num(value, nonempty) || this.is_string(value, nonempty) || this.is_bool(value) );
594
  },
595
-
596
  /**
597
  * Checks if value is empty
598
  * @param mixed value Value to check
@@ -613,7 +613,7 @@ var Utilities = {
613
  x++;
614
  }
615
  }
616
-
617
  // Advanced check
618
  if ( !ret ) {
619
  // Validate type
@@ -638,7 +638,7 @@ var Utilities = {
638
  // Evaluate plain object
639
  if ( Object.getOwnPropertyNames ) {
640
  // Modern browser check
641
- ret = ( Object.getOwnPropertyNames(value).length === 0 );
642
  } else if ( value.hasOwnProperty ) {
643
  // Legacy browser check
644
  ret = true;
@@ -658,18 +658,18 @@ var Utilities = {
658
  }
659
  return ret;
660
  },
661
-
662
  /**
663
  * Check if object is a jQuery.Promise instance
664
  * Will also match (but not guarantee) jQuery.Deferred instances
665
  * @uses is_method()
666
- * @param obj obj Object to check
667
  * @return bool TRUE if object is Promise/Deferred
668
  */
669
  is_promise: function(obj) {
670
  return ( this.is_method(obj, ['then', 'done', 'always', 'fail', 'pipe']) );
671
  },
672
-
673
  /**
674
  * Return formatted string
675
  * @param string fmt Format template
@@ -702,7 +702,7 @@ var Utilities = {
702
  params[x] = '';
703
  }
704
  }
705
-
706
  // Replace all placeholders at once if single parameter set
707
  if ( params.length === 1 ) {
708
  fmt = fmt.replace(ph, params[0].toString());
@@ -721,12 +721,12 @@ var Utilities = {
721
  }
722
  return fmt;
723
  },
724
-
725
  /**
726
  * Checks if key(s) exist in an object
727
  * @param object obj Object to check
728
  * @param string|array key Key(s) to check for in object
729
- * @param bool all (optional) All keys must exist in object? (Default: TRUE)
730
  * @return bool TRUE if key(s) exist in object
731
  */
732
  in_obj: function(obj, key, all) {
@@ -752,7 +752,7 @@ var Utilities = {
752
  }
753
  return ret;
754
  },
755
-
756
  /**
757
  * Retrieve an object's keys
758
  * @param obj Object to parse
@@ -776,7 +776,7 @@ var Utilities = {
776
  }
777
  return keys;
778
  },
779
-
780
  /**
781
  * Find common elements of 2 or more arrays
782
  * @param array arr1 First array
@@ -820,7 +820,7 @@ var Utilities = {
820
  // Return intersection results
821
  return ret;
822
  },
823
-
824
  /**
825
  * Generates a GUID string.
826
  * @returns string The generated GUID.
@@ -835,7 +835,7 @@ var Utilities = {
835
  }
836
  return _p8() + _p8(true) + _p8(true) + _p8();
837
  },
838
-
839
  /**
840
  * Parse URI
841
  * @param string uri URI to parse
@@ -908,18 +908,18 @@ var SLB_Base = Class.extend(Base);
908
  */
909
  var Core = {
910
  /* Properties */
911
-
912
  base: true,
913
  context: [],
914
-
915
  /**
916
  * New object initializer
917
  * @var obj
918
  */
919
  Class: SLB_Base,
920
-
921
  /* Methods */
922
-
923
  /**
924
  * Init
925
  * Set variables, DOM, etc.
9
  /**
10
  * Extendible class
11
  * Adapted from John Resig
12
+ * @link http://ejohn.org/blog/simple-javascript-inheritance/
13
  */
14
  var c_init = false;
15
  var Class = function() {};
21
  */
22
  Class.extend = function(members) {
23
  var _super = this.prototype;
24
+
25
  // Copy instance to prototype
26
  c_init = true;
27
  var proto = new this();
28
  c_init = false;
29
+
30
+ var val, name;
31
  // Scrub prototype objects (Decouple from super class)
32
  for ( name in proto ) {
33
  if ( $.isPlainObject(proto[name]) ) {
35
  proto[name] = val;
36
  }
37
  }
38
+
39
  /**
40
  * Create class method with access to super class method
41
  * @param string nm Method name
67
  proto[name] = ( $.isPlainObject(members[name]) ) ? $.extend({}, members[name]) : members[name];
68
  }
69
  }
70
+
71
  /**
72
  * Class constructor
73
  * Supports pre-construction initilization (`Class._init()`)
85
  }
86
  }
87
  }
88
+
89
+
90
  // Populate new prototype
91
  Class.prototype = proto;
92
+
93
  // Set constructor
94
  Class.prototype.constructor = Class;
95
+
96
  // Set extender
97
  Class.extend = this.extend;
98
+
99
  // Return function
100
  return Class;
101
  };
105
  */
106
  var Base = {
107
  /* Properties */
108
+
109
  /**
110
  * Base object flag
111
  * @var bool
121
  * @var string
122
  */
123
  prefix: 'slb',
124
+
125
  /* Methods */
126
+
127
  /**
128
  * Constructor
129
  * Sets instance parent
131
  _init: function() {
132
  this._set_parent();
133
  },
134
+
135
  /**
136
  * Set instance parent
137
  * Set utilities parent to current instance
143
  }
144
  this.util._parent = this;
145
  },
146
+
147
  /**
148
  * Attach new member to instance
149
  * Member can be property (value) or method
172
  }
173
  return ret;
174
  },
175
+
176
  /**
177
  * Check for child object
178
  * Child object can be multi-level (e.g. Child.Level2child.Level3child)
179
+ *
180
  * @param string child Name of child object
181
  */
182
  has_child: function(child) {
184
  if ( !this.util.is_string(child) ) {
185
  return false;
186
  }
187
+
188
  var children = child.split('.');
189
  child = null;
190
  var o = this;
202
  }
203
  return true;
204
  },
205
+
206
  /**
207
  * Check if instance is set as a base
208
  * @uses base
211
  is_base: function() {
212
  return !!this.base;
213
  },
214
+
215
  /**
216
  * Get parent instance
217
  * @uses `Base._parent` property
232
  */
233
  var Utilities = {
234
  /* Properties */
235
+
236
  _base: null,
237
  _parent: null,
238
+
239
  /* Methods */
240
+
241
  /* Connections */
242
+
243
  /**
244
  * Get base ancestor
245
  * @return obj Base ancestor
262
  }
263
  return this._base;
264
  },
265
+
266
  /**
267
  * Get parent object or parent property value
268
  * @param string prop (optional) Property to retrieve
281
  }
282
  return ret;
283
  },
284
+
285
  /* Prefix */
286
+
287
  /**
288
  * Retrieve valid separator
289
  * If supplied argument is not a valid separator, use default separator
294
  var sep_default = '_';
295
  return ( this.is_string(sep, false) ) ? sep : sep_default;
296
  },
297
+
298
  /**
299
  * Retrieve prefix
300
  * @return string Prefix
303
  var p = this.get_parent('prefix');
304
  return ( this.is_string(p, false) ) ? p : '';
305
  },
306
+
307
  /**
308
  * Check if string is prefixed
309
  */
310
  has_prefix: function(val, sep) {
311
  return ( this.is_string(val) && 0 === val.indexOf(this.get_prefix() + this.get_sep(sep)) );
312
  },
313
+
314
  /**
315
  * Add Prefix to a string
316
  * @param string val Value to add prefix to
327
  if ( !this.is_bool(once) ) {
328
  once = true;
329
  }
330
+
331
  return ( once && this.has_prefix(val, sep) ) ? val : [this.get_prefix(), val].join(sep);
332
  },
333
+
334
  /**
335
  * Remove Prefix from a string
336
  * @param string val Value to add prefix to
358
  }
359
  return val;
360
  },
361
+
362
  /* Attributes */
363
+
364
  /*
365
  * Get attribute name
366
  * @param string attr_base Attribute's base name
378
  }
379
  return attr;
380
  },
381
+
382
  /* Request */
383
+
384
  /**
385
  * Retrieve valid context
386
  * @return array Context
394
  // Return context
395
  return b.context;
396
  },
397
+
398
  /**
399
  * Check if a context exists in current request
400
  * If multiple contexts are supplied, result will be TRUE if at least ONE context exists
401
+ *
402
  * @param string|array ctx Context to check for
403
  * @return bool TRUE if context exists, FALSE otherwise
404
  */
409
  }
410
  return ( this.is_array(ctx) && this.arr_intersect(this.get_context(), ctx).length > 0 );
411
  },
412
+
413
  /* Helpers */
414
+
415
  /**
416
  * Check if value is set/defined
417
  * @param mixed val Value to check
420
  is_set: function(val) {
421
  return ( typeof val !== 'undefined' );
422
  },
423
+
424
  /**
425
  * Validate data type
426
  * @param mixed val Value to validate
443
  break;
444
  }
445
  }
446
+
447
  // Validate empty values
448
  if ( ret && ( !this.is_set(nonempty) || !!nonempty ) ) {
449
  ret = !this.is_empty(val);
450
  }
451
  return ret;
452
  },
453
+
454
  /**
455
  * Check if value is a string
456
  * @uses is_type()
461
  is_string: function(value, nonempty) {
462
  return this.is_type(value, 'string', nonempty);
463
  },
464
+
465
  /**
466
  * Check if value is an array
467
  * @uses is_type()
472
  is_array: function(value, nonempty) {
473
  return ( this.is_type(value, 'array', nonempty) );
474
  },
475
+
476
  /**
477
  * Check if value is a boolean
478
  * @uses is_type()
482
  is_bool: function(value) {
483
  return this.is_type(value, 'boolean', false);
484
  },
485
+
486
  /**
487
  * Check if value is an object
488
  * @uses is_type()
493
  is_obj: function(value, nonempty) {
494
  return this.is_type(value, 'object', nonempty);
495
  },
496
+
497
  /**
498
  * Check if value is a function
499
  * @uses is_type()
503
  is_func: function(value) {
504
  return this.is_type(value, 'function', false);
505
  },
506
+
507
  /**
508
  * Checks if an object has a method
509
  * @param obj obj Object to check
525
  }
526
  return ret;
527
  },
528
+
529
  /**
530
  * Check if object is instance of a class
531
  * @param obj obj Instance object
538
  }
539
  return ( this.is_obj(obj) && ( obj instanceof parent ) );
540
  },
541
+
542
  /**
543
  * Check if object is class
544
  * Optionally check if class is sub-class of another class
555
  }
556
  return ret;
557
  },
558
+
559
  /**
560
  * Check if value is a number
561
  * @uses is_type()
570
  };
571
  return ( this.is_type(value, 'number', nonempty) && !f.nan(value) && f.finite(value) );
572
  },
573
+
574
  /**
575
  * Check if value is a integer
576
  * @uses is_type()
581
  is_int: function(value, nonempty) {
582
  return ( this.is_num(value, nonempty) && Math.floor(value) === value );
583
  },
584
+
585
  /**
586
  * Check if value is scalar (string, number, boolean)
587
  * @uses is_type()
592
  is_scalar: function(value, nonempty) {
593
  return ( this.is_num(value, nonempty) || this.is_string(value, nonempty) || this.is_bool(value) );
594
  },
595
+
596
  /**
597
  * Checks if value is empty
598
  * @param mixed value Value to check
613
  x++;
614
  }
615
  }
616
+
617
  // Advanced check
618
  if ( !ret ) {
619
  // Validate type
638
  // Evaluate plain object
639
  if ( Object.getOwnPropertyNames ) {
640
  // Modern browser check
641
+ ret = ( Object.getOwnPropertyNames(value).length === 0 );
642
  } else if ( value.hasOwnProperty ) {
643
  // Legacy browser check
644
  ret = true;
658
  }
659
  return ret;
660
  },
661
+
662
  /**
663
  * Check if object is a jQuery.Promise instance
664
  * Will also match (but not guarantee) jQuery.Deferred instances
665
  * @uses is_method()
666
+ * @param obj obj Object to check
667
  * @return bool TRUE if object is Promise/Deferred
668
  */
669
  is_promise: function(obj) {
670
  return ( this.is_method(obj, ['then', 'done', 'always', 'fail', 'pipe']) );
671
  },
672
+
673
  /**
674
  * Return formatted string
675
  * @param string fmt Format template
702
  params[x] = '';
703
  }
704
  }
705
+
706
  // Replace all placeholders at once if single parameter set
707
  if ( params.length === 1 ) {
708
  fmt = fmt.replace(ph, params[0].toString());
721
  }
722
  return fmt;
723
  },
724
+
725
  /**
726
  * Checks if key(s) exist in an object
727
  * @param object obj Object to check
728
  * @param string|array key Key(s) to check for in object
729
+ * @param bool all (optional) All keys must exist in object? (Default: TRUE)
730
  * @return bool TRUE if key(s) exist in object
731
  */
732
  in_obj: function(obj, key, all) {
752
  }
753
  return ret;
754
  },
755
+
756
  /**
757
  * Retrieve an object's keys
758
  * @param obj Object to parse
776
  }
777
  return keys;
778
  },
779
+
780
  /**
781
  * Find common elements of 2 or more arrays
782
  * @param array arr1 First array
820
  // Return intersection results
821
  return ret;
822
  },
823
+
824
  /**
825
  * Generates a GUID string.
826
  * @returns string The generated GUID.
835
  }
836
  return _p8() + _p8(true) + _p8(true) + _p8();
837
  },
838
+
839
  /**
840
  * Parse URI
841
  * @param string uri URI to parse
908
  */
909
  var Core = {
910
  /* Properties */
911
+
912
  base: true,
913
  context: [],
914
+
915
  /**
916
  * New object initializer
917
  * @var obj
918
  */
919
  Class: SLB_Base,
920
+
921
  /* Methods */
922
+
923
  /**
924
  * Init
925
  * Set variables, DOM, etc.
client/js/dev/lib.view.js CHANGED
@@ -10,7 +10,7 @@ if ( !!window.SLB && !!SLB.attach ) { (function ($) {
10
  /*-** Controller **-*/
11
 
12
  var View = {
13
-
14
  /* Properties */
15
 
16
  /**
@@ -24,40 +24,40 @@ var View = {
24
  * > type: Asset type (attachment, image, etc.)
25
  */
26
  assets: {},
27
-
28
  /**
29
  * Component types that can have default instances
30
  * @var array
31
  */
32
  component_defaults: [],
33
-
34
  /**
35
  * Collection of jQuery.Deferred instances added during loading routine
36
  * @var array
37
  */
38
  loading: [],
39
-
40
  /**
41
  * Cache
42
  * @var object
43
  */
44
  cache: {},
45
-
46
  /**
47
  * Temporary component instances
48
  * For use by controller when no component instance is available
49
  * > Key: Component slug
50
- * > Value: Component instance
51
  */
52
  component_temps: {},
53
-
54
  /* Options */
55
  options: {},
56
-
57
  /* Methods */
58
-
59
  /* Init */
60
-
61
  /**
62
  * Instance initialization
63
  */
@@ -68,7 +68,7 @@ var View = {
68
  // Components
69
  this.init_components();
70
  },
71
-
72
  /**
73
  * Update component references in component definitions
74
  */
@@ -96,7 +96,7 @@ var View = {
96
  }
97
  }
98
  },
99
-
100
  /**
101
  * Initialize Components
102
  */
@@ -105,7 +105,7 @@ var View = {
105
  this.Viewer
106
  ];
107
  },
108
-
109
  /**
110
  * Client Initialization
111
  * @param obj options Global options
@@ -116,9 +116,9 @@ var View = {
116
  $.when.apply($, this.loading).always(function() {
117
  // Set options
118
  $.extend(true, t.options, options);
119
-
120
  /* Event handlers */
121
-
122
  // History
123
  $(window).on('popstate', function(e) {
124
  var state = e.originalEvent.state;
@@ -128,14 +128,14 @@ var View = {
128
  return e.preventDefault();
129
  }
130
  });
131
-
132
  /* Set defaults */
133
-
134
  // Items
135
  t.init_items();
136
  });
137
  },
138
-
139
  /* Components */
140
 
141
  /**
@@ -147,7 +147,7 @@ var View = {
147
  can_make_default_component: function(type) {
148
  return ( -1 !== $.inArray(type, this.component_defaults) );
149
  },
150
-
151
  /**
152
  * Check if object is valid component class
153
  * @param func comp Component to check
@@ -156,7 +156,7 @@ var View = {
156
  is_component: function(comp) {
157
  return ( this.util.is_class(comp, this.Component) );
158
  },
159
-
160
  /**
161
  * Retrieve collection of components of specified type
162
  * @param func type Component type
@@ -175,7 +175,7 @@ var View = {
175
  }
176
  return ret;
177
  },
178
-
179
  /**
180
  * Retrieve component from specific collection
181
  * @param function type Component type
@@ -192,7 +192,7 @@ var View = {
192
  if ( !this.util.is_string(id) ) {
193
  id = null;
194
  }
195
-
196
  // Get component from collection
197
  var coll = this.get_components(type);
198
  if ( this.util.is_obj(coll) ) {
@@ -201,7 +201,7 @@ var View = {
201
  ret = coll[tid];
202
  }
203
  }
204
-
205
  // Default: Create default component
206
  if ( this.util.is_empty(ret) ) {
207
  if ( this.util.is_string(id) || this.can_make_default_component(type) ) {
@@ -211,7 +211,7 @@ var View = {
211
  // Return component
212
  return ret;
213
  },
214
-
215
  /**
216
  * Create new component instance and save to appropriate collection
217
  * @param function type Component type to create
@@ -245,7 +245,7 @@ var View = {
245
  else {
246
  ret = new type(id, options);
247
  }
248
-
249
  // Add new component to collection
250
  if ( this.util.is_type(ret, type) ) {
251
  // Get collection
@@ -265,7 +265,7 @@ var View = {
265
  // Return new component
266
  return ret;
267
  },
268
-
269
  /**
270
  * Create new temporary component instance
271
  * @param function type Component type
@@ -281,7 +281,7 @@ var View = {
281
  }
282
  return ret;
283
  },
284
-
285
  /**
286
  * Retrieve temporary component instance
287
  * Creates new temp component instance for type if not previously created
@@ -291,18 +291,18 @@ var View = {
291
  get_component_temp: function(type) {
292
  return ( this.has_component_temp(type) ) ? this.component_temps[type.prototype._slug] : this.add_component_temp(type);
293
  },
294
-
295
  /**
296
  * Check if temporary component instance exists
297
  * @param function type Component type to check for
298
- * @return bool TRUE if temp instance exists, FALSE otherwise
299
  */
300
  has_component_temp: function(type) {
301
  return ( this.is_component(type) && ( type.prototype._slug in this.component_temps ) ) ? true : false;
302
  },
303
-
304
  /* Properties */
305
-
306
  /**
307
  * Retrieve specified options
308
  * @param array opts Array of option names
@@ -323,11 +323,11 @@ var View = {
323
  if ( !( opts[x] in this.options ) ) {
324
  continue;
325
  }
326
- ret[ opts[x] ] = this.options[ opts[x] ];
327
  }
328
  return ret;
329
  },
330
-
331
  /**
332
  * Retrieve option
333
  * @uses View.options
@@ -344,9 +344,9 @@ var View = {
344
  }
345
  return ret;
346
  },
347
-
348
  /* Viewers */
349
-
350
  /**
351
  * Add viewer instance to collection
352
  * @param string id Viewer ID
@@ -361,7 +361,7 @@ var View = {
361
  // Return viewer
362
  return v;
363
  },
364
-
365
  /**
366
  * Retrieve all viewer instances
367
  * @return obj Viewer instances
@@ -369,7 +369,7 @@ var View = {
369
  get_viewers: function() {
370
  return this.get_components(this.Viewer);
371
  },
372
-
373
  /**
374
  * Check if viewer exists
375
  * @param string v Viewer ID
@@ -378,7 +378,7 @@ var View = {
378
  has_viewer: function(v) {
379
  return ( this.util.is_string(v) && v in this.get_viewers() ) ? true : false;
380
  },
381
-
382
  /**
383
  * Retrieve Viewer instance
384
  * Default viewer retrieved if specified viewer does not exist
@@ -398,9 +398,9 @@ var View = {
398
  }
399
  return this.get_viewers()[v];
400
  },
401
-
402
  /* Items */
403
-
404
  /**
405
  * Set event handlers
406
  */
@@ -414,13 +414,13 @@ var View = {
414
  }
415
  return !ret;
416
  };
417
-
418
  // Get activated links
419
  var sel = this.util.format('a[href][%s="%s"]', this.util.get_attribute('active'), 1);
420
  // Add event handler
421
  $(document).on('click', sel, null, handler);
422
  },
423
-
424
  /**
425
  * Retrieve cached items
426
  * @return obj Items collection
@@ -428,7 +428,7 @@ var View = {
428
  get_items: function() {
429
  return this.get_components(this.Content_Item);
430
  },
431
-
432
  /**
433
  * Retrieve specific Content_Item instance
434
  * @param mixed Item reference
@@ -439,14 +439,14 @@ var View = {
439
  */
440
  get_item: function(ref) {
441
  // Evaluate reference type
442
-
443
  // Content Item instance
444
  if ( this.util.is_type(ref, this.Content_Item) ) {
445
  return ref;
446
  }
447
  // Retrieve item instance
448
  var item = null;
449
-
450
  // DOM element
451
  if ( this.util.in_obj(ref, 'nodeType') ) {
452
  // Check if item instance attached to element
@@ -466,7 +466,7 @@ var View = {
466
  }
467
  return item;
468
  },
469
-
470
  /**
471
  * Create new item instance
472
  * @param obj el DOM element representing item
@@ -475,16 +475,16 @@ var View = {
475
  add_item: function(el) {
476
  return ( new this.Content_Item(el) );
477
  },
478
-
479
  /**
480
  * Display item in viewer
481
  * @param obj el DOM element representing item
482
- * @return bool Display result (TRUE if item displayed without issues)
483
  */
484
  show_item: function(el) {
485
  return this.get_item(el).show();
486
  },
487
-
488
  /**
489
  * Cache item instance
490
  * @uses View.get_items() to retrieve item cache
@@ -500,9 +500,9 @@ var View = {
500
  // Return item instance
501
  return item;
502
  },
503
-
504
  /* Content Handler */
505
-
506
  /**
507
  * Retrieve content handlers
508
  * @return object Content handlers
@@ -510,11 +510,11 @@ var View = {
510
  get_content_handlers: function() {
511
  return this.get_components(this.Content_Handler);
512
  },
513
-
514
  /**
515
  * Find matching content handler for item
516
  * @param Content_Item|string item Item to find handler for (or ID of Handler)
517
- * @return Content_Handler|null Matching content handler (NULL if no matching handler found)
518
  */
519
  get_content_handler: function(item) {
520
  // Determine handler to retrieve
@@ -523,7 +523,7 @@ var View = {
523
  var types = this.get_content_handlers();
524
  return ( type in types ) ? types[type] : null;
525
  },
526
-
527
  /**
528
  * Add/Update Content Handler
529
  * @param string id Handler ID
@@ -551,9 +551,9 @@ var View = {
551
  }
552
  return hdl;
553
  },
554
-
555
  /* Group */
556
-
557
  /**
558
  * Add new group
559
  * @param string g Group ID
@@ -569,7 +569,7 @@ var View = {
569
 
570
  return g;
571
  },
572
-
573
  /**
574
  * Retrieve groups
575
  * @uses groups property
@@ -578,7 +578,7 @@ var View = {
578
  get_groups: function() {
579
  return this.get_components(this.Group);
580
  },
581
-
582
  /**
583
  * Retrieve specified group
584
  * New group created if not yet set
@@ -591,7 +591,7 @@ var View = {
591
  get_group: function(g) {
592
  return ( !this.has_group(g) ) ? this.add_group(g) : this.get_groups()[g];
593
  },
594
-
595
  /**
596
  * Checks if group is registered
597
  * @uses get_groups() to retrieve registered groups
@@ -600,9 +600,9 @@ var View = {
600
  has_group: function(g) {
601
  return ( this.util.is_string(g) && ( g in this.get_groups() ) );
602
  },
603
-
604
  /* Theme */
605
-
606
  /**
607
  * Add/Update theme
608
  * @param string name Theme name
@@ -616,16 +616,16 @@ var View = {
616
  }
617
  var dfr = $.Deferred();
618
  this.loading.push(dfr);
619
-
620
  // Get model if it already exists
621
  var model = this.get_theme_model(id);
622
-
623
  // Create default attributes for new theme
624
  if ( this.util.is_empty(model) ) {
625
  // Save default model
626
  model = this.save_theme_model( {'parent': null, 'id': id} );
627
  }
628
-
629
  // Add custom attributes
630
  if ( this.util.is_obj(attr) ) {
631
  // Sanitize
@@ -634,22 +634,22 @@ var View = {
634
  }
635
  $.extend(model, attr);
636
  }
637
-
638
  // Load styles
639
  if ( this.util.in_obj(attr, 'styles') ) {
640
  this.load_styles(attr.styles);
641
  }
642
-
643
  // Link parent model
644
  if ( !this.util.is_obj(model.parent) ) {
645
  model.parent = this.get_theme_model(model.parent);
646
  }
647
-
648
  // Complete loading when all components loaded
649
  dfr.resolve();
650
  return model;
651
  },
652
-
653
  /**
654
  * Retrieve theme models
655
  * @return obj Theme models
@@ -658,7 +658,7 @@ var View = {
658
  // Retrieve matching theme model
659
  return this.Theme.prototype._models;
660
  },
661
-
662
  /**
663
  * Retrieve theme model
664
  * @param string id Theme to retrieve
@@ -668,7 +668,7 @@ var View = {
668
  var ms = this.get_theme_models();
669
  return ( this.util.in_obj(ms, id) ) ? ms[id] : {};
670
  },
671
-
672
  /**
673
  * Save theme model
674
  * @uses View.get_theme_models() to retrieve Theme model collection
@@ -682,7 +682,7 @@ var View = {
682
  }
683
  return model;
684
  },
685
-
686
  /**
687
  * Add/Update Template Tag Handler
688
  * @param string id Handler ID
@@ -694,7 +694,7 @@ var View = {
694
  return false;
695
  }
696
  var hdl;
697
- var hdls = this.get_template_tag_handlers();
698
  if ( this.util.in_obj(hdls, id) ) {
699
  // Update existing handler
700
  hdl = hdls[id];
@@ -714,7 +714,7 @@ var View = {
714
  }
715
  return hdl;
716
  },
717
-
718
  /**
719
  * Retrieve Template Tag Handler collection
720
  * @return obj Template_Tag_Handler objects
@@ -722,7 +722,7 @@ var View = {
722
  get_template_tag_handlers: function() {
723
  return this.Template_Tag.prototype.handlers;
724
  },
725
-
726
  /**
727
  * Retrieve template tag handler
728
  * @param string id ID of tag handler to retrieve
@@ -731,12 +731,12 @@ var View = {
731
  get_template_tag_handler: function(id) {
732
  var handlers = this.get_template_tag_handlers();
733
  // Retrieve existing handler or return new handler
734
- return ( this.util.in_obj(handlers, id) ) ? handlers[id] : null;
735
  },
736
-
737
  /**
738
  * Load styles
739
- * @param array styles Styles to load
740
  */
741
  load_styles: function(styles) {
742
  if ( this.util.is_array(styles) ) {
@@ -757,21 +757,21 @@ var View = {
757
  /* Components */
758
  var Component = {
759
  /*-** Properties **-*/
760
-
761
  /* Internal/Configuration */
762
-
763
  /**
764
  * Base name of component type
765
  * @var string
766
  */
767
  _slug: 'component',
768
-
769
  /**
770
  * Component namespace
771
- * @var string
772
  */
773
  _ns: null,
774
-
775
  /**
776
  * Valid component references for current component
777
  * @var object
@@ -779,20 +779,20 @@ var Component = {
779
  * > Value (function): Data type of component
780
  */
781
  _refs: {},
782
-
783
  /**
784
  * Whether DOM element and component are connected in 1:1 relationship
785
  * Some components will be assigned to different DOM elements depending on usage
786
  * @var bool
787
  */
788
  _reciprocal: false,
789
-
790
  /**
791
  * DOM Element tied to component
792
- * @var DOM Element
793
  */
794
  _dom: null,
795
-
796
  /**
797
  * Component attributes
798
  * @var object
@@ -806,25 +806,25 @@ var Component = {
806
  * @var object
807
  */
808
  _attr_default: {},
809
-
810
  /**
811
  * Flag indicates whether default attributes have previously been parsed
812
  * @var bool
813
  */
814
  _attr_default_parsed: false,
815
-
816
  /**
817
  * Attributes passed to constructor
818
  * @var obj
819
  */
820
  _attr_init: null,
821
-
822
  /**
823
  * Defines how parent properties should be remapped to component properties
824
  * @var object
825
  */
826
  _attr_map: {},
827
-
828
  /**
829
  * Event handlers
830
  * @var object
@@ -832,7 +832,7 @@ var Component = {
832
  * > Value: array Handlers
833
  */
834
  _events: {},
835
-
836
  /**
837
  * Status management
838
  * @var object
@@ -840,15 +840,15 @@ var Component = {
840
  * > Value: Status value
841
  */
842
  _status: null,
843
-
844
  /**
845
  * Component ID
846
  * @var string
847
  */
848
  _id: '',
849
-
850
  /* Init */
851
-
852
  /**
853
  * Constructor
854
  * @param string id (optional) Component ID (Default ID will be generated if no valid ID provided)
@@ -864,7 +864,7 @@ var Component = {
864
  // Call hooks
865
  this._hooks();
866
  },
867
-
868
  /**
869
  * Set Component parent to View module
870
  * @uses `_super._set_parent()`
@@ -872,17 +872,17 @@ var Component = {
872
  _set_parent: function() {
873
  this._super(View);
874
  },
875
-
876
  /**
877
  * Register hooks on init
878
  * Placeholder method to be overridden by child classes
879
  */
880
  _hooks: function() {},
881
-
882
  /* Methods */
883
-
884
  /* Properties */
885
-
886
  /**
887
  * Set instance ID
888
  * Instance ID can only be set once (will not change ID if valid ID already set)
@@ -898,7 +898,7 @@ var Component = {
898
  }
899
  return this._id;
900
  },
901
-
902
  /**
903
  * Retrieve instance ID
904
  * @uses id as ID base
@@ -913,10 +913,10 @@ var Component = {
913
  if ( this.util.is_bool(ns) && ns ) {
914
  id = this.add_ns(id);
915
  }
916
-
917
  return id;
918
  },
919
-
920
  /**
921
  * Get namespace
922
  * @uses _slug for namespace segment
@@ -929,7 +929,7 @@ var Component = {
929
  }
930
  return this._ns;
931
  },
932
-
933
  /**
934
  * Add namespace to value
935
  * @param string val Value to namespace
@@ -938,7 +938,7 @@ var Component = {
938
  add_ns: function(val) {
939
  return ( this.util.is_string(val) ) ? this.get_ns() + '_' + val : '';
940
  },
941
-
942
  /**
943
  * Retrieve status
944
  * @param string id Status to retrieve
@@ -952,7 +952,7 @@ var Component = {
952
  }
953
  return ret;
954
  },
955
-
956
  /**
957
  * Set status
958
  * @param string id Status to retrieve
@@ -977,7 +977,7 @@ var Component = {
977
  }
978
  return val;
979
  },
980
-
981
  /**
982
  * Get controller object
983
  * @uses get_parent() (alias)
@@ -986,9 +986,9 @@ var Component = {
986
  get_controller: function() {
987
  return this.get_parent();
988
  },
989
-
990
  /* Components */
991
-
992
  /**
993
  * Check if reference exists in object
994
  * @param string ref Reference ID
@@ -997,7 +997,7 @@ var Component = {
997
  has_reference: function(ref) {
998
  return ( this.util.is_string(ref) && ( ref in this ) && ( ref in this.get_references() ) ) ? true : false;
999
  },
1000
-
1001
  /**
1002
  * Retrieve object references
1003
  * @uses _refs
@@ -1007,7 +1007,7 @@ var Component = {
1007
  get_references: function() {
1008
  return this._refs;
1009
  },
1010
-
1011
  /**
1012
  * Retrieve reference data type
1013
  * @param string ref Reference ID
@@ -1016,7 +1016,7 @@ var Component = {
1016
  get_reference: function(ref) {
1017
  return ( this.has_reference(ref) ) ? this._refs[ref] : null;
1018
  },
1019
-
1020
  /**
1021
  * Retrieve component reference from current object
1022
  * > Procedure:
@@ -1035,24 +1035,24 @@ var Component = {
1035
  if ( !this.has_reference(cname) ) {
1036
  return c;
1037
  }
1038
-
1039
  // Initialize options
1040
  var opt_defaults = {
1041
  check_attr: true,
1042
  get_default: false
1043
  };
1044
  options = $.extend({}, opt_defaults, options);
1045
-
1046
  // Get component type
1047
  var ctype = this.get_reference(cname);
1048
-
1049
  // Phase 1: Check if component reference previously set
1050
  if ( this.util.is_type(this[cname], ctype) ) {
1051
  return this[cname];
1052
  }
1053
  // If reference not set, iterate through component hierarchy until reference is found
1054
  c = this[cname] = null;
1055
-
1056
  // Phase 2: Check attributes
1057
  if ( options.check_attr ) {
1058
  c = this.get_attribute(cname);
@@ -1061,14 +1061,14 @@ var Component = {
1061
  c = this.set_component(cname, c);
1062
  }
1063
  }
1064
-
1065
  // Phase 3: From controller (optional)
1066
  if ( this.util.is_empty(c) && options.get_default ) {
1067
  c = this.get_controller().get_component(ctype);
1068
  }
1069
  return c;
1070
  },
1071
-
1072
  /**
1073
  * Sets component reference on current object
1074
  * > Component property reset (set to NULL) if invalid component supplied
@@ -1083,31 +1083,31 @@ var Component = {
1083
  if ( !this.has_reference(name) ) {
1084
  return invalid;
1085
  }
1086
-
1087
  // Validate reference
1088
  if ( this.util.is_empty(ref) ) {
1089
  ref = invalid;
1090
  } else {
1091
  var ctype = this.get_reference(name);
1092
-
1093
  // Get component from controller when ID supplied
1094
  if ( this.util.is_string(ref, false) ) {
1095
  ref = this.get_controller().get_component(ctype, ref);
1096
  }
1097
-
1098
  // Validation callback
1099
  if ( !this.util.is_type(ref, ctype) || ( this.util.is_func(validate) && !validate.call(this, ref) ) ) {
1100
  ref = invalid;
1101
  }
1102
  }
1103
-
1104
  // Set (or clear) component reference
1105
  this[name] = ref;
1106
  // Return value for confirmation
1107
  return this[name];
1108
  },
1109
-
1110
-
1111
  /**
1112
  * Clear component reference
1113
  * @uses set_component() to handle component manipulation
@@ -1118,7 +1118,7 @@ var Component = {
1118
  },
1119
 
1120
  /* Attributes */
1121
-
1122
  /**
1123
  * Initialize attributes
1124
  * @param bool force (optional) Force full initialization of attributes (Default: FALSE)
@@ -1140,7 +1140,7 @@ var Component = {
1140
  $.extend(a, this.get_dom_attributes());
1141
  }
1142
  },
1143
-
1144
  /**
1145
  * Generate default attributes for component
1146
  * @uses View.get_options() to get values from controller
@@ -1152,7 +1152,7 @@ var Component = {
1152
  // Get options from controller
1153
  if ( !this._attr_default_parsed && this.util.is_obj(this._attr_map) ) {
1154
  var opts = this.get_controller().get_options(this.util.obj_keys(this._attr_map));
1155
-
1156
  if ( this.util.is_obj(opts) ) {
1157
  // Remap
1158
  for ( var opt in this._attr_map ) {
@@ -1170,7 +1170,7 @@ var Component = {
1170
  }
1171
  return this._attr_default;
1172
  },
1173
-
1174
  /**
1175
  * Retrieve DOM attributes
1176
  * @return obj DOM Attributes
@@ -1196,7 +1196,7 @@ var Component = {
1196
  }
1197
  return attrs;
1198
  },
1199
-
1200
  /**
1201
  * Retrieve all instance attributes
1202
  * @uses init_attributes() to initialize attributes (if necessary)
@@ -1209,7 +1209,7 @@ var Component = {
1209
  // Return attributes
1210
  return this._attributes;
1211
  },
1212
-
1213
  /**
1214
  * Retrieve value of specified attribute for value
1215
  * @param string key Attribute to retrieve
@@ -1230,7 +1230,7 @@ var Component = {
1230
  if ( !this.util.is_bool(enforce_type) ) {
1231
  enforce_type = true;
1232
  }
1233
-
1234
  // Get attribute value
1235
  var ret = ( this.has_attribute(key) ) ? this.get_attributes()[key] : def;
1236
  // Validate type
@@ -1265,7 +1265,7 @@ var Component = {
1265
  }
1266
  return ret;
1267
  },
1268
-
1269
  /**
1270
  * Call attribute as method
1271
  * @param string attr Attribute to call
@@ -1282,7 +1282,7 @@ var Component = {
1282
  }
1283
  return attr;
1284
  },
1285
-
1286
  /**
1287
  * Check if attribute exists
1288
  * @param string key Attribute name
@@ -1291,7 +1291,7 @@ var Component = {
1291
  has_attribute: function(key) {
1292
  return ( this.util.is_string(key) && ( key in this.get_attributes() ) );
1293
  },
1294
-
1295
  /**
1296
  * Set component attributes
1297
  * @param obj attributes Attributes to set
@@ -1305,13 +1305,13 @@ var Component = {
1305
 
1306
  // Initialize attributes
1307
  this.init_attributes(full);
1308
-
1309
  // Merge new/existing attributes
1310
  if ( this.util.is_obj(attributes) ) {
1311
  $.extend(this._attributes, attributes);
1312
  }
1313
  },
1314
-
1315
  /**
1316
  * Set value for a component attribute
1317
  * @uses get_attributes() to retrieve attributes
@@ -1325,7 +1325,7 @@ var Component = {
1325
  }
1326
  return val;
1327
  },
1328
-
1329
  /* DOM */
1330
 
1331
  /**
@@ -1336,7 +1336,7 @@ var Component = {
1336
  dom_get_selector: function(element) {
1337
  return ( this.util.is_string(element) ) ? '.' + this.add_ns(element) : '';
1338
  },
1339
-
1340
  dom_get_attribute: function() {
1341
  return this.util.get_attribute(this._slug);
1342
  },
@@ -1357,7 +1357,7 @@ var Component = {
1357
  }
1358
  return el;
1359
  },
1360
-
1361
  /**
1362
  * Retrieve attached DOM element
1363
  * @uses _dom to retrieve attached DOM element
@@ -1374,7 +1374,7 @@ var Component = {
1374
  'put': false
1375
  };
1376
  options = ( this.util.is_obj(options) ) ? $.extend({}, opts_default, options) : opts_default;
1377
-
1378
  // Init Component DOM
1379
  if ( options.init && !this.get_status('dom_init') ) {
1380
  this.set_status('dom_init');
@@ -1394,13 +1394,13 @@ var Component = {
1394
  }
1395
  return $(ret);
1396
  },
1397
-
1398
  /**
1399
  * Initialize DOM element
1400
  * To be overridden by child classes
1401
  */
1402
  dom_init: function() {},
1403
-
1404
  /**
1405
  * Wrap output in DOM element
1406
  * Wrapper element created and added to main DOM element if not yet created
@@ -1450,28 +1450,28 @@ var Component = {
1450
  $(r).append(options.content);
1451
  return $(r);
1452
  },
1453
-
1454
  /**
1455
  * Check if DOM element is set for instance
1456
- * DOM is initialized before evaluation
1457
  * @return bool TRUE if DOM element set, FALSE otherwise
1458
  */
1459
  dom_has: function() {
1460
  return ( !!this.dom_get().length );
1461
  },
1462
-
1463
  /* Data */
1464
-
1465
  /**
1466
  * Retrieve key used to store data in DOM element
1467
- * @return string Data key
1468
  */
1469
  get_data_key: function() {
1470
  return this.get_ns();
1471
  },
1472
-
1473
  /* Events */
1474
-
1475
  /**
1476
  * Register event handler for custom event
1477
  * Structure
@@ -1485,11 +1485,11 @@ var Component = {
1485
  * @param function fn Event handler
1486
  * @param obj options Handler registration options
1487
  * > clear (bool) Clear existing event handlers before setting current handler (Default: FALSE)
1488
- * @return obj Component instance (allows chaining)
1489
  */
1490
  on: function(event, fn, options) {
1491
  // Handle request types
1492
- if ( !this.util.is_string(event) || !this.util.is_func(fn) ) {
1493
  var t = this;
1494
  var args = Array.prototype.slice.call(arguments, 1);
1495
  if ( this.util.is_array(event) ) {
@@ -1507,7 +1507,7 @@ var Component = {
1507
  }
1508
 
1509
  // Options
1510
-
1511
  // Default options
1512
  var options_std = {
1513
  clear: false
@@ -1531,7 +1531,7 @@ var Component = {
1531
  es[event].push(fn);
1532
  return this;
1533
  },
1534
-
1535
  /**
1536
  * Trigger custom event
1537
  * Event handlers are executed in the context of the current component instance
@@ -1592,18 +1592,18 @@ View.Component = Component = SLB.Class.extend(Component);
1592
  * @param obj options Init options
1593
  */
1594
  var Viewer = {
1595
-
1596
  /* Configuration */
1597
-
1598
  _slug: 'viewer',
1599
-
1600
  _refs: {
1601
  item: 'Content_Item',
1602
  theme: 'Theme'
1603
  },
1604
-
1605
  _reciprocal: true,
1606
-
1607
  _attr_default: {
1608
  loop: true,
1609
  animate: true,
@@ -1627,7 +1627,7 @@ var Viewer = {
1627
  loading: 'loading'
1628
  }
1629
  },
1630
-
1631
  _attr_map: {
1632
  'theme': null,
1633
  'group_loop': 'loop',
@@ -1640,40 +1640,40 @@ var Viewer = {
1640
  'slideshow_autostart': null,
1641
  'slideshow_duration': null
1642
  },
1643
-
1644
  /* References */
1645
-
1646
  /**
1647
  * Item currently loaded in viewer
1648
  * @var object Content_Item
1649
  */
1650
  item: null,
1651
-
1652
  /**
1653
  * Queued item to be loaded once viewer is available
1654
  * @var object Content_Item
1655
  */
1656
  item_queued: null,
1657
-
1658
  /**
1659
  * Theme used by viewer
1660
  * @var object Theme
1661
  */
1662
  theme: null,
1663
-
1664
  /* Properties */
1665
-
1666
  item_working: null,
1667
-
1668
  active: false,
1669
  init: false,
1670
  open: false,
1671
  loading: false,
1672
-
1673
  /* Methods */
1674
-
1675
  /* Init */
1676
-
1677
  _hooks: function() {
1678
  var t = this;
1679
  this
@@ -1686,9 +1686,9 @@ var Viewer = {
1686
  });
1687
  });
1688
  },
1689
-
1690
  /* References */
1691
-
1692
  /**
1693
  * Retrieve item instance current attached to viewer
1694
  * @return Content_Item|NULL Current item instance
@@ -1696,7 +1696,7 @@ var Viewer = {
1696
  get_item: function() {
1697
  return this.get_component('item');
1698
  },
1699
-
1700
  /**
1701
  * Set item reference
1702
  * Validates item before setting
@@ -1711,7 +1711,7 @@ var Viewer = {
1711
  });
1712
  return ( !this.util.is_empty(i) );
1713
  },
1714
-
1715
  /**
1716
  * Clear item from viewer
1717
  * Resets item state and removes reference (if necessary)
@@ -1730,7 +1730,7 @@ var Viewer = {
1730
  this.clear_component('item');
1731
  }
1732
  },
1733
-
1734
  /**
1735
  * Retrieve theme reference
1736
  * @return object Theme reference
@@ -1744,7 +1744,7 @@ var Viewer = {
1744
  }
1745
  return ret;
1746
  },
1747
-
1748
  /**
1749
  * Set viewer's theme
1750
  * @param object theme Theme object
@@ -1752,9 +1752,9 @@ var Viewer = {
1752
  set_theme: function(theme) {
1753
  this.set_component('theme', theme);
1754
  },
1755
-
1756
  /* Properties */
1757
-
1758
  /**
1759
  * Lock the viewer
1760
  * Indicates that item is currently being processed
@@ -1763,7 +1763,7 @@ var Viewer = {
1763
  lock: function() {
1764
  return this.set_status('item_working', $.Deferred());
1765
  },
1766
-
1767
  /**
1768
  * Retrieve lock
1769
  * @param bool simple (optional) Whether to return a simple status of the locked status (Default: FALSE)
@@ -1791,11 +1791,11 @@ var Viewer = {
1791
  }
1792
  return ( full ) ? r : r.promise();
1793
  },
1794
-
1795
  is_locked: function() {
1796
  return this.get_lock(true);
1797
  },
1798
-
1799
  /**
1800
  * Unlock the viewer
1801
  * Any callbacks registered for this action will be executed
@@ -1804,7 +1804,7 @@ var Viewer = {
1804
  unlock: function() {
1805
  return this.get_lock(false, true).resolve();
1806
  },
1807
-
1808
  /**
1809
  * Set Viewer active status
1810
  * @param bool mode (optional) Activate or deactivate status (Default: TRUE)
@@ -1816,7 +1816,7 @@ var Viewer = {
1816
  }
1817
  return this.set_status('active', mode);
1818
  },
1819
-
1820
  /**
1821
  * Check Viewer active status
1822
  * @return bool Active status
@@ -1824,7 +1824,7 @@ var Viewer = {
1824
  is_active: function() {
1825
  return this.get_status('active');
1826
  },
1827
-
1828
  /**
1829
  * Set loading mode
1830
  * @param bool mode (optional) Set (TRUE) or unset (FALSE) loading mode (Default: TRUE)
@@ -1853,7 +1853,7 @@ var Viewer = {
1853
  }
1854
  return dfr.promise();
1855
  },
1856
-
1857
  /**
1858
  * Unset loading mode
1859
  * @see set_loading()
@@ -1862,7 +1862,7 @@ var Viewer = {
1862
  unset_loading: function() {
1863
  return this.set_loading(false);
1864
  },
1865
-
1866
  /**
1867
  * Retrieve loading status
1868
  * @return bool Loading status (Default: FALSE)
@@ -1870,17 +1870,17 @@ var Viewer = {
1870
  get_loading: function() {
1871
  return ( this.util.is_bool(this.loading) ) ? this.loading : false;
1872
  },
1873
-
1874
  /**
1875
  * Check if viewer is currently loading content
1876
  * @return bool Loading status (Default: FALSE)
1877
  */
1878
  is_loading: function() {
1879
- return this.get_loading();
1880
  },
1881
-
1882
  /* Display */
1883
-
1884
  /**
1885
  * Display content in viewer
1886
  * @param Content_Item item Item to show
@@ -1898,7 +1898,7 @@ var Viewer = {
1898
  valid = ( this.get_theme() && this.get_theme().get_template().get_layout(false) !== "" ) ? true : false;
1899
  this.set_attribute(vt, valid);
1900
  }
1901
-
1902
  if ( !valid ) {
1903
  this.close();
1904
  return false;
@@ -1931,9 +1931,9 @@ var Viewer = {
1931
  });
1932
  }
1933
  },
1934
-
1935
  /* History Management */
1936
-
1937
  history_handle: function(e) {
1938
  var state = e.originalEvent.state;
1939
  // Load item
@@ -1947,10 +1947,10 @@ var Viewer = {
1947
  // Close viewer
1948
  if ( -1 !== count ) {
1949
  this.close();
1950
- }
1951
  }
1952
  },
1953
-
1954
  history_get: function(full) {
1955
  return this.get_status('history_count', full);
1956
  },
@@ -1999,16 +1999,16 @@ var Viewer = {
1999
  history.go( -1 * count );
2000
  }
2001
  },
2002
-
2003
  /**
2004
  * Check if viewer is currently open
2005
- * Checks if node is actually visible in DOM
2006
- * @return bool TRUE if viewer is open, FALSE otherwise
2007
  */
2008
  is_open: function() {
2009
  return ( this.dom_get().css('display') === 'none' ) ? false : true;
2010
  },
2011
-
2012
  /**
2013
  * Load output into DOM
2014
  */
@@ -2070,7 +2070,7 @@ var Viewer = {
2070
  // Set classes
2071
  var d = v.dom_get();
2072
  var classes = ['item_single', 'item_multi'];
2073
- var ms = ['addClass', 'removeClass'];
2074
  if ( !v.get_item().get_group().is_single() ) {
2075
  ms.reverse();
2076
  }
@@ -2101,7 +2101,7 @@ var Viewer = {
2101
  // Render
2102
  thm.render();
2103
  },
2104
-
2105
  /**
2106
  * Retrieve container element
2107
  * Creates default container element if not yet created
@@ -2123,7 +2123,7 @@ var Viewer = {
2123
  }
2124
  return c;
2125
  },
2126
-
2127
  /**
2128
  * Custom Viewer DOM initialization
2129
  */
@@ -2148,7 +2148,7 @@ var Viewer = {
2148
  }
2149
  thm.render(true);
2150
  },
2151
-
2152
  /**
2153
  * Prepare DOM for viewer
2154
  */
@@ -2156,7 +2156,7 @@ var Viewer = {
2156
  var m = ( this.util.is_bool(mode) && !mode ) ? 'removeClass' : 'addClass';
2157
  $('html')[m](this.util.add_prefix('overlay'));
2158
  },
2159
-
2160
  /**
2161
  * Restore DOM
2162
  * Required after viewer is closed
@@ -2164,9 +2164,9 @@ var Viewer = {
2164
  dom_restore: function() {
2165
  this.dom_prep(false);
2166
  },
2167
-
2168
  /* Layout */
2169
-
2170
  get_layout: function() {
2171
  var ret = this.dom_get('layout', {
2172
  'put': {
@@ -2177,15 +2177,15 @@ var Viewer = {
2177
  });
2178
  return ret;
2179
  },
2180
-
2181
  /* Animation */
2182
-
2183
  animation_enabled: function() {
2184
  return this.get_attribute('animate', true);
2185
  },
2186
-
2187
  /* Overlay */
2188
-
2189
  /**
2190
  * Determine if overlay is enabled for viewer
2191
  * @return bool TRUE if overlay is enabled, FALSE otherwise
@@ -2194,7 +2194,7 @@ var Viewer = {
2194
  var ov = this.get_attribute('overlay_enabled');
2195
  return ( this.util.is_bool(ov) ) ? ov : false;
2196
  },
2197
-
2198
  /**
2199
  * Retrieve overlay DOM element
2200
  * @return jQuery Overlay element (NULL if no overlay set for viewer)
@@ -2213,7 +2213,7 @@ var Viewer = {
2213
  }
2214
  return $(o);
2215
  },
2216
-
2217
  /**
2218
  * Unload viewer
2219
  */
@@ -2224,7 +2224,7 @@ var Viewer = {
2224
  dfr.resolve();
2225
  return dfr.promise();
2226
  },
2227
-
2228
  /**
2229
  * Reset viewer
2230
  */
@@ -2245,20 +2245,20 @@ var Viewer = {
2245
  // Clear for next item
2246
  this.unlock();
2247
  },
2248
-
2249
  /* Content */
2250
-
2251
  get_labels: function() {
2252
  return this.get_attribute('labels', {});
2253
  },
2254
-
2255
  get_label: function(name) {
2256
  var lbls = this.get_labels();
2257
  return ( name in lbls ) ? lbls[name] : '';
2258
  },
2259
-
2260
  /* Interactivity */
2261
-
2262
  /**
2263
  * Initialize event handlers upon opening lightbox
2264
  */
@@ -2268,13 +2268,13 @@ var Viewer = {
2268
  if ( this.open ) {
2269
  return false;
2270
  }
2271
-
2272
  // Control event bubbling
2273
  var l = this.get_layout();
2274
  l.children().click(function(ev) {
2275
  ev.stopPropagation();
2276
  });
2277
-
2278
  /* Close */
2279
  var v = this;
2280
  var close = function() {
@@ -2287,7 +2287,7 @@ var Viewer = {
2287
  // Fire event
2288
  this.trigger('events-open');
2289
  },
2290
-
2291
  /**
2292
  * Initialize event handlers upon completing lightbox rendering
2293
  */
@@ -2298,7 +2298,7 @@ var Viewer = {
2298
  // Fire event
2299
  this.trigger('events-complete');
2300
  },
2301
-
2302
  keys_enable: function(mode) {
2303
  if ( !this.util.is_bool(mode) ) {
2304
  mode = true;
@@ -2314,11 +2314,11 @@ var Viewer = {
2314
  $(document).off(e);
2315
  }
2316
  },
2317
-
2318
  keys_disable: function() {
2319
  this.keys_enable(false);
2320
  },
2321
-
2322
  keys_control: function(ev) {
2323
  var handlers = {
2324
  27: this.close, /* esc */
@@ -2335,16 +2335,16 @@ var Viewer = {
2335
  return false;
2336
  }
2337
  },
2338
-
2339
  /**
2340
  * Check if slideshow functionality is enabled
2341
  * @return bool TRUE if slideshow is enabled, FALSE otherwise
2342
  */
2343
  slideshow_enabled: function() {
2344
  var o = this.get_attribute('slideshow_enabled');
2345
- return ( this.util.is_bool(o) && o && this.get_item() && !this.get_item().get_group().is_single() ) ? true : false;
2346
  },
2347
-
2348
  /**
2349
  * Checks if slideshow is currently active
2350
  * @return bool TRUE if slideshow is active, FALSE otherwise
@@ -2352,14 +2352,14 @@ var Viewer = {
2352
  slideshow_active: function() {
2353
  return ( this.slideshow_enabled() && ( this.get_attribute('slideshow_active') || ( !this.init && this.get_attribute('slideshow_autostart') ) ) ) ? true : false;
2354
  },
2355
-
2356
  /**
2357
  * Clear slideshow timer
2358
  */
2359
  slideshow_clear_timer: function() {
2360
  clearInterval(this.get_attribute('slideshow_timer'));
2361
  },
2362
-
2363
  /**
2364
  * Start slideshow timer
2365
  * @param function callback Callback function
@@ -2367,7 +2367,7 @@ var Viewer = {
2367
  slideshow_set_timer: function(callback) {
2368
  this.set_attribute('slideshow_timer', setInterval(callback, this.get_attribute('slideshow_duration') * 1000));
2369
  },
2370
-
2371
  /**
2372
  * Start Slideshow
2373
  */
@@ -2384,13 +2384,13 @@ var Viewer = {
2384
  this.slideshow_set_timer(function() {
2385
  // Pause slideshow until next item fully loaded
2386
  v.slideshow_pause();
2387
-
2388
  // Show next item
2389
  v.item_next();
2390
  });
2391
  this.trigger('slideshow-start');
2392
  },
2393
-
2394
  /**
2395
  * Stop Slideshow
2396
  * @param bool full (optional) Full stop (TRUE) or pause (FALSE) (Default: TRUE)
@@ -2407,7 +2407,7 @@ var Viewer = {
2407
  this.slideshow_clear_timer();
2408
  this.trigger('slideshow-stop');
2409
  },
2410
-
2411
  slideshow_toggle: function() {
2412
  if ( !this.slideshow_enabled() ) {
2413
  return false;
@@ -2419,7 +2419,7 @@ var Viewer = {
2419
  }
2420
  this.trigger('slideshow-toggle');
2421
  },
2422
-
2423
  /**
2424
  * Pause Slideshow
2425
  * @param bool mode (optional) Pause (TRUE) or Resume (FALSE) slideshow (default: TRUE)
@@ -2441,14 +2441,14 @@ var Viewer = {
2441
  }
2442
  this.trigger('slideshow-pause');
2443
  },
2444
-
2445
  /**
2446
  * Resume slideshow
2447
  */
2448
  slideshow_resume: function() {
2449
  this.slideshow_pause(false);
2450
  },
2451
-
2452
  /**
2453
  * Next item
2454
  */
@@ -2466,7 +2466,7 @@ var Viewer = {
2466
  }
2467
  g.show_next();
2468
  },
2469
-
2470
  /**
2471
  * Previous item
2472
  */
@@ -2483,7 +2483,7 @@ var Viewer = {
2483
  }
2484
  g.show_prev();
2485
  },
2486
-
2487
  /**
2488
  * Close viewer
2489
  */
@@ -2515,41 +2515,41 @@ View.Viewer = Component.extend(Viewer);
2515
  */
2516
  var Group = {
2517
  /* Configuration */
2518
-
2519
  _slug: 'group',
2520
  _reciprocal: true,
2521
  _refs: {
2522
  'current': 'Content_Item'
2523
  },
2524
-
2525
  /* References */
2526
-
2527
  current: null,
2528
-
2529
  /* Properties */
2530
-
2531
  /**
2532
  * Selector for getting group items
2533
- * @var string
2534
  */
2535
  selector: null,
2536
-
2537
  /* Methods */
2538
-
2539
  /* Init */
2540
-
2541
  _hooks: function() {
2542
  var t = this;
2543
  this.on(['item-prev', 'item-next'], function() {
2544
  t.trigger('item-change');
2545
  });
2546
  },
2547
-
2548
  /* Properties */
2549
-
2550
  /**
2551
  * Retrieve selector for group items
2552
- * @return string Group items selector
2553
  */
2554
  get_selector: function() {
2555
  if ( this.util.is_empty(this.selector) ) {
@@ -2558,7 +2558,7 @@ var Group = {
2558
  }
2559
  return this.selector;
2560
  },
2561
-
2562
  /**
2563
  * Retrieve group items
2564
  */
@@ -2569,7 +2569,7 @@ var Group = {
2569
  }
2570
  return items;
2571
  },
2572
-
2573
  /**
2574
  * Retrieve item at specified index
2575
  * If no index specified, first item is returned
@@ -2591,7 +2591,7 @@ var Group = {
2591
  // Return specified item
2592
  return items.get(idx);
2593
  },
2594
-
2595
  /**
2596
  * Retrieve (zero-based) position of specified item in group
2597
  * @param Content_Item item Item to locate in group
@@ -2613,7 +2613,7 @@ var Group = {
2613
  // Sanitize
2614
  return ( !this.util.is_empty( this.get_current() ) );
2615
  },
2616
-
2617
  /**
2618
  * Retrieve current item
2619
  * @uses Group.current
@@ -2626,7 +2626,7 @@ var Group = {
2626
  }
2627
  return this.current;
2628
  },
2629
-
2630
  /**
2631
  * Sets current group item
2632
  * @param Content_Item item Item to set as current
@@ -2638,7 +2638,7 @@ var Group = {
2638
  this.current = item;
2639
  }
2640
  },
2641
-
2642
  get_next: function(item) {
2643
  // Validate
2644
  if ( !this.util.is_type(item, View.Content_Item) ) {
@@ -2657,7 +2657,7 @@ var Group = {
2657
  }
2658
  return next;
2659
  },
2660
-
2661
  get_prev: function(item) {
2662
  // Validate
2663
  if ( !this.util.is_type(item, View.Content_Item) ) {
@@ -2677,7 +2677,7 @@ var Group = {
2677
  }
2678
  return prev;
2679
  },
2680
-
2681
  show_next: function(item) {
2682
  if ( this.get_size() > 1 ) {
2683
  // Retrieve item
@@ -2697,7 +2697,7 @@ var Group = {
2697
  this.trigger('item-next');
2698
  }
2699
  },
2700
-
2701
  show_prev: function(item) {
2702
  if ( this.get_size() > 1 ) {
2703
  // Retrieve item
@@ -2717,15 +2717,15 @@ var Group = {
2717
  this.trigger('item-prev');
2718
  }
2719
  },
2720
-
2721
  /**
2722
  * Retrieve total number of items in group
2723
- * @return int Number of items in group
2724
  */
2725
  get_size: function() {
2726
  return this.get_items().length;
2727
  },
2728
-
2729
  is_single: function() {
2730
  return ( this.get_size() === 1 );
2731
  }
@@ -2738,30 +2738,30 @@ View.Group = Component.extend(Group);
2738
  * @param obj options Init options
2739
  */
2740
  var Content_Handler = {
2741
-
2742
  /* Configuration */
2743
-
2744
  _slug: 'content_handler',
2745
  _refs: {
2746
  'item': 'Content_Item'
2747
  },
2748
-
2749
  /* References */
2750
-
2751
  item: null,
2752
-
2753
  /* Properties */
2754
-
2755
  /**
2756
  * Raw layout template
2757
- * @var string
2758
  */
2759
  template: '',
2760
-
2761
  /* Methods */
2762
-
2763
  /* Item */
2764
-
2765
  /**
2766
  * Check if item instance set for type
2767
  * @uses get_item()
@@ -2771,7 +2771,7 @@ var Content_Handler = {
2771
  has_item: function() {
2772
  return ( this.util.is_empty(this.get_item()) ) ? false : true;
2773
  },
2774
-
2775
  /**
2776
  * Retrieve item instance set on type
2777
  * @uses get_component()
@@ -2780,7 +2780,7 @@ var Content_Handler = {
2780
  get_item: function() {
2781
  return this.get_component('item');
2782
  },
2783
-
2784
  /**
2785
  * Set item instance for type
2786
  * Items are only meant to be set/used while item is being processed
@@ -2793,7 +2793,7 @@ var Content_Handler = {
2793
  var r = this.set_component('item', item);
2794
  return r;
2795
  },
2796
-
2797
  /**
2798
  * Clear item instance from type
2799
  * Sets value to NULL
@@ -2801,13 +2801,13 @@ var Content_Handler = {
2801
  clear_item: function() {
2802
  this.clear_component('item');
2803
  },
2804
-
2805
  /* Evaluation */
2806
-
2807
  /**
2808
  * Check if item matches content handler
2809
  * @param object item Content_Item instance to check for type match
2810
- * @return bool TRUE if type matches, FALSE otherwise
2811
  */
2812
  match: function(item) {
2813
  // Validate
@@ -2816,7 +2816,7 @@ var Content_Handler = {
2816
  // Stop processing types with no matching algorithm
2817
  if ( !this.util.is_empty(m) ) {
2818
  // Process regex patterns
2819
-
2820
  // String-based
2821
  if ( this.util.is_string(m) ) {
2822
  // Create new regexp object
@@ -2835,9 +2835,9 @@ var Content_Handler = {
2835
  // Default
2836
  return false;
2837
  },
2838
-
2839
  /* Processing/Output */
2840
-
2841
  /**
2842
  * Loads item data
2843
  * @param obj item Content item to load data for
@@ -2852,7 +2852,7 @@ var Content_Handler = {
2852
  }
2853
  return dfr.promise();
2854
  },
2855
-
2856
  /**
2857
  * Render output to display item
2858
  * @param Content_Item item Item to render output for
@@ -2874,7 +2874,7 @@ View.Content_Handler = Component.extend(Content_Handler);
2874
  */
2875
  var Content_Item = {
2876
  /* Configuration */
2877
-
2878
  _slug: 'content_item',
2879
  _reciprocal: true,
2880
  _refs: {
@@ -2882,7 +2882,7 @@ var Content_Item = {
2882
  'group': 'Group',
2883
  'type': 'Content_Handler'
2884
  },
2885
-
2886
  _attr_default: {
2887
  source: null,
2888
  permalink: null,
@@ -2892,31 +2892,31 @@ var Content_Item = {
2892
  internal: false,
2893
  output: null
2894
  },
2895
-
2896
  /* References */
2897
-
2898
  group: null,
2899
  viewer: null,
2900
  type: null,
2901
-
2902
  /* Properties */
2903
-
2904
  data: null,
2905
  loaded: null,
2906
-
2907
  /* Init */
2908
-
2909
  _c: function(el) {
2910
  // Save element to instance
2911
  this.dom_set(el);
2912
  // Default initialization
2913
  this._super();
2914
  },
2915
-
2916
  /* Methods */
2917
-
2918
  /*-** Attributes **-*/
2919
-
2920
  /**
2921
  * Build default attributes
2922
  * Populates attributes with asset properties (attachments)
@@ -2954,9 +2954,9 @@ var Content_Item = {
2954
  }
2955
  return this._attr_default;
2956
  },
2957
-
2958
  /*-** Properties **-*/
2959
-
2960
  /**
2961
  * Retrieve item output
2962
  * Output generated based on content handler if not previously generated
@@ -2988,7 +2988,7 @@ var Content_Item = {
2988
  }
2989
  return dfr.promise();
2990
  },
2991
-
2992
  /**
2993
  * Cache output for future retrieval
2994
  * @uses set_attribute() to cache output
@@ -2998,16 +2998,16 @@ var Content_Item = {
2998
  this.set_attribute('output', out);
2999
  }
3000
  },
3001
-
3002
  /**
3003
  * Retrieve item output
3004
  * Alias for `get_output()`
3005
- * @return jQuery.Promise Deferred that is resolved when content is retrieved
3006
  */
3007
  get_content: function() {
3008
  return this.get_output();
3009
  },
3010
-
3011
  /**
3012
  * Retrieve item URI
3013
  * @param string mode (optional) Which URI should be retrieved
@@ -3029,7 +3029,7 @@ var Content_Item = {
3029
  ret = ret.replace(/&(#38|amp);/, '&');
3030
  return ret;
3031
  },
3032
-
3033
  /**
3034
  * Retrieve item title
3035
  */
@@ -3040,16 +3040,43 @@ var Content_Item = {
3040
  if ( this.has_attribute(prop_cached) ) {
3041
  return this.get_attribute(prop_cached, '');
3042
  }
3043
-
3044
  var title = '';
3045
  // Generate title from DOM values
3046
  var dom = this.dom_get();
3047
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3048
  // DOM-based caption
3049
  if ( dom.length ) {
3050
  // Link title (generally must be manually-entered)
3051
  title = dom.attr(prop);
3052
-
3053
  // Figcaption element
3054
  if ( !title ) {
3055
  title = dom.closest('figure').find('figcaption').first().html();
@@ -3060,35 +3087,50 @@ var Content_Item = {
3060
  title = dom.closest('figure').find('.wp-caption-text').first().html();
3061
  }
3062
  }
3063
-
3064
  // Saved attributes
3065
  if ( !title ) {
3066
  var props = ['caption', 'title'];
3067
  for ( var x = 0; x < props.length; x++ ) {
3068
- title = this.get_attribute(props[x], '');
3069
  if ( !this.util.is_empty(title) ) {
3070
  break;
3071
  }
3072
  }
3073
  }
3074
-
3075
  // Fallbacks
3076
  if ( !title && dom.length ) {
3077
- // Alt attribute
3078
- title = dom.find('img').first().attr('alt');
3079
-
3080
  // Element text
3081
  if ( !title ) {
3082
- title = dom.get(0).innerText.trim();
3083
  }
3084
  }
3085
-
3086
- // Validate
3087
- if ( !this.util.is_string(title, false) ) {
3088
- title = '';
3089
- }
3090
- // Strip default title
3091
- if ( !this.util.is_empty(title) && !this.get_viewer().get_attribute('title_default') ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3092
  var f = this.get_uri('source');
3093
  var i = f.lastIndexOf('/');
3094
  if ( -1 !== i ) {
@@ -3097,27 +3139,23 @@ var Content_Item = {
3097
  if ( -1 !== i ) {
3098
  f = f.substr(0, i);
3099
  }
3100
- if ( title === f ) {
3101
- title = '';
3102
- }
3103
  }
 
 
 
 
3104
  }
3105
-
3106
-
3107
- // Cache retrieved value
3108
- this.set_attribute(prop_cached, title);
3109
- // Return value
3110
- return title;
3111
  },
3112
-
3113
  /**
3114
  * Retrieve item dimensions
3115
- * @return obj Item `width` and `height` properties (px)
3116
  */
3117
  get_dimensions: function() {
3118
  return $.extend({'width': 0, 'height': 0}, this.get_attribute('dimensions'), {});
3119
  },
3120
-
3121
  /**
3122
  * Save item data to instance
3123
  * Item data is saved when rendered
@@ -3126,11 +3164,11 @@ var Content_Item = {
3126
  set_data: function(data) {
3127
  this.data = data;
3128
  },
3129
-
3130
  get_data: function() {
3131
  return this.data;
3132
  },
3133
-
3134
  /**
3135
  * Determine gallery type
3136
  * @return string|null Gallery type ID (NULL if item not in gallery)
@@ -3141,7 +3179,7 @@ var Content_Item = {
3141
  'wp': '.gallery-icon',
3142
  'ngg': '.ngg-gallery-thumbnail'
3143
  };
3144
-
3145
  var dom = this.dom_get();
3146
  for ( var type in types ) {
3147
  if ( dom.parent(types[type]).length > 0 ) {
@@ -3151,7 +3189,7 @@ var Content_Item = {
3151
  }
3152
  return ret;
3153
  },
3154
-
3155
  /**
3156
  * Check if current link is part of a gallery
3157
  * @param string gType (optional) Gallery type to check for
@@ -3170,15 +3208,15 @@ var Content_Item = {
3170
  // Check for specific gallery type
3171
  return ( gType === type ) ? true : false;
3172
  },
3173
-
3174
  /*-** Component References **-*/
3175
-
3176
  /* Viewer */
3177
-
3178
  get_viewer: function() {
3179
  return this.get_component('viewer', {get_default: true});
3180
  },
3181
-
3182
  /**
3183
  * Sets item's viewer property
3184
  * @uses View.get_viewer() to retrieve global viewer
@@ -3189,7 +3227,7 @@ var Content_Item = {
3189
  set_viewer: function(v) {
3190
  return this.set_component('viewer', v);
3191
  },
3192
-
3193
  /* Group */
3194
 
3195
  /**
@@ -3212,7 +3250,7 @@ var Content_Item = {
3212
  }
3213
  return g;
3214
  },
3215
-
3216
  /**
3217
  * Sets item's group property
3218
  * @uses View.get_group() to retrieve global group
@@ -3225,13 +3263,13 @@ var Content_Item = {
3225
  if ( this.util.is_string(g) ) {
3226
  g = this.get_controller().get_group(g);
3227
  }
3228
-
3229
  // Set (or clear) group property
3230
  this.group = ( this.util.is_type(g, View.Group) ) ? g : false;
3231
  },
3232
-
3233
  /* Content Handler */
3234
-
3235
  /**
3236
  * Retrieve item type
3237
  * @uses get_component() to retrieve saved reference to Content_Handler instance
@@ -3245,7 +3283,7 @@ var Content_Item = {
3245
  }
3246
  return t;
3247
  },
3248
-
3249
  /**
3250
  * Save content handler reference
3251
  * @uses set_component() to save type reference
@@ -3254,7 +3292,7 @@ var Content_Item = {
3254
  set_type: function(type) {
3255
  return this.set_component('type', type);
3256
  },
3257
-
3258
  /**
3259
  * Check if content handler exists for item
3260
  * @return bool TRUE if content handler exists, FALSE otherwise
@@ -3263,9 +3301,9 @@ var Content_Item = {
3263
  var ret = !this.util.is_empty(this.get_type());
3264
  return ret;
3265
  },
3266
-
3267
  /* Actions */
3268
-
3269
  /**
3270
  * Display item in viewer
3271
  * @uses get_viewer() to retrieve viewer instance for item
@@ -3286,10 +3324,10 @@ var Content_Item = {
3286
  var ret = v.show(this);
3287
  return ret;
3288
  },
3289
-
3290
  /**
3291
  * Load item data
3292
- *
3293
  * Retrieves item data from external sources (if necessary)
3294
  * @uses this.loaded to save loaded state
3295
  * @return obj Promise that is resolved when item data is loaded
@@ -3301,7 +3339,7 @@ var Content_Item = {
3301
  }
3302
  return this.loaded.promise();
3303
  },
3304
-
3305
  reset: function() {
3306
  this.set_attribute('options_show', null);
3307
  }
@@ -3313,13 +3351,13 @@ View.Content_Item = Component.extend(Content_Item);
3313
  * Modeled Component
3314
  */
3315
  var Modeled_Component = {
3316
-
3317
  _slug: 'modeled_component',
3318
-
3319
  /* Methods */
3320
-
3321
  /* Attributes */
3322
-
3323
  /**
3324
  * Retrieve attribute
3325
  * Gives priority to model values
@@ -3353,7 +3391,7 @@ var Modeled_Component = {
3353
  }
3354
  return ret;
3355
  },
3356
-
3357
  /**
3358
  * Get attribute recursively
3359
  * Merges objects from ancestors together
@@ -3385,7 +3423,7 @@ var Modeled_Component = {
3385
  * @param string key Attribute to set
3386
  * @param mixed val Value to set for attribute
3387
  * @param bool|obj use_model (optional) Set the value on the model (Default: TRUE)
3388
- * > bool: Set attribute on current model (TRUE) or as standard attribute (FALSE)
3389
  * > obj: Model object to set attribute on
3390
  * @return mixed Attribute value
3391
  */
@@ -3400,7 +3438,7 @@ var Modeled_Component = {
3400
  // Determine where to set attribute
3401
  if ( !!use_model ) {
3402
  var model = this.util.is_obj(use_model) ? use_model : this.get_model();
3403
-
3404
  // Set attribute in model
3405
  model[key] = val;
3406
  } else {
@@ -3410,9 +3448,9 @@ var Modeled_Component = {
3410
  return val;
3411
  },
3412
 
3413
-
3414
  /* Model */
3415
-
3416
  /**
3417
  * Retrieve Template model
3418
  * @return obj Model (Default: Empty object)
@@ -3437,7 +3475,7 @@ var Modeled_Component = {
3437
  },
3438
 
3439
 
3440
-
3441
  /**
3442
  * Check if specified attribute exists in model
3443
  * @param string key Attribute to check for
@@ -3446,7 +3484,7 @@ var Modeled_Component = {
3446
  in_model: function(key) {
3447
  return ( this.util.in_obj(this.get_model(), key) ) ? true : false;
3448
  },
3449
-
3450
  /**
3451
  * Retrieve all ancestor models
3452
  * @param bool inc_current (optional) Include current model in list (Default: FALSE)
@@ -3465,7 +3503,7 @@ var Modeled_Component = {
3465
  }
3466
  return ret;
3467
  },
3468
-
3469
  /**
3470
  * Retrieve first ancestor of current theme with specified attribute
3471
  * > Current model is also evaluated
@@ -3518,28 +3556,28 @@ Modeled_Component = Component.extend(Modeled_Component);
3518
  * Theme
3519
  */
3520
  var Theme = {
3521
-
3522
  /* Configuration */
3523
-
3524
  _slug: 'theme',
3525
  _refs: {
3526
  'viewer': 'Viewer',
3527
  'template': 'Template'
3528
  },
3529
  _models: {},
3530
-
3531
  _attr_default: {
3532
  template: null,
3533
  model: null
3534
  },
3535
-
3536
  /* References */
3537
-
3538
  viewer: null,
3539
  template: null,
3540
-
3541
  /* Methods */
3542
-
3543
  /**
3544
  * Custom constructor
3545
  * @see Component._c()
@@ -3552,20 +3590,20 @@ var Theme = {
3552
  }
3553
  // Pass parameters to parent constructor
3554
  this._super(id, attributes);
3555
-
3556
  // Set viewer instance
3557
  this.set_viewer(viewer);
3558
-
3559
  // Set theme model
3560
  this.set_model(id);
3561
  },
3562
-
3563
  /* Viewer */
3564
-
3565
  get_viewer: function() {
3566
  return this.get_component('viewer', {check_attr: false, get_default: true});
3567
  },
3568
-
3569
  /**
3570
  * Sets theme's viewer property
3571
  * @uses View.get_viewer() to retrieve global viewer
@@ -3576,9 +3614,9 @@ var Theme = {
3576
  set_viewer: function(v) {
3577
  return this.set_component('viewer', v);
3578
  },
3579
-
3580
  /* Template */
3581
-
3582
  /**
3583
  * Retrieve template instance
3584
  * @return Template instance
@@ -3594,9 +3632,9 @@ var Theme = {
3594
  }
3595
  return ret;
3596
  },
3597
-
3598
  /* Tags */
3599
-
3600
  /**
3601
  * Retrieve tags from template
3602
  * All tags will be retrieved by default
@@ -3609,7 +3647,7 @@ var Theme = {
3609
  get_tags: function(name, prop) {
3610
  return this.get_template().get_tags(name, prop);
3611
  },
3612
-
3613
  /**
3614
  * Retrieve tag DOM elements
3615
  * @see Template.dom_get_tag()
@@ -3617,7 +3655,7 @@ var Theme = {
3617
  dom_get_tag: function(tag, prop) {
3618
  return $(this.get_template().dom_get_tag(tag, prop));
3619
  },
3620
-
3621
  /**
3622
  * Retrieve template tag CSS selector
3623
  * @uses Template.get_tag_selector()
@@ -3628,9 +3666,9 @@ var Theme = {
3628
  get_tag_selector: function(name, prop) {
3629
  return this.get_template().get_tag_selector(name, prop);
3630
  },
3631
-
3632
  /* Model */
3633
-
3634
  /**
3635
  * Retrieve theme models
3636
  * @return obj Theme models
@@ -3638,7 +3676,7 @@ var Theme = {
3638
  get_models: function() {
3639
  return this._models;
3640
  },
3641
-
3642
  /**
3643
  * Retrieve specified theme model
3644
  * @param string id (optional) Theme model to retrieve
@@ -3664,7 +3702,7 @@ var Theme = {
3664
  }
3665
  return ret;
3666
  },
3667
-
3668
  /**
3669
  * Set model for current theme instance
3670
  * @param string id (optional) Theme ID (Default theme retrieved if ID invalid)
@@ -3681,9 +3719,9 @@ var Theme = {
3681
  }
3682
  */
3683
  },
3684
-
3685
  /* Properties */
3686
-
3687
  /**
3688
  * Generate class names for DOM node
3689
  * @param string rtype (optional) Return data type
@@ -3709,7 +3747,7 @@ var Theme = {
3709
  // Return class names
3710
  return cls;
3711
  },
3712
-
3713
  /**
3714
  * Get custom measurement
3715
  * @param string attr Measurement to retrieve
@@ -3720,13 +3758,13 @@ var Theme = {
3720
  var meas = null;
3721
  // Validate
3722
  if ( !this.util.is_string(attr) ) {
3723
- return meas;
3724
  }
3725
  if ( !this.util.is_obj(def, false) ) {
3726
  def = {};
3727
  }
3728
  // Manage cache
3729
- var attr_cache = this.util.format('%s_cache', attr);
3730
  var cache = this.get_attribute(attr_cache, {}, false);
3731
  var status = '_status';
3732
  var item = this.get_viewer().get_item();
@@ -3766,7 +3804,7 @@ var Theme = {
3766
  // Return measurement (copy)
3767
  return $.extend({}, meas);
3768
  },
3769
-
3770
  /**
3771
  * Get default measurement using attribute's default handler
3772
  * @param string attr Measurement attribute
@@ -3790,7 +3828,7 @@ var Theme = {
3790
  }
3791
  return attr;
3792
  },
3793
-
3794
  /**
3795
  * Retrieve theme offset
3796
  * @return obj Theme offset with `width` & `height` properties
@@ -3798,7 +3836,7 @@ var Theme = {
3798
  get_offset: function() {
3799
  return this.get_measurement('offset', { 'width': 0, 'height': 0});
3800
  },
3801
-
3802
  /**
3803
  * Generate default offset
3804
  * @return obj Theme offsets with `width` & `height` properties
@@ -3833,7 +3871,7 @@ var Theme = {
3833
  offset[key] = -1 * val;
3834
  });
3835
  }
3836
-
3837
  // Set offset
3838
  offset.width += l.width();
3839
  offset.height += l.height();
@@ -3847,15 +3885,15 @@ var Theme = {
3847
  vc.empty().remove();
3848
  return offset;
3849
  },
3850
-
3851
  /**
3852
  * Retrieve theme margins
3853
- * @return obj Theme margin with `width` & `height` properties
3854
  */
3855
  get_margin: function() {
3856
  return this.get_measurement('margin', {'width': 0, 'height': 0});
3857
  },
3858
-
3859
  /**
3860
  * Retrieve item dimensions
3861
  * Dimensions are adjusted to fit window (if necessary)
@@ -3888,7 +3926,7 @@ var Theme = {
3888
  }
3889
  return $.extend({}, dims);
3890
  },
3891
-
3892
  /**
3893
  * Retrieve theme dimensions
3894
  * @return obj Theme dimensions with `width` & `height` properties
@@ -3901,7 +3939,7 @@ var Theme = {
3901
  });
3902
  return dims;
3903
  },
3904
-
3905
  /**
3906
  * Retrieve all breakpoints
3907
  * @return object Breakpoints
@@ -3909,7 +3947,7 @@ var Theme = {
3909
  get_breakpoints: function() {
3910
  return this.get_attribute_recursive('breakpoints');
3911
  },
3912
-
3913
  /**
3914
  * Get breakpoint value
3915
  * @param string target Breakpoint target
@@ -3925,9 +3963,9 @@ var Theme = {
3925
  }
3926
  return ret;
3927
  },
3928
-
3929
  /* Output */
3930
-
3931
  /**
3932
  * Render Theme output
3933
  * @param bool init (optional) Initialize theme (Default: FALSE)
@@ -3952,7 +3990,7 @@ var Theme = {
3952
  // Render template
3953
  tpl.render(init);
3954
  },
3955
-
3956
  transition: function(event, clear_queue) {
3957
  var dfr = null;
3958
  var attr = 'transition';
@@ -4024,10 +4062,10 @@ View.Theme = Modeled_Component.extend(Theme);
4024
  */
4025
  var Template = {
4026
  /* Configuration */
4027
-
4028
  _slug: 'template',
4029
  _reciprocal: true,
4030
-
4031
  _refs: {
4032
  'theme': 'Theme'
4033
  },
@@ -4038,11 +4076,11 @@ var Template = {
4038
  * @var string
4039
  */
4040
  layout_uri: '',
4041
-
4042
  /**
4043
  * Raw layout template
4044
  * @var string
4045
- */
4046
  layout_raw: '',
4047
  /**
4048
  * Parsed layout
@@ -4063,17 +4101,17 @@ var Template = {
4063
  */
4064
  model: null
4065
  },
4066
-
4067
  /* References */
4068
-
4069
  theme: null,
4070
-
4071
  /* Methods */
4072
-
4073
  _c: function(attributes) {
4074
  this._super('', attributes);
4075
  },
4076
-
4077
  _hooks: function() {
4078
  // TODO: Refactor to event that can save retrieved tags
4079
  // (`dom_init` event called during attribute initialization so tags are not saved)
@@ -4091,14 +4129,14 @@ var Template = {
4091
  });
4092
  });
4093
  },
4094
-
4095
  get_theme: function() {
4096
  var ret = this.get_component('theme');
4097
  return ret;
4098
  },
4099
-
4100
  /* Output */
4101
-
4102
  /**
4103
  * Render output
4104
  * @param bool init (optional) Whether to initialize layout (TRUE) or render item (FALSE) (Default: FALSE)
@@ -4158,9 +4196,9 @@ var Template = {
4158
  this.trigger('render-init', this.dom_get());
4159
  }
4160
  },
4161
-
4162
  /*-** Layout **-*/
4163
-
4164
  /**
4165
  * Retrieve layout
4166
  * @param bool parsed (optional) TRUE retrieves parsed layout, FALSE retrieves raw layout (Default: TRUE)
@@ -4175,7 +4213,7 @@ var Template = {
4175
  var l = ( parsed ) ? this.parse_layout() : this.get_attribute('layout_raw', '');
4176
  return l;
4177
  },
4178
-
4179
  /**
4180
  * Parse layout
4181
  * Converts template tags to HTML elements
@@ -4196,11 +4234,11 @@ var Template = {
4196
  ret = this.parse_tags(ret);
4197
  // Save parsed layout
4198
  this.set_attribute(a, ret);
4199
-
4200
  // Return parsed layout
4201
  return ret;
4202
  },
4203
-
4204
  /**
4205
  * Sanitize layout
4206
  * @param obj|string l Layout string or jQuery object
@@ -4214,7 +4252,7 @@ var Template = {
4214
  // Set return type
4215
  var rtype = ( this.util.is_string(l) ) ? 'string' : null;
4216
  /* Quarantine hard-coded tags */
4217
-
4218
  // Create DOM structure from raw template
4219
  var dom = $(l);
4220
  // Find hard-coded tag nodes
@@ -4236,9 +4274,9 @@ var Template = {
4236
  }
4237
  return l;
4238
  },
4239
-
4240
  /*-** Tags **-*/
4241
-
4242
  /**
4243
  * Extract tags from template
4244
  * Tags are replaced with DOM element placeholders
@@ -4263,7 +4301,7 @@ var Template = {
4263
  }
4264
  return l;
4265
  },
4266
-
4267
  /**
4268
  * Create DOM element container for tag
4269
  * @param string Tag ID (will be prefixed)
@@ -4272,13 +4310,13 @@ var Template = {
4272
  get_tag_container: function(tag) {
4273
  // Build element
4274
  var attr = this.get_tag_attribute();
4275
- return this.util.format('<span %s="%s"></span>', attr, encodeURI(tag));
4276
  },
4277
-
4278
  get_tag_attribute: function() {
4279
  return this.get_tag_temp().dom_get_attribute();
4280
  },
4281
-
4282
  /**
4283
  * Retrieve Template_Tag instance at specified index
4284
  * @param int idx (optional) Index to retrieve tag from
@@ -4295,7 +4333,7 @@ var Template = {
4295
  }
4296
  return ret;
4297
  },
4298
-
4299
  /**
4300
  * Retrieve tags from template
4301
  * Subset of tags may be retrieved based on parameter values
@@ -4368,7 +4406,7 @@ var Template = {
4368
  }
4369
  return ( this.util.is_array(tags, false) ) ? tags : [];
4370
  },
4371
-
4372
  /**
4373
  * Check if template contains tags
4374
  * @return bool TRUE if tags exist, FALSE otherwise
@@ -4376,7 +4414,7 @@ var Template = {
4376
  has_tags: function() {
4377
  return ( this.get_tags().length > 0 ) ? true : false;
4378
  },
4379
-
4380
  /**
4381
  * Retrieve temporary tag instance
4382
  * @return Template_Tag Temporary tag
@@ -4384,7 +4422,7 @@ var Template = {
4384
  get_tag_temp: function() {
4385
  return this.get_controller().get_component_temp(View.Template_Tag);
4386
  },
4387
-
4388
  /**
4389
  * Retrieve Template tag CSS selector
4390
  * @uses Template.get_tag_temp() to retrieve temporary tag instance
@@ -4405,18 +4443,18 @@ var Template = {
4405
  tag.set_attribute('prop', prop);
4406
  return tag.get_selector('full');
4407
  },
4408
-
4409
  /*-** DOM **-*/
4410
-
4411
  /**
4412
- * Custom DOM initialization
4413
  */
4414
  dom_init: function() {
4415
  // Create DOM object from parsed layout
4416
  this.dom_set(this.get_layout());
4417
  this.trigger('dom_init');
4418
  },
4419
-
4420
  /**
4421
  * Retrieve DOM element(s) for specified tag
4422
  * @param string tag Name of tag to retrieve
@@ -4442,7 +4480,7 @@ var Template = {
4442
  View.Template = Modeled_Component.extend(Template);
4443
 
4444
  /**
4445
- * Template tag
4446
  */
4447
  var Template_Tag = {
4448
  /* Configuration */
@@ -4457,19 +4495,19 @@ var Template_Tag = {
4457
  /**
4458
  * Tag Handlers
4459
  * Collection of Template_Tag_Handler instances
4460
- * @var obj
4461
  */
4462
  handlers: {},
4463
  /* Methods */
4464
-
4465
  /**
4466
  * Constructor
4467
- * @param
4468
  */
4469
  _c: function(tag_match) {
4470
  this.parse(tag_match);
4471
  },
4472
-
4473
  /**
4474
  * Set instance attributes using tag extracted from template
4475
  * @param string tag_match Extracted tag match
@@ -4509,7 +4547,7 @@ var Template_Tag = {
4509
  // Save to instance
4510
  this.set_attributes(attrs, true);
4511
  },
4512
-
4513
  /**
4514
  * Render tag output
4515
  * @param Content_Item item
@@ -4524,7 +4562,7 @@ var Template_Tag = {
4524
  return {'tag': tag, 'output': output};
4525
  });
4526
  },
4527
-
4528
  /**
4529
  * Retrieve tag name
4530
  * @return string Tag name (DEFAULT: NULL)
@@ -4532,14 +4570,14 @@ var Template_Tag = {
4532
  get_name: function() {
4533
  return this.get_attribute('name');
4534
  },
4535
-
4536
  /**
4537
  * Retrieve tag property
4538
  */
4539
  get_prop: function() {
4540
  return this.get_attribute('prop');
4541
  },
4542
-
4543
  /**
4544
  * Retrieve tag handler
4545
  * @return Template_Tag_Handler Handler instance (Empty instance if handler does not exist)
@@ -4547,7 +4585,7 @@ var Template_Tag = {
4547
  get_handler: function() {
4548
  return ( this.has_handler() ) ? this.handlers[this.get_name()] : new View.Template_Tag_Handler('');
4549
  },
4550
-
4551
  /**
4552
  * Check if handler exists for tag
4553
  * @return bool TRUE if handler exists, FALSE otherwise
@@ -4555,7 +4593,7 @@ var Template_Tag = {
4555
  has_handler: function() {
4556
  return ( this.get_name() in this.handlers );
4557
  },
4558
-
4559
  /**
4560
  * Generate class names for DOM node
4561
  * @param string rtype (optional) Return data type
@@ -4582,7 +4620,7 @@ var Template_Tag = {
4582
  // Return class names
4583
  return cls;
4584
  },
4585
-
4586
  /**
4587
  * Generate DOM-compatible class name based with varied levels of specificity
4588
  * @param int level (optional) Class name specificity
@@ -4615,7 +4653,7 @@ var Template_Tag = {
4615
  // Format & return
4616
  return ( !this.util.is_string(cls) ) ? this.get_ns() : this.add_ns(cls);
4617
  },
4618
-
4619
  /**
4620
  * Generate tag selector based on specified class name level
4621
  * @param string level (optional) Class name specificity (@see get_class() for parameter values)
@@ -4648,9 +4686,9 @@ var Template_Tag_Handler = {
4648
  dynamic: false,
4649
  props: {}
4650
  },
4651
-
4652
  /* Methods */
4653
-
4654
  /**
4655
  * Render tag output
4656
  * @param Content_Item item Item currently being displayed
@@ -4664,7 +4702,7 @@ var Template_Tag_Handler = {
4664
  // Return promise
4665
  return dfr.promise();
4666
  },
4667
-
4668
  add_prop: function(prop, fn) {
4669
  // Get attribute
4670
  var a = 'props';
@@ -4681,7 +4719,7 @@ var Template_Tag_Handler = {
4681
  // Save attribute
4682
  this.set_attribute(a, props);
4683
  },
4684
-
4685
  handle_prop: function(prop, item, instance) {
4686
  // Locate property
4687
  var props = this.get_attribute('props');
10
  /*-** Controller **-*/
11
 
12
  var View = {
13
+
14
  /* Properties */
15
 
16
  /**
24
  * > type: Asset type (attachment, image, etc.)
25
  */
26
  assets: {},
27
+
28
  /**
29
  * Component types that can have default instances
30
  * @var array
31
  */
32
  component_defaults: [],
33
+
34
  /**
35
  * Collection of jQuery.Deferred instances added during loading routine
36
  * @var array
37
  */
38
  loading: [],
39
+
40
  /**
41
  * Cache
42
  * @var object
43
  */
44
  cache: {},
45
+
46
  /**
47
  * Temporary component instances
48
  * For use by controller when no component instance is available
49
  * > Key: Component slug
50
+ * > Value: Component instance
51
  */
52
  component_temps: {},
53
+
54
  /* Options */
55
  options: {},
56
+
57
  /* Methods */
58
+
59
  /* Init */
60
+
61
  /**
62
  * Instance initialization
63
  */
68
  // Components
69
  this.init_components();
70
  },
71
+
72
  /**
73
  * Update component references in component definitions
74
  */
96
  }
97
  }
98
  },
99
+
100
  /**
101
  * Initialize Components
102
  */
105
  this.Viewer
106
  ];
107
  },
108
+
109
  /**
110
  * Client Initialization
111
  * @param obj options Global options
116
  $.when.apply($, this.loading).always(function() {
117
  // Set options
118
  $.extend(true, t.options, options);
119
+
120
  /* Event handlers */
121
+
122
  // History
123
  $(window).on('popstate', function(e) {
124
  var state = e.originalEvent.state;
128
  return e.preventDefault();
129
  }
130
  });
131
+
132
  /* Set defaults */
133
+
134
  // Items
135
  t.init_items();
136
  });
137
  },
138
+
139
  /* Components */
140
 
141
  /**
147
  can_make_default_component: function(type) {
148
  return ( -1 !== $.inArray(type, this.component_defaults) );
149
  },
150
+
151
  /**
152
  * Check if object is valid component class
153
  * @param func comp Component to check
156
  is_component: function(comp) {
157
  return ( this.util.is_class(comp, this.Component) );
158
  },
159
+
160
  /**
161
  * Retrieve collection of components of specified type
162
  * @param func type Component type
175
  }
176
  return ret;
177
  },
178
+
179
  /**
180
  * Retrieve component from specific collection
181
  * @param function type Component type
192
  if ( !this.util.is_string(id) ) {
193
  id = null;
194
  }
195
+
196
  // Get component from collection
197
  var coll = this.get_components(type);
198
  if ( this.util.is_obj(coll) ) {
201
  ret = coll[tid];
202
  }
203
  }
204
+
205
  // Default: Create default component
206
  if ( this.util.is_empty(ret) ) {
207
  if ( this.util.is_string(id) || this.can_make_default_component(type) ) {
211
  // Return component
212
  return ret;
213
  },
214
+
215
  /**
216
  * Create new component instance and save to appropriate collection
217
  * @param function type Component type to create
245
  else {
246
  ret = new type(id, options);
247
  }
248
+
249
  // Add new component to collection
250
  if ( this.util.is_type(ret, type) ) {
251
  // Get collection
265
  // Return new component
266
  return ret;
267
  },
268
+
269
  /**
270
  * Create new temporary component instance
271
  * @param function type Component type
281
  }
282
  return ret;
283
  },
284
+
285
  /**
286
  * Retrieve temporary component instance
287
  * Creates new temp component instance for type if not previously created
291
  get_component_temp: function(type) {
292
  return ( this.has_component_temp(type) ) ? this.component_temps[type.prototype._slug] : this.add_component_temp(type);
293
  },
294
+
295
  /**
296
  * Check if temporary component instance exists
297
  * @param function type Component type to check for
298
+ * @return bool TRUE if temp instance exists, FALSE otherwise
299
  */
300
  has_component_temp: function(type) {
301
  return ( this.is_component(type) && ( type.prototype._slug in this.component_temps ) ) ? true : false;
302
  },
303
+
304
  /* Properties */
305
+
306
  /**
307
  * Retrieve specified options
308
  * @param array opts Array of option names
323
  if ( !( opts[x] in this.options ) ) {
324
  continue;
325
  }
326
+ ret[ opts[x] ] = this.options[ opts[x] ];
327
  }
328
  return ret;
329
  },
330
+
331
  /**
332
  * Retrieve option
333
  * @uses View.options
344
  }
345
  return ret;
346
  },
347
+
348
  /* Viewers */
349
+
350
  /**
351
  * Add viewer instance to collection
352
  * @param string id Viewer ID
361
  // Return viewer
362
  return v;
363
  },
364
+
365
  /**
366
  * Retrieve all viewer instances
367
  * @return obj Viewer instances
369
  get_viewers: function() {
370
  return this.get_components(this.Viewer);
371
  },
372
+
373
  /**
374
  * Check if viewer exists
375
  * @param string v Viewer ID
378
  has_viewer: function(v) {
379
  return ( this.util.is_string(v) && v in this.get_viewers() ) ? true : false;
380
  },
381
+
382
  /**
383
  * Retrieve Viewer instance
384
  * Default viewer retrieved if specified viewer does not exist
398
  }
399
  return this.get_viewers()[v];
400
  },
401
+
402
  /* Items */
403
+
404
  /**
405
  * Set event handlers
406
  */
414
  }
415
  return !ret;
416
  };
417
+
418
  // Get activated links
419
  var sel = this.util.format('a[href][%s="%s"]', this.util.get_attribute('active'), 1);
420
  // Add event handler
421
  $(document).on('click', sel, null, handler);
422
  },
423
+
424
  /**
425
  * Retrieve cached items
426
  * @return obj Items collection
428
  get_items: function() {
429
  return this.get_components(this.Content_Item);
430
  },
431
+
432
  /**
433
  * Retrieve specific Content_Item instance
434
  * @param mixed Item reference
439
  */
440
  get_item: function(ref) {
441
  // Evaluate reference type
442
+
443
  // Content Item instance
444
  if ( this.util.is_type(ref, this.Content_Item) ) {
445
  return ref;
446
  }
447
  // Retrieve item instance
448
  var item = null;
449
+
450
  // DOM element
451
  if ( this.util.in_obj(ref, 'nodeType') ) {
452
  // Check if item instance attached to element
466
  }
467
  return item;
468
  },
469
+
470
  /**
471
  * Create new item instance
472
  * @param obj el DOM element representing item
475
  add_item: function(el) {
476
  return ( new this.Content_Item(el) );
477
  },
478
+
479
  /**
480
  * Display item in viewer
481
  * @param obj el DOM element representing item
482
+ * @return bool Display result (TRUE if item displayed without issues)
483
  */
484
  show_item: function(el) {
485
  return this.get_item(el).show();
486
  },
487
+
488
  /**
489
  * Cache item instance
490
  * @uses View.get_items() to retrieve item cache
500
  // Return item instance
501
  return item;
502
  },
503
+
504
  /* Content Handler */
505
+
506
  /**
507
  * Retrieve content handlers
508
  * @return object Content handlers
510
  get_content_handlers: function() {
511
  return this.get_components(this.Content_Handler);
512
  },
513
+
514
  /**
515
  * Find matching content handler for item
516
  * @param Content_Item|string item Item to find handler for (or ID of Handler)
517
+ * @return Content_Handler|null Matching content handler (NULL if no matching handler found)
518
  */
519
  get_content_handler: function(item) {
520
  // Determine handler to retrieve
523
  var types = this.get_content_handlers();
524
  return ( type in types ) ? types[type] : null;
525
  },
526
+
527
  /**
528
  * Add/Update Content Handler
529
  * @param string id Handler ID
551
  }
552
  return hdl;
553
  },
554
+
555
  /* Group */
556
+
557
  /**
558
  * Add new group
559
  * @param string g Group ID
569
 
570
  return g;
571
  },
572
+
573
  /**
574
  * Retrieve groups
575
  * @uses groups property
578
  get_groups: function() {
579
  return this.get_components(this.Group);
580
  },
581
+
582
  /**
583
  * Retrieve specified group
584
  * New group created if not yet set
591
  get_group: function(g) {
592
  return ( !this.has_group(g) ) ? this.add_group(g) : this.get_groups()[g];
593
  },
594
+
595
  /**
596
  * Checks if group is registered
597
  * @uses get_groups() to retrieve registered groups
600
  has_group: function(g) {
601
  return ( this.util.is_string(g) && ( g in this.get_groups() ) );
602
  },
603
+
604
  /* Theme */
605
+
606
  /**
607
  * Add/Update theme
608
  * @param string name Theme name
616
  }
617
  var dfr = $.Deferred();
618
  this.loading.push(dfr);
619
+
620
  // Get model if it already exists
621
  var model = this.get_theme_model(id);
622
+
623
  // Create default attributes for new theme
624
  if ( this.util.is_empty(model) ) {
625
  // Save default model
626
  model = this.save_theme_model( {'parent': null, 'id': id} );
627
  }
628
+
629
  // Add custom attributes
630
  if ( this.util.is_obj(attr) ) {
631
  // Sanitize
634
  }
635
  $.extend(model, attr);
636
  }
637
+
638
  // Load styles
639
  if ( this.util.in_obj(attr, 'styles') ) {
640
  this.load_styles(attr.styles);
641
  }
642
+
643
  // Link parent model
644
  if ( !this.util.is_obj(model.parent) ) {
645
  model.parent = this.get_theme_model(model.parent);
646
  }
647
+
648
  // Complete loading when all components loaded
649
  dfr.resolve();
650
  return model;
651
  },
652
+
653
  /**
654
  * Retrieve theme models
655
  * @return obj Theme models
658
  // Retrieve matching theme model
659
  return this.Theme.prototype._models;
660
  },
661
+
662
  /**
663
  * Retrieve theme model
664
  * @param string id Theme to retrieve
668
  var ms = this.get_theme_models();
669
  return ( this.util.in_obj(ms, id) ) ? ms[id] : {};
670
  },
671
+
672
  /**
673
  * Save theme model
674
  * @uses View.get_theme_models() to retrieve Theme model collection
682
  }
683
  return model;
684
  },
685
+
686
  /**
687
  * Add/Update Template Tag Handler
688
  * @param string id Handler ID
694
  return false;
695
  }
696
  var hdl;
697
+ var hdls = this.get_template_tag_handlers();
698
  if ( this.util.in_obj(hdls, id) ) {
699
  // Update existing handler
700
  hdl = hdls[id];
714
  }
715
  return hdl;
716
  },
717
+
718
  /**
719
  * Retrieve Template Tag Handler collection
720
  * @return obj Template_Tag_Handler objects
722
  get_template_tag_handlers: function() {
723
  return this.Template_Tag.prototype.handlers;
724
  },
725
+
726
  /**
727
  * Retrieve template tag handler
728
  * @param string id ID of tag handler to retrieve
731
  get_template_tag_handler: function(id) {
732
  var handlers = this.get_template_tag_handlers();
733
  // Retrieve existing handler or return new handler
734
+ return ( this.util.in_obj(handlers, id) ) ? handlers[id] : null;
735
  },
736
+
737
  /**
738
  * Load styles
739
+ * @param array styles Styles to load
740
  */
741
  load_styles: function(styles) {
742
  if ( this.util.is_array(styles) ) {
757
  /* Components */
758
  var Component = {
759
  /*-** Properties **-*/
760
+
761
  /* Internal/Configuration */
762
+
763
  /**
764
  * Base name of component type
765
  * @var string
766
  */
767
  _slug: 'component',
768
+
769
  /**
770
  * Component namespace
771
+ * @var string
772
  */
773
  _ns: null,
774
+
775
  /**
776
  * Valid component references for current component
777
  * @var object
779
  * > Value (function): Data type of component
780
  */
781
  _refs: {},
782
+
783
  /**
784
  * Whether DOM element and component are connected in 1:1 relationship
785
  * Some components will be assigned to different DOM elements depending on usage
786
  * @var bool
787
  */
788
  _reciprocal: false,
789
+
790
  /**
791
  * DOM Element tied to component
792
+ * @var DOM Element
793
  */
794
  _dom: null,
795
+
796
  /**
797
  * Component attributes
798
  * @var object
806
  * @var object
807
  */
808
  _attr_default: {},
809
+
810
  /**
811
  * Flag indicates whether default attributes have previously been parsed
812
  * @var bool
813
  */
814
  _attr_default_parsed: false,
815
+
816
  /**
817
  * Attributes passed to constructor
818
  * @var obj
819
  */
820
  _attr_init: null,
821
+
822
  /**
823
  * Defines how parent properties should be remapped to component properties
824
  * @var object
825
  */
826
  _attr_map: {},
827
+
828
  /**
829
  * Event handlers
830
  * @var object
832
  * > Value: array Handlers
833
  */
834
  _events: {},
835
+
836
  /**
837
  * Status management
838
  * @var object
840
  * > Value: Status value
841
  */
842
  _status: null,
843
+
844
  /**
845
  * Component ID
846
  * @var string
847
  */
848
  _id: '',
849
+
850
  /* Init */
851
+
852
  /**
853
  * Constructor
854
  * @param string id (optional) Component ID (Default ID will be generated if no valid ID provided)
864
  // Call hooks
865
  this._hooks();
866
  },
867
+
868
  /**
869
  * Set Component parent to View module
870
  * @uses `_super._set_parent()`
872
  _set_parent: function() {
873
  this._super(View);
874
  },
875
+
876
  /**
877
  * Register hooks on init
878
  * Placeholder method to be overridden by child classes
879
  */
880
  _hooks: function() {},
881
+
882
  /* Methods */
883
+
884
  /* Properties */
885
+
886
  /**
887
  * Set instance ID
888
  * Instance ID can only be set once (will not change ID if valid ID already set)
898
  }
899
  return this._id;
900
  },
901
+
902
  /**
903
  * Retrieve instance ID
904
  * @uses id as ID base
913
  if ( this.util.is_bool(ns) && ns ) {
914
  id = this.add_ns(id);
915
  }
916
+
917
  return id;
918
  },
919
+
920
  /**
921
  * Get namespace
922
  * @uses _slug for namespace segment
929
  }
930
  return this._ns;
931
  },
932
+
933
  /**
934
  * Add namespace to value
935
  * @param string val Value to namespace
938
  add_ns: function(val) {
939
  return ( this.util.is_string(val) ) ? this.get_ns() + '_' + val : '';
940
  },
941
+
942
  /**
943
  * Retrieve status
944
  * @param string id Status to retrieve
952
  }
953
  return ret;
954
  },
955
+
956
  /**
957
  * Set status
958
  * @param string id Status to retrieve
977
  }
978
  return val;
979
  },
980
+
981
  /**
982
  * Get controller object
983
  * @uses get_parent() (alias)
986
  get_controller: function() {
987
  return this.get_parent();
988
  },
989
+
990
  /* Components */
991
+
992
  /**
993
  * Check if reference exists in object
994
  * @param string ref Reference ID
997
  has_reference: function(ref) {
998
  return ( this.util.is_string(ref) && ( ref in this ) && ( ref in this.get_references() ) ) ? true : false;
999
  },
1000
+
1001
  /**
1002
  * Retrieve object references
1003
  * @uses _refs
1007
  get_references: function() {
1008
  return this._refs;
1009
  },
1010
+
1011
  /**
1012
  * Retrieve reference data type
1013
  * @param string ref Reference ID
1016
  get_reference: function(ref) {
1017
  return ( this.has_reference(ref) ) ? this._refs[ref] : null;
1018
  },
1019
+
1020
  /**
1021
  * Retrieve component reference from current object
1022
  * > Procedure:
1035
  if ( !this.has_reference(cname) ) {
1036
  return c;
1037
  }
1038
+
1039
  // Initialize options
1040
  var opt_defaults = {
1041
  check_attr: true,
1042
  get_default: false
1043
  };
1044
  options = $.extend({}, opt_defaults, options);
1045
+
1046
  // Get component type
1047
  var ctype = this.get_reference(cname);
1048
+
1049
  // Phase 1: Check if component reference previously set
1050
  if ( this.util.is_type(this[cname], ctype) ) {
1051
  return this[cname];
1052
  }
1053
  // If reference not set, iterate through component hierarchy until reference is found
1054
  c = this[cname] = null;
1055
+
1056
  // Phase 2: Check attributes
1057
  if ( options.check_attr ) {
1058
  c = this.get_attribute(cname);
1061
  c = this.set_component(cname, c);
1062
  }
1063
  }
1064
+
1065
  // Phase 3: From controller (optional)
1066
  if ( this.util.is_empty(c) && options.get_default ) {
1067
  c = this.get_controller().get_component(ctype);
1068
  }
1069
  return c;
1070
  },
1071
+
1072
  /**
1073
  * Sets component reference on current object
1074
  * > Component property reset (set to NULL) if invalid component supplied
1083
  if ( !this.has_reference(name) ) {
1084
  return invalid;
1085
  }
1086
+
1087
  // Validate reference
1088
  if ( this.util.is_empty(ref) ) {
1089
  ref = invalid;
1090
  } else {
1091
  var ctype = this.get_reference(name);
1092
+
1093
  // Get component from controller when ID supplied
1094
  if ( this.util.is_string(ref, false) ) {
1095
  ref = this.get_controller().get_component(ctype, ref);
1096
  }
1097
+
1098
  // Validation callback
1099
  if ( !this.util.is_type(ref, ctype) || ( this.util.is_func(validate) && !validate.call(this, ref) ) ) {
1100
  ref = invalid;
1101
  }
1102
  }
1103
+
1104
  // Set (or clear) component reference
1105
  this[name] = ref;
1106
  // Return value for confirmation
1107
  return this[name];
1108
  },
1109
+
1110
+
1111
  /**
1112
  * Clear component reference
1113
  * @uses set_component() to handle component manipulation
1118
  },
1119
 
1120
  /* Attributes */
1121
+
1122
  /**
1123
  * Initialize attributes
1124
  * @param bool force (optional) Force full initialization of attributes (Default: FALSE)
1140
  $.extend(a, this.get_dom_attributes());
1141
  }
1142
  },
1143
+
1144
  /**
1145
  * Generate default attributes for component
1146
  * @uses View.get_options() to get values from controller
1152
  // Get options from controller
1153
  if ( !this._attr_default_parsed && this.util.is_obj(this._attr_map) ) {
1154
  var opts = this.get_controller().get_options(this.util.obj_keys(this._attr_map));
1155
+
1156
  if ( this.util.is_obj(opts) ) {
1157
  // Remap
1158
  for ( var opt in this._attr_map ) {
1170
  }
1171
  return this._attr_default;
1172
  },
1173
+
1174
  /**
1175
  * Retrieve DOM attributes
1176
  * @return obj DOM Attributes
1196
  }
1197
  return attrs;
1198
  },
1199
+
1200
  /**
1201
  * Retrieve all instance attributes
1202
  * @uses init_attributes() to initialize attributes (if necessary)
1209
  // Return attributes
1210
  return this._attributes;
1211
  },
1212
+
1213
  /**
1214
  * Retrieve value of specified attribute for value
1215
  * @param string key Attribute to retrieve
1230
  if ( !this.util.is_bool(enforce_type) ) {
1231
  enforce_type = true;
1232
  }
1233
+
1234
  // Get attribute value
1235
  var ret = ( this.has_attribute(key) ) ? this.get_attributes()[key] : def;
1236
  // Validate type
1265
  }
1266
  return ret;
1267
  },
1268
+
1269
  /**
1270
  * Call attribute as method
1271
  * @param string attr Attribute to call
1282
  }
1283
  return attr;
1284
  },
1285
+
1286
  /**
1287
  * Check if attribute exists
1288
  * @param string key Attribute name
1291
  has_attribute: function(key) {
1292
  return ( this.util.is_string(key) && ( key in this.get_attributes() ) );
1293
  },
1294
+
1295
  /**
1296
  * Set component attributes
1297
  * @param obj attributes Attributes to set
1305
 
1306
  // Initialize attributes
1307
  this.init_attributes(full);
1308
+
1309
  // Merge new/existing attributes
1310
  if ( this.util.is_obj(attributes) ) {
1311
  $.extend(this._attributes, attributes);
1312
  }
1313
  },
1314
+
1315
  /**
1316
  * Set value for a component attribute
1317
  * @uses get_attributes() to retrieve attributes
1325
  }
1326
  return val;
1327
  },
1328
+
1329
  /* DOM */
1330
 
1331
  /**
1336
  dom_get_selector: function(element) {
1337
  return ( this.util.is_string(element) ) ? '.' + this.add_ns(element) : '';
1338
  },
1339
+
1340
  dom_get_attribute: function() {
1341
  return this.util.get_attribute(this._slug);
1342
  },
1357
  }
1358
  return el;
1359
  },
1360
+
1361
  /**
1362
  * Retrieve attached DOM element
1363
  * @uses _dom to retrieve attached DOM element
1374
  'put': false
1375
  };
1376
  options = ( this.util.is_obj(options) ) ? $.extend({}, opts_default, options) : opts_default;
1377
+
1378
  // Init Component DOM
1379
  if ( options.init && !this.get_status('dom_init') ) {
1380
  this.set_status('dom_init');
1394
  }
1395
  return $(ret);
1396
  },
1397
+
1398
  /**
1399
  * Initialize DOM element
1400
  * To be overridden by child classes
1401
  */
1402
  dom_init: function() {},
1403
+
1404
  /**
1405
  * Wrap output in DOM element
1406
  * Wrapper element created and added to main DOM element if not yet created
1450
  $(r).append(options.content);
1451
  return $(r);
1452
  },
1453
+
1454
  /**
1455
  * Check if DOM element is set for instance
1456
+ * DOM is initialized before evaluation
1457
  * @return bool TRUE if DOM element set, FALSE otherwise
1458
  */
1459
  dom_has: function() {
1460
  return ( !!this.dom_get().length );
1461
  },
1462
+
1463
  /* Data */
1464
+
1465
  /**
1466
  * Retrieve key used to store data in DOM element
1467
+ * @return string Data key
1468
  */
1469
  get_data_key: function() {
1470
  return this.get_ns();
1471
  },
1472
+
1473
  /* Events */
1474
+
1475
  /**
1476
  * Register event handler for custom event
1477
  * Structure
1485
  * @param function fn Event handler
1486
  * @param obj options Handler registration options
1487
  * > clear (bool) Clear existing event handlers before setting current handler (Default: FALSE)
1488
+ * @return obj Component instance (allows chaining)
1489
  */
1490
  on: function(event, fn, options) {
1491
  // Handle request types
1492
+ if ( !this.util.is_string(event) || !this.util.is_func(fn) ) {
1493
  var t = this;
1494
  var args = Array.prototype.slice.call(arguments, 1);
1495
  if ( this.util.is_array(event) ) {
1507
  }
1508
 
1509
  // Options
1510
+
1511
  // Default options
1512
  var options_std = {
1513
  clear: false
1531
  es[event].push(fn);
1532
  return this;
1533
  },
1534
+
1535
  /**
1536
  * Trigger custom event
1537
  * Event handlers are executed in the context of the current component instance
1592
  * @param obj options Init options
1593
  */
1594
  var Viewer = {
1595
+
1596
  /* Configuration */
1597
+
1598
  _slug: 'viewer',
1599
+
1600
  _refs: {
1601
  item: 'Content_Item',
1602
  theme: 'Theme'
1603
  },
1604
+
1605
  _reciprocal: true,
1606
+
1607
  _attr_default: {
1608
  loop: true,
1609
  animate: true,
1627
  loading: 'loading'
1628
  }
1629
  },
1630
+
1631
  _attr_map: {
1632
  'theme': null,
1633
  'group_loop': 'loop',
1640
  'slideshow_autostart': null,
1641
  'slideshow_duration': null
1642
  },
1643
+
1644
  /* References */
1645
+
1646
  /**
1647
  * Item currently loaded in viewer
1648
  * @var object Content_Item
1649
  */
1650
  item: null,
1651
+
1652
  /**
1653
  * Queued item to be loaded once viewer is available
1654
  * @var object Content_Item
1655
  */
1656
  item_queued: null,
1657
+
1658
  /**
1659
  * Theme used by viewer
1660
  * @var object Theme
1661
  */
1662
  theme: null,
1663
+
1664
  /* Properties */
1665
+
1666
  item_working: null,
1667
+
1668
  active: false,
1669
  init: false,
1670
  open: false,
1671
  loading: false,
1672
+
1673
  /* Methods */
1674
+
1675
  /* Init */
1676
+
1677
  _hooks: function() {
1678
  var t = this;
1679
  this
1686
  });
1687
  });
1688
  },
1689
+
1690
  /* References */
1691
+
1692
  /**
1693
  * Retrieve item instance current attached to viewer
1694
  * @return Content_Item|NULL Current item instance
1696
  get_item: function() {
1697
  return this.get_component('item');
1698
  },
1699
+
1700
  /**
1701
  * Set item reference
1702
  * Validates item before setting
1711
  });
1712
  return ( !this.util.is_empty(i) );
1713
  },
1714
+
1715
  /**
1716
  * Clear item from viewer
1717
  * Resets item state and removes reference (if necessary)
1730
  this.clear_component('item');
1731
  }
1732
  },
1733
+
1734
  /**
1735
  * Retrieve theme reference
1736
  * @return object Theme reference
1744
  }
1745
  return ret;
1746
  },
1747
+
1748
  /**
1749
  * Set viewer's theme
1750
  * @param object theme Theme object
1752
  set_theme: function(theme) {
1753
  this.set_component('theme', theme);
1754
  },
1755
+
1756
  /* Properties */
1757
+
1758
  /**
1759
  * Lock the viewer
1760
  * Indicates that item is currently being processed
1763
  lock: function() {
1764
  return this.set_status('item_working', $.Deferred());
1765
  },
1766
+
1767
  /**
1768
  * Retrieve lock
1769
  * @param bool simple (optional) Whether to return a simple status of the locked status (Default: FALSE)
1791
  }
1792
  return ( full ) ? r : r.promise();
1793
  },
1794
+
1795
  is_locked: function() {
1796
  return this.get_lock(true);
1797
  },
1798
+
1799
  /**
1800
  * Unlock the viewer
1801
  * Any callbacks registered for this action will be executed
1804
  unlock: function() {
1805
  return this.get_lock(false, true).resolve();
1806
  },
1807
+
1808
  /**
1809
  * Set Viewer active status
1810
  * @param bool mode (optional) Activate or deactivate status (Default: TRUE)
1816
  }
1817
  return this.set_status('active', mode);
1818
  },
1819
+
1820
  /**
1821
  * Check Viewer active status
1822
  * @return bool Active status
1824
  is_active: function() {
1825
  return this.get_status('active');
1826
  },
1827
+
1828
  /**
1829
  * Set loading mode
1830
  * @param bool mode (optional) Set (TRUE) or unset (FALSE) loading mode (Default: TRUE)
1853
  }
1854
  return dfr.promise();
1855
  },
1856
+
1857
  /**
1858
  * Unset loading mode
1859
  * @see set_loading()
1862
  unset_loading: function() {
1863
  return this.set_loading(false);
1864
  },
1865
+
1866
  /**
1867
  * Retrieve loading status
1868
  * @return bool Loading status (Default: FALSE)
1870
  get_loading: function() {
1871
  return ( this.util.is_bool(this.loading) ) ? this.loading : false;
1872
  },
1873
+
1874
  /**
1875
  * Check if viewer is currently loading content
1876
  * @return bool Loading status (Default: FALSE)
1877
  */
1878
  is_loading: function() {
1879
+ return this.get_loading();
1880
  },
1881
+
1882
  /* Display */
1883
+
1884
  /**
1885
  * Display content in viewer
1886
  * @param Content_Item item Item to show
1898
  valid = ( this.get_theme() && this.get_theme().get_template().get_layout(false) !== "" ) ? true : false;
1899
  this.set_attribute(vt, valid);
1900
  }
1901
+
1902
  if ( !valid ) {
1903
  this.close();
1904
  return false;
1931
  });
1932
  }
1933
  },
1934
+
1935
  /* History Management */
1936
+
1937
  history_handle: function(e) {
1938
  var state = e.originalEvent.state;
1939
  // Load item
1947
  // Close viewer
1948
  if ( -1 !== count ) {
1949
  this.close();
1950
+ }
1951
  }
1952
  },
1953
+
1954
  history_get: function(full) {
1955
  return this.get_status('history_count', full);
1956
  },
1999
  history.go( -1 * count );
2000
  }
2001
  },
2002
+
2003
  /**
2004
  * Check if viewer is currently open
2005
+ * Checks if node is actually visible in DOM
2006
+ * @return bool TRUE if viewer is open, FALSE otherwise
2007
  */
2008
  is_open: function() {
2009
  return ( this.dom_get().css('display') === 'none' ) ? false : true;
2010
  },
2011
+
2012
  /**
2013
  * Load output into DOM
2014
  */
2070
  // Set classes
2071
  var d = v.dom_get();
2072
  var classes = ['item_single', 'item_multi'];
2073
+ var ms = ['addClass', 'removeClass'];
2074
  if ( !v.get_item().get_group().is_single() ) {
2075
  ms.reverse();
2076
  }
2101
  // Render
2102
  thm.render();
2103
  },
2104
+
2105
  /**
2106
  * Retrieve container element
2107
  * Creates default container element if not yet created
2123
  }
2124
  return c;
2125
  },
2126
+
2127
  /**
2128
  * Custom Viewer DOM initialization
2129
  */
2148
  }
2149
  thm.render(true);
2150
  },
2151
+
2152
  /**
2153
  * Prepare DOM for viewer
2154
  */
2156
  var m = ( this.util.is_bool(mode) && !mode ) ? 'removeClass' : 'addClass';
2157
  $('html')[m](this.util.add_prefix('overlay'));
2158
  },
2159
+
2160
  /**
2161
  * Restore DOM
2162
  * Required after viewer is closed
2164
  dom_restore: function() {
2165
  this.dom_prep(false);
2166
  },
2167
+
2168
  /* Layout */
2169
+
2170
  get_layout: function() {
2171
  var ret = this.dom_get('layout', {
2172
  'put': {
2177
  });
2178
  return ret;
2179
  },
2180
+
2181
  /* Animation */
2182
+
2183
  animation_enabled: function() {
2184
  return this.get_attribute('animate', true);
2185
  },
2186
+
2187
  /* Overlay */
2188
+
2189
  /**
2190
  * Determine if overlay is enabled for viewer
2191
  * @return bool TRUE if overlay is enabled, FALSE otherwise
2194
  var ov = this.get_attribute('overlay_enabled');
2195
  return ( this.util.is_bool(ov) ) ? ov : false;
2196
  },
2197
+
2198
  /**
2199
  * Retrieve overlay DOM element
2200
  * @return jQuery Overlay element (NULL if no overlay set for viewer)
2213
  }
2214
  return $(o);
2215
  },
2216
+
2217
  /**
2218
  * Unload viewer
2219
  */
2224
  dfr.resolve();
2225
  return dfr.promise();
2226
  },
2227
+
2228
  /**
2229
  * Reset viewer
2230
  */
2245
  // Clear for next item
2246
  this.unlock();
2247
  },
2248
+
2249
  /* Content */
2250
+
2251
  get_labels: function() {
2252
  return this.get_attribute('labels', {});
2253
  },
2254
+
2255
  get_label: function(name) {
2256
  var lbls = this.get_labels();
2257
  return ( name in lbls ) ? lbls[name] : '';
2258
  },
2259
+
2260
  /* Interactivity */
2261
+
2262
  /**
2263
  * Initialize event handlers upon opening lightbox
2264
  */
2268
  if ( this.open ) {
2269
  return false;
2270
  }
2271
+
2272
  // Control event bubbling
2273
  var l = this.get_layout();
2274
  l.children().click(function(ev) {
2275
  ev.stopPropagation();
2276
  });
2277
+
2278
  /* Close */
2279
  var v = this;
2280
  var close = function() {
2287
  // Fire event
2288
  this.trigger('events-open');
2289
  },
2290
+
2291
  /**
2292
  * Initialize event handlers upon completing lightbox rendering
2293
  */
2298
  // Fire event
2299
  this.trigger('events-complete');
2300
  },
2301
+
2302
  keys_enable: function(mode) {
2303
  if ( !this.util.is_bool(mode) ) {
2304
  mode = true;
2314
  $(document).off(e);
2315
  }
2316
  },
2317
+
2318
  keys_disable: function() {
2319
  this.keys_enable(false);
2320
  },
2321
+
2322
  keys_control: function(ev) {
2323
  var handlers = {
2324
  27: this.close, /* esc */
2335
  return false;
2336
  }
2337
  },
2338
+
2339
  /**
2340
  * Check if slideshow functionality is enabled
2341
  * @return bool TRUE if slideshow is enabled, FALSE otherwise
2342
  */
2343
  slideshow_enabled: function() {
2344
  var o = this.get_attribute('slideshow_enabled');
2345
+ return ( this.util.is_bool(o) && o && this.get_item() && !this.get_item().get_group().is_single() ) ? true : false;
2346
  },
2347
+
2348
  /**
2349
  * Checks if slideshow is currently active
2350
  * @return bool TRUE if slideshow is active, FALSE otherwise
2352
  slideshow_active: function() {
2353
  return ( this.slideshow_enabled() && ( this.get_attribute('slideshow_active') || ( !this.init && this.get_attribute('slideshow_autostart') ) ) ) ? true : false;
2354
  },
2355
+
2356
  /**
2357
  * Clear slideshow timer
2358
  */
2359
  slideshow_clear_timer: function() {
2360
  clearInterval(this.get_attribute('slideshow_timer'));
2361
  },
2362
+
2363
  /**
2364
  * Start slideshow timer
2365
  * @param function callback Callback function
2367
  slideshow_set_timer: function(callback) {
2368
  this.set_attribute('slideshow_timer', setInterval(callback, this.get_attribute('slideshow_duration') * 1000));
2369
  },
2370
+
2371
  /**
2372
  * Start Slideshow
2373
  */
2384
  this.slideshow_set_timer(function() {
2385
  // Pause slideshow until next item fully loaded
2386
  v.slideshow_pause();
2387
+
2388
  // Show next item
2389
  v.item_next();
2390
  });
2391
  this.trigger('slideshow-start');
2392
  },
2393
+
2394
  /**
2395
  * Stop Slideshow
2396
  * @param bool full (optional) Full stop (TRUE) or pause (FALSE) (Default: TRUE)
2407
  this.slideshow_clear_timer();
2408
  this.trigger('slideshow-stop');
2409
  },
2410
+
2411
  slideshow_toggle: function() {
2412
  if ( !this.slideshow_enabled() ) {
2413
  return false;
2419
  }
2420
  this.trigger('slideshow-toggle');
2421
  },
2422
+
2423
  /**
2424
  * Pause Slideshow
2425
  * @param bool mode (optional) Pause (TRUE) or Resume (FALSE) slideshow (default: TRUE)
2441
  }
2442
  this.trigger('slideshow-pause');
2443
  },
2444
+
2445
  /**
2446
  * Resume slideshow
2447
  */
2448
  slideshow_resume: function() {
2449
  this.slideshow_pause(false);
2450
  },
2451
+
2452
  /**
2453
  * Next item
2454
  */
2466
  }
2467
  g.show_next();
2468
  },
2469
+
2470
  /**
2471
  * Previous item
2472
  */
2483
  }
2484
  g.show_prev();
2485
  },
2486
+
2487
  /**
2488
  * Close viewer
2489
  */
2515
  */
2516
  var Group = {
2517
  /* Configuration */
2518
+
2519
  _slug: 'group',
2520
  _reciprocal: true,
2521
  _refs: {
2522
  'current': 'Content_Item'
2523
  },
2524
+
2525
  /* References */
2526
+
2527
  current: null,
2528
+
2529
  /* Properties */
2530
+
2531
  /**
2532
  * Selector for getting group items
2533
+ * @var string
2534
  */
2535
  selector: null,
2536
+
2537
  /* Methods */
2538
+
2539
  /* Init */
2540
+
2541
  _hooks: function() {
2542
  var t = this;
2543
  this.on(['item-prev', 'item-next'], function() {
2544
  t.trigger('item-change');
2545
  });
2546
  },
2547
+
2548
  /* Properties */
2549
+
2550
  /**
2551
  * Retrieve selector for group items
2552
+ * @return string Group items selector
2553
  */
2554
  get_selector: function() {
2555
  if ( this.util.is_empty(this.selector) ) {
2558
  }
2559
  return this.selector;
2560
  },
2561
+
2562
  /**
2563
  * Retrieve group items
2564
  */
2569
  }
2570
  return items;
2571
  },
2572
+
2573
  /**
2574
  * Retrieve item at specified index
2575
  * If no index specified, first item is returned
2591
  // Return specified item
2592
  return items.get(idx);
2593
  },
2594
+
2595
  /**
2596
  * Retrieve (zero-based) position of specified item in group
2597
  * @param Content_Item item Item to locate in group
2613
  // Sanitize
2614
  return ( !this.util.is_empty( this.get_current() ) );
2615
  },
2616
+
2617
  /**
2618
  * Retrieve current item
2619
  * @uses Group.current
2626
  }
2627
  return this.current;
2628
  },
2629
+
2630
  /**
2631
  * Sets current group item
2632
  * @param Content_Item item Item to set as current
2638
  this.current = item;
2639
  }
2640
  },
2641
+
2642
  get_next: function(item) {
2643
  // Validate
2644
  if ( !this.util.is_type(item, View.Content_Item) ) {
2657
  }
2658
  return next;
2659
  },
2660
+
2661
  get_prev: function(item) {
2662
  // Validate
2663
  if ( !this.util.is_type(item, View.Content_Item) ) {
2677
  }
2678
  return prev;
2679
  },
2680
+
2681
  show_next: function(item) {
2682
  if ( this.get_size() > 1 ) {
2683
  // Retrieve item
2697
  this.trigger('item-next');
2698
  }
2699
  },
2700
+
2701
  show_prev: function(item) {
2702
  if ( this.get_size() > 1 ) {
2703
  // Retrieve item
2717
  this.trigger('item-prev');
2718
  }
2719
  },
2720
+
2721
  /**
2722
  * Retrieve total number of items in group
2723
+ * @return int Number of items in group
2724
  */
2725
  get_size: function() {
2726
  return this.get_items().length;
2727
  },
2728
+
2729
  is_single: function() {
2730
  return ( this.get_size() === 1 );
2731
  }
2738
  * @param obj options Init options
2739
  */
2740
  var Content_Handler = {
2741
+
2742
  /* Configuration */
2743
+
2744
  _slug: 'content_handler',
2745
  _refs: {
2746
  'item': 'Content_Item'
2747
  },
2748
+
2749
  /* References */
2750
+
2751
  item: null,
2752
+
2753
  /* Properties */
2754
+
2755
  /**
2756
  * Raw layout template
2757
+ * @var string
2758
  */
2759
  template: '',
2760
+
2761
  /* Methods */
2762
+
2763
  /* Item */
2764
+
2765
  /**
2766
  * Check if item instance set for type
2767
  * @uses get_item()
2771
  has_item: function() {
2772
  return ( this.util.is_empty(this.get_item()) ) ? false : true;
2773
  },
2774
+
2775
  /**
2776
  * Retrieve item instance set on type
2777
  * @uses get_component()
2780
  get_item: function() {
2781
  return this.get_component('item');
2782
  },
2783
+
2784
  /**
2785
  * Set item instance for type
2786
  * Items are only meant to be set/used while item is being processed
2793
  var r = this.set_component('item', item);
2794
  return r;
2795
  },
2796
+
2797
  /**
2798
  * Clear item instance from type
2799
  * Sets value to NULL
2801
  clear_item: function() {
2802
  this.clear_component('item');
2803
  },
2804
+
2805
  /* Evaluation */
2806
+
2807
  /**
2808
  * Check if item matches content handler
2809
  * @param object item Content_Item instance to check for type match
2810
+ * @return bool TRUE if type matches, FALSE otherwise
2811
  */
2812
  match: function(item) {
2813
  // Validate
2816
  // Stop processing types with no matching algorithm
2817
  if ( !this.util.is_empty(m) ) {
2818
  // Process regex patterns
2819
+
2820
  // String-based
2821
  if ( this.util.is_string(m) ) {
2822
  // Create new regexp object
2835
  // Default
2836
  return false;
2837
  },
2838
+
2839
  /* Processing/Output */
2840
+
2841
  /**
2842
  * Loads item data
2843
  * @param obj item Content item to load data for
2852
  }
2853
  return dfr.promise();
2854
  },
2855
+
2856
  /**
2857
  * Render output to display item
2858
  * @param Content_Item item Item to render output for
2874
  */
2875
  var Content_Item = {
2876
  /* Configuration */
2877
+
2878
  _slug: 'content_item',
2879
  _reciprocal: true,
2880
  _refs: {
2882
  'group': 'Group',
2883
  'type': 'Content_Handler'
2884
  },
2885
+
2886
  _attr_default: {
2887
  source: null,
2888
  permalink: null,
2892
  internal: false,
2893
  output: null
2894
  },
2895
+
2896
  /* References */
2897
+
2898
  group: null,
2899
  viewer: null,
2900
  type: null,
2901
+
2902
  /* Properties */
2903
+
2904
  data: null,
2905
  loaded: null,
2906
+
2907
  /* Init */
2908
+
2909
  _c: function(el) {
2910
  // Save element to instance
2911
  this.dom_set(el);
2912
  // Default initialization
2913
  this._super();
2914
  },
2915
+
2916
  /* Methods */
2917
+
2918
  /*-** Attributes **-*/
2919
+
2920
  /**
2921
  * Build default attributes
2922
  * Populates attributes with asset properties (attachments)
2954
  }
2955
  return this._attr_default;
2956
  },
2957
+
2958
  /*-** Properties **-*/
2959
+
2960
  /**
2961
  * Retrieve item output
2962
  * Output generated based on content handler if not previously generated
2988
  }
2989
  return dfr.promise();
2990
  },
2991
+
2992
  /**
2993
  * Cache output for future retrieval
2994
  * @uses set_attribute() to cache output
2998
  this.set_attribute('output', out);
2999
  }
3000
  },
3001
+
3002
  /**
3003
  * Retrieve item output
3004
  * Alias for `get_output()`
3005
+ * @return jQuery.Promise Deferred that is resolved when content is retrieved
3006
  */
3007
  get_content: function() {
3008
  return this.get_output();
3009
  },
3010
+
3011
  /**
3012
  * Retrieve item URI
3013
  * @param string mode (optional) Which URI should be retrieved
3029
  ret = ret.replace(/&(#38|amp);/, '&');
3030
  return ret;
3031
  },
3032
+
3033
  /**
3034
  * Retrieve item title
3035
  */
3040
  if ( this.has_attribute(prop_cached) ) {
3041
  return this.get_attribute(prop_cached, '');
3042
  }
3043
+
3044
  var title = '';
3045
  // Generate title from DOM values
3046
  var dom = this.dom_get();
3047
+ var t = this;
3048
+ /**
3049
+ * Validate title value.
3050
+ *
3051
+ * Removes default title based on user option.
3052
+ *
3053
+ * @param string title Title to check.
3054
+ * @return string Current title or empty string (if default title set and not permitted).
3055
+ */
3056
+ var validate = function(title) {
3057
+ // Return empty string if empty title set.
3058
+ if ( typeof title !== 'string' || '' === title.trim() ) {
3059
+ return '';
3060
+ }
3061
+ // Cleanup title.
3062
+ title = title.trim();
3063
+ // Stop processing if default title is allowed.
3064
+ if ( t.get_viewer().get_attribute('title_default') ) {
3065
+ return title;
3066
+ }
3067
+
3068
+ // Check if default title is used.
3069
+ if ( title === t.get_title_default() ) {
3070
+ title = '';
3071
+ }
3072
+ return title;
3073
+ };
3074
+
3075
  // DOM-based caption
3076
  if ( dom.length ) {
3077
  // Link title (generally must be manually-entered)
3078
  title = dom.attr(prop);
3079
+
3080
  // Figcaption element
3081
  if ( !title ) {
3082
  title = dom.closest('figure').find('figcaption').first().html();
3087
  title = dom.closest('figure').find('.wp-caption-text').first().html();
3088
  }
3089
  }
3090
+
3091
  // Saved attributes
3092
  if ( !title ) {
3093
  var props = ['caption', 'title'];
3094
  for ( var x = 0; x < props.length; x++ ) {
3095
+ title = validate( this.get_attribute(props[x], '') );
3096
  if ( !this.util.is_empty(title) ) {
3097
  break;
3098
  }
3099
  }
3100
  }
3101
+
3102
  // Fallbacks
3103
  if ( !title && dom.length ) {
3104
+ // Image Alt attribute
3105
+ title = validate( dom.find('img').first().attr('alt') );
3106
+
3107
  // Element text
3108
  if ( !title ) {
3109
+ title = validate( dom.get(0).innerText.trim() );
3110
  }
3111
  }
3112
+
3113
+ // Final validation.
3114
+ title = validate(title);
3115
+
3116
+ // Cache retrieved value
3117
+ this.set_attribute(prop_cached, title);
3118
+ // Return value
3119
+ return title;
3120
+ },
3121
+
3122
+ /**
3123
+ * Retrieve default title.
3124
+ *
3125
+ * WordPress-generated default title for attachments is base file name (without extension).
3126
+ *
3127
+ * @return string Default title.
3128
+ */
3129
+ get_title_default: function() {
3130
+ var val = '';
3131
+ var prop = 'title_default';
3132
+ // Build default title if necessary.
3133
+ if ( !this.has_attribute(prop) ) {
3134
  var f = this.get_uri('source');
3135
  var i = f.lastIndexOf('/');
3136
  if ( -1 !== i ) {
3139
  if ( -1 !== i ) {
3140
  f = f.substr(0, i);
3141
  }
 
 
 
3142
  }
3143
+ // Save default title
3144
+ val = this.set_attribute(prop, f);
3145
+ } else {
3146
+ val = this.get_attribute(prop);
3147
  }
3148
+ return val;
 
 
 
 
 
3149
  },
3150
+
3151
  /**
3152
  * Retrieve item dimensions
3153
+ * @return obj Item `width` and `height` properties (px)
3154
  */
3155
  get_dimensions: function() {
3156
  return $.extend({'width': 0, 'height': 0}, this.get_attribute('dimensions'), {});
3157
  },
3158
+
3159
  /**
3160
  * Save item data to instance
3161
  * Item data is saved when rendered
3164
  set_data: function(data) {
3165
  this.data = data;
3166
  },
3167
+
3168
  get_data: function() {
3169
  return this.data;
3170
  },
3171
+
3172
  /**
3173
  * Determine gallery type
3174
  * @return string|null Gallery type ID (NULL if item not in gallery)
3179
  'wp': '.gallery-icon',
3180
  'ngg': '.ngg-gallery-thumbnail'
3181
  };
3182
+
3183
  var dom = this.dom_get();
3184
  for ( var type in types ) {
3185
  if ( dom.parent(types[type]).length > 0 ) {
3189
  }
3190
  return ret;
3191
  },
3192
+
3193
  /**
3194
  * Check if current link is part of a gallery
3195
  * @param string gType (optional) Gallery type to check for
3208
  // Check for specific gallery type
3209
  return ( gType === type ) ? true : false;
3210
  },
3211
+
3212
  /*-** Component References **-*/
3213
+
3214
  /* Viewer */
3215
+
3216
  get_viewer: function() {
3217
  return this.get_component('viewer', {get_default: true});
3218
  },
3219
+
3220
  /**
3221
  * Sets item's viewer property
3222
  * @uses View.get_viewer() to retrieve global viewer
3227
  set_viewer: function(v) {
3228
  return this.set_component('viewer', v);
3229
  },
3230
+
3231
  /* Group */
3232
 
3233
  /**
3250
  }
3251
  return g;
3252
  },
3253
+
3254
  /**
3255
  * Sets item's group property
3256
  * @uses View.get_group() to retrieve global group
3263
  if ( this.util.is_string(g) ) {
3264
  g = this.get_controller().get_group(g);
3265
  }
3266
+
3267
  // Set (or clear) group property
3268
  this.group = ( this.util.is_type(g, View.Group) ) ? g : false;
3269
  },
3270
+
3271
  /* Content Handler */
3272
+
3273
  /**
3274
  * Retrieve item type
3275
  * @uses get_component() to retrieve saved reference to Content_Handler instance
3283
  }
3284
  return t;
3285
  },
3286
+
3287
  /**
3288
  * Save content handler reference
3289
  * @uses set_component() to save type reference
3292
  set_type: function(type) {
3293
  return this.set_component('type', type);
3294
  },
3295
+
3296
  /**
3297
  * Check if content handler exists for item
3298
  * @return bool TRUE if content handler exists, FALSE otherwise
3301
  var ret = !this.util.is_empty(this.get_type());
3302
  return ret;
3303
  },
3304
+
3305
  /* Actions */
3306
+
3307
  /**
3308
  * Display item in viewer
3309
  * @uses get_viewer() to retrieve viewer instance for item
3324
  var ret = v.show(this);
3325
  return ret;
3326
  },
3327
+
3328
  /**
3329
  * Load item data
3330
+ *
3331
  * Retrieves item data from external sources (if necessary)
3332
  * @uses this.loaded to save loaded state
3333
  * @return obj Promise that is resolved when item data is loaded
3339
  }
3340
  return this.loaded.promise();
3341
  },
3342
+
3343
  reset: function() {
3344
  this.set_attribute('options_show', null);
3345
  }
3351
  * Modeled Component
3352
  */
3353
  var Modeled_Component = {
3354
+
3355
  _slug: 'modeled_component',
3356
+
3357
  /* Methods */
3358
+
3359
  /* Attributes */
3360
+
3361
  /**
3362
  * Retrieve attribute
3363
  * Gives priority to model values
3391
  }
3392
  return ret;
3393
  },
3394
+
3395
  /**
3396
  * Get attribute recursively
3397
  * Merges objects from ancestors together
3423
  * @param string key Attribute to set
3424
  * @param mixed val Value to set for attribute
3425
  * @param bool|obj use_model (optional) Set the value on the model (Default: TRUE)
3426
+ * > bool: Set attribute on current model (TRUE) or as standard attribute (FALSE)
3427
  * > obj: Model object to set attribute on
3428
  * @return mixed Attribute value
3429
  */
3438
  // Determine where to set attribute
3439
  if ( !!use_model ) {
3440
  var model = this.util.is_obj(use_model) ? use_model : this.get_model();
3441
+
3442
  // Set attribute in model
3443
  model[key] = val;
3444
  } else {
3448
  return val;
3449
  },
3450
 
3451
+
3452
  /* Model */
3453
+
3454
  /**
3455
  * Retrieve Template model
3456
  * @return obj Model (Default: Empty object)
3475
  },
3476
 
3477
 
3478
+
3479
  /**
3480
  * Check if specified attribute exists in model
3481
  * @param string key Attribute to check for
3484
  in_model: function(key) {
3485
  return ( this.util.in_obj(this.get_model(), key) ) ? true : false;
3486
  },
3487
+
3488
  /**
3489
  * Retrieve all ancestor models
3490
  * @param bool inc_current (optional) Include current model in list (Default: FALSE)
3503
  }
3504
  return ret;
3505
  },
3506
+
3507
  /**
3508
  * Retrieve first ancestor of current theme with specified attribute
3509
  * > Current model is also evaluated
3556
  * Theme
3557
  */
3558
  var Theme = {
3559
+
3560
  /* Configuration */
3561
+
3562
  _slug: 'theme',
3563
  _refs: {
3564
  'viewer': 'Viewer',
3565
  'template': 'Template'
3566
  },
3567
  _models: {},
3568
+
3569
  _attr_default: {
3570
  template: null,
3571
  model: null
3572
  },
3573
+
3574
  /* References */
3575
+
3576
  viewer: null,
3577
  template: null,
3578
+
3579
  /* Methods */
3580
+
3581
  /**
3582
  * Custom constructor
3583
  * @see Component._c()
3590
  }
3591
  // Pass parameters to parent constructor
3592
  this._super(id, attributes);
3593
+
3594
  // Set viewer instance
3595
  this.set_viewer(viewer);
3596
+
3597
  // Set theme model
3598
  this.set_model(id);
3599
  },
3600
+
3601
  /* Viewer */
3602
+
3603
  get_viewer: function() {
3604
  return this.get_component('viewer', {check_attr: false, get_default: true});
3605
  },
3606
+
3607
  /**
3608
  * Sets theme's viewer property
3609
  * @uses View.get_viewer() to retrieve global viewer
3614
  set_viewer: function(v) {
3615
  return this.set_component('viewer', v);
3616
  },
3617
+
3618
  /* Template */
3619
+
3620
  /**
3621
  * Retrieve template instance
3622
  * @return Template instance
3632
  }
3633
  return ret;
3634
  },
3635
+
3636
  /* Tags */
3637
+
3638
  /**
3639
  * Retrieve tags from template
3640
  * All tags will be retrieved by default
3647
  get_tags: function(name, prop) {
3648
  return this.get_template().get_tags(name, prop);
3649
  },
3650
+
3651
  /**
3652
  * Retrieve tag DOM elements
3653
  * @see Template.dom_get_tag()
3655
  dom_get_tag: function(tag, prop) {
3656
  return $(this.get_template().dom_get_tag(tag, prop));
3657
  },
3658
+
3659
  /**
3660
  * Retrieve template tag CSS selector
3661
  * @uses Template.get_tag_selector()
3666
  get_tag_selector: function(name, prop) {
3667
  return this.get_template().get_tag_selector(name, prop);
3668
  },
3669
+
3670
  /* Model */
3671
+
3672
  /**
3673
  * Retrieve theme models
3674
  * @return obj Theme models
3676
  get_models: function() {
3677
  return this._models;
3678
  },
3679
+
3680
  /**
3681
  * Retrieve specified theme model
3682
  * @param string id (optional) Theme model to retrieve
3702
  }
3703
  return ret;
3704
  },
3705
+
3706
  /**
3707
  * Set model for current theme instance
3708
  * @param string id (optional) Theme ID (Default theme retrieved if ID invalid)
3719
  }
3720
  */
3721
  },
3722
+
3723
  /* Properties */
3724
+
3725
  /**
3726
  * Generate class names for DOM node
3727
  * @param string rtype (optional) Return data type
3747
  // Return class names
3748
  return cls;
3749
  },
3750
+
3751
  /**
3752
  * Get custom measurement
3753
  * @param string attr Measurement to retrieve
3758
  var meas = null;
3759
  // Validate
3760
  if ( !this.util.is_string(attr) ) {
3761
+ return meas;
3762
  }
3763
  if ( !this.util.is_obj(def, false) ) {
3764
  def = {};
3765
  }
3766
  // Manage cache
3767
+ var attr_cache = this.util.format('%s_cache', attr);
3768
  var cache = this.get_attribute(attr_cache, {}, false);
3769
  var status = '_status';
3770
  var item = this.get_viewer().get_item();
3804
  // Return measurement (copy)
3805
  return $.extend({}, meas);
3806
  },
3807
+
3808
  /**
3809
  * Get default measurement using attribute's default handler
3810
  * @param string attr Measurement attribute
3828
  }
3829
  return attr;
3830
  },
3831
+
3832
  /**
3833
  * Retrieve theme offset
3834
  * @return obj Theme offset with `width` & `height` properties
3836
  get_offset: function() {
3837
  return this.get_measurement('offset', { 'width': 0, 'height': 0});
3838
  },
3839
+
3840
  /**
3841
  * Generate default offset
3842
  * @return obj Theme offsets with `width` & `height` properties
3871
  offset[key] = -1 * val;
3872
  });
3873
  }
3874
+
3875
  // Set offset
3876
  offset.width += l.width();
3877
  offset.height += l.height();
3885
  vc.empty().remove();
3886
  return offset;
3887
  },
3888
+
3889
  /**
3890
  * Retrieve theme margins
3891
+ * @return obj Theme margin with `width` & `height` properties
3892
  */
3893
  get_margin: function() {
3894
  return this.get_measurement('margin', {'width': 0, 'height': 0});
3895
  },
3896
+
3897
  /**
3898
  * Retrieve item dimensions
3899
  * Dimensions are adjusted to fit window (if necessary)
3926
  }
3927
  return $.extend({}, dims);
3928
  },
3929
+
3930
  /**
3931
  * Retrieve theme dimensions
3932
  * @return obj Theme dimensions with `width` & `height` properties
3939
  });
3940
  return dims;
3941
  },
3942
+
3943
  /**
3944
  * Retrieve all breakpoints
3945
  * @return object Breakpoints
3947
  get_breakpoints: function() {
3948
  return this.get_attribute_recursive('breakpoints');
3949
  },
3950
+
3951
  /**
3952
  * Get breakpoint value
3953
  * @param string target Breakpoint target
3963
  }
3964
  return ret;
3965
  },
3966
+
3967
  /* Output */
3968
+
3969
  /**
3970
  * Render Theme output
3971
  * @param bool init (optional) Initialize theme (Default: FALSE)
3990
  // Render template
3991
  tpl.render(init);
3992
  },
3993
+
3994
  transition: function(event, clear_queue) {
3995
  var dfr = null;
3996
  var attr = 'transition';
4062
  */
4063
  var Template = {
4064
  /* Configuration */
4065
+
4066
  _slug: 'template',
4067
  _reciprocal: true,
4068
+
4069
  _refs: {
4070
  'theme': 'Theme'
4071
  },
4076
  * @var string
4077
  */
4078
  layout_uri: '',
4079
+
4080
  /**
4081
  * Raw layout template
4082
  * @var string
4083
+ */
4084
  layout_raw: '',
4085
  /**
4086
  * Parsed layout
4101
  */
4102
  model: null
4103
  },
4104
+
4105
  /* References */
4106
+
4107
  theme: null,
4108
+
4109
  /* Methods */
4110
+
4111
  _c: function(attributes) {
4112
  this._super('', attributes);
4113
  },
4114
+
4115
  _hooks: function() {
4116
  // TODO: Refactor to event that can save retrieved tags
4117
  // (`dom_init` event called during attribute initialization so tags are not saved)
4129
  });
4130
  });
4131
  },
4132
+
4133
  get_theme: function() {
4134
  var ret = this.get_component('theme');
4135
  return ret;
4136
  },
4137
+
4138
  /* Output */
4139
+
4140
  /**
4141
  * Render output
4142
  * @param bool init (optional) Whether to initialize layout (TRUE) or render item (FALSE) (Default: FALSE)
4196
  this.trigger('render-init', this.dom_get());
4197
  }
4198
  },
4199
+
4200
  /*-** Layout **-*/
4201
+
4202
  /**
4203
  * Retrieve layout
4204
  * @param bool parsed (optional) TRUE retrieves parsed layout, FALSE retrieves raw layout (Default: TRUE)
4213
  var l = ( parsed ) ? this.parse_layout() : this.get_attribute('layout_raw', '');
4214
  return l;
4215
  },
4216
+
4217
  /**
4218
  * Parse layout
4219
  * Converts template tags to HTML elements
4234
  ret = this.parse_tags(ret);
4235
  // Save parsed layout
4236
  this.set_attribute(a, ret);
4237
+
4238
  // Return parsed layout
4239
  return ret;
4240
  },
4241
+
4242
  /**
4243
  * Sanitize layout
4244
  * @param obj|string l Layout string or jQuery object
4252
  // Set return type
4253
  var rtype = ( this.util.is_string(l) ) ? 'string' : null;
4254
  /* Quarantine hard-coded tags */
4255
+
4256
  // Create DOM structure from raw template
4257
  var dom = $(l);
4258
  // Find hard-coded tag nodes
4274
  }
4275
  return l;
4276
  },
4277
+
4278
  /*-** Tags **-*/
4279
+
4280
  /**
4281
  * Extract tags from template
4282
  * Tags are replaced with DOM element placeholders
4301
  }
4302
  return l;
4303
  },
4304
+
4305
  /**
4306
  * Create DOM element container for tag
4307
  * @param string Tag ID (will be prefixed)
4310
  get_tag_container: function(tag) {
4311
  // Build element
4312
  var attr = this.get_tag_attribute();
4313
+ return this.util.format('<span %s="%s"></span>', attr, encodeURI(tag));
4314
  },
4315
+
4316
  get_tag_attribute: function() {
4317
  return this.get_tag_temp().dom_get_attribute();
4318
  },
4319
+
4320
  /**
4321
  * Retrieve Template_Tag instance at specified index
4322
  * @param int idx (optional) Index to retrieve tag from
4333
  }
4334
  return ret;
4335
  },
4336
+
4337
  /**
4338
  * Retrieve tags from template
4339
  * Subset of tags may be retrieved based on parameter values
4406
  }
4407
  return ( this.util.is_array(tags, false) ) ? tags : [];
4408
  },
4409
+
4410
  /**
4411
  * Check if template contains tags
4412
  * @return bool TRUE if tags exist, FALSE otherwise
4414
  has_tags: function() {
4415
  return ( this.get_tags().length > 0 ) ? true : false;
4416
  },
4417
+
4418
  /**
4419
  * Retrieve temporary tag instance
4420
  * @return Template_Tag Temporary tag
4422
  get_tag_temp: function() {
4423
  return this.get_controller().get_component_temp(View.Template_Tag);
4424
  },
4425
+
4426
  /**
4427
  * Retrieve Template tag CSS selector
4428
  * @uses Template.get_tag_temp() to retrieve temporary tag instance
4443
  tag.set_attribute('prop', prop);
4444
  return tag.get_selector('full');
4445
  },
4446
+
4447
  /*-** DOM **-*/
4448
+
4449
  /**
4450
+ * Custom DOM initialization
4451
  */
4452
  dom_init: function() {
4453
  // Create DOM object from parsed layout
4454
  this.dom_set(this.get_layout());
4455
  this.trigger('dom_init');
4456
  },
4457
+
4458
  /**
4459
  * Retrieve DOM element(s) for specified tag
4460
  * @param string tag Name of tag to retrieve
4480
  View.Template = Modeled_Component.extend(Template);
4481
 
4482
  /**
4483
+ * Template tag
4484
  */
4485
  var Template_Tag = {
4486
  /* Configuration */
4495
  /**
4496
  * Tag Handlers
4497
  * Collection of Template_Tag_Handler instances
4498
+ * @var obj
4499
  */
4500
  handlers: {},
4501
  /* Methods */
4502
+
4503
  /**
4504
  * Constructor
4505
+ * @param
4506
  */
4507
  _c: function(tag_match) {
4508
  this.parse(tag_match);
4509
  },
4510
+
4511
  /**
4512
  * Set instance attributes using tag extracted from template
4513
  * @param string tag_match Extracted tag match
4547
  // Save to instance
4548
  this.set_attributes(attrs, true);
4549
  },
4550
+
4551
  /**
4552
  * Render tag output
4553
  * @param Content_Item item
4562
  return {'tag': tag, 'output': output};
4563
  });
4564
  },
4565
+
4566
  /**
4567
  * Retrieve tag name
4568
  * @return string Tag name (DEFAULT: NULL)
4570
  get_name: function() {
4571
  return this.get_attribute('name');
4572
  },
4573
+
4574
  /**
4575
  * Retrieve tag property
4576
  */
4577
  get_prop: function() {
4578
  return this.get_attribute('prop');
4579
  },
4580
+
4581
  /**
4582
  * Retrieve tag handler
4583
  * @return Template_Tag_Handler Handler instance (Empty instance if handler does not exist)
4585
  get_handler: function() {
4586
  return ( this.has_handler() ) ? this.handlers[this.get_name()] : new View.Template_Tag_Handler('');
4587
  },
4588
+
4589
  /**
4590
  * Check if handler exists for tag
4591
  * @return bool TRUE if handler exists, FALSE otherwise
4593
  has_handler: function() {
4594
  return ( this.get_name() in this.handlers );
4595
  },
4596
+
4597
  /**
4598
  * Generate class names for DOM node
4599
  * @param string rtype (optional) Return data type
4620
  // Return class names
4621
  return cls;
4622
  },
4623
+
4624
  /**
4625
  * Generate DOM-compatible class name based with varied levels of specificity
4626
  * @param int level (optional) Class name specificity
4653
  // Format & return
4654
  return ( !this.util.is_string(cls) ) ? this.get_ns() : this.add_ns(cls);
4655
  },
4656
+
4657
  /**
4658
  * Generate tag selector based on specified class name level
4659
  * @param string level (optional) Class name specificity (@see get_class() for parameter values)
4686
  dynamic: false,
4687
  props: {}
4688
  },
4689
+
4690
  /* Methods */
4691
+
4692
  /**
4693
  * Render tag output
4694
  * @param Content_Item item Item currently being displayed
4702
  // Return promise
4703
  return dfr.promise();
4704
  },
4705
+
4706
  add_prop: function(prop, fn) {
4707
  // Get attribute
4708
  var a = 'props';
4719
  // Save attribute
4720
  this.set_attribute(a, props);
4721
  },
4722
+
4723
  handle_prop: function(prop, item, instance) {
4724
  // Locate property
4725
  var props = this.get_attribute('props');
client/js/prod/lib.admin.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.attach&&!function($){SLB.attach("Admin",{init:function(){postboxes&&postboxes.add_postbox_toggles(pagenow)}}),$(document).ready(function(){SLB.Admin.init()})}(jQuery);
1
+ window.SLB&&SLB.attach&&function($){SLB.attach("Admin",{init:function(){postboxes&&postboxes.add_postbox_toggles(pagenow)}}),$(document).ready(function(){SLB.Admin.init()})}(jQuery);
client/js/prod/lib.core.js CHANGED
@@ -1 +1 @@
1
- window.jQuery&&!function($){"use strict";var c_init=!1,Class=function(){};Class.extend=function(members){function Class(){c_init||("function"==typeof this._init&&this._init.apply(this,arguments),"function"==typeof this._c&&this._c.apply(this,arguments))}var _super=this.prototype;c_init=!0;var proto=new this;c_init=!1;var val,name;for(name in proto)$.isPlainObject(proto[name])&&(val=$.extend({},proto[name]),proto[name]=val);var make_handler=function(nm,fn){return function(){var tmp=this._super;this._super=_super[nm];var ret=fn.apply(this,arguments);return this._super=tmp,ret}};for(name in members)"function"==typeof members[name]&&"function"==typeof _super[name]?proto[name]=make_handler(name,members[name]):proto[name]=$.isPlainObject(members[name])?$.extend({},members[name]):members[name];return Class.prototype=proto,Class.prototype.constructor=Class,Class.extend=this.extend,Class};var Base={base:!1,_parent:null,prefix:"slb",_init:function(){this._set_parent()},_set_parent:function(p){this.util.is_set(p)&&(this._parent=p),this.util._parent=this},attach:function(member,data,simple){var ret=data;return simple="undefined"!=typeof simple&&!!simple,"string"===$.type(member)&&($.isPlainObject(data)&&!simple&&(data._parent=this,data=this.Class.extend(data)),this[member]="function"===$.type(data)?new data:data,ret=this[member]),ret},has_child:function(child){if(!this.util.is_string(child))return!1;var children=child.split(".");child=null;var x,o=this;for(x=0;x<children.length;x++)if(child=children[x],""!==child){if(!this.util.is_obj(o)||!o[child])return!1;o=o[child]}return!0},is_base:function(){return!!this.base},get_parent:function(){var p=this._parent;return p||(this._parent={}),this._parent}},Utilities={_base:null,_parent:null,get_base:function(){if(!this._base){for(var p=this.get_parent(),p_prev=null,methods=["is_base","get_parent"];p_prev!==p&&this.is_method(p,methods)&&!p.is_base();)p_prev=p,p=p.get_parent();this._base=p}return this._base},get_parent:function(prop){var ret=this._parent;return ret||(ret=this._parent={}),this.is_string(prop)&&(ret=this.in_obj(ret,prop)?ret[prop]:null),ret},get_sep:function(sep){var sep_default="_";return this.is_string(sep,!1)?sep:sep_default},get_prefix:function(){var p=this.get_parent("prefix");return this.is_string(p,!1)?p:""},has_prefix:function(val,sep){return this.is_string(val)&&0===val.indexOf(this.get_prefix()+this.get_sep(sep))},add_prefix:function(val,sep,once){return this.is_string(val)?(sep=this.get_sep(sep),this.is_bool(once)||(once=!0),once&&this.has_prefix(val,sep)?val:[this.get_prefix(),val].join(sep)):this.get_prefix()},remove_prefix:function(val,sep,once){if(!this.is_string(val,!0))return"";if(sep=this.get_sep(sep),this.is_bool(once)||(once=!0),this.has_prefix(val,sep)){var prfx=this.get_prefix()+sep;do val=val.substr(prfx.length);while(!once&&this.has_prefix(val,sep))}return val},get_attribute:function(attr_base){var sep="-",top="data",attr=[top,this.get_prefix()].join(sep);return this.is_string(attr_base)&&0!==attr_base.indexOf(attr+sep)&&(attr=[attr,attr_base].join(sep)),attr},get_context:function(){var b=this.get_base();return $.isArray(b.context)||(b.context=[]),b.context},is_context:function(ctx){return this.is_string(ctx)&&(ctx=[ctx]),this.is_array(ctx)&&this.arr_intersect(this.get_context(),ctx).length>0},is_set:function(val){return"undefined"!=typeof val},is_type:function(val,type,nonempty){var ret=!1;if(this.is_set(val)&&null!==val&&this.is_set(type))switch($.type(type)){case"function":ret=val instanceof type;break;case"string":ret=$.type(val)===type;break;default:ret=!1}return!ret||this.is_set(nonempty)&&!nonempty||(ret=!this.is_empty(val)),ret},is_string:function(value,nonempty){return this.is_type(value,"string",nonempty)},is_array:function(value,nonempty){return this.is_type(value,"array",nonempty)},is_bool:function(value){return this.is_type(value,"boolean",!1)},is_obj:function(value,nonempty){return this.is_type(value,"object",nonempty)},is_func:function(value){return this.is_type(value,"function",!1)},is_method:function(obj,key){var ret=!1;if(this.is_string(key)&&(key=[key]),this.in_obj(obj,key)){ret=!0;for(var x=0;ret&&x<key.length;)ret=this.is_func(obj[key[x]]),x++}return ret},is_instance:function(obj,parent){return!!this.is_func(parent)&&(this.is_obj(obj)&&obj instanceof parent)},is_class:function(cls,parent){var ret=this.is_func(cls)&&"prototype"in cls;return ret&&this.is_set(parent)&&(ret=this.is_instance(cls.prototype,parent)),ret},is_num:function(value,nonempty){var f={nan:Number.isNaN?Number.isNaN:isNaN,finite:Number.isFinite?Number.isFinite:isFinite};return this.is_type(value,"number",nonempty)&&!f.nan(value)&&f.finite(value)},is_int:function(value,nonempty){return this.is_num(value,nonempty)&&Math.floor(value)===value},is_scalar:function(value,nonempty){return this.is_num(value,nonempty)||this.is_string(value,nonempty)||this.is_bool(value)},is_empty:function(value,type){var ret=!1;if(this.is_set(value))for(var empties=[null,"",!1,0],x=0;!ret&&x<empties.length;)ret=empties[x]===value,x++;else ret=!0;if(!ret)if(this.is_set(type)||(type=$.type(value)),this.is_type(value,type,!1))switch(type){case"string":case"array":ret=0===value.length;break;case"number":ret=0==value;break;case"object":if($.isPlainObject(value)){if(Object.getOwnPropertyNames)ret=0===Object.getOwnPropertyNames(value).length;else if(value.hasOwnProperty){ret=!0;for(var key in value)if(value.hasOwnProperty(key)){ret=!1;break}}}else ret=!1}else ret=!0;return ret},is_promise:function(obj){return this.is_method(obj,["then","done","always","fail","pipe"])},format:function(fmt,val){if(!this.is_string(fmt))return"";var params=[],ph="%s",strip=function(txt){return txt.indexOf(ph)!==-1?txt.replace(ph,""):txt};if(arguments.length<2||fmt.indexOf(ph)===-1)return strip(fmt);params=Array.prototype.slice.call(arguments,1),val=null;for(var x=0;x<params.length;x++)this.is_scalar(params[x],!1)||(params[x]="");if(1===params.length)fmt=fmt.replace(ph,params[0].toString());else{for(var idx=0,len=params.length,rlen=ph.length,pos=0;(pos=fmt.indexOf(ph))&&pos!==-1&&idx<len;)fmt=fmt.substr(0,pos)+params[idx].toString()+fmt.substr(pos+rlen),idx++;fmt=strip(fmt)}return fmt},in_obj:function(obj,key,all){this.is_bool(all)||(all=!0),this.is_string(key)&&(key=[key]);var ret=!1;if(this.is_obj(obj)&&this.is_array(key))for(var val,x=0;x<key.length&&(val=key[x],ret=!!(this.is_string(val)&&val in obj),!(!all&&ret||all&&!ret));x++);return ret},obj_keys:function(obj){var keys=[];if(!this.is_obj(obj))return keys;if(Object.keys)keys=Object.keys(obj);else{var prop;for(prop in obj)obj.hasOwnProperty(prop)&&keys.push(prop)}return keys},arr_intersect:function(arr1,arr2){var x,ret=[],params=Array.prototype.slice.call(arguments),arrs=[];for(x=0;x<params.length;x++)this.is_array(params[x],!1)&&arrs.push(params[x]);if(arrs.length<2)return ret;params=arr1=arr2=null;var add,sub,base=arrs.shift();for(x=0;x<base.length;x++){for(add=!0,sub=0;sub<arrs.length;sub++)if(arrs[sub].indexOf(base[x])===-1){add=!1;break}add&&ret.push(base[x])}return ret},guid:function(){function _p8(s){var p=(Math.random().toString(16)+"000000000").substr(2,8);return s?"-"+p.substr(0,4)+"-"+p.substr(4,4):p}return _p8()+_p8(!0)+_p8(!0)+_p8()},parse_uri:function(uri){return $('<a href="'+uri+'"/>').get(0)},parse_query:function(uri){var delim={vars:"&",val:"="},query={raw:[],parsed:{},string:""};if(uri=this.parse_uri(uri),0===uri.search.indexOf("?")){query.raw=uri.search.substr(1).split(delim.vars);var i,temp,key,val;for(i=0;i<query.raw.length;i++)temp=query.raw[i].split(delim.val),key=temp.shift(),val=temp.length>0?temp.join(delim.val):null,query.parsed[key]=val}return query.parsed},build_query:function(query){var val,q=[],delim={vars:"&",val:"="};for(var key in query)val=null!==query[key]?delim.val+query[key]:"",q.push(key+val);return q.join(delim.vars)}};Base.attach("util",Utilities,!0);var SLB_Base=Class.extend(Base),Core={base:!0,context:[],Class:SLB_Base,_init:function(){this._super(),$("html").addClass(this.util.get_prefix())}},SLB_Core=SLB_Base.extend(Core);window.SLB=new SLB_Core}(jQuery);
1
+ window.jQuery&&function($){"use strict";function Class(){}var c_init=!1,Base={base:!(Class.extend=function(members){var _super=this.prototype;c_init=!0;var val,name,proto=new this;for(name in c_init=!1,proto)$.isPlainObject(proto[name])&&(val=$.extend({},proto[name]),proto[name]=val);function make_handler(nm,fn){return function(){var tmp=this._super;this._super=_super[nm];var ret=fn.apply(this,arguments);return this._super=tmp,ret}}for(name in members)"function"==typeof members[name]&&"function"==typeof _super[name]?proto[name]=make_handler(name,members[name]):proto[name]=$.isPlainObject(members[name])?$.extend({},members[name]):members[name];function Class(){c_init||("function"==typeof this._init&&this._init.apply(this,arguments),"function"==typeof this._c&&this._c.apply(this,arguments))}return((Class.prototype=proto).constructor=Class).extend=this.extend,Class}),_parent:null,prefix:"slb",_init:function(){this._set_parent()},_set_parent:function(p){this.util.is_set(p)&&(this._parent=p),this.util._parent=this},attach:function(member,data,simple){var ret=data;return simple=void 0!==simple&&!!simple,"string"===$.type(member)&&($.isPlainObject(data)&&!simple&&(data._parent=this,data=this.Class.extend(data)),this[member]="function"===$.type(data)?new data:data,ret=this[member]),ret},has_child:function(child){if(!this.util.is_string(child))return!1;var children=child.split(".");child=null;var x,o=this;for(x=0;x<children.length;x++)if(""!==(child=children[x])){if(!this.util.is_obj(o)||!o[child])return!1;o=o[child]}return!0},is_base:function(){return!!this.base},get_parent:function(){return this._parent||(this._parent={}),this._parent}},Utilities={_base:null,_parent:null,get_base:function(){if(!this._base){for(var p=this.get_parent(),p_prev=null,methods=["is_base","get_parent"];p_prev!==p&&this.is_method(p,methods)&&!p.is_base();)p=(p_prev=p).get_parent();this._base=p}return this._base},get_parent:function(prop){var ret=this._parent;return ret=ret||(this._parent={}),this.is_string(prop)&&(ret=this.in_obj(ret,prop)?ret[prop]:null),ret},get_sep:function(sep){return this.is_string(sep,!1)?sep:"_"},get_prefix:function(){var p=this.get_parent("prefix");return this.is_string(p,!1)?p:""},has_prefix:function(val,sep){return this.is_string(val)&&0===val.indexOf(this.get_prefix()+this.get_sep(sep))},add_prefix:function(val,sep,once){return this.is_string(val)?(sep=this.get_sep(sep),this.is_bool(once)||(once=!0),once&&this.has_prefix(val,sep)?val:[this.get_prefix(),val].join(sep)):this.get_prefix()},remove_prefix:function(val,sep,once){if(!this.is_string(val,!0))return"";if(sep=this.get_sep(sep),this.is_bool(once)||(once=!0),this.has_prefix(val,sep))for(var prfx=this.get_prefix()+sep;val=val.substr(prfx.length),!once&&this.has_prefix(val,sep););return val},get_attribute:function(attr_base){var attr=["data",this.get_prefix()].join("-");return this.is_string(attr_base)&&0!==attr_base.indexOf(attr+"-")&&(attr=[attr,attr_base].join("-")),attr},get_context:function(){var b=this.get_base();return $.isArray(b.context)||(b.context=[]),b.context},is_context:function(ctx){return this.is_string(ctx)&&(ctx=[ctx]),this.is_array(ctx)&&0<this.arr_intersect(this.get_context(),ctx).length},is_set:function(val){return void 0!==val},is_type:function(val,type,nonempty){var ret=!1;if(this.is_set(val)&&null!==val&&this.is_set(type))switch($.type(type)){case"function":ret=val instanceof type;break;case"string":ret=$.type(val)===type;break;default:ret=!1}return!ret||this.is_set(nonempty)&&!nonempty||(ret=!this.is_empty(val)),ret},is_string:function(value,nonempty){return this.is_type(value,"string",nonempty)},is_array:function(value,nonempty){return this.is_type(value,"array",nonempty)},is_bool:function(value){return this.is_type(value,"boolean",!1)},is_obj:function(value,nonempty){return this.is_type(value,"object",nonempty)},is_func:function(value){return this.is_type(value,"function",!1)},is_method:function(obj,key){var ret=!1;if(this.is_string(key)&&(key=[key]),this.in_obj(obj,key)){ret=!0;for(var x=0;ret&&x<key.length;)ret=this.is_func(obj[key[x]]),x++}return ret},is_instance:function(obj,parent){return!!this.is_func(parent)&&(this.is_obj(obj)&&obj instanceof parent)},is_class:function(cls,parent){var ret=this.is_func(cls)&&"prototype"in cls;return ret&&this.is_set(parent)&&(ret=this.is_instance(cls.prototype,parent)),ret},is_num:function(value,nonempty){var f={nan:Number.isNaN?Number.isNaN:isNaN,finite:Number.isFinite?Number.isFinite:isFinite};return this.is_type(value,"number",nonempty)&&!f.nan(value)&&f.finite(value)},is_int:function(value,nonempty){return this.is_num(value,nonempty)&&Math.floor(value)===value},is_scalar:function(value,nonempty){return this.is_num(value,nonempty)||this.is_string(value,nonempty)||this.is_bool(value)},is_empty:function(value,type){var ret=!1;if(this.is_set(value))for(var empties=[null,"",!1,0],x=0;!ret&&x<empties.length;)ret=empties[x]===value,x++;else ret=!0;if(!ret)if(this.is_set(type)||(type=$.type(value)),this.is_type(value,type,!1))switch(type){case"string":case"array":ret=0===value.length;break;case"number":ret=0==value;break;case"object":if($.isPlainObject(value)){if(Object.getOwnPropertyNames)ret=0===Object.getOwnPropertyNames(value).length;else if(value.hasOwnProperty)for(var key in ret=!0,value)if(value.hasOwnProperty(key)){ret=!1;break}}else ret=!1}else ret=!0;return ret},is_promise:function(obj){return this.is_method(obj,["then","done","always","fail","pipe"])},format:function(fmt,val){if(!this.is_string(fmt))return"";function strip(txt){return-1!==txt.indexOf(ph)?txt.replace(ph,""):txt}var params=[],ph="%s";if(arguments.length<2||-1===fmt.indexOf(ph))return strip(fmt);params=Array.prototype.slice.call(arguments,1),val=null;for(var x=0;x<params.length;x++)this.is_scalar(params[x],!1)||(params[x]="");if(1===params.length)fmt=fmt.replace(ph,params[0].toString());else{for(var idx=0,len=params.length,rlen=ph.length,pos=0;(pos=fmt.indexOf(ph))&&-1!==pos&&idx<len;)fmt=fmt.substr(0,pos)+params[idx].toString()+fmt.substr(pos+rlen),idx++;fmt=strip(fmt)}return fmt},in_obj:function(obj,key,all){this.is_bool(all)||(all=!0),this.is_string(key)&&(key=[key]);var ret=!1;if(this.is_obj(obj)&&this.is_array(key))for(var val,x=0;x<key.length&&(val=key[x],ret=!!(this.is_string(val)&&val in obj),!(!all&&ret||all&&!ret));x++);return ret},obj_keys:function(obj){var prop,keys=[];if(!this.is_obj(obj))return keys;if(Object.keys)keys=Object.keys(obj);else for(prop in obj)obj.hasOwnProperty(prop)&&keys.push(prop);return keys},arr_intersect:function(arr1,arr2){var x,ret=[],params=Array.prototype.slice.call(arguments),arrs=[];for(x=0;x<params.length;x++)this.is_array(params[x],!1)&&arrs.push(params[x]);if(arrs.length<2)return ret;params=arr1=arr2=null;var add,sub,base=arrs.shift();for(x=0;x<base.length;x++){for(add=!0,sub=0;sub<arrs.length;sub++)if(-1===arrs[sub].indexOf(base[x])){add=!1;break}add&&ret.push(base[x])}return ret},guid:function(){function _p8(s){var p=(Math.random().toString(16)+"000000000").substr(2,8);return s?"-"+p.substr(0,4)+"-"+p.substr(4,4):p}return _p8()+_p8(!0)+_p8(!0)+_p8()},parse_uri:function(uri){return $('<a href="'+uri+'"/>').get(0)},parse_query:function(uri){var i,temp,key,val,delim_vars="&",delim_val="=",query={raw:[],parsed:{},string:""};if(0===(uri=this.parse_uri(uri)).search.indexOf("?"))for(query.raw=uri.search.substr(1).split(delim_vars),i=0;i<query.raw.length;i++)key=(temp=query.raw[i].split(delim_val)).shift(),val=0<temp.length?temp.join(delim_val):null,query.parsed[key]=val;return query.parsed},build_query:function(query){var val,q=[],delim_vars="&",delim_val="=";for(var key in query)val=null!==query[key]?delim_val+query[key]:"",q.push(key+val);return q.join(delim_vars)}};Base.attach("util",Utilities,!0);var SLB_Base=Class.extend(Base),Core={base:!0,context:[],Class:SLB_Base,_init:function(){this._super(),$("html").addClass(this.util.get_prefix())}},SLB_Core=SLB_Base.extend(Core);window.SLB=new SLB_Core}(jQuery);
client/js/prod/lib.view.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.attach&&function($){var View={assets:{},component_defaults:[],loading:[],cache:{},component_temps:{},options:{},_init:function(){this._super(),this.init_refs(),this.init_components()},init_refs:function(){var r,ref,prop;for(prop in this)if(prop=this[prop],this.is_component(prop)&&!this.util.is_empty(prop.prototype._refs))for(r in prop.prototype._refs)ref=prop.prototype._refs[r],this.util.is_string(ref)&&ref in this&&(ref=prop.prototype._refs[r]=this[ref]),this.util.is_class(ref)||delete prop.prototype_refs[r]},init_components:function(){this.component_defaults=[this.Viewer]},init:function(options){var t=this;$.when.apply($,this.loading).always(function(){$.extend(!0,t.options,options),$(window).on("popstate",function(e){var state=e.originalEvent.state;if(t.util.in_obj(state,["item","viewer"]))return t.get_viewer(state.viewer).history_handle(e),e.preventDefault()}),t.init_items()})},can_make_default_component:function(type){return-1!==$.inArray(type,this.component_defaults)},is_component:function(comp){return this.util.is_class(comp,this.Component)},get_components:function(type){var ret={};if(this.is_component(type)){var coll=type.prototype._slug+"s";coll in this.cache||(this.cache[coll]={}),ret=this.cache[coll]}return ret},get_component:function(type,id){var ret=null;if(!this.util.is_func(type))return ret;this.util.is_string(id)||(id=null);var coll=this.get_components(type);if(this.util.is_obj(coll)){var tid=this.util.is_string(id)?id:this.util.add_prefix("default");tid in coll&&(ret=coll[tid])}return this.util.is_empty(ret)&&(this.util.is_string(id)||this.can_make_default_component(type))&&(ret=this.add_component(type,id)),ret},add_component:function(type,id,options){if(!this.util.is_func(type))return!1;if(this.util.is_empty(id)&&!this.can_make_default_component(type))return!1;var ret=null;this.util.is_empty(id)&&(id=this.util.add_prefix("default")),this.util.is_obj(options)||(options={});var m="component"!==type.prototype._slug?"add_"+type.prototype._slug:null;if(ret=!this.util.is_empty(m)&&m in this&&this.util.is_func(this[m])?this[m](id,options):new type(id,options),this.util.is_type(ret,type)){var coll=this.get_components(type);switch($.type(coll)){case"object":coll[id]=ret;break;case"array":coll.push(ret)}}else ret=null;return ret},add_component_temp:function(type){var ret=null;return this.is_component(type)&&(ret=new type(""),this.component_temps[ret._slug]=ret),ret},get_component_temp:function(type){return this.has_component_temp(type)?this.component_temps[type.prototype._slug]:this.add_component_temp(type)},has_component_temp:function(type){return!!(this.is_component(type)&&type.prototype._slug in this.component_temps)},get_options:function(opts){var ret={};if(this.util.is_string(opts)&&(opts=[opts]),!this.util.is_array(opts))return ret;for(var x=0;x<opts.length;x++)opts[x]in this.options&&(ret[opts[x]]=this.options[opts[x]]);return ret},get_option:function(opt,def){var ret=this.get_options(opt);return ret=this.util.is_obj(ret)&&opt in ret?ret[opt]:this.util.is_set(def)?def:null},add_viewer:function(id,options){var v=new this.Viewer(id,options);return this.get_viewers()[v.get_id()]=v},get_viewers:function(){return this.get_components(this.Viewer)},has_viewer:function(v){return!!(this.util.is_string(v)&&v in this.get_viewers())},get_viewer:function(v){return this.has_viewer(v)||(v=this.util.add_prefix("default"),this.has_viewer(v)||(v=(v=this.add_viewer(v)).get_id())),this.get_viewers()[v]},init_items:function(){var t=this,sel=this.util.format('a[href][%s="%s"]',this.util.get_attribute("active"),1);$(document).on("click",sel,null,function(){var ret=t.show_item(this);return t.util.is_bool(ret)||(ret=!0),!ret})},get_items:function(){return this.get_components(this.Content_Item)},get_item:function(ref){if(this.util.is_type(ref,this.Content_Item))return ref;var item=null;if(this.util.in_obj(ref,"nodeType")){var key=this.get_component_temp(this.Content_Item).get_data_key();item=$(ref).data(key)}else if(this.util.is_string(ref,!1)){var items=this.get_items();ref in items&&(item=items[ref])}return this.util.is_instance(item,this.Content_Item)||(item=this.add_item(ref)),item},add_item:function(el){return new this.Content_Item(el)},show_item:function(el){return this.get_item(el).show()},save_item:function(item){return this.util.is_instance(item,this.Content_Item)?this.get_items()[item.get_id()]=item:item},get_content_handlers:function(){return this.get_components(this.Content_Handler)},get_content_handler:function(item){var type=this.util.is_instance(item,this.Content_Item)?item.get_attribute("type",""):item.toString(),types=this.get_content_handlers();return type in types?types[type]:null},extend_content_handler:function(id,attr){var hdl=null;if(!this.util.is_string(id)||!this.util.is_obj(attr))return hdl;null===(hdl=this.get_content_handler(id))?this.get_content_handlers()[id]=hdl=new this.Content_Handler(id,attr):hdl.set_attributes(attr);return this.util.in_obj(attr,"styles")&&this.load_styles(attr.styles),hdl},add_group:function(g,attrs){return g=new this.Group(g,attrs),this.get_groups()[g.get_id()]=g},get_groups:function(){return this.get_components(this.Group)},get_group:function(g){return this.has_group(g)?this.get_groups()[g]:this.add_group(g)},has_group:function(g){return this.util.is_string(g)&&g in this.get_groups()},extend_theme:function(id,attr){if(!this.util.is_string(id))return!1;var dfr=$.Deferred();this.loading.push(dfr);var model=this.get_theme_model(id);return this.util.is_empty(model)&&(model=this.save_theme_model({parent:null,id:id})),this.util.is_obj(attr)&&("id"in attr&&delete attr.id,$.extend(model,attr)),this.util.in_obj(attr,"styles")&&this.load_styles(attr.styles),this.util.is_obj(model.parent)||(model.parent=this.get_theme_model(model.parent)),dfr.resolve(),model},get_theme_models:function(){return this.Theme.prototype._models},get_theme_model:function(id){var ms=this.get_theme_models();return this.util.in_obj(ms,id)?ms[id]:{}},save_theme_model:function(model){return this.util.in_obj(model,"id")&&this.util.is_string(model.id)&&(this.get_theme_models()[model.id]=model),model},extend_template_tag_handler:function(id,attr){if(!this.util.is_string(id)||!this.util.is_obj(attr))return!1;var hdl,hdls=this.get_template_tag_handlers();return this.util.in_obj(hdls,id)?(hdl=hdls[id]).set_attributes(attr):hdls[(hdl=new this.Template_Tag_Handler(id,attr)).get_id()]=hdl,this.util.in_obj(attr,"styles")&&this.load_styles(attr.styles),this.util.in_obj(attr,"_hooks")&&attr._hooks.call(hdl),hdl},get_template_tag_handlers:function(){return this.Template_Tag.prototype.handlers},get_template_tag_handler:function(id){var handlers=this.get_template_tag_handlers();return this.util.in_obj(handlers,id)?handlers[id]:null},load_styles:function(styles){if(this.util.is_array(styles)){for(var style,out=[],x=0;x<styles.length;x++)style=styles[x],this.util.in_obj(style,"uri")&&this.util.is_string(style.uri)&&out.push('<link rel="stylesheet" type="text/css" href="'+style.uri+'" />');$("head").append(out.join(""))}}},Component={_slug:"component",_ns:null,_refs:{},_reciprocal:!1,_dom:null,_attributes:!1,_attr_default:{},_attr_default_parsed:!1,_attr_init:null,_attr_map:{},_events:{},_status:null,_id:"",_c:function(id,attributes){this._set_id(id),this.util.is_obj(attributes)&&(this._attr_init=attributes),this._hooks()},_set_parent:function(){this._super(View)},_hooks:function(){},_set_id:function(id){return this.util.is_empty(this._id)&&(this._id=this.util.is_string(id)?id:this.util.guid()),this._id},get_id:function(ns){var id=this._id;return this.util.is_bool(ns)&&ns&&(id=this.add_ns(id)),id},get_ns:function(){return null===this._ns&&(this._ns=this.util.add_prefix(this._slug)),this._ns},add_ns:function(val){return this.util.is_string(val)?this.get_ns()+"_"+val:""},get_status:function(id,raw){var ret=!1;return this.util.in_obj(this._status,id)&&(ret=raw?this._status[id]:!!this._status[id]),ret},set_status:function(id,val){return this.util.is_string(id)?(this.util.is_set(val)||(val=!0),this.util.is_obj(this._status,!1)||(this._status={}),this._status[id]=val):this.util.is_set(val)||(val=!1),val},get_controller:function(){return this.get_parent()},has_reference:function(ref){return!!(this.util.is_string(ref)&&ref in this&&ref in this.get_references())},get_references:function(){return this._refs},get_reference:function(ref){return this.has_reference(ref)?this._refs[ref]:null},get_component:function(cname,options){var c=null;if(!this.has_reference(cname))return c;options=$.extend({},{check_attr:!0,get_default:!1},options);var ctype=this.get_reference(cname);return this.util.is_type(this[cname],ctype)?this[cname]:(c=this[cname]=null,options.check_attr&&(c=this.get_attribute(cname),this.util.is_empty(c)||(c=this.set_component(cname,c))),this.util.is_empty(c)&&options.get_default&&(c=this.get_controller().get_component(ctype)),c)},set_component:function(name,ref,validate){if(!this.has_reference(name))return null;if(this.util.is_empty(ref))ref=null;else{var ctype=this.get_reference(name);this.util.is_string(ref,!1)&&(ref=this.get_controller().get_component(ctype,ref)),(!this.util.is_type(ref,ctype)||this.util.is_func(validate)&&!validate.call(this,ref))&&(ref=null)}return this[name]=ref,this[name]},clear_component:function(name){this.set_component(name,null)},init_attributes:function(force){if(this.util.is_bool(force)||(force=!1),force||!this.util.is_obj(this._attributes)){var a=this._attributes={};$.extend(a,this.init_default_attributes()),this.util.is_obj(this._attr_init)&&$.extend(a,this._attr_init),$.extend(a,this.get_dom_attributes())}},init_default_attributes:function(){if(!this._attr_default_parsed&&this.util.is_obj(this._attr_map)){var opts=this.get_controller().get_options(this.util.obj_keys(this._attr_map));if(this.util.is_obj(opts)){for(var opt in this._attr_map)opt in opts&&null!==this._attr_map[opt]&&(opts[this._attr_map[opt]]=opts[opt],delete opts[opt]);$.extend(!0,this._attr_default,opts)}this._attr_default_parsed=!0}return this._attr_default},get_dom_attributes:function(){var attrs={},el=this.dom_get(null,{init:!1});if(0<el.length){var attrs_full=$(el).get(0).attributes;if(this.util.is_obj(attrs_full)){var attr_key,attr_prefix=this.util.get_attribute();$.each(attrs_full,function(idx,attr){if(-1===attr.name.indexOf(attr_prefix))return!0;attr_key=attr.name.substr(attr_prefix.length+1),attrs[attr_key]=attr.value})}}return attrs},get_attributes:function(){return this.init_attributes(),this._attributes},get_attribute:function(key,def,enforce_type){if(this.util.is_set(def)||(def=null),!this.util.is_string(key))return def;this.util.is_bool(enforce_type)||(enforce_type=!0);var ret=this.has_attribute(key)?this.get_attributes()[key]:def;return enforce_type&&ret!==def&&null!==def&&!this.util.is_type(ret,$.type(def),!1)&&(this.util.is_scalar(def,!1)&&this.util.is_scalar(ret,!1)?this.util.is_string(def,!1)?ret=ret.toString():this.util.is_num(def,!1)&&!this.util.is_num(ret,!1)?(ret=this.util.is_int(def,!1)?parseInt(ret):parseFloat(ret),this.util.is_num(ret,!1)||(ret=def)):ret=this.util.is_bool(def,!1)?this.util.is_string(ret)||this.util.is_num(ret):def:ret=def),ret},call_attribute:function(attr,args){return attr=this.get_attribute(attr),this.util.is_func(attr)&&(args=Array.prototype.slice.call(arguments,1),attr=attr.apply(this,args)),attr},has_attribute:function(key){return this.util.is_string(key)&&key in this.get_attributes()},set_attributes:function(attributes,full){this.util.is_bool(full)||(full=!1),this.init_attributes(full),this.util.is_obj(attributes)&&$.extend(this._attributes,attributes)},set_attribute:function(key,val){return this.util.is_string(key)&&this.util.is_set(val)&&(this.get_attributes()[key]=val),val},dom_get_selector:function(element){return this.util.is_string(element)?"."+this.add_ns(element):""},dom_get_attribute:function(){return this.util.get_attribute(this._slug)},dom_set:function(el){return(el=$(el)).data(this.get_data_key(),this),this._reciprocal&&(this._dom=el),el},dom_get:function(element,options){var opts_default={init:!0,put:!1};(options=this.util.is_obj(options)?$.extend({},opts_default,options):opts_default).init&&!this.get_status("dom_init")&&(this.set_status("dom_init"),this.dom_init());var ret=this._dom;if(ret&&this.util.is_string(element)){var ch=$(ret).find(this.dom_get_selector(element));ch.length?ret=ch:(!0===options.put||this.util.is_obj(options.put))&&(ret=this.dom_put(element,options.put))}return $(ret)},dom_init:function(){},dom_put:function(element,content){var r=null;if(!this.dom_has()||!this.util.is_string(element))return $(r);var strip=["tag","content","success"],options={tag:"div",content:"",class:this.add_ns(element)};this.util.is_empty(content)||(this.util.is_type(content,jQuery,!1)||this.util.is_string(content,!1)?options.content=content:this.util.is_obj(content,!1)&&$.extend(options,content));for(var attrs=$.extend({},options),x=0;x<strip.length;x++)delete attrs[strip[x]];var d=this.dom_get();return(r=$(this.dom_get_selector(element),d)).length||(r=$(this.util.format("<%s />",options.tag),attrs).appendTo(d)).length&&this.util.is_method(options,"success")&&options.success.call(r,r),$(r).append(options.content),$(r)},dom_has:function(){return!!this.dom_get().length},get_data_key:function(){return this.get_ns()},on:function(event,fn,options){if(!this.util.is_string(event)||!this.util.is_func(fn)){var t=this,args=Array.prototype.slice.call(arguments,1);return this.util.is_array(event)?$.each(event,function(idx,val){t.on.apply(t,[val].concat(args))}):this.util.is_obj(event)&&$.each(event,function(ev,hdl){t.on.apply(t,[ev,hdl].concat(args))}),this}this.util.is_obj(options,!1)||(options={}),options=$.extend({},{clear:!1},options),this.util.is_obj(this._events,!1)||(this._events={});var es=this._events;return event in es&&this.util.is_obj(es[event],!1)&&!options.clear||(es[event]=[]),es[event].push(fn),this},trigger:function(event,data){var dfr=$.Deferred(),dfrs=[],t=this;if(this.util.is_array(event))return $.each(event,function(idx,val){dfrs.push(t.trigger(val,data))}),$.when.apply(t,dfrs).done(function(){dfr.resolve()}),dfr.promise();if(!(this.util.is_string(event)&&event in this._events))return dfr.resolve(),dfr.promise();var ev={type:event,data:null};return this.util.is_set(data)&&(ev.data=data),$.each(this._events[event],function(idx,fn){dfrs.push(fn.call(t,ev,t))}),$.when.apply(this,dfrs).done(function(){dfr.resolve()}),dfr.promise()}};View.Component=Component=SLB.Class.extend(Component);var Viewer={_slug:"viewer",_refs:{item:"Content_Item",theme:"Theme"},_reciprocal:!0,_attr_default:{loop:!0,animate:!0,autofit:!0,overlay_enabled:!0,overlay_opacity:"0.8",title_default:!1,container:null,slideshow_enabled:!0,slideshow_autostart:!1,slideshow_duration:2,slideshow_active:!1,slideshow_timer:null,labels:{close:"close",nav_prev:"&laquo; prev",nav_next:"next &raquo;",slideshow_start:"start slideshow",slideshow_stop:"stop slideshow",group_status:"Image %current% of %total%",loading:"loading"}},_attr_map:{theme:null,group_loop:"loop",ui_autofit:"autofit",ui_animate:"animate",ui_overlay_opacity:"overlay_opacity",ui_labels:"labels",ui_title_default:"title_default",slideshow_enabled:null,slideshow_autostart:null,slideshow_duration:null},item:null,item_queued:null,theme:null,item_working:null,active:!1,init:!1,open:!1,loading:!1,_hooks:function(){var t=this;this.on(["item-prev","item-next"],function(){t.trigger("item-change")}).on(["close","item-change"],function(){t.unload().done(function(){t.unlock()})})},get_item:function(){return this.get_component("item")},set_item:function(item){this.clear_item(!1);var i=this.set_component("item",item,function(item){return item.has_type()});return!this.util.is_empty(i)},clear_item:function(full){this.util.is_bool(full)||(full=!0);var item=this.get_item();item&&item.reset(),full&&this.clear_component("item")},get_theme:function(){var ret=this.get_component("theme",{check_attr:!1});return this.util.is_empty(ret)&&(ret=this.set_component("theme",new View.Theme(this))),ret},set_theme:function(theme){this.set_component("theme",theme)},lock:function(){return this.set_status("item_working",$.Deferred())},get_lock:function(simple,full){this.util.is_bool(simple)||(simple=!1),this.util.is_bool(full)||(full=!1);var s="item_working";if(simple)return this.get_status(s);var r=this.get_status(s,!0);return this.util.is_promise(r)||(r=this.lock()),full?r:r.promise()},is_locked:function(){return this.get_lock(!0)},unlock:function(){return this.get_lock(!1,!0).resolve()},set_active:function(mode){return this.util.is_bool(mode)||(mode=!0),this.set_status("active",mode)},is_active:function(){return this.get_status("active")},set_loading:function(mode){var dfr=$.Deferred();this.util.is_bool(mode)||(mode=!0),this.loading=mode,this.slideshow_active()&&this.slideshow_pause(mode);var m=mode?"addClass":"removeClass";return $(this.dom_get())[m]("loading"),mode?this.get_theme().transition("load").always(function(){dfr.resolve()}):dfr.resolve(),dfr.promise()},unset_loading:function(){return this.set_loading(!1)},get_loading:function(){return!!this.util.is_bool(this.loading)&&this.loading},is_loading:function(){return this.get_loading()},show:function(item){this.item_queued=item;var vt="theme_valid",valid=!0;if(this.has_attribute(vt)?valid=this.get_attribute(vt,!0):(valid=!(!this.get_theme()||""===this.get_theme().get_template().get_layout(!1)),this.set_attribute(vt,valid)),!valid)return this.close(),!1;var v=this,fin=function(){if(v.lock(),v.set_status("show_deferred",!1),!v.set_item(v.item_queued))return v.close(),!1;v.history_add(),v.set_active(),v.render()};this.is_locked()?this.get_status("show_deferred")||(this.set_status("show_deferred"),this.get_lock().always(function(){fin()})):fin()},history_handle:function(e){var state=e.originalEvent.state;if(this.util.is_string(state.item,!1))this.get_controller().get_item(state.item).show({event:e}),this.trigger("item-change");else{var count=this.history_get(!0);this.history_set(0),-1!==count&&this.close()}},history_get:function(full){return this.get_status("history_count",full)},history_set:function(val){return this.set_status("history_count",val)},history_add:function(){if(!history.pushState)return!1;var item=this.get_item(),opts=item.get_attribute("options_show"),count=this.history_get()?this.history_get(!0):0;if(this.util.in_obj(opts,"event")){var e=opts.event.originalEvent;this.util.in_obj(e,"state")&&this.util.in_obj(e.state,"count")&&(count=e.state.count)}else{var state={viewer:this.get_id(),item:null,count:count};count||history.replaceState(state,null),state.item=this.get_controller().save_item(item).get_id(),state.count=++count,history.pushState(state,"")}this.history_set(count)},history_reset:function(){var count=this.history_get(!0);count&&(this.history_set(-1),history.go(-1*count))},is_open:function(){return"none"!==this.dom_get().css("display")},render:function(){var v=this,thm=this.get_theme();v.dom_prep(),this.get_status("render-events")||(this.set_status("render-events"),thm.on("render-loading",function(ev,thm){var dfr=$.Deferred();if(!v.is_active())return dfr.reject(),dfr.promise();var set_pos=function(){v.dom_get().css("top",$(window).scrollTop())},always=function(){v.set_loading().always(function(){dfr.resolve()})};return v.is_open()?thm.transition("unload").fail(function(){set_pos(),thm.dom_get_tag("item","content").attr("style","")}).always(always):thm.transition("open").always(function(){always(),v.events_open(),v.open=!0}).fail(function(){set_pos(),v.get_overlay().show(),v.dom_get().show()}),dfr.promise()}).on("render-complete",function(ev,thm){if(!v.is_active())return!1;var d=v.dom_get(),classes=["item_single","item_multi"],ms=["addClass","removeClass"];v.get_item().get_group().is_single()||ms.reverse(),$.each(ms,function(idx,val){d[val](classes[idx])}),v.events_complete(),thm.transition("complete").fail(function(){if(v.get_attribute("autofit",!0)){var dims=$.extend({display:"inline-block"},thm.get_item_dimensions());thm.dom_get_tag("item","content").css(dims)}}).always(function(){v.unset_loading(),v.trigger("render-complete"),v.init=!0})})),thm.render()},dom_get_container:function(){var sel=this.get_attribute("container");this.util.is_empty(sel)&&(sel="#"+this.add_ns("wrap"));var c=$(sel);if(!c.length){var id=0===sel.indexOf("#")?sel.substr(1):sel;c=$("<div />",{id:id}).appendTo("body")}return c},dom_init:function(){var d=this.dom_set($("<div/>",{id:this.get_id(!0),class:this.get_ns()})).appendTo(this.dom_get_container()).hide(),thm=this.get_theme();d.addClass(thm.get_classes(" "));var v=this;this.get_status("render-init")||(this.set_status("render-init"),thm.on("render-init",function(ev){v.dom_put("layout",ev.data)})),thm.render(!0)},dom_prep:function(mode){var m=this.util.is_bool(mode)&&!mode?"removeClass":"addClass";$("html")[m](this.util.add_prefix("overlay"))},dom_restore:function(){this.dom_prep(!1)},get_layout:function(){return this.dom_get("layout",{put:{success:function(){$(this).hide()}}})},animation_enabled:function(){return this.get_attribute("animate",!0)},overlay_enabled:function(){var ov=this.get_attribute("overlay_enabled");return!!this.util.is_bool(ov)&&ov},get_overlay:function(){var o=null,v=this;return this.overlay_enabled()&&(o=this.dom_get("overlay",{put:{success:function(){$(this).hide().css("opacity",v.get_attribute("overlay_opacity"))}}})),$(o)},unload:function(){var dfr=$.Deferred();return this.get_theme().dom_get_tag("item").text(""),dfr.resolve(),dfr.promise()},reset:function(){this.dom_get().hide(),this.dom_restore(),this.history_reset(),this.clear_item(),this.set_active(!1),this.set_loading(!1),this.slideshow_stop(),this.keys_disable(),this.unlock()},get_labels:function(){return this.get_attribute("labels",{})},get_label:function(name){var lbls=this.get_labels();return name in lbls?lbls[name]:""},events_open:function(){if(this.keys_enable(),this.open)return!1;var l=this.get_layout();l.children().click(function(ev){ev.stopPropagation()});var v=this,close=function(){v.close()};l.click(close),this.get_overlay().click(close),this.trigger("events-open")},events_complete:function(){if(this.init)return!1;this.trigger("events-complete")},keys_enable:function(mode){this.util.is_bool(mode)||(mode=!0);var e=["keyup",this.util.get_prefix()].join("."),v=this;mode?$(document).on(e,function(ev){return v.keys_control(ev)}):$(document).off(e)},keys_disable:function(){this.keys_enable(!1)},keys_control:function(ev){var handlers={27:this.close,37:this.item_prev,39:this.item_next};if("rtl"===document.documentElement.getAttribute("dir")&&(handlers[37]=this.item_next,handlers[39]=this.item_prev),ev.which in handlers)return handlers[ev.which].call(this),!1},slideshow_enabled:function(){var o=this.get_attribute("slideshow_enabled");return!(!(this.util.is_bool(o)&&o&&this.get_item())||this.get_item().get_group().is_single())},slideshow_active:function(){return!(!this.slideshow_enabled()||!(this.get_attribute("slideshow_active")||!this.init&&this.get_attribute("slideshow_autostart")))},slideshow_clear_timer:function(){clearInterval(this.get_attribute("slideshow_timer"))},slideshow_set_timer:function(callback){this.set_attribute("slideshow_timer",setInterval(callback,1e3*this.get_attribute("slideshow_duration")))},slideshow_start:function(){if(!this.slideshow_enabled())return!1;this.set_attribute("slideshow_active",!0),this.dom_get().addClass("slideshow_active"),this.slideshow_clear_timer();var v=this;this.slideshow_set_timer(function(){v.slideshow_pause(),v.item_next()}),this.trigger("slideshow-start")},slideshow_stop:function(full){this.util.is_bool(full)||(full=!0),full&&(this.set_attribute("slideshow_active",!1),this.dom_get().removeClass("slideshow_active")),this.slideshow_clear_timer(),this.trigger("slideshow-stop")},slideshow_toggle:function(){if(!this.slideshow_enabled())return!1;this.slideshow_active()?this.slideshow_stop():this.slideshow_start(),this.trigger("slideshow-toggle")},slideshow_pause:function(mode){this.util.is_bool(mode)||(mode=!0),this.slideshow_active()&&(mode?this.slideshow_stop(!1):this.slideshow_start()),this.trigger("slideshow-pause")},slideshow_resume:function(){this.slideshow_pause(!1)},item_next:function(){var g=this.get_item().get_group(!0),v=this,ev="item-next",st=["events","viewer",ev].join("_");g.get_status(st)||(g.set_status(st),g.on(ev,function(e){v.trigger(e.type)})),g.show_next()},item_prev:function(){var g=this.get_item().get_group(!0),v=this,ev="item-prev",st=["events","viewer",ev].join("_");g.get_status(st)||(g.set_status(st),g.on(ev,function(){v.trigger(ev)})),g.show_prev()},close:function(){this.set_active(!1);var v=this,thm=this.get_theme();return thm.transition("unload").always(function(){thm.transition("close",!0).always(function(){v.reset(),v.trigger("close")})}).fail(function(){thm.dom_get_tag("item","content").attr("style","")}),!1}};View.Viewer=Component.extend(Viewer);var Group={_slug:"group",_reciprocal:!0,_refs:{current:"Content_Item"},current:null,selector:null,_hooks:function(){var t=this;this.on(["item-prev","item-next"],function(){t.trigger("item-change")})},get_selector:function(){return this.util.is_empty(this.selector)&&(this.selector=this.util.format('a[%s="%s"]',this.dom_get_attribute(),this.get_id())),this.selector},get_items:function(){var items=$(this.get_selector());return 0===items.length&&this.has_current()&&(items=this.get_current().dom_get()),items},get_item:function(idx){this.util.is_int(idx)||(idx=0);var items=this.get_items(),max=this.get_size()-1;return max<idx&&(idx=max),items.get(idx)},get_pos:function(item){return this.util.is_empty(item)&&(item=this.get_current()),this.util.is_type(item,View.Content_Item)?this.get_items().index(item.dom_get()):-1},has_current:function(){return!this.util.is_empty(this.get_current())},get_current:function(){return null===this.current||this.util.is_type(this.current,View.Content_Item)||(this.current=null),this.current},set_current:function(item){this.util.is_type(item,View.Content_Item)&&(this.current=item)},get_next:function(item){if(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),1===this.get_size())return item;var next=null,pos=this.get_pos(item);return-1!==pos&&(0!==(pos=pos+1<this.get_size()?pos+1:0)||item.get_viewer().get_attribute("loop"))&&(next=this.get_item(pos)),next},get_prev:function(item){if(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),1===this.get_size())return item;var prev=null,pos=this.get_pos(item);return-1===pos||0===pos&&!item.get_viewer().get_attribute("loop")||(0===pos&&(pos=this.get_size()),pos-=1,prev=this.get_item(pos)),prev},show_next:function(item){if(1<this.get_size()){var next=this.get_next(item);next||(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),item.get_viewer().close());var i=this.get_controller().get_item(next);this.set_current(i),i.show(),this.trigger("item-next")}},show_prev:function(item){if(1<this.get_size()){var prev=this.get_prev(item);prev||(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),item.get_viewer().close());var i=this.get_controller().get_item(prev);this.set_current(i),i.show(),this.trigger("item-prev")}},get_size:function(){return this.get_items().length},is_single:function(){return 1===this.get_size()}};View.Group=Component.extend(Group);var Content_Handler={_slug:"content_handler",_refs:{item:"Content_Item"},item:null,template:"",has_item:function(){return!this.util.is_empty(this.get_item())},get_item:function(){return this.get_component("item")},set_item:function(item){return this.set_component("item",item)},clear_item:function(){this.clear_component("item")},match:function(item){var m=this.get_attribute("match");if(!this.util.is_empty(m)){if(this.util.is_string(m)&&(m=new RegExp(m,"i"),this.set_attribute("match",m)),this.util.is_type(m,RegExp))return m.test(item.get_uri());if(this.util.is_func(m))return!!m.call(this,item)}return!1},load:function(item){var dfr=$.Deferred();return null===this.call_attribute("load",item,dfr)&&dfr.resolve(),dfr.promise()},render:function(item){var dfr=$.Deferred();return this.call_attribute("render",item,dfr),dfr.promise()}};View.Content_Handler=Component.extend(Content_Handler);var Content_Item={_slug:"content_item",_reciprocal:!0,_refs:{viewer:"Viewer",group:"Group",type:"Content_Handler"},_attr_default:{source:null,permalink:null,dimensions:null,title:"",group:null,internal:!1,output:null},group:null,viewer:null,type:null,data:null,loaded:null,_c:function(el){this.dom_set(el),this._super()},init_default_attributes:function(){this._super();var d=this.dom_get(),key=d.attr(this.util.get_attribute("asset"))||null,assets=this.get_controller().assets||null;if(this.util.is_string(key)){var attrs=[{},this._attr_default,{permalink:d.attr("href")}];if(this.util.is_obj(assets)){var t=this;attrs.push(function(key){var ret={};return key in assets&&t.util.is_obj(assets[key])&&(ret=assets[key]),ret}(key))}this._attr_default=$.extend.apply(this,attrs)}return this._attr_default},get_output:function(){var dfr=$.Deferred(),ret=this.get_attribute("output");if(this.util.is_string(ret))dfr.resolve(ret);else if(this.has_type()){var type=this.get_type(),item=this;type.render(this).done(function(output){item.set_output(output),dfr.resolve(output)})}else dfr.resolve("");return dfr.promise()},set_output:function(out){this.util.is_string(out,!1)&&this.set_attribute("output",out)},get_content:function(){return this.get_output()},get_uri:function(mode){-1===$.inArray(mode,["source","permalink"])&&(mode="source");var ret=this.get_attribute(mode);return this.util.is_string(ret)||(ret="source"===mode?this.get_attribute("permalink"):""),ret=ret.replace(/&(#38|amp);/,"&")},get_title:function(){if(this.has_attribute("title_cached"))return this.get_attribute("title_cached","");var title="",dom=this.dom_get();if(dom.length&&((title=dom.attr("title"))||(title=dom.closest("figure").find("figcaption").first().html()),title||(title=dom.closest("figure").find(".wp-caption-text").first().html())),!title)for(var props=["caption","title"],x=0;x<props.length&&(title=this.get_attribute(props[x],""),this.util.is_empty(title));x++);if(!title&&dom.length&&((title=dom.find("img").first().attr("alt"))||(title=dom.get(0).innerText.trim())),this.util.is_string(title,!1)||(title=""),!this.util.is_empty(title)&&!this.get_viewer().get_attribute("title_default")){var f=this.get_uri("source"),i=f.lastIndexOf("/");-1!==i&&(-1!==(i=(f=f.substr(i+1)).lastIndexOf("."))&&(f=f.substr(0,i)),title===f&&(title=""))}return this.set_attribute("title_cached",title),title},get_dimensions:function(){return $.extend({width:0,height:0},this.get_attribute("dimensions"),{})},set_data:function(data){this.data=data},get_data:function(){return this.data},gallery_type:function(){var ret=null,types={wp:".gallery-icon",ngg:".ngg-gallery-thumbnail"},dom=this.dom_get();for(var type in types)if(0<dom.parent(types[type]).length){ret=type;break}return ret},in_gallery:function(gType){var type=this.gallery_type();return null!==type&&(!this.util.is_string(gType)||gType===type)},get_viewer:function(){return this.get_component("viewer",{get_default:!0})},set_viewer:function(v){return this.set_component("viewer",v)},get_group:function(set_current){var g=this.get_component("group");return g||(g=this.set_component("group",new View.Group),set_current=!0),set_current&&g.set_current(this),g},set_group:function(g){this.util.is_string(g)&&(g=this.get_controller().get_group(g)),this.group=!!this.util.is_type(g,View.Group)&&g},get_type:function(){var t=this.get_component("type",{check_attr:!1});return t||(t=this.set_type(this.get_controller().get_content_handler(this))),t},set_type:function(type){return this.set_component("type",type)},has_type:function(){return!this.util.is_empty(this.get_type())},show:function(options){if(!this.has_type())return!1;this.set_attribute("options_show",options);var v=this.get_viewer();return this.load(),v.show(this)},load:function(){return this.util.is_promise(this.loaded)||(this.loaded=this.get_type().load(this)),this.loaded.promise()},reset:function(){this.set_attribute("options_show",null)}};View.Content_Item=Component.extend(Content_Item);var Modeled_Component={_slug:"modeled_component",get_attribute:function(key,def,check_model,enforce_type){if(!this.util.is_string(key))return this._super(key,def,enforce_type);this.util.is_bool(check_model)||(check_model=!0);var ret=null;if(check_model){var m=this.get_ancestor(key,!1);this.util.in_obj(m,key)&&(ret=m[key])}return null===ret&&(ret=this._super(key,def,enforce_type)),ret},get_attribute_recursive:function(key,def,enforce_type){var ret=this.get_attribute(key,def,!0,enforce_type);if(this.util.is_obj(ret)){var models=this.get_ancestors(!1);ret=[ret];var t=this;$.each(models,function(idx,model){key in model&&t.util.is_obj(model[key])&&ret.push(model[key])}),ret.push({}),ret=$.extend.apply($,ret.reverse())}return ret},set_attribute:function(key,val,use_model){if(!this.util.is_string(key)||!this.util.is_set(val))return!1;(this.util.is_bool(use_model)||this.util.is_obj(use_model)||(use_model=!0),use_model)?(this.util.is_obj(use_model)?use_model:this.get_model())[key]=val:this._super(key,val);return val},get_model:function(){var m=this.get_attribute("model",null,!1);return this.util.is_obj(m)||(m={},this.set_attribute("model",m,!1)),m},has_model:function(){return!this.util.is_empty(this.get_model())},in_model:function(key){return!!this.util.in_obj(this.get_model(),key)},get_ancestors:function(inc_current){for(var ret=[],m=this.get_model();this.util.is_obj(m);)ret.push(m),m=this.util.in_obj(m,"parent")&&this.util.is_obj(m.parent)?m.parent:null;return inc_current||ret.shift(),ret},get_ancestor:function(attr,safe_mode){if(!this.util.is_string(attr))return!1;this.util.is_bool(safe_mode)||(safe_mode=!0);for(var mcurr=this.get_model(),m=mcurr,found=!1;this.util.is_obj(m);){if(this.util.in_obj(m,attr)&&!this.util.is_empty(m[attr])){found=!0;break}m=this.util.in_obj(m,"parent")?m.parent:null}return found||(safe_mode?(this.util.is_empty(m)&&(m=mcurr),this.util.in_obj(m,attr)||(m[attr]=null)):m=null),m}};Modeled_Component=Component.extend(Modeled_Component);var Theme={_slug:"theme",_refs:{viewer:"Viewer",template:"Template"},_models:{},_attr_default:{template:null,model:null},viewer:null,template:null,_c:function(id,attributes,viewer){1===arguments.length&&this.util.is_type(id,View.Viewer)&&(viewer=id,id=null),this._super(id,attributes),this.set_viewer(viewer),this.set_model(id)},get_viewer:function(){return this.get_component("viewer",{check_attr:!1,get_default:!0})},set_viewer:function(v){return this.set_component("viewer",v)},get_template:function(){var ret=this.get_component("template");if(this.util.is_empty(ret)){var attr={theme:this,model:this.get_model()};ret=this.set_component("template",new View.Template(attr))}return ret},get_tags:function(name,prop){return this.get_template().get_tags(name,prop)},dom_get_tag:function(tag,prop){return $(this.get_template().dom_get_tag(tag,prop))},get_tag_selector:function(name,prop){return this.get_template().get_tag_selector(name,prop)},get_models:function(){return this._models},get_model:function(id){var ret=null;if(!this.util.is_set(id)&&this.util.is_obj(this.get_attribute("model",null,!1)))ret=this._super();else{var models=this.get_models();this.util.is_string(id)||(id=this.get_controller().get_option("theme_default")),this.util.in_obj(models,id)||(id=$.map(models,function(v,key){return key})[0]),ret=models[id]}return ret},set_model:function(id){this.set_attribute("model",this.get_model(id),!1)},get_classes:function(rtype){var cls=[],thm=this,models=this.get_ancestors(!0);return $.each(models,function(idx,model){cls.push(thm.add_ns(model.id))}),this.util.is_string(rtype)&&(cls=cls.join(rtype)),cls},get_measurement:function(attr,def){var meas=null;if(!this.util.is_string(attr))return meas;this.util.is_obj(def,!1)||(def={});var attr_cache=this.util.format("%s_cache",attr),cache=this.get_attribute(attr_cache,{},!1),status="_status",item=this.get_viewer().get_item(),w=$(window);status in cache&&this.util.is_obj(cache._status)&&cache._status.width===w.width()&&cache._status.height===w.height()||(cache={}),this.util.is_empty(cache)&&(cache._status={width:w.width(),height:w.height(),index:[]});var pos=$.inArray(item,cache._status.index);return-1!==pos&&pos in cache&&(meas=cache[pos]),this.util.is_obj(meas)||(meas=this.call_attribute(attr),this.util.is_obj(meas)||(meas=this.get_measurement_default(attr))),meas=this.util.is_obj(meas)?$.extend({},def,meas):def,cache[pos=cache._status.index.push(item)-1]=meas,this.set_attribute(attr_cache,cache,!1),$.extend({},meas)},get_measurement_default:function(attr){return this.util.is_string(attr)?(attr=this.util.format("get_%s_default",attr),this.util.in_obj(this,attr)?(attr=this[attr],this.util.is_func(attr)&&(attr=attr.call(this))):attr=null,attr):null},get_offset:function(){return this.get_measurement("offset",{width:0,height:0})},get_offset_default:function(){var offset={width:0,height:0},v=this.get_viewer(),vn=v.dom_get(),vc=vn.clone().attr("id","").css({visibility:"hidden",position:"absolute",top:""}).removeClass("loading").appendTo(vn.parent()),l=vc.find(v.dom_get_selector("layout"));if(l.length){l.find("*").css({width:"",height:"",display:""});var tags=this.get_tags("item","content");if(tags.length){var offset_item=v.get_item().get_dimensions();tags=$(l.find(tags[0].get_selector("full")).get(0)).css({width:offset_item.width,height:offset_item.height}),$.each(offset_item,function(key,val){offset[key]=-1*val})}offset.width+=l.width(),offset.height+=l.height(),$.each(offset,function(key,val){val<0&&(offset[key]=0)})}return vc.empty().remove(),offset},get_margin:function(){return this.get_measurement("margin",{width:0,height:0})},get_item_dimensions:function(){var v=this.get_viewer(),dims=v.get_item().get_dimensions();if(v.get_attribute("autofit",!1)){var margin=this.get_margin(),offset=this.get_offset();offset.height+=margin.height,offset.width+=margin.width;var max={width:$(window).width(),height:$(window).height()};max.width>offset.width&&(max.width-=offset.width),max.height>offset.height&&(max.height-=offset.height);var factor=Math.min(max.width/dims.width,max.height/dims.height);factor<1&&$.each(dims,function(key){dims[key]=Math.round(dims[key]*factor)})}return $.extend({},dims)},get_dimensions:function(){var dims=this.get_item_dimensions(),offset=this.get_offset();return $.each(dims,function(key){dims[key]+=offset[key]}),dims},get_breakpoints:function(){return this.get_attribute_recursive("breakpoints")},get_breakpoint:function(target){var ret=0;if(this.util.is_string(target)){var b=this.get_attribute_recursive("breakpoints");this.util.is_obj(b)&&target in b&&(ret=b[target])}return ret},render:function(init){var thm=this,tpl=this.get_template(),st="events_render";this.get_status(st)||(this.set_status(st),tpl.on(["render-init","render-loading","render-complete"],function(ev){return thm.trigger(ev.type,ev.data)})),tpl.render(init)},transition:function(event,clear_queue){var dfr=null,attr="transition",v=this.get_viewer(),fx_temp=null,anim_on=v.animation_enabled();if(v.get_attribute(attr,!0)&&this.util.is_string(event)){clear_queue&&v.get_layout().find("*").each(function(){for(var el=$(this);el.queue().length;)el.stop(!1,!0)});var trns,attr_set=[attr,"set"].join("_");if(this.get_attribute(attr_set))trns=this.get_attribute(attr,{});else{var models=this.get_ancestors(!0);trns=[],this.set_attribute(attr_set,!0);var thm=this;$.each(models,function(idx,model){attr in model&&thm.util.is_obj(model[attr])&&trns.push(model[attr])}),trns.push({}),trns=this.set_attribute(attr,$.extend.apply($,trns.reverse()))}this.util.is_method(trns,event)&&(anim_on||(fx_temp=$.fx.off,$.fx.off=!0),dfr=trns[event].call(this,v,$.Deferred()))}return this.util.is_promise(dfr)||(dfr=$.Deferred()).reject(),dfr.always(function(){null!==fx_temp&&($.fx.off=fx_temp)}),dfr.promise()}};View.Theme=Modeled_Component.extend(Theme);var Template={_slug:"template",_reciprocal:!0,_refs:{theme:"Theme"},_attr_default:{layout_uri:"",layout_raw:"",layout_parsed:"",tags:null,model:null},theme:null,_c:function(attributes){this._super("",attributes)},_hooks:function(){this.on("dom_init",function(ev){var tags=this.get_tags(null,null,!0),names=[],t=this;$.each(tags,function(idx,tag){var name=tag.get_name();-1===$.inArray(name,names)&&(names.push(name),tag.get_handler().trigger(ev.type,{template:t}))})})},get_theme:function(){return this.get_component("theme")},render:function(init){var v=this.get_theme().get_viewer();if(this.util.is_bool(init)||(init=!1),init)this.trigger("render-init",this.dom_get());else{if(!v.is_active())return!1;var item=v.get_item();if(!this.util.is_type(item,View.Content_Item))return v.close(),!1;if(v.is_active()&&this.has_tags()){var loading_promise=this.trigger("render-loading"),tpl=this,tags=this.get_tags(),tag_promises=[];$.when(item.load(),loading_promise).done(function(){return!!v.is_active()&&($.each(tags,function(idx,tag){if(!v.is_active())return!1;tag_promises.push(tag.render(item).done(function(r){if(!v.is_active())return!1;r.tag.dom_get().html(r.output)}))}),!!v.is_active()&&void $.when.apply($,tag_promises).done(function(){tpl.trigger("render-complete")}))})}}},get_layout:function(parsed){return this.util.is_bool(parsed)||(parsed=!0),parsed?this.parse_layout():this.get_attribute("layout_raw","")},parse_layout:function(){var a="layout_parsed",ret=this.get_attribute(a);return this.util.is_string(ret)||(ret=this.sanitize_layout(this.get_layout(!1)),ret=this.parse_tags(ret),this.set_attribute(a,ret)),ret},sanitize_layout:function(l){if(this.util.is_empty(l))return l;var rtype=this.util.is_string(l)?"string":null,dom=$(l),tag_temp=this.get_tag_temp(),cls=tag_temp.get_class(),cls_new=["x",cls].join("_");switch($(tag_temp.get_selector(),dom).each(function(){$(this).removeClass(cls).addClass(cls_new)}),rtype){case"string":l=dom=dom.wrap("<div />").parent().html();break;default:l=dom}return l},parse_tags:function(l){if(!this.util.is_string(l))return"";for(var match,re=/\{{2}\s*(\w.*?)\s*\}{2}/gim;match=re.exec(l);)l=l.substring(0,match.index)+this.get_tag_container(match[1])+l.substring(match.index+match[0].length);return l},get_tag_container:function(tag){var attr=this.get_tag_attribute();return this.util.format('<span %s="%s"></span>',attr,encodeURI(tag))},get_tag_attribute:function(){return this.get_tag_temp().dom_get_attribute()},get_tag:function(idx){var ret=null;if(this.has_tags()){var tags=this.get_tags();(!this.util.is_int(idx)||idx<0||idx>=tags.length)&&(idx=0),ret=tags[idx]}return ret},get_tags:function(name,prop,isolate){this.util.is_bool(isolate)||(isolate=!1);var a="tags",tags=this.get_attribute(a);if(!this.util.is_array(tags)){tags=[];var d=this.dom_get(),attr=this.get_tag_attribute(),nodes=$(d).find("["+attr+"]");$(nodes).each(function(){var el=$(this),tag=new View.Template_Tag(decodeURI(el.attr(attr)));tag.has_handler()&&(tags.push(tag),isolate||(tag.dom_set(el),el.addClass(tag.get_classes(" ")))),isolate||el.removeAttr(attr)}),isolate||this.set_attribute(a,tags,!1)}if(!this.util.is_empty(tags)&&this.util.is_string(name)){this.util.is_string(prop)||(prop=!1);for(var tags_filtered=[],tc=null,x=0;x<tags.length;x++)name===(tc=tags[x]).get_name()&&(prop&&prop!==tc.get_prop()||tags_filtered.push(tc));tags=tags_filtered}return this.util.is_array(tags,!1)?tags:[]},has_tags:function(){return 0<this.get_tags().length},get_tag_temp:function(){return this.get_controller().get_component_temp(View.Template_Tag)},get_tag_selector:function(name,prop){this.util.is_string(name)||(name=""),this.util.is_string(prop)||(prop="");var tag=this.get_tag_temp();return tag.set_attribute("name",name),tag.set_attribute("prop",prop),tag.get_selector("full")},dom_init:function(){this.dom_set(this.get_layout()),this.trigger("dom_init")},dom_get_tag:function(tag,prop){var ret=$(),tags=this.get_tags(tag,prop);if(tags.length){var level=null;this.util.is_string(tag)&&(level=this.util.is_string(prop)?"full":"tag");var sel="."+tags[0].get_class(level);ret=this.dom_get().find(sel)}return ret}};View.Template=Modeled_Component.extend(Template);var Template_Tag={_slug:"template_tag",_reciprocal:!0,_attr_default:{name:null,prop:null,match:null},handlers:{},_c:function(tag_match){this.parse(tag_match)},parse:function(tag_match){if(!this.util.is_string(tag_match))return!1;var part,parts=tag_match.split("|");if(!parts.length)return null;var attrs={name:null,prop:null,match:tag_match};attrs.name=parts[0],-1!==attrs.name.indexOf(".")&&(attrs.name=attrs.name.split(".",2),attrs.prop=attrs.name[1],attrs.name=attrs.name[0]);for(var x=1;x<parts.length;x++)1<(part=parts[x].split(":",1)).length&&!(part[0]in attrs)&&(attrs[part[0]]=part[1]);this.set_attributes(attrs,!0)},render:function(item){var tag=this;return tag.get_handler().render(item,tag).pipe(function(output){return{tag:tag,output:output}})},get_name:function(){return this.get_attribute("name")},get_prop:function(){return this.get_attribute("prop")},get_handler:function(){return this.has_handler()?this.handlers[this.get_name()]:new View.Template_Tag_Handler("")},has_handler:function(){return this.get_name()in this.handlers},get_classes:function(rtype){var cls=[this.get_class(),this.get_class("tag"),this.get_class("full")];return this.util.is_string(rtype)&&(cls=cls.join(rtype)),cls},get_class:function(level){var cls="";switch(level){case"tag":cls=this.get_name();break;case"full":var i,parts=[this.get_name(),this.get_prop()],a=[];for(i=0;i<parts.length;i++)this.util.is_string(parts[i])&&a.push(parts[i]);cls=a.join("_")}return this.util.is_string(cls)?this.add_ns(cls):this.get_ns()},get_selector:function(level){var ret=this.get_class(level);return ret=this.util.is_string(ret)?"."+ret:""}};View.Template_Tag=Component.extend(Template_Tag);var Template_Tag_Handler={_slug:"template_tag_handler",_attr_default:{supports_modifiers:!1,dynamic:!1,props:{}},render:function(item,instance){var dfr=$.Deferred();return this.call_attribute("render",item,instance,dfr),dfr.promise()},add_prop:function(prop,fn){var a="props",props=this.get_attribute(a);if(!this.util.is_string(prop)||!this.util.is_func(fn))return!1;this.util.is_obj(props,!1)||(props={}),props[prop]=fn,this.set_attribute(a,props)},handle_prop:function(prop,item,instance){var props=this.get_attribute("props");return this.util.is_obj(props)&&prop in props&&this.util.is_func(props[prop])?props[prop].call(this,item,instance):item.get_viewer().get_label(prop)}};View.Template_Tag_Handler=Component.extend(Template_Tag_Handler),View=SLB.attach("View",View)}(jQuery);
1
+ window.SLB&&SLB.attach&&function($){var View={assets:{},component_defaults:[],loading:[],cache:{},component_temps:{},options:{},_init:function(){this._super(),this.init_refs(),this.init_components()},init_refs:function(){var r,ref,prop;for(prop in this)if(prop=this[prop],this.is_component(prop)&&!this.util.is_empty(prop.prototype._refs))for(r in prop.prototype._refs)ref=prop.prototype._refs[r],this.util.is_string(ref)&&ref in this&&(ref=prop.prototype._refs[r]=this[ref]),this.util.is_class(ref)||delete prop.prototype_refs[r]},init_components:function(){this.component_defaults=[this.Viewer]},init:function(options){var t=this;$.when.apply($,this.loading).always(function(){$.extend(!0,t.options,options),$(window).on("popstate",function(e){var state=e.originalEvent.state;if(t.util.in_obj(state,["item","viewer"]))return t.get_viewer(state.viewer).history_handle(e),e.preventDefault()}),t.init_items()})},can_make_default_component:function(type){return-1!==$.inArray(type,this.component_defaults)},is_component:function(comp){return this.util.is_class(comp,this.Component)},get_components:function(type){var ret={};if(this.is_component(type)){var coll=type.prototype._slug+"s";coll in this.cache||(this.cache[coll]={}),ret=this.cache[coll]}return ret},get_component:function(type,id){var ret=null;if(!this.util.is_func(type))return ret;this.util.is_string(id)||(id=null);var coll=this.get_components(type);if(this.util.is_obj(coll)){var tid=this.util.is_string(id)?id:this.util.add_prefix("default");tid in coll&&(ret=coll[tid])}return this.util.is_empty(ret)&&(this.util.is_string(id)||this.can_make_default_component(type))&&(ret=this.add_component(type,id)),ret},add_component:function(type,id,options){if(!this.util.is_func(type))return!1;if(this.util.is_empty(id)&&!this.can_make_default_component(type))return!1;var ret=null;this.util.is_empty(id)&&(id=this.util.add_prefix("default")),this.util.is_obj(options)||(options={});var m="component"!==type.prototype._slug?"add_"+type.prototype._slug:null;if(ret=!this.util.is_empty(m)&&m in this&&this.util.is_func(this[m])?this[m](id,options):new type(id,options),this.util.is_type(ret,type)){var coll=this.get_components(type);switch($.type(coll)){case"object":coll[id]=ret;break;case"array":coll.push(ret)}}else ret=null;return ret},add_component_temp:function(type){var ret=null;return this.is_component(type)&&(ret=new type(""),this.component_temps[ret._slug]=ret),ret},get_component_temp:function(type){return this.has_component_temp(type)?this.component_temps[type.prototype._slug]:this.add_component_temp(type)},has_component_temp:function(type){return!!(this.is_component(type)&&type.prototype._slug in this.component_temps)},get_options:function(opts){var ret={};if(this.util.is_string(opts)&&(opts=[opts]),!this.util.is_array(opts))return ret;for(var x=0;x<opts.length;x++)opts[x]in this.options&&(ret[opts[x]]=this.options[opts[x]]);return ret},get_option:function(opt,def){var ret=this.get_options(opt);return ret=this.util.is_obj(ret)&&opt in ret?ret[opt]:this.util.is_set(def)?def:null},add_viewer:function(id,options){var v=new this.Viewer(id,options);return this.get_viewers()[v.get_id()]=v},get_viewers:function(){return this.get_components(this.Viewer)},has_viewer:function(v){return!!(this.util.is_string(v)&&v in this.get_viewers())},get_viewer:function(v){return this.has_viewer(v)||(v=this.util.add_prefix("default"),this.has_viewer(v)||(v=(v=this.add_viewer(v)).get_id())),this.get_viewers()[v]},init_items:function(){var t=this,sel=this.util.format('a[href][%s="%s"]',this.util.get_attribute("active"),1);$(document).on("click",sel,null,function(){var ret=t.show_item(this);return t.util.is_bool(ret)||(ret=!0),!ret})},get_items:function(){return this.get_components(this.Content_Item)},get_item:function(ref){if(this.util.is_type(ref,this.Content_Item))return ref;var item=null;if(this.util.in_obj(ref,"nodeType")){var key=this.get_component_temp(this.Content_Item).get_data_key();item=$(ref).data(key)}else if(this.util.is_string(ref,!1)){var items=this.get_items();ref in items&&(item=items[ref])}return this.util.is_instance(item,this.Content_Item)||(item=this.add_item(ref)),item},add_item:function(el){return new this.Content_Item(el)},show_item:function(el){return this.get_item(el).show()},save_item:function(item){return this.util.is_instance(item,this.Content_Item)?this.get_items()[item.get_id()]=item:item},get_content_handlers:function(){return this.get_components(this.Content_Handler)},get_content_handler:function(item){var type=this.util.is_instance(item,this.Content_Item)?item.get_attribute("type",""):item.toString(),types=this.get_content_handlers();return type in types?types[type]:null},extend_content_handler:function(id,attr){var hdl=null;if(!this.util.is_string(id)||!this.util.is_obj(attr))return hdl;null===(hdl=this.get_content_handler(id))?this.get_content_handlers()[id]=hdl=new this.Content_Handler(id,attr):hdl.set_attributes(attr);return this.util.in_obj(attr,"styles")&&this.load_styles(attr.styles),hdl},add_group:function(g,attrs){return g=new this.Group(g,attrs),this.get_groups()[g.get_id()]=g},get_groups:function(){return this.get_components(this.Group)},get_group:function(g){return this.has_group(g)?this.get_groups()[g]:this.add_group(g)},has_group:function(g){return this.util.is_string(g)&&g in this.get_groups()},extend_theme:function(id,attr){if(!this.util.is_string(id))return!1;var dfr=$.Deferred();this.loading.push(dfr);var model=this.get_theme_model(id);return this.util.is_empty(model)&&(model=this.save_theme_model({parent:null,id:id})),this.util.is_obj(attr)&&("id"in attr&&delete attr.id,$.extend(model,attr)),this.util.in_obj(attr,"styles")&&this.load_styles(attr.styles),this.util.is_obj(model.parent)||(model.parent=this.get_theme_model(model.parent)),dfr.resolve(),model},get_theme_models:function(){return this.Theme.prototype._models},get_theme_model:function(id){var ms=this.get_theme_models();return this.util.in_obj(ms,id)?ms[id]:{}},save_theme_model:function(model){return this.util.in_obj(model,"id")&&this.util.is_string(model.id)&&(this.get_theme_models()[model.id]=model),model},extend_template_tag_handler:function(id,attr){if(!this.util.is_string(id)||!this.util.is_obj(attr))return!1;var hdl,hdls=this.get_template_tag_handlers();return this.util.in_obj(hdls,id)?(hdl=hdls[id]).set_attributes(attr):hdls[(hdl=new this.Template_Tag_Handler(id,attr)).get_id()]=hdl,this.util.in_obj(attr,"styles")&&this.load_styles(attr.styles),this.util.in_obj(attr,"_hooks")&&attr._hooks.call(hdl),hdl},get_template_tag_handlers:function(){return this.Template_Tag.prototype.handlers},get_template_tag_handler:function(id){var handlers=this.get_template_tag_handlers();return this.util.in_obj(handlers,id)?handlers[id]:null},load_styles:function(styles){if(this.util.is_array(styles)){for(var style,out=[],x=0;x<styles.length;x++)style=styles[x],this.util.in_obj(style,"uri")&&this.util.is_string(style.uri)&&out.push('<link rel="stylesheet" type="text/css" href="'+style.uri+'" />');$("head").append(out.join(""))}}},Component={_slug:"component",_ns:null,_refs:{},_reciprocal:!1,_dom:null,_attributes:!1,_attr_default:{},_attr_default_parsed:!1,_attr_init:null,_attr_map:{},_events:{},_status:null,_id:"",_c:function(id,attributes){this._set_id(id),this.util.is_obj(attributes)&&(this._attr_init=attributes),this._hooks()},_set_parent:function(){this._super(View)},_hooks:function(){},_set_id:function(id){return this.util.is_empty(this._id)&&(this._id=this.util.is_string(id)?id:this.util.guid()),this._id},get_id:function(ns){var id=this._id;return this.util.is_bool(ns)&&ns&&(id=this.add_ns(id)),id},get_ns:function(){return null===this._ns&&(this._ns=this.util.add_prefix(this._slug)),this._ns},add_ns:function(val){return this.util.is_string(val)?this.get_ns()+"_"+val:""},get_status:function(id,raw){var ret=!1;return this.util.in_obj(this._status,id)&&(ret=raw?this._status[id]:!!this._status[id]),ret},set_status:function(id,val){return this.util.is_string(id)?(this.util.is_set(val)||(val=!0),this.util.is_obj(this._status,!1)||(this._status={}),this._status[id]=val):this.util.is_set(val)||(val=!1),val},get_controller:function(){return this.get_parent()},has_reference:function(ref){return!!(this.util.is_string(ref)&&ref in this&&ref in this.get_references())},get_references:function(){return this._refs},get_reference:function(ref){return this.has_reference(ref)?this._refs[ref]:null},get_component:function(cname,options){var c=null;if(!this.has_reference(cname))return c;options=$.extend({},{check_attr:!0,get_default:!1},options);var ctype=this.get_reference(cname);return this.util.is_type(this[cname],ctype)?this[cname]:(c=this[cname]=null,options.check_attr&&(c=this.get_attribute(cname),this.util.is_empty(c)||(c=this.set_component(cname,c))),this.util.is_empty(c)&&options.get_default&&(c=this.get_controller().get_component(ctype)),c)},set_component:function(name,ref,validate){if(!this.has_reference(name))return null;if(this.util.is_empty(ref))ref=null;else{var ctype=this.get_reference(name);this.util.is_string(ref,!1)&&(ref=this.get_controller().get_component(ctype,ref)),this.util.is_type(ref,ctype)&&(!this.util.is_func(validate)||validate.call(this,ref))||(ref=null)}return this[name]=ref,this[name]},clear_component:function(name){this.set_component(name,null)},init_attributes:function(force){if(this.util.is_bool(force)||(force=!1),force||!this.util.is_obj(this._attributes)){var a=this._attributes={};$.extend(a,this.init_default_attributes()),this.util.is_obj(this._attr_init)&&$.extend(a,this._attr_init),$.extend(a,this.get_dom_attributes())}},init_default_attributes:function(){if(!this._attr_default_parsed&&this.util.is_obj(this._attr_map)){var opts=this.get_controller().get_options(this.util.obj_keys(this._attr_map));if(this.util.is_obj(opts)){for(var opt in this._attr_map)opt in opts&&null!==this._attr_map[opt]&&(opts[this._attr_map[opt]]=opts[opt],delete opts[opt]);$.extend(!0,this._attr_default,opts)}this._attr_default_parsed=!0}return this._attr_default},get_dom_attributes:function(){var attrs={},el=this.dom_get(null,{init:!1});if(0<el.length){var attrs_full=$(el).get(0).attributes;if(this.util.is_obj(attrs_full)){var attr_key,attr_prefix=this.util.get_attribute();$.each(attrs_full,function(idx,attr){if(-1===attr.name.indexOf(attr_prefix))return!0;attr_key=attr.name.substr(attr_prefix.length+1),attrs[attr_key]=attr.value})}}return attrs},get_attributes:function(){return this.init_attributes(),this._attributes},get_attribute:function(key,def,enforce_type){if(this.util.is_set(def)||(def=null),!this.util.is_string(key))return def;this.util.is_bool(enforce_type)||(enforce_type=!0);var ret=this.has_attribute(key)?this.get_attributes()[key]:def;return enforce_type&&ret!==def&&null!==def&&!this.util.is_type(ret,$.type(def),!1)&&(this.util.is_scalar(def,!1)&&this.util.is_scalar(ret,!1)?this.util.is_string(def,!1)?ret=ret.toString():this.util.is_num(def,!1)&&!this.util.is_num(ret,!1)?(ret=this.util.is_int(def,!1)?parseInt(ret):parseFloat(ret),this.util.is_num(ret,!1)||(ret=def)):ret=this.util.is_bool(def,!1)?this.util.is_string(ret)||this.util.is_num(ret):def:ret=def),ret},call_attribute:function(attr,args){return attr=this.get_attribute(attr),this.util.is_func(attr)&&(args=Array.prototype.slice.call(arguments,1),attr=attr.apply(this,args)),attr},has_attribute:function(key){return this.util.is_string(key)&&key in this.get_attributes()},set_attributes:function(attributes,full){this.util.is_bool(full)||(full=!1),this.init_attributes(full),this.util.is_obj(attributes)&&$.extend(this._attributes,attributes)},set_attribute:function(key,val){return this.util.is_string(key)&&this.util.is_set(val)&&(this.get_attributes()[key]=val),val},dom_get_selector:function(element){return this.util.is_string(element)?"."+this.add_ns(element):""},dom_get_attribute:function(){return this.util.get_attribute(this._slug)},dom_set:function(el){return(el=$(el)).data(this.get_data_key(),this),this._reciprocal&&(this._dom=el),el},dom_get:function(element,options){var opts_default={init:!0,put:!1};(options=this.util.is_obj(options)?$.extend({},opts_default,options):opts_default).init&&!this.get_status("dom_init")&&(this.set_status("dom_init"),this.dom_init());var ret=this._dom;if(ret&&this.util.is_string(element)){var ch=$(ret).find(this.dom_get_selector(element));ch.length?ret=ch:!0!==options.put&&!this.util.is_obj(options.put)||(ret=this.dom_put(element,options.put))}return $(ret)},dom_init:function(){},dom_put:function(element,content){var r=null;if(!this.dom_has()||!this.util.is_string(element))return $(r);var strip=["tag","content","success"],options={tag:"div",content:"",class:this.add_ns(element)};this.util.is_empty(content)||(this.util.is_type(content,jQuery,!1)||this.util.is_string(content,!1)?options.content=content:this.util.is_obj(content,!1)&&$.extend(options,content));for(var attrs=$.extend({},options),x=0;x<strip.length;x++)delete attrs[strip[x]];var d=this.dom_get();return(r=$(this.dom_get_selector(element),d)).length||(r=$(this.util.format("<%s />",options.tag),attrs).appendTo(d)).length&&this.util.is_method(options,"success")&&options.success.call(r,r),$(r).append(options.content),$(r)},dom_has:function(){return!!this.dom_get().length},get_data_key:function(){return this.get_ns()},on:function(event,fn,options){if(!this.util.is_string(event)||!this.util.is_func(fn)){var t=this,args=Array.prototype.slice.call(arguments,1);return this.util.is_array(event)?$.each(event,function(idx,val){t.on.apply(t,[val].concat(args))}):this.util.is_obj(event)&&$.each(event,function(ev,hdl){t.on.apply(t,[ev,hdl].concat(args))}),this}this.util.is_obj(options,!1)||(options={}),options=$.extend({},{clear:!1},options),this.util.is_obj(this._events,!1)||(this._events={});var es=this._events;return event in es&&this.util.is_obj(es[event],!1)&&!options.clear||(es[event]=[]),es[event].push(fn),this},trigger:function(event,data){var dfr=$.Deferred(),dfrs=[],t=this;if(this.util.is_array(event))return $.each(event,function(idx,val){dfrs.push(t.trigger(val,data))}),$.when.apply(t,dfrs).done(function(){dfr.resolve()}),dfr.promise();if(!(this.util.is_string(event)&&event in this._events))return dfr.resolve(),dfr.promise();var ev={type:event,data:null};return this.util.is_set(data)&&(ev.data=data),$.each(this._events[event],function(idx,fn){dfrs.push(fn.call(t,ev,t))}),$.when.apply(this,dfrs).done(function(){dfr.resolve()}),dfr.promise()}};View.Component=Component=SLB.Class.extend(Component);var Viewer={_slug:"viewer",_refs:{item:"Content_Item",theme:"Theme"},_reciprocal:!0,_attr_default:{loop:!0,animate:!0,autofit:!0,overlay_enabled:!0,overlay_opacity:"0.8",title_default:!1,container:null,slideshow_enabled:!0,slideshow_autostart:!1,slideshow_duration:2,slideshow_active:!1,slideshow_timer:null,labels:{close:"close",nav_prev:"&laquo; prev",nav_next:"next &raquo;",slideshow_start:"start slideshow",slideshow_stop:"stop slideshow",group_status:"Image %current% of %total%",loading:"loading"}},_attr_map:{theme:null,group_loop:"loop",ui_autofit:"autofit",ui_animate:"animate",ui_overlay_opacity:"overlay_opacity",ui_labels:"labels",ui_title_default:"title_default",slideshow_enabled:null,slideshow_autostart:null,slideshow_duration:null},item:null,item_queued:null,theme:null,item_working:null,active:!1,init:!1,open:!1,loading:!1,_hooks:function(){var t=this;this.on(["item-prev","item-next"],function(){t.trigger("item-change")}).on(["close","item-change"],function(){t.unload().done(function(){t.unlock()})})},get_item:function(){return this.get_component("item")},set_item:function(item){this.clear_item(!1);var i=this.set_component("item",item,function(item){return item.has_type()});return!this.util.is_empty(i)},clear_item:function(full){this.util.is_bool(full)||(full=!0);var item=this.get_item();item&&item.reset(),full&&this.clear_component("item")},get_theme:function(){var ret=this.get_component("theme",{check_attr:!1});return this.util.is_empty(ret)&&(ret=this.set_component("theme",new View.Theme(this))),ret},set_theme:function(theme){this.set_component("theme",theme)},lock:function(){return this.set_status("item_working",$.Deferred())},get_lock:function(simple,full){this.util.is_bool(simple)||(simple=!1),this.util.is_bool(full)||(full=!1);var s="item_working";if(simple)return this.get_status(s);var r=this.get_status(s,!0);return this.util.is_promise(r)||(r=this.lock()),full?r:r.promise()},is_locked:function(){return this.get_lock(!0)},unlock:function(){return this.get_lock(!1,!0).resolve()},set_active:function(mode){return this.util.is_bool(mode)||(mode=!0),this.set_status("active",mode)},is_active:function(){return this.get_status("active")},set_loading:function(mode){var dfr=$.Deferred();this.util.is_bool(mode)||(mode=!0),this.loading=mode,this.slideshow_active()&&this.slideshow_pause(mode);var m=mode?"addClass":"removeClass";return $(this.dom_get())[m]("loading"),mode?this.get_theme().transition("load").always(function(){dfr.resolve()}):dfr.resolve(),dfr.promise()},unset_loading:function(){return this.set_loading(!1)},get_loading:function(){return!!this.util.is_bool(this.loading)&&this.loading},is_loading:function(){return this.get_loading()},show:function(item){this.item_queued=item;var vt="theme_valid",valid=!0;if(this.has_attribute(vt)?valid=this.get_attribute(vt,!0):(valid=!(!this.get_theme()||""===this.get_theme().get_template().get_layout(!1)),this.set_attribute(vt,valid)),!valid)return this.close(),!1;function fin(){if(v.lock(),v.set_status("show_deferred",!1),!v.set_item(v.item_queued))return v.close(),!1;v.history_add(),v.set_active(),v.render()}var v=this;this.is_locked()?this.get_status("show_deferred")||(this.set_status("show_deferred"),this.get_lock().always(function(){fin()})):fin()},history_handle:function(e){var state=e.originalEvent.state;if(this.util.is_string(state.item,!1))this.get_controller().get_item(state.item).show({event:e}),this.trigger("item-change");else{var count=this.history_get(!0);this.history_set(0),-1!==count&&this.close()}},history_get:function(full){return this.get_status("history_count",full)},history_set:function(val){return this.set_status("history_count",val)},history_add:function(){if(!history.pushState)return!1;var item=this.get_item(),opts=item.get_attribute("options_show"),count=this.history_get()?this.history_get(!0):0;if(this.util.in_obj(opts,"event")){var e=opts.event.originalEvent;this.util.in_obj(e,"state")&&this.util.in_obj(e.state,"count")&&(count=e.state.count)}else{var state={viewer:this.get_id(),item:null,count:count};count||history.replaceState(state,null),state.item=this.get_controller().save_item(item).get_id(),state.count=++count,history.pushState(state,"")}this.history_set(count)},history_reset:function(){var count=this.history_get(!0);count&&(this.history_set(-1),history.go(-1*count))},is_open:function(){return"none"!==this.dom_get().css("display")},render:function(){var v=this,thm=this.get_theme();v.dom_prep(),this.get_status("render-events")||(this.set_status("render-events"),thm.on("render-loading",function(ev,thm){var dfr=$.Deferred();if(!v.is_active())return dfr.reject(),dfr.promise();function set_pos(){v.dom_get().css("top",$(window).scrollTop())}function always(){v.set_loading().always(function(){dfr.resolve()})}return v.is_open()?thm.transition("unload").fail(function(){set_pos(),thm.dom_get_tag("item","content").attr("style","")}).always(always):thm.transition("open").always(function(){always(),v.events_open(),v.open=!0}).fail(function(){set_pos(),v.get_overlay().show(),v.dom_get().show()}),dfr.promise()}).on("render-complete",function(ev,thm){if(!v.is_active())return!1;var d=v.dom_get(),classes=["item_single","item_multi"],ms=["addClass","removeClass"];v.get_item().get_group().is_single()||ms.reverse(),$.each(ms,function(idx,val){d[val](classes[idx])}),v.events_complete(),thm.transition("complete").fail(function(){if(v.get_attribute("autofit",!0)){var dims=$.extend({display:"inline-block"},thm.get_item_dimensions());thm.dom_get_tag("item","content").css(dims)}}).always(function(){v.unset_loading(),v.trigger("render-complete"),v.init=!0})})),thm.render()},dom_get_container:function(){var sel=this.get_attribute("container");this.util.is_empty(sel)&&(sel="#"+this.add_ns("wrap"));var c=$(sel);if(!c.length){var id=0===sel.indexOf("#")?sel.substr(1):sel;c=$("<div />",{id:id}).appendTo("body")}return c},dom_init:function(){var d=this.dom_set($("<div/>",{id:this.get_id(!0),class:this.get_ns()})).appendTo(this.dom_get_container()).hide(),thm=this.get_theme();d.addClass(thm.get_classes(" "));var v=this;this.get_status("render-init")||(this.set_status("render-init"),thm.on("render-init",function(ev){v.dom_put("layout",ev.data)})),thm.render(!0)},dom_prep:function(mode){var m=this.util.is_bool(mode)&&!mode?"removeClass":"addClass";$("html")[m](this.util.add_prefix("overlay"))},dom_restore:function(){this.dom_prep(!1)},get_layout:function(){return this.dom_get("layout",{put:{success:function(){$(this).hide()}}})},animation_enabled:function(){return this.get_attribute("animate",!0)},overlay_enabled:function(){var ov=this.get_attribute("overlay_enabled");return!!this.util.is_bool(ov)&&ov},get_overlay:function(){var o=null,v=this;return this.overlay_enabled()&&(o=this.dom_get("overlay",{put:{success:function(){$(this).hide().css("opacity",v.get_attribute("overlay_opacity"))}}})),$(o)},unload:function(){var dfr=$.Deferred();return this.get_theme().dom_get_tag("item").text(""),dfr.resolve(),dfr.promise()},reset:function(){this.dom_get().hide(),this.dom_restore(),this.history_reset(),this.clear_item(),this.set_active(!1),this.set_loading(!1),this.slideshow_stop(),this.keys_disable(),this.unlock()},get_labels:function(){return this.get_attribute("labels",{})},get_label:function(name){var lbls=this.get_labels();return name in lbls?lbls[name]:""},events_open:function(){if(this.keys_enable(),this.open)return!1;var l=this.get_layout();l.children().click(function(ev){ev.stopPropagation()});function close(){v.close()}var v=this;l.click(close),this.get_overlay().click(close),this.trigger("events-open")},events_complete:function(){if(this.init)return!1;this.trigger("events-complete")},keys_enable:function(mode){this.util.is_bool(mode)||(mode=!0);var e=["keyup",this.util.get_prefix()].join("."),v=this;mode?$(document).on(e,function(ev){return v.keys_control(ev)}):$(document).off(e)},keys_disable:function(){this.keys_enable(!1)},keys_control:function(ev){var handlers={27:this.close,37:this.item_prev,39:this.item_next};if("rtl"===document.documentElement.getAttribute("dir")&&(handlers[37]=this.item_next,handlers[39]=this.item_prev),ev.which in handlers)return handlers[ev.which].call(this),!1},slideshow_enabled:function(){var o=this.get_attribute("slideshow_enabled");return!(!(this.util.is_bool(o)&&o&&this.get_item())||this.get_item().get_group().is_single())},slideshow_active:function(){return!(!this.slideshow_enabled()||!(this.get_attribute("slideshow_active")||!this.init&&this.get_attribute("slideshow_autostart")))},slideshow_clear_timer:function(){clearInterval(this.get_attribute("slideshow_timer"))},slideshow_set_timer:function(callback){this.set_attribute("slideshow_timer",setInterval(callback,1e3*this.get_attribute("slideshow_duration")))},slideshow_start:function(){if(!this.slideshow_enabled())return!1;this.set_attribute("slideshow_active",!0),this.dom_get().addClass("slideshow_active"),this.slideshow_clear_timer();var v=this;this.slideshow_set_timer(function(){v.slideshow_pause(),v.item_next()}),this.trigger("slideshow-start")},slideshow_stop:function(full){this.util.is_bool(full)||(full=!0),full&&(this.set_attribute("slideshow_active",!1),this.dom_get().removeClass("slideshow_active")),this.slideshow_clear_timer(),this.trigger("slideshow-stop")},slideshow_toggle:function(){if(!this.slideshow_enabled())return!1;this.slideshow_active()?this.slideshow_stop():this.slideshow_start(),this.trigger("slideshow-toggle")},slideshow_pause:function(mode){this.util.is_bool(mode)||(mode=!0),this.slideshow_active()&&(mode?this.slideshow_stop(!1):this.slideshow_start()),this.trigger("slideshow-pause")},slideshow_resume:function(){this.slideshow_pause(!1)},item_next:function(){var g=this.get_item().get_group(!0),v=this,ev="item-next",st=["events","viewer",ev].join("_");g.get_status(st)||(g.set_status(st),g.on(ev,function(e){v.trigger(e.type)})),g.show_next()},item_prev:function(){var g=this.get_item().get_group(!0),v=this,ev="item-prev",st=["events","viewer",ev].join("_");g.get_status(st)||(g.set_status(st),g.on(ev,function(){v.trigger(ev)})),g.show_prev()},close:function(){this.set_active(!1);var v=this,thm=this.get_theme();return thm.transition("unload").always(function(){thm.transition("close",!0).always(function(){v.reset(),v.trigger("close")})}).fail(function(){thm.dom_get_tag("item","content").attr("style","")}),!1}};View.Viewer=Component.extend(Viewer);var Group={_slug:"group",_reciprocal:!0,_refs:{current:"Content_Item"},current:null,selector:null,_hooks:function(){var t=this;this.on(["item-prev","item-next"],function(){t.trigger("item-change")})},get_selector:function(){return this.util.is_empty(this.selector)&&(this.selector=this.util.format('a[%s="%s"]',this.dom_get_attribute(),this.get_id())),this.selector},get_items:function(){var items=$(this.get_selector());return 0===items.length&&this.has_current()&&(items=this.get_current().dom_get()),items},get_item:function(idx){this.util.is_int(idx)||(idx=0);var items=this.get_items(),max=this.get_size()-1;return max<idx&&(idx=max),items.get(idx)},get_pos:function(item){return this.util.is_empty(item)&&(item=this.get_current()),this.util.is_type(item,View.Content_Item)?this.get_items().index(item.dom_get()):-1},has_current:function(){return!this.util.is_empty(this.get_current())},get_current:function(){return null===this.current||this.util.is_type(this.current,View.Content_Item)||(this.current=null),this.current},set_current:function(item){this.util.is_type(item,View.Content_Item)&&(this.current=item)},get_next:function(item){if(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),1===this.get_size())return item;var next=null,pos=this.get_pos(item);return-1!==pos&&(0===(pos=pos+1<this.get_size()?pos+1:0)&&!item.get_viewer().get_attribute("loop")||(next=this.get_item(pos))),next},get_prev:function(item){if(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),1===this.get_size())return item;var prev=null,pos=this.get_pos(item);return-1===pos||0===pos&&!item.get_viewer().get_attribute("loop")||(0===pos&&(pos=this.get_size()),pos-=1,prev=this.get_item(pos)),prev},show_next:function(item){if(1<this.get_size()){var next=this.get_next(item);next||(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),item.get_viewer().close());var i=this.get_controller().get_item(next);this.set_current(i),i.show(),this.trigger("item-next")}},show_prev:function(item){if(1<this.get_size()){var prev=this.get_prev(item);prev||(this.util.is_type(item,View.Content_Item)||(item=this.get_current()),item.get_viewer().close());var i=this.get_controller().get_item(prev);this.set_current(i),i.show(),this.trigger("item-prev")}},get_size:function(){return this.get_items().length},is_single:function(){return 1===this.get_size()}};View.Group=Component.extend(Group);var Content_Handler={_slug:"content_handler",_refs:{item:"Content_Item"},item:null,template:"",has_item:function(){return!this.util.is_empty(this.get_item())},get_item:function(){return this.get_component("item")},set_item:function(item){return this.set_component("item",item)},clear_item:function(){this.clear_component("item")},match:function(item){var m=this.get_attribute("match");if(!this.util.is_empty(m)){if(this.util.is_string(m)&&(m=new RegExp(m,"i"),this.set_attribute("match",m)),this.util.is_type(m,RegExp))return m.test(item.get_uri());if(this.util.is_func(m))return!!m.call(this,item)}return!1},load:function(item){var dfr=$.Deferred();return null===this.call_attribute("load",item,dfr)&&dfr.resolve(),dfr.promise()},render:function(item){var dfr=$.Deferred();return this.call_attribute("render",item,dfr),dfr.promise()}};View.Content_Handler=Component.extend(Content_Handler);var Content_Item={_slug:"content_item",_reciprocal:!0,_refs:{viewer:"Viewer",group:"Group",type:"Content_Handler"},_attr_default:{source:null,permalink:null,dimensions:null,title:"",group:null,internal:!1,output:null},group:null,viewer:null,type:null,data:null,loaded:null,_c:function(el){this.dom_set(el),this._super()},init_default_attributes:function(){this._super();var d=this.dom_get(),key=d.attr(this.util.get_attribute("asset"))||null,assets=this.get_controller().assets||null;if(this.util.is_string(key)){var attrs=[{},this._attr_default,{permalink:d.attr("href")}];if(this.util.is_obj(assets)){var t=this;attrs.push(function(key){var ret={};return key in assets&&t.util.is_obj(assets[key])&&(ret=assets[key]),ret}(key))}this._attr_default=$.extend.apply(this,attrs)}return this._attr_default},get_output:function(){var dfr=$.Deferred(),ret=this.get_attribute("output");if(this.util.is_string(ret))dfr.resolve(ret);else if(this.has_type()){var type=this.get_type(),item=this;type.render(this).done(function(output){item.set_output(output),dfr.resolve(output)})}else dfr.resolve("");return dfr.promise()},set_output:function(out){this.util.is_string(out,!1)&&this.set_attribute("output",out)},get_content:function(){return this.get_output()},get_uri:function(mode){-1===$.inArray(mode,["source","permalink"])&&(mode="source");var ret=this.get_attribute(mode);return this.util.is_string(ret)||(ret="source"===mode?this.get_attribute("permalink"):""),ret=ret.replace(/&(#38|amp);/,"&")},get_title:function(){if(this.has_attribute("title_cached"))return this.get_attribute("title_cached","");function validate(title){return"string"!=typeof title||""===title.trim()?"":(title=title.trim(),t.get_viewer().get_attribute("title_default")||title===t.get_title_default()&&(title=""),title)}var title="",dom=this.dom_get(),t=this;if(dom.length&&(title=(title=(title=dom.attr("title"))||dom.closest("figure").find("figcaption").first().html())||dom.closest("figure").find(".wp-caption-text").first().html()),!title)for(var props=["caption","title"],x=0;x<props.length&&(title=validate(this.get_attribute(props[x],"")),this.util.is_empty(title));x++);return!title&&dom.length&&(title=(title=validate(dom.find("img").first().attr("alt")))||validate(dom.get(0).innerText.trim())),title=validate(title),this.set_attribute("title_cached",title),title},get_title_default:function(){var val="",prop="title_default";if(this.has_attribute(prop))val=this.get_attribute(prop);else{var f=this.get_uri("source"),i=f.lastIndexOf("/");-1!==i&&-1!==(i=(f=f.substr(i+1)).lastIndexOf("."))&&(f=f.substr(0,i)),val=this.set_attribute(prop,f)}return val},get_dimensions:function(){return $.extend({width:0,height:0},this.get_attribute("dimensions"),{})},set_data:function(data){this.data=data},get_data:function(){return this.data},gallery_type:function(){var ret=null,types={wp:".gallery-icon",ngg:".ngg-gallery-thumbnail"},dom=this.dom_get();for(var type in types)if(0<dom.parent(types[type]).length){ret=type;break}return ret},in_gallery:function(gType){var type=this.gallery_type();return null!==type&&(!this.util.is_string(gType)||gType===type)},get_viewer:function(){return this.get_component("viewer",{get_default:!0})},set_viewer:function(v){return this.set_component("viewer",v)},get_group:function(set_current){var g=this.get_component("group");return g||(g=this.set_component("group",new View.Group),set_current=!0),set_current&&g.set_current(this),g},set_group:function(g){this.util.is_string(g)&&(g=this.get_controller().get_group(g)),this.group=!!this.util.is_type(g,View.Group)&&g},get_type:function(){var t=this.get_component("type",{check_attr:!1});return t=t||this.set_type(this.get_controller().get_content_handler(this))},set_type:function(type){return this.set_component("type",type)},has_type:function(){return!this.util.is_empty(this.get_type())},show:function(options){if(!this.has_type())return!1;this.set_attribute("options_show",options);var v=this.get_viewer();return this.load(),v.show(this)},load:function(){return this.util.is_promise(this.loaded)||(this.loaded=this.get_type().load(this)),this.loaded.promise()},reset:function(){this.set_attribute("options_show",null)}};View.Content_Item=Component.extend(Content_Item);var Modeled_Component={_slug:"modeled_component",get_attribute:function(key,def,check_model,enforce_type){if(!this.util.is_string(key))return this._super(key,def,enforce_type);this.util.is_bool(check_model)||(check_model=!0);var ret=null;if(check_model){var m=this.get_ancestor(key,!1);this.util.in_obj(m,key)&&(ret=m[key])}return null===ret&&(ret=this._super(key,def,enforce_type)),ret},get_attribute_recursive:function(key,def,enforce_type){var ret=this.get_attribute(key,def,!0,enforce_type);if(this.util.is_obj(ret)){var models=this.get_ancestors(!1);ret=[ret];var t=this;$.each(models,function(idx,model){key in model&&t.util.is_obj(model[key])&&ret.push(model[key])}),ret.push({}),ret=$.extend.apply($,ret.reverse())}return ret},set_attribute:function(key,val,use_model){if(!this.util.is_string(key)||!this.util.is_set(val))return!1;(this.util.is_bool(use_model)||this.util.is_obj(use_model)||(use_model=!0),use_model)?(this.util.is_obj(use_model)?use_model:this.get_model())[key]=val:this._super(key,val);return val},get_model:function(){var m=this.get_attribute("model",null,!1);return this.util.is_obj(m)||(m={},this.set_attribute("model",m,!1)),m},has_model:function(){return!this.util.is_empty(this.get_model())},in_model:function(key){return!!this.util.in_obj(this.get_model(),key)},get_ancestors:function(inc_current){for(var ret=[],m=this.get_model();this.util.is_obj(m);)ret.push(m),m=this.util.in_obj(m,"parent")&&this.util.is_obj(m.parent)?m.parent:null;return inc_current||ret.shift(),ret},get_ancestor:function(attr,safe_mode){if(!this.util.is_string(attr))return!1;this.util.is_bool(safe_mode)||(safe_mode=!0);for(var mcurr=this.get_model(),m=mcurr,found=!1;this.util.is_obj(m);){if(this.util.in_obj(m,attr)&&!this.util.is_empty(m[attr])){found=!0;break}m=this.util.in_obj(m,"parent")?m.parent:null}return found||(safe_mode?(this.util.is_empty(m)&&(m=mcurr),this.util.in_obj(m,attr)||(m[attr]=null)):m=null),m}};Modeled_Component=Component.extend(Modeled_Component);var Theme={_slug:"theme",_refs:{viewer:"Viewer",template:"Template"},_models:{},_attr_default:{template:null,model:null},viewer:null,template:null,_c:function(id,attributes,viewer){1===arguments.length&&this.util.is_type(id,View.Viewer)&&(viewer=id,id=null),this._super(id,attributes),this.set_viewer(viewer),this.set_model(id)},get_viewer:function(){return this.get_component("viewer",{check_attr:!1,get_default:!0})},set_viewer:function(v){return this.set_component("viewer",v)},get_template:function(){var ret=this.get_component("template");if(this.util.is_empty(ret)){var attr={theme:this,model:this.get_model()};ret=this.set_component("template",new View.Template(attr))}return ret},get_tags:function(name,prop){return this.get_template().get_tags(name,prop)},dom_get_tag:function(tag,prop){return $(this.get_template().dom_get_tag(tag,prop))},get_tag_selector:function(name,prop){return this.get_template().get_tag_selector(name,prop)},get_models:function(){return this._models},get_model:function(id){var ret=null;if(!this.util.is_set(id)&&this.util.is_obj(this.get_attribute("model",null,!1)))ret=this._super();else{var models=this.get_models();this.util.is_string(id)||(id=this.get_controller().get_option("theme_default")),this.util.in_obj(models,id)||(id=$.map(models,function(v,key){return key})[0]),ret=models[id]}return ret},set_model:function(id){this.set_attribute("model",this.get_model(id),!1)},get_classes:function(rtype){var cls=[],thm=this,models=this.get_ancestors(!0);return $.each(models,function(idx,model){cls.push(thm.add_ns(model.id))}),this.util.is_string(rtype)&&(cls=cls.join(rtype)),cls},get_measurement:function(attr,def){var meas=null;if(!this.util.is_string(attr))return meas;this.util.is_obj(def,!1)||(def={});var attr_cache=this.util.format("%s_cache",attr),cache=this.get_attribute(attr_cache,{},!1),status="_status",item=this.get_viewer().get_item(),w=$(window);status in cache&&this.util.is_obj(cache._status)&&cache._status.width===w.width()&&cache._status.height===w.height()||(cache={}),this.util.is_empty(cache)&&(cache._status={width:w.width(),height:w.height(),index:[]});var pos=$.inArray(item,cache._status.index);return-1!==pos&&pos in cache&&(meas=cache[pos]),this.util.is_obj(meas)||(meas=this.call_attribute(attr),this.util.is_obj(meas)||(meas=this.get_measurement_default(attr))),meas=this.util.is_obj(meas)?$.extend({},def,meas):def,pos=cache._status.index.push(item)-1,cache[pos]=meas,this.set_attribute(attr_cache,cache,!1),$.extend({},meas)},get_measurement_default:function(attr){return this.util.is_string(attr)?(attr=this.util.format("get_%s_default",attr),this.util.in_obj(this,attr)?(attr=this[attr],this.util.is_func(attr)&&(attr=attr.call(this))):attr=null,attr):null},get_offset:function(){return this.get_measurement("offset",{width:0,height:0})},get_offset_default:function(){var offset={width:0,height:0},v=this.get_viewer(),vn=v.dom_get(),vc=vn.clone().attr("id","").css({visibility:"hidden",position:"absolute",top:""}).removeClass("loading").appendTo(vn.parent()),l=vc.find(v.dom_get_selector("layout"));if(l.length){l.find("*").css({width:"",height:"",display:""});var tags=this.get_tags("item","content");if(tags.length){var offset_item=v.get_item().get_dimensions();tags=$(l.find(tags[0].get_selector("full")).get(0)).css({width:offset_item.width,height:offset_item.height}),$.each(offset_item,function(key,val){offset[key]=-1*val})}offset.width+=l.width(),offset.height+=l.height(),$.each(offset,function(key,val){val<0&&(offset[key]=0)})}return vc.empty().remove(),offset},get_margin:function(){return this.get_measurement("margin",{width:0,height:0})},get_item_dimensions:function(){var v=this.get_viewer(),dims=v.get_item().get_dimensions();if(v.get_attribute("autofit",!1)){var margin=this.get_margin(),offset=this.get_offset();offset.height+=margin.height,offset.width+=margin.width;var max={width:$(window).width(),height:$(window).height()};max.width>offset.width&&(max.width-=offset.width),max.height>offset.height&&(max.height-=offset.height);var factor=Math.min(max.width/dims.width,max.height/dims.height);factor<1&&$.each(dims,function(key){dims[key]=Math.round(dims[key]*factor)})}return $.extend({},dims)},get_dimensions:function(){var dims=this.get_item_dimensions(),offset=this.get_offset();return $.each(dims,function(key){dims[key]+=offset[key]}),dims},get_breakpoints:function(){return this.get_attribute_recursive("breakpoints")},get_breakpoint:function(target){var ret=0;if(this.util.is_string(target)){var b=this.get_attribute_recursive("breakpoints");this.util.is_obj(b)&&target in b&&(ret=b[target])}return ret},render:function(init){var thm=this,tpl=this.get_template(),st="events_render";this.get_status(st)||(this.set_status(st),tpl.on(["render-init","render-loading","render-complete"],function(ev){return thm.trigger(ev.type,ev.data)})),tpl.render(init)},transition:function(event,clear_queue){var dfr=null,attr="transition",v=this.get_viewer(),fx_temp=null,anim_on=v.animation_enabled();if(v.get_attribute(attr,!0)&&this.util.is_string(event)){clear_queue&&v.get_layout().find("*").each(function(){for(var el=$(this);el.queue().length;)el.stop(!1,!0)});var trns,attr_set=[attr,"set"].join("_");if(this.get_attribute(attr_set))trns=this.get_attribute(attr,{});else{var models=this.get_ancestors(!0);trns=[],this.set_attribute(attr_set,!0);var thm=this;$.each(models,function(idx,model){attr in model&&thm.util.is_obj(model[attr])&&trns.push(model[attr])}),trns.push({}),trns=this.set_attribute(attr,$.extend.apply($,trns.reverse()))}this.util.is_method(trns,event)&&(anim_on||(fx_temp=$.fx.off,$.fx.off=!0),dfr=trns[event].call(this,v,$.Deferred()))}return this.util.is_promise(dfr)||(dfr=$.Deferred()).reject(),dfr.always(function(){null!==fx_temp&&($.fx.off=fx_temp)}),dfr.promise()}};View.Theme=Modeled_Component.extend(Theme);var Template={_slug:"template",_reciprocal:!0,_refs:{theme:"Theme"},_attr_default:{layout_uri:"",layout_raw:"",layout_parsed:"",tags:null,model:null},theme:null,_c:function(attributes){this._super("",attributes)},_hooks:function(){this.on("dom_init",function(ev){var tags=this.get_tags(null,null,!0),names=[],t=this;$.each(tags,function(idx,tag){var name=tag.get_name();-1===$.inArray(name,names)&&(names.push(name),tag.get_handler().trigger(ev.type,{template:t}))})})},get_theme:function(){return this.get_component("theme")},render:function(init){var v=this.get_theme().get_viewer();if(this.util.is_bool(init)||(init=!1),init)this.trigger("render-init",this.dom_get());else{if(!v.is_active())return!1;var item=v.get_item();if(!this.util.is_type(item,View.Content_Item))return v.close(),!1;if(v.is_active()&&this.has_tags()){var loading_promise=this.trigger("render-loading"),tpl=this,tags=this.get_tags(),tag_promises=[];$.when(item.load(),loading_promise).done(function(){return!!v.is_active()&&($.each(tags,function(idx,tag){if(!v.is_active())return!1;tag_promises.push(tag.render(item).done(function(r){if(!v.is_active())return!1;r.tag.dom_get().html(r.output)}))}),!!v.is_active()&&void $.when.apply($,tag_promises).done(function(){tpl.trigger("render-complete")}))})}}},get_layout:function(parsed){return this.util.is_bool(parsed)||(parsed=!0),parsed?this.parse_layout():this.get_attribute("layout_raw","")},parse_layout:function(){var a="layout_parsed",ret=this.get_attribute(a);return this.util.is_string(ret)||(ret=this.sanitize_layout(this.get_layout(!1)),ret=this.parse_tags(ret),this.set_attribute(a,ret)),ret},sanitize_layout:function(l){if(this.util.is_empty(l))return l;var rtype=this.util.is_string(l)?"string":null,dom=$(l),tag_temp=this.get_tag_temp(),cls=tag_temp.get_class(),cls_new=["x",cls].join("_");switch($(tag_temp.get_selector(),dom).each(function(){$(this).removeClass(cls).addClass(cls_new)}),rtype){case"string":l=dom=dom.wrap("<div />").parent().html();break;default:l=dom}return l},parse_tags:function(l){if(!this.util.is_string(l))return"";for(var match,re=/\{{2}\s*(\w.*?)\s*\}{2}/gim;match=re.exec(l);)l=l.substring(0,match.index)+this.get_tag_container(match[1])+l.substring(match.index+match[0].length);return l},get_tag_container:function(tag){var attr=this.get_tag_attribute();return this.util.format('<span %s="%s"></span>',attr,encodeURI(tag))},get_tag_attribute:function(){return this.get_tag_temp().dom_get_attribute()},get_tag:function(idx){var ret=null;if(this.has_tags()){var tags=this.get_tags();(!this.util.is_int(idx)||idx<0||idx>=tags.length)&&(idx=0),ret=tags[idx]}return ret},get_tags:function(name,prop,isolate){this.util.is_bool(isolate)||(isolate=!1);var a="tags",tags=this.get_attribute(a);if(!this.util.is_array(tags)){tags=[];var d=this.dom_get(),attr=this.get_tag_attribute(),nodes=$(d).find("["+attr+"]");$(nodes).each(function(){var el=$(this),tag=new View.Template_Tag(decodeURI(el.attr(attr)));tag.has_handler()&&(tags.push(tag),isolate||(tag.dom_set(el),el.addClass(tag.get_classes(" ")))),isolate||el.removeAttr(attr)}),isolate||this.set_attribute(a,tags,!1)}if(!this.util.is_empty(tags)&&this.util.is_string(name)){this.util.is_string(prop)||(prop=!1);for(var tags_filtered=[],tc=null,x=0;x<tags.length;x++)name===(tc=tags[x]).get_name()&&(prop&&prop!==tc.get_prop()||tags_filtered.push(tc));tags=tags_filtered}return this.util.is_array(tags,!1)?tags:[]},has_tags:function(){return 0<this.get_tags().length},get_tag_temp:function(){return this.get_controller().get_component_temp(View.Template_Tag)},get_tag_selector:function(name,prop){this.util.is_string(name)||(name=""),this.util.is_string(prop)||(prop="");var tag=this.get_tag_temp();return tag.set_attribute("name",name),tag.set_attribute("prop",prop),tag.get_selector("full")},dom_init:function(){this.dom_set(this.get_layout()),this.trigger("dom_init")},dom_get_tag:function(tag,prop){var ret=$(),tags=this.get_tags(tag,prop);if(tags.length){var level=null;this.util.is_string(tag)&&(level=this.util.is_string(prop)?"full":"tag");var sel="."+tags[0].get_class(level);ret=this.dom_get().find(sel)}return ret}};View.Template=Modeled_Component.extend(Template);var Template_Tag={_slug:"template_tag",_reciprocal:!0,_attr_default:{name:null,prop:null,match:null},handlers:{},_c:function(tag_match){this.parse(tag_match)},parse:function(tag_match){if(!this.util.is_string(tag_match))return!1;var part,parts=tag_match.split("|");if(!parts.length)return null;var attrs={name:null,prop:null,match:tag_match};attrs.name=parts[0],-1!==attrs.name.indexOf(".")&&(attrs.name=attrs.name.split(".",2),attrs.prop=attrs.name[1],attrs.name=attrs.name[0]);for(var x=1;x<parts.length;x++)1<(part=parts[x].split(":",1)).length&&!(part[0]in attrs)&&(attrs[part[0]]=part[1]);this.set_attributes(attrs,!0)},render:function(item){var tag=this;return tag.get_handler().render(item,tag).pipe(function(output){return{tag:tag,output:output}})},get_name:function(){return this.get_attribute("name")},get_prop:function(){return this.get_attribute("prop")},get_handler:function(){return this.has_handler()?this.handlers[this.get_name()]:new View.Template_Tag_Handler("")},has_handler:function(){return this.get_name()in this.handlers},get_classes:function(rtype){var cls=[this.get_class(),this.get_class("tag"),this.get_class("full")];return this.util.is_string(rtype)&&(cls=cls.join(rtype)),cls},get_class:function(level){var cls="";switch(level){case"tag":cls=this.get_name();break;case"full":var i,parts=[this.get_name(),this.get_prop()],a=[];for(i=0;i<parts.length;i++)this.util.is_string(parts[i])&&a.push(parts[i]);cls=a.join("_")}return this.util.is_string(cls)?this.add_ns(cls):this.get_ns()},get_selector:function(level){var ret=this.get_class(level);return ret=this.util.is_string(ret)?"."+ret:""}};View.Template_Tag=Component.extend(Template_Tag);var Template_Tag_Handler={_slug:"template_tag_handler",_attr_default:{supports_modifiers:!1,dynamic:!1,props:{}},render:function(item,instance){var dfr=$.Deferred();return this.call_attribute("render",item,instance,dfr),dfr.promise()},add_prop:function(prop,fn){var a="props",props=this.get_attribute(a);if(!this.util.is_string(prop)||!this.util.is_func(fn))return!1;this.util.is_obj(props,!1)||(props={}),props[prop]=fn,this.set_attribute(a,props)},handle_prop:function(prop,item,instance){var props=this.get_attribute("props");return this.util.is_obj(props)&&prop in props&&this.util.is_func(props[prop])?props[prop].call(this,item,instance):item.get_viewer().get_label(prop)}};View.Template_Tag_Handler=Component.extend(Template_Tag_Handler),View=SLB.attach("View",View)}(jQuery);
client/sass/admin.scss CHANGED
@@ -7,19 +7,19 @@
7
  .block {
8
  display: inline-block;
9
  }
10
-
11
  label.title {
12
  width: 200px;
13
  padding: 10px;
14
  }
15
-
16
  .input {
17
  font-size: 11px;
18
  line-height: 20px;
19
  margin-bottom: 9px;
20
  padding: 8px 10px;
21
  }
22
-
23
  .input select {
24
  min-width: 12em;
25
  }
7
  .block {
8
  display: inline-block;
9
  }
10
+
11
  label.title {
12
  width: 200px;
13
  padding: 10px;
14
  }
15
+
16
  .input {
17
  font-size: 11px;
18
  line-height: 20px;
19
  margin-bottom: 9px;
20
  padding: 8px 10px;
21
  }
22
+
23
  .input select {
24
  min-width: 12em;
25
  }
content-handlers/image/js/dev/handler.image.js CHANGED
@@ -20,7 +20,7 @@ SLB.View.extend_content_handler('image', {
20
  // Resolve deferred
21
  dfr.resolve(out);
22
  };
23
-
24
  // Attach event handler
25
  $(img).on('load', function(e) { handler(e); });
26
  // Load image
20
  // Resolve deferred
21
  dfr.resolve(out);
22
  };
23
+
24
  // Attach event handler
25
  $(img).on('load', function(e) { handler(e); });
26
  // Load image
content-handlers/image/js/prod/handler.image.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.has_child("View.extend_content_handler")&&!function($){SLB.View.extend_content_handler("image",{render:function(item,dfr){var img=new Image,handler=function(){item.set_data(img),item.set_attribute("dimensions",{width:img.width,height:img.height});var out=$("<img />",{src:item.get_uri()});dfr.resolve(out)};return $(img).on("load",function(e){handler(e)}),img.src=item.get_uri(),dfr.promise()}})}(jQuery);
1
+ window.SLB&&SLB.has_child("View.extend_content_handler")&&function($){SLB.View.extend_content_handler("image",{render:function(item,dfr){var img=new Image;return $(img).on("load",function(e){!function(){item.set_data(img),item.set_attribute("dimensions",{width:img.width,height:img.height});var out=$("<img />",{src:item.get_uri()});dfr.resolve(out)}()}),img.src=item.get_uri(),dfr.promise()}})}(jQuery);
controller.php CHANGED
@@ -1,33 +1,33 @@
1
- <?php
2
  /**
3
  * Controller
4
  * @package Simple Lightbox
5
  * @author Archetyped
6
  */
7
  class SLB_Lightbox extends SLB_Base {
8
-
9
  /*-** Properties **-*/
10
-
11
  protected $model = true;
12
-
13
  /**
14
  * Fields
15
  * @var SLB_Fields
16
  */
17
  public $fields = null;
18
-
19
  /**
20
  * Themes collection
21
  * @var SLB_Themes
22
  */
23
  var $themes = null;
24
-
25
  /**
26
  * Content types
27
  * @var SLB_Content_Handlers
28
  */
29
  var $handlers = null;
30
-
31
  /**
32
  * Template tags
33
  * @var SLB_Template_Tags
@@ -35,40 +35,88 @@ class SLB_Lightbox extends SLB_Base {
35
  var $template_tags = null;
36
 
37
  /**
38
- * Collection of processed media items for output to client
39
- * > Key (string) Attachment URI
40
- * > Value (assoc-array) Attachment properties (url, etc.)
41
- * > source: Source URL
42
- * @var array
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  */
44
- var $media_items = array();
45
-
46
- /**
47
- * Collection of unprocessed media items
48
- * Multi-dimensional array
49
- * > props (array) Media properties indexed by ID
50
- * > Key: (string) Unique ID (system-generated)
51
- * > Value: (object) Media properties
52
- * > type: (string) Item type (Default: null)
53
- * > id: (int) WP item ID (Default: null)
54
- * > uri (array) Index of cached URIs
55
- * > Key: (string) Item URI
56
- * > Value: (string) Item ID (pointer to item in `id` array)
57
- * @var array
 
 
 
 
 
 
 
58
  */
59
- private $media_items_raw = array( 'props' => array(), 'uri' => array() );
60
-
61
  /**
62
  * Manage excluded content
63
  * @var object
64
  */
65
  private $exclude = null;
66
-
67
  private $groups = array (
68
  'auto' => 0,
69
  'manual' => array(),
70
  );
71
-
72
  /**
73
  * Validated URIs
74
  * Caches validation of parsed URIs
@@ -77,22 +125,22 @@ class SLB_Lightbox extends SLB_Base {
77
  * @var array
78
  */
79
  private $validated_uris = array();
80
-
81
  /* Widget properties */
82
-
83
  /**
84
  * Used to track if widget is currently being processed or not
85
  * Set to Widget ID currently being processed
86
  * @var bool|string
87
  */
88
  private $widget_processing = false;
89
-
90
  /**
91
  * Parameters for widget being processed
92
  * @param array
93
  */
94
  private $widget_processing_params = null;
95
-
96
  /**
97
  * Manage nested widget processing
98
  * Used to avoid premature widget output
@@ -102,7 +150,7 @@ class SLB_Lightbox extends SLB_Base {
102
 
103
  /**
104
  * Constructor
105
- */
106
  public function __construct() {
107
  parent::__construct();
108
  // Init instances
@@ -112,14 +160,14 @@ class SLB_Lightbox extends SLB_Base {
112
  $this->template_tags = new SLB_Template_Tags($this);
113
  }
114
  }
115
-
116
  /* Init */
117
-
118
  public function _init() {
119
  parent::_init();
120
  $this->util->do_action('init');
121
  }
122
-
123
  /**
124
  * Declare client files (scripts, styles)
125
  * @uses parent::_client_files()
@@ -152,7 +200,7 @@ class SLB_Lightbox extends SLB_Base {
152
  );
153
  parent::_client_files($files);
154
  }
155
-
156
  /**
157
  * Register hooks
158
  * @uses parent::_hooks()
@@ -163,18 +211,18 @@ class SLB_Lightbox extends SLB_Base {
163
  /* Admin */
164
  add_action('admin_menu', $this->m('admin_menus'));
165
  $this->util->add_filter('admin_plugin_row_meta_support', $this->m('admin_plugin_row_meta_support'));
166
-
167
  /* Init */
168
  add_action('wp', $this->m('_hooks_init'));
169
  }
170
-
171
  /**
172
  * Init Hooks
173
  */
174
  public function _hooks_init() {
175
  if ( $this->is_enabled() ) {
176
  $priority = $this->util->priority('low');
177
-
178
  // Init lightbox
179
  add_action('wp_footer', $this->m('client_footer'));
180
  $this->util->add_action('footer_script', $this->m('client_init'), 1);
@@ -188,17 +236,17 @@ class SLB_Lightbox extends SLB_Base {
188
  $this->util->add_filter('pre_process_links', $this->m('exclude_content'));
189
  $this->util->add_filter('pre_exclude_content', $this->m('exclude_shortcodes'));
190
  $this->util->add_filter('post_process_links', $this->m('restore_excluded_content'));
191
-
192
  // Grouping
193
  if ( $this->options->get_bool('group_post') ) {
194
- $this->util->add_filter('get_group_id', $this->m('post_group_id'), 1);
195
  }
196
-
197
  // Shortcode grouping
198
  if ( $this->options->get_bool('group_gallery') ) {
199
  add_filter('the_content', $this->m('group_shortcodes'), 1);
200
  }
201
-
202
  // Widgets
203
  if ( $this->options->get_bool('enabled_widget') ) {
204
  add_action('dynamic_sidebar_before', $this->m('widget_process_nested'));
@@ -210,7 +258,7 @@ class SLB_Lightbox extends SLB_Base {
210
  add_action('dynamic_sidebar_before', $this->m('widget_block_start'));
211
  add_action('dynamic_sidebar_after', $this->m('widget_block_finish'));
212
  }
213
-
214
  // Menus
215
  if ( $this->options->get_bool('enabled_menu') ) {
216
  add_filter('wp_nav_menu', $this->m('menu_process'), $priority, 2);
@@ -234,7 +282,7 @@ class SLB_Lightbox extends SLB_Base {
234
  }
235
  return $group_segments;
236
  }
237
-
238
  /**
239
  * Init options
240
  */
@@ -266,7 +314,7 @@ class SLB_Lightbox extends SLB_Base {
266
  'slideshow_duration' => array('title' => __('Slide Duration (Seconds)', 'simple-lightbox'), 'default' => '6', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => array('ui', 40), 'in_client' => true),
267
  'group_loop' => array('title' => __('Loop through items', 'simple-lightbox'),'default' => true, 'group' => array('ui', 50), 'in_client' => true),
268
  'ui_overlay_opacity' => array('title' => __('Overlay Opacity (0 - 1)', 'simple-lightbox'), 'default' => '0.8', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => array('ui', 60), 'in_client' => true),
269
- 'ui_title_default' => array('title' => __('Enable default title', 'simple-lightbox'), 'default' => false, 'group' => array('ui', 70), 'in_client' => true),
270
  'txt_loading' => array('title' => __('Loading indicator', 'simple-lightbox'), 'default' => 'Loading', 'group' => array('labels', 20)),
271
  'txt_close' => array('title' => __('Close button', 'simple-lightbox'), 'default' => 'Close', 'group' => array('labels', 10)),
272
  'txt_nav_next' => array('title' => __('Next Item button', 'simple-lightbox'), 'default' => 'Next', 'group' => array('labels', 30)),
@@ -300,7 +348,7 @@ class SLB_Lightbox extends SLB_Base {
300
  'txt_closeLink' => 'txt_link_close',
301
  'txt_nextLink' => 'txt_link_next',
302
  'txt_prevLink' => 'txt_link_prev',
303
- 'txt_startSlideshow' => 'txt_slideshow_start',
304
  'txt_stopSlideshow' => 'txt_slideshow_stop',
305
  'txt_loadingMsg' => 'txt_loading',
306
  'txt_link_next' => 'txt_nav_next',
@@ -308,12 +356,12 @@ class SLB_Lightbox extends SLB_Base {
308
  'txt_link_close' => 'txt_close',
309
  )
310
  );
311
-
312
  parent::_set_options($opts);
313
  }
314
 
315
  /* Methods */
316
-
317
  /*-** Admin **-*/
318
 
319
  /**
@@ -330,13 +378,13 @@ class SLB_Lightbox extends SLB_Base {
330
  $pg_opts = $this->admin->add_theme_page('options', $lbls_opts)
331
  ->require_form()
332
  ->add_content('options', 'Options', $this->options);
333
-
334
  // Add Support information
335
  $support = $this->util->get_plugin_info('SupportURI');
336
  if ( !empty($support) ) {
337
  $pg_opts->add_content('support', __('Feedback & Support', 'simple-lightbox'), $this->m('theme_page_callback_support'), 'secondary');
338
  }
339
-
340
  // Add Actions
341
  $lbls_reset = array (
342
  'title' => __('Reset', 'simple-lightbox'),
@@ -346,7 +394,7 @@ class SLB_Lightbox extends SLB_Base {
346
  );
347
  $this->admin->add_action('reset', $lbls_reset, $this->options);
348
  }
349
-
350
  /**
351
  * Support information
352
  */
@@ -359,7 +407,7 @@ class SLB_Lightbox extends SLB_Base {
359
  $lnk_txt = __('Get Support &amp; Provide Feedback', 'simple-lightbox');
360
  echo $this->util->build_html_link($lnk_uri, $lnk_txt, array('target' => '_blank', 'class' => 'button'));
361
  }
362
-
363
  /**
364
  * Filter support link text in plugin metadata
365
  * @param string $text Original link text
@@ -370,7 +418,7 @@ class SLB_Lightbox extends SLB_Base {
370
  }
371
 
372
  /*-** Functionality **-*/
373
-
374
  /**
375
  * Checks whether lightbox is currently enabled/disabled
376
  * @return bool TRUE if lightbox is currently enabled, FALSE otherwise
@@ -404,10 +452,10 @@ class SLB_Lightbox extends SLB_Base {
404
  // Return value (force boolean)
405
  return !!$ret;
406
  }
407
-
408
  /**
409
  * Make sure content is valid for processing/activation
410
- *
411
  * @param string $content Content to validate
412
  * @return bool TRUE if content is valid (FALSE otherwise)
413
  */
@@ -419,16 +467,16 @@ class SLB_Lightbox extends SLB_Base {
419
  // Non-string value
420
  if ( !is_string($content) )
421
  return false;
422
-
423
  // Empty string
424
  $content = trim($content);
425
  if ( empty($content) )
426
  return false;
427
-
428
  // Content is valid
429
  return $this->util->apply_filters('is_content_valid', true, $content);
430
  }
431
-
432
  /**
433
  * Activates galleries extracted from post
434
  * @see get_post_galleries()
@@ -445,7 +493,7 @@ class SLB_Lightbox extends SLB_Base {
445
  if ( is_array($gallery) ) {
446
  return $galleries;
447
  }
448
-
449
  // Activate galleries
450
  $group = ( $this->options->get_bool('group_gallery') ) ? true : null;
451
  foreach ( $galleries as $key => $val ) {
@@ -454,17 +502,17 @@ class SLB_Lightbox extends SLB_Base {
454
  }
455
  // Activate links in gallery
456
  $gallery = $this->process_links($val, $group);
457
-
458
  // Save modified gallery
459
  $galleries[$key] = $gallery;
460
  }
461
-
462
  return $galleries;
463
  }
464
-
465
  /**
466
  * Scans post content for image links and activates them
467
- *
468
  * Lightbox will not be activated for feeds
469
  * @param string $content Content to activate
470
  * @param string (optonal) $group Group ID for content
@@ -477,23 +525,23 @@ class SLB_Lightbox extends SLB_Base {
477
  }
478
  // Filter content before processing links
479
  $content = $this->util->apply_filters('pre_process_links', $content);
480
-
481
  // Process links
482
  $content = $this->process_links($content, $group);
483
-
484
  // Filter content after processing links
485
  $content = $this->util->apply_filters('post_process_links', $content);
486
-
487
  return $content;
488
  }
489
-
490
  /**
491
  * Process links in content
492
  * @global obj $wpdb DB instance
493
  * @global obj $post Current post
494
  * @param string $content Text containing links
495
  * @param string (optional) $group Group to add links to (Default: none)
496
- * @return string Content with processed links
497
  */
498
  protected function process_links($content, $group = null) {
499
  // Extract links
@@ -515,7 +563,7 @@ class SLB_Lightbox extends SLB_Base {
515
  $uri_proto = (object) array('raw' => '', 'source' => '', 'parts' => '');
516
  }
517
  $uri_parts_required = array('host' => '');
518
-
519
  // Setup group properties
520
  $g_props = (object) array(
521
  'enabled' => $this->options->get_bool('group_links'),
@@ -527,14 +575,14 @@ class SLB_Lightbox extends SLB_Base {
527
  if ( $g_props->enabled ) {
528
  $g_props->base = ( is_scalar($group) ) ? trim(strval($group)) : '';
529
  }
530
-
531
  // Initialize content handlers
532
  if ( !( $this->handlers instanceof SLB_Content_Handlers ) ) {
533
  $this->handlers = new SLB_Content_Handlers($this);
534
  }
535
-
536
  // Iterate through and activate supported links
537
-
538
  foreach ( $links as $link ) {
539
  // Init vars
540
  $pid = 0;
@@ -544,30 +592,30 @@ class SLB_Lightbox extends SLB_Base {
544
  $props_extra = array();
545
  $key = null;
546
  $internal = false;
547
-
548
  // Parse link attributes
549
  $attrs = $this->util->parse_attribute_string($link_new, array('href' => ''));
550
  // Get URI
551
  $uri->raw = $attrs['href'];
552
-
553
  // Stop processing invalid links
554
  if ( !$this->validate_uri($uri->raw)
555
  || $this->has_attribute($attrs, 'active', false) // Previously-processed
556
  ) {
557
  continue;
558
  }
559
-
560
  // Normalize URI (make absolute)
561
  $uri->source = WP_HTTP::make_absolute_url($uri->raw, $uri_origin['scheme'] . '://' . $uri_origin['host']);
562
-
563
  // URI cached?
564
  $key = $this->get_media_item_id($uri->source);
565
-
566
  // Internal URI? (e.g. attachments)
567
  if ( !$key ) {
568
  $uri->parts = array_merge( $uri_parts_required, (array) parse_url($uri->source) );
569
  $internal = ( $uri->parts['host'] === $uri_origin['host'] ) ? true : false;
570
-
571
  // Attachment?
572
  if ( $internal && is_local_attachment($uri->source) ) {
573
  $pid = url_to_postid($uri->source);
@@ -581,7 +629,7 @@ class SLB_Lightbox extends SLB_Base {
581
  unset($src);
582
  }
583
  }
584
-
585
  // Determine content type
586
  if ( !$key ) {
587
  // Get handler match
@@ -595,23 +643,23 @@ class SLB_Lightbox extends SLB_Base {
595
  unset($props_extra['uri']);
596
  }
597
  }
598
-
599
  // Cache valid item
600
  if ( !!$type ) {
601
  $key = $this->cache_media_item($uri, $type, $internal, $props_extra);
602
  }
603
  }
604
-
605
  // Stop processing invalid links
606
  if ( !$key ) {
607
  // Cache invalid URI
608
  $this->validated_uris[$uri->source] = false;
609
  if ( $uri->raw !== $uri->source ) {
610
- $this->validated_uris[$uri->raw] = false;
611
  }
612
  continue;
613
  }
614
-
615
  // Activate link
616
  $this->set_attribute($attrs, 'active');
617
  $this->set_attribute($attrs, 'asset', $key);
@@ -619,7 +667,7 @@ class SLB_Lightbox extends SLB_Base {
619
  if ( $internal ) {
620
  $this->set_attribute($attrs, 'internal', $pid);
621
  }
622
-
623
  // Set group (if enabled)
624
  if ( $g_props->enabled ) {
625
  $group = array();
@@ -630,31 +678,31 @@ class SLB_Lightbox extends SLB_Base {
630
  } elseif ( !empty($g_props->base) ) {
631
  $group[] = $g_props->base;
632
  }
633
-
634
  /**
635
  * Filter group ID components
636
- *
637
  * @see process_links()
638
- *
639
  * @param array $group Components used to build group ID
640
  */
641
  $group = $this->util->apply_filters('get_group_id', $group);
642
-
643
  // Default group
644
  if ( empty($group) || !is_array($group) ) {
645
  $group = $this->get_prefix();
646
  } else {
647
  $group = implode('_', $group);
648
  }
649
-
650
  // Set group attribute
651
  $this->set_attribute($attrs, $g_props->attr, $group);
652
  unset($g);
653
  }
654
-
655
  // Filter attributes
656
  $attrs = $this->util->apply_filters('process_link_attributes', $attrs);
657
-
658
  // Update link in content
659
  $link_new = '<a ' . $this->util->build_attribute_string($attrs) . '>';
660
  $content = str_replace($link, $link_new, $content);
@@ -664,7 +712,7 @@ class SLB_Lightbox extends SLB_Base {
664
  if ( !!$this->widget_processing && 'the_content' == current_filter() ) {
665
  $content = $this->exclude_wrap($content);
666
  }
667
-
668
  return $content;
669
  }
670
 
@@ -675,20 +723,20 @@ class SLB_Lightbox extends SLB_Base {
675
  * @return array Links in content
676
  */
677
  function get_links($content, $unique = false) {
678
- $rgx = "/\<a[^\>]+href=.*?\>/i";
679
- $links = array();
680
  preg_match_all($rgx, $content, $links);
681
  $links = $links[0];
682
  if ( $unique )
683
  $links = array_unique($links);
684
  return $links;
685
  }
686
-
687
  /**
688
  * Validate URI
689
  * Matches specified URI against internal & external regex patterns
690
  * URI is **invalid** if it matches a regex
691
- *
692
  * @param string $uri URI to validate
693
  * @return bool TRUE if URI is valid
694
  */
@@ -710,7 +758,7 @@ class SLB_Lightbox extends SLB_Base {
710
  // Get patterns
711
  if ( is_null($patterns) ) {
712
  $patterns = $this->util->apply_filters('validate_uri_regex', array());
713
- }
714
  // Iterate through patterns until match found
715
  foreach ( $patterns as $pattern ) {
716
  if ( 1 === preg_match($pattern, $uri) ) {
@@ -719,23 +767,23 @@ class SLB_Lightbox extends SLB_Base {
719
  }
720
  }
721
  }
722
-
723
  // Cache
724
  $this->validated_uris[$uri] = $valid;
725
  return $valid;
726
  }
727
-
728
  /**
729
  * Add URI validation regex pattern
730
- * @param
731
  */
732
  public function validate_uri_regex_default($patterns) {
733
  $patterns[] = '@^https?://[^/]*(wikipedia|wikimedia)\.org/wiki/file:.*$@i';
734
  return $patterns;
735
- }
736
-
737
  /* Client */
738
-
739
  /**
740
  * Checks if output should be loaded in current request
741
  * @uses `is_enabled()`
@@ -745,7 +793,7 @@ class SLB_Lightbox extends SLB_Base {
745
  public function is_request_valid() {
746
  return ( $this->is_enabled() && $this->has_cached_media_items() ) ? true : false;
747
  }
748
-
749
  /**
750
  * Sets options/settings to initialize lightbox functionality on page load
751
  * @return void
@@ -753,17 +801,17 @@ class SLB_Lightbox extends SLB_Base {
753
  function client_init($client_script) {
754
  // Get options
755
  $options = $this->options->build_client_output();
756
-
757
  // Load UI Strings
758
  if ( ($labels = $this->build_labels()) && !empty($labels) ) {
759
  $options['ui_labels'] = $labels;
760
  }
761
-
762
  // Build client output
763
  $client_script[] = $this->util->call_client_method('View.init', $options);
764
  return $client_script;
765
  }
766
-
767
  /**
768
  * Output code in footer
769
  * > Media attachment URLs
@@ -773,14 +821,14 @@ class SLB_Lightbox extends SLB_Base {
773
  function client_footer() {
774
  if ( !$this->has_cached_media_items() )
775
  return false;
776
-
777
  // Set up hooks
778
  add_action('wp_print_footer_scripts', $this->m('client_footer_script'));
779
-
780
  // Build client output
781
  $this->util->do_action('footer');
782
  }
783
-
784
  /**
785
  * Output client footer scripts
786
  */
@@ -790,164 +838,163 @@ class SLB_Lightbox extends SLB_Base {
790
  echo $this->util->build_script_element($client_script, 'footer', true, true);
791
  }
792
  }
793
-
794
  /**
795
  * Add media information to client output
796
- *
797
- * @param array $commands Client script commands
798
- * @return array Modified script commands
799
  * TODO Refactor
800
  */
801
- function client_script_media($client_script) {
802
  global $wpdb;
803
-
804
- // Init variables
805
- $this->media_items = array();
806
- $props = array('id', 'type', 'description', 'title', 'source', 'caption');
807
- $props = (object) array_combine($props, $props);
808
- $props_map = array('description' => 'post_content', 'title' => 'post_title', 'caption' => 'post_excerpt');
809
-
810
- // Separate media into buckets by type
811
- $m_internals = array();
812
- $type = $id = null;
813
-
814
- $m_items = $this->media_items = $this->get_cached_media_items();
815
- foreach ( $m_items as $key => $p ) {
816
- // Set aside internal links for additional processing
817
- if ( $p->internal && !isset($m_internals[$key]) ) {
818
- $m_internals[$key] =& $m_items[$key];
819
  }
820
  }
 
821
  unset($key, $p);
822
-
823
- // Process internal links
824
  if ( !empty($m_internals) ) {
825
- $uris_base = array();
826
  $uri_prefix = wp_upload_dir();
827
  $uri_prefix = $this->util->normalize_path($uri_prefix['baseurl'], true);
828
  foreach ( $m_internals as $key => $p ) {
829
- // Prepare internal links
830
- // Create relative URIs for attachment data retrieval
831
  if ( !$p->id && strpos($p->source, $uri_prefix) === 0 ) {
832
  $uris_base[str_replace($uri_prefix, '', $p->source)] = $key;
833
  }
834
  }
 
835
  unset($key, $p);
836
-
837
- // Retrieve attachment IDs
838
  $uris_flat = "('" . implode("','", array_keys($uris_base)) . "')";
839
  $q = $wpdb->prepare("SELECT post_id, meta_value FROM $wpdb->postmeta WHERE `meta_key` = %s AND LOWER(`meta_value`) IN $uris_flat LIMIT %d", '_wp_attached_file', count($uris_base));
840
  $pids = $wpdb->get_results($q);
841
- // Match IDs to URIs
842
  if ( $pids ) {
843
  foreach ( $pids as $pd ) {
844
  $file =& $pd->meta_value;
845
  if ( isset($uris_base[$file]) ) {
846
- $m_internals[ $uris_base[$file] ]->{$props->id} = absint($pd->post_id);
847
  }
848
  }
849
  }
850
- // Destroy worker vars
851
  unset($uris_base, $uris_flat, $q, $pids, $pd, $file);
852
  }
853
-
854
- // Process items with attachment IDs
855
- $pids = array();
856
- foreach ( $m_items as $key => $p ) {
857
- // Add post ID to query
858
  if ( !!$p->id ) {
859
- // Create array for ID (support multiple URIs per ID)
860
  if ( !isset($pids[$p->id]) ) {
861
- $pids[$p->id] = array();
862
  }
863
- // Add URI to ID
864
  $pids[$p->id][] = $key;
865
  }
866
  }
 
867
  unset($key, $p);
868
-
869
- // Retrieve attachment properties
870
  if ( !empty($pids) ) {
871
  $pids_flat = array_keys($pids);
872
- // Retrieve attachment post data
873
  $atts = get_posts(array('post_type' => 'attachment', 'include' => $pids_flat));
874
-
875
- // Process attachments
876
  if ( $atts ) {
877
- // Retrieve attachment metadata
 
878
  $pids_flat = "('" . implode("','", $pids_flat) . "')";
879
  $atts_meta = $wpdb->get_results($wpdb->prepare("SELECT `post_id`,`meta_value` FROM $wpdb->postmeta WHERE `post_id` IN $pids_flat AND `meta_key` = %s LIMIT %d", '_wp_attachment_metadata', count($atts)));
880
- // Restructure metadata array by post ID
881
  if ( $atts_meta ) {
882
- $meta = array();
883
  foreach ( $atts_meta as $att_meta ) {
884
  $meta[$att_meta->post_id] = $att_meta->meta_value;
885
  }
886
  $atts_meta = $meta;
 
887
  unset($meta);
888
  } else {
889
- $atts_meta = array();
890
  }
891
- $props_size = array('file', 'width', 'height');
892
- $props_exclude = array('hwstring_small');
 
 
 
 
 
 
 
 
893
  foreach ( $atts as $att ) {
894
- // Set post data
895
- $m = array();
896
-
897
- // Remap post data to properties
898
- foreach ( $props_map as $prop_key => $prop_source ) {
899
- $m[$props->{$prop_key}] = $att->{$prop_source};
 
900
  }
901
- unset($prop_key, $prop_source);
902
-
903
- // Add metadata
904
- if ( isset($atts_meta[$att->ID]) && ($a = unserialize($atts_meta[$att->ID])) && is_array($a) ) {
905
- // Move original size into `sizes` array
906
- foreach ( $props_size as $d ) {
907
- if ( !isset($a[$d]) ) {
908
- continue;
909
- }
910
- $a['sizes']['original'][$d] = $a[$d];
911
- unset($a[$d]);
912
- }
913
 
914
- // Strip extraneous metadata
915
- foreach ( $props_exclude as $d ) {
 
 
 
 
916
  if ( isset($a[$d]) ) {
917
- unset($a[$d]);
918
  }
919
  }
920
-
921
- // Merge post data & meta data
922
- $m = array_merge($a, $m);
923
- // Destroy worker vars
924
- unset($a, $d);
925
  }
926
-
927
- // Save attachment data (post & meta) to original object(s)
928
  if ( isset($pids[$att->ID]) ) {
929
  foreach ( $pids[$att->ID] as $key ) {
930
- $this->media_items[$key] = array_merge( (array) $m_items[$key], $m);
931
  }
932
  }
933
  }
 
 
934
  }
 
935
  unset($atts, $atts_meta, $m, $a, $uri, $pids, $pids_flat);
936
  }
937
 
938
- // Filter media item properties
939
- foreach ( $this->media_items as $key => $props ) {
940
- $this->media_items[$key] = $this->util->apply_filters('media_item_properties', (object) $props);
941
- }
942
 
943
- // Build client output
944
  $obj = 'View.assets';
945
  $client_script[] = $this->util->extend_client_object($obj, $this->media_items);
946
  return $client_script;
947
  }
948
 
949
  /*-** Media **-*/
950
-
951
  /**
952
  * Cache media properties for later processing
953
  * @uses array self::$media_items_raw Stores media items for output
@@ -961,32 +1008,36 @@ class SLB_Lightbox extends SLB_Base {
961
  * @return string Unique ID for cached media item
962
  */
963
  private function cache_media_item($uri, $type, $internal, $props = null) {
964
- // Validate
965
  if ( !is_object($uri) || !is_string($type) ) {
966
  return false;
967
  }
968
- // Check if URI already cached
969
  $key = $this->get_media_item_id($uri->source);
970
- // Cache new item
971
  if ( null == $key ) {
972
- // Generate Unique ID
973
  do {
974
  $key = (string) mt_rand();
975
  } while ( isset($this->media_items_raw['props'][$key]) );
976
- // Build properties object
977
- $i = array('id' => null);
978
  if ( is_array($props) && !empty($props) ) {
979
  $i = array_merge($i, $props);
980
  }
981
- $i = array_merge($i, array('type' => $type, 'source' => $uri->source, 'internal' => $internal));
982
- // Cache item properties
 
 
 
 
983
  $this->media_items_raw['props'][$key] = (object) $i;
984
- // Cache Source URI (point to properties object)
985
  $this->media_items_raw['uri'][$uri->source] = $key;
986
  }
987
  return $key;
988
  }
989
-
990
  /**
991
  * Retrieve ID for media item
992
  * @uses self::$media_items_raw
@@ -999,7 +1050,7 @@ class SLB_Lightbox extends SLB_Base {
999
  }
1000
  return null;
1001
  }
1002
-
1003
  /**
1004
  * Checks if media item has already been cached
1005
  * @param string $uri URI of media item
@@ -1008,7 +1059,7 @@ class SLB_Lightbox extends SLB_Base {
1008
  private function media_item_cached($uri) {
1009
  return ( is_string($uri) && !empty($uri) && isset($this->media_items_raw['uri'][$uri]) ) ? true : false;
1010
  }
1011
-
1012
  /**
1013
  * Retrieve cached media item
1014
  * @param string $uri Media item URI
@@ -1021,7 +1072,7 @@ class SLB_Lightbox extends SLB_Base {
1021
  }
1022
  return null;
1023
  }
1024
-
1025
  /**
1026
  * Retrieve cached media items (properties)
1027
  * @uses self::$media_items_raw
@@ -1030,17 +1081,17 @@ class SLB_Lightbox extends SLB_Base {
1030
  private function &get_cached_media_items() {
1031
  return $this->media_items_raw['props'];
1032
  }
1033
-
1034
  /**
1035
  * Check if media items have been cached
1036
  * @return boolean
1037
  */
1038
  private function has_cached_media_items() {
1039
- return ( empty($this->media_items_raw['props']) ) ? false : true;
1040
  }
1041
-
1042
  /*-** Exclusion **-*/
1043
-
1044
  /**
1045
  * Retrieve exclude object
1046
  * Initialize object properties if necessary
@@ -1058,11 +1109,11 @@ class SLB_Lightbox extends SLB_Base {
1058
  }
1059
  return $this->exclude;
1060
  }
1061
-
1062
  /**
1063
  * Get exclusion tags (open/close)
1064
  * Example: open => [slb_exclude], close => [/slb_exclude]
1065
- *
1066
  * @return object Exclusion tags
1067
  */
1068
  private function get_exclude_tags() {
@@ -1078,11 +1129,11 @@ class SLB_Lightbox extends SLB_Base {
1078
  }
1079
  return $tags;
1080
  }
1081
-
1082
  /**
1083
  * Get exclusion tag ("[slb_exclude]")
1084
  * @uses `get_exclude_tags()` to retrieve tag
1085
- *
1086
  * @param string $type (optional) Tag to retrieve (open or close)
1087
  * @return string Exclusion tag
1088
  */
@@ -1094,7 +1145,7 @@ class SLB_Lightbox extends SLB_Base {
1094
  }
1095
  return $tags->{$type};
1096
  }
1097
-
1098
  /**
1099
  * Build exclude placeholder
1100
  * @return object Exclude placeholder properties
@@ -1121,7 +1172,7 @@ class SLB_Lightbox extends SLB_Base {
1121
  }
1122
  return $ph;
1123
  }
1124
-
1125
  /**
1126
  * Wrap content in exclusion tags
1127
  * @uses `get_exclude_tag()` to wrap content with exclusion tag
@@ -1137,7 +1188,7 @@ class SLB_Lightbox extends SLB_Base {
1137
  $tags = $this->get_exclude_tags();
1138
  return $tags->open . $content . $tags->close;
1139
  }
1140
-
1141
  /**
1142
  * Remove excluded content
1143
  * Caches content for restoring later
@@ -1156,7 +1207,7 @@ class SLB_Lightbox extends SLB_Base {
1156
  $cache =& $ex->cache[$group];
1157
 
1158
  $content = $this->util->apply_filters('pre_exclude_content', $content);
1159
-
1160
  // Search content
1161
  $matches = null;
1162
  if ( false !== strpos($content, $ex->tags->open) && preg_match_all($ex->tags->search, $content, $matches) ) {
@@ -1174,14 +1225,14 @@ class SLB_Lightbox extends SLB_Base {
1174
  unset($midx, $match);
1175
  // Replace content with placeholder
1176
  $content = str_replace($matches[0], $ph, $content);
1177
-
1178
  // Cleanup
1179
  unset($matches, $ph);
1180
  }
1181
-
1182
  return $content;
1183
  }
1184
-
1185
  /**
1186
  * Exclude shortcodes from link activation
1187
  * @param string $content Content to exclude shortcodes from
@@ -1194,11 +1245,11 @@ class SLB_Lightbox extends SLB_Base {
1194
  $shortcodes = array_fill_keys($shortcodes, $this->m('exclude_shortcodes_handler'));
1195
  return $this->util->do_shortcode($content, $shortcodes);
1196
  }
1197
-
1198
  /**
1199
  * Wrap shortcode in exclude tags
1200
  * @uses Util->make_shortcode() to rebuild original shortcode
1201
- *
1202
  * @param array $attr Shortcode attributes
1203
  * @param string $content Content enclosed in shortcode
1204
  * @param string $tag Shortcode name
@@ -1209,7 +1260,7 @@ class SLB_Lightbox extends SLB_Base {
1209
  // Exclude shortcode
1210
  return $this->exclude_wrap($code);
1211
  }
1212
-
1213
  /**
1214
  * Restore excluded content
1215
  * @param string $content Content to restore excluded content to
@@ -1226,7 +1277,7 @@ class SLB_Lightbox extends SLB_Base {
1226
  return $content;
1227
  }
1228
  $cache =& $ex->cache[$group];
1229
-
1230
  // Search content for placeholders
1231
  $matches = null;
1232
  if ( false !== strpos($content, $ex->ph->open . $ex->ph->base) && preg_match_all($ex->ph->search, $content, $matches) ) {
@@ -1247,12 +1298,12 @@ class SLB_Lightbox extends SLB_Base {
1247
  // Cleanup
1248
  unset($idx, $ph, $matches, $key);
1249
  }
1250
-
1251
  return $content;
1252
  }
1253
-
1254
  /*-** Grouping **-*/
1255
-
1256
  /**
1257
  * Builds wrapper for grouping
1258
  * @return string Format for wrapping content in group
@@ -1264,7 +1315,7 @@ class SLB_Lightbox extends SLB_Base {
1264
  }
1265
  return $fmt;
1266
  }
1267
-
1268
  /**
1269
  * Wraps shortcodes for automatic grouping
1270
  * @uses `the_content` Filter hook
@@ -1283,7 +1334,7 @@ class SLB_Lightbox extends SLB_Base {
1283
  // Process gallery shortcodes
1284
  return $this->util->do_shortcode($content, $shortcodes);
1285
  }
1286
-
1287
  /**
1288
  * Groups shortcodes for later processing
1289
  * @param array $attr Shortcode attributes
@@ -1296,7 +1347,7 @@ class SLB_Lightbox extends SLB_Base {
1296
  // Wrap shortcode
1297
  return sprintf( $this->group_get_wrapper(), $code);
1298
  }
1299
-
1300
  /**
1301
  * Activate groups in content
1302
  * @param string $content Content to activate
@@ -1326,9 +1377,9 @@ class SLB_Lightbox extends SLB_Base {
1326
  }
1327
  return $this->process_links($content, $group);
1328
  }
1329
-
1330
  /*-** Widgets **-*/
1331
-
1332
  /**
1333
  * Set widget up for processing/activation
1334
  * Buffers widget output for further processing
@@ -1350,7 +1401,7 @@ class SLB_Lightbox extends SLB_Base {
1350
  // Begin output buffer
1351
  ob_start();
1352
  }
1353
-
1354
  /**
1355
  * Handles inter-widget processing
1356
  * After widget output generated, Before next widget starts
@@ -1360,7 +1411,7 @@ class SLB_Lightbox extends SLB_Base {
1360
  $this->widget_process_finish();
1361
  return $params;
1362
  }
1363
-
1364
  /**
1365
  * Complete widget processing
1366
  * Activate widget output
@@ -1380,7 +1431,7 @@ class SLB_Lightbox extends SLB_Base {
1380
  }
1381
  // Activate widget output
1382
  $out = $this->activate_links(ob_get_clean());
1383
-
1384
  // Clear grouping callback
1385
  if ( $this->options->get_bool('group_widget') ) {
1386
  $this->util->remove_filter('get_group_id', $this->m('widget_group_id'));
@@ -1391,7 +1442,7 @@ class SLB_Lightbox extends SLB_Base {
1391
  // Output widget
1392
  echo $out;
1393
  }
1394
-
1395
  /**
1396
  * Add widget ID to link group ID
1397
  * Widget ID precedes all other group segments
@@ -1406,7 +1457,7 @@ class SLB_Lightbox extends SLB_Base {
1406
  }
1407
  return $group_segments;
1408
  }
1409
-
1410
  /**
1411
  * Handles nested activation in widgets
1412
  * @uses widget_processing
@@ -1418,11 +1469,11 @@ class SLB_Lightbox extends SLB_Base {
1418
  if ( !$this->widget_processing ) {
1419
  return;
1420
  }
1421
-
1422
  // Increment nesting level
1423
  $this->widget_processing_level++;
1424
  }
1425
-
1426
  /**
1427
  * Mark the end of a nested widget
1428
  * @uses $widget_processing_level
@@ -1433,7 +1484,7 @@ class SLB_Lightbox extends SLB_Base {
1433
  $this->widget_processing_level--;
1434
  }
1435
  }
1436
-
1437
  /**
1438
  * Begin blocking widget activation
1439
  * @return void
@@ -1441,7 +1492,7 @@ class SLB_Lightbox extends SLB_Base {
1441
  public function widget_block_start() {
1442
  $this->util->add_filter('is_content_valid', $this->m('widget_block_handle'));
1443
  }
1444
-
1445
  /**
1446
  * Stop blocking widget activation
1447
  * @return void
@@ -1449,16 +1500,16 @@ class SLB_Lightbox extends SLB_Base {
1449
  public function widget_block_finish() {
1450
  $this->util->remove_filter('is_content_valid', $this->m('widget_block_handle'));
1451
  }
1452
-
1453
  /**
1454
  * Handle widget activation blocking
1455
  */
1456
  public function widget_block_handle($is_content_valid) {
1457
  return false;
1458
  }
1459
-
1460
  /*-** Menus **-*/
1461
-
1462
  /**
1463
  * Process navigation menu links
1464
  *
@@ -1482,16 +1533,16 @@ class SLB_Lightbox extends SLB_Base {
1482
  } else {
1483
  $group = null;
1484
  }
1485
-
1486
  // Process menu
1487
  $nav_menu = $this->activate_links($nav_menu, $group);
1488
-
1489
  return $nav_menu;
1490
  }
1491
-
1492
  /**
1493
  * Generate unique group ID
1494
- *
1495
  * @param string $group Group ID to check
1496
  * @return string Unique group ID
1497
  */
@@ -1506,7 +1557,7 @@ class SLB_Lightbox extends SLB_Base {
1506
  }
1507
  return $group;
1508
  }
1509
-
1510
  /*-** Helpers **-*/
1511
 
1512
  /**
@@ -1551,10 +1602,10 @@ class SLB_Lightbox extends SLB_Base {
1551
  }
1552
  // Add attribute
1553
  $attrs = array_merge($attrs, array( $this->make_attribute_name($name) => strval($value) ));
1554
-
1555
  return $attrs;
1556
  }
1557
-
1558
  /**
1559
  * Convert attribute string into array
1560
  * @param string $attr_string Attribute string
@@ -1578,10 +1629,10 @@ class SLB_Lightbox extends SLB_Base {
1578
  $ret = $ret_f;
1579
  }
1580
  }
1581
-
1582
  return $ret;
1583
  }
1584
-
1585
  /**
1586
  * Retrieve attribute value
1587
  * @param string|array $attrs Attributes to retrieve attribute value from
@@ -1601,7 +1652,7 @@ class SLB_Lightbox extends SLB_Base {
1601
  }
1602
  return $ret;
1603
  }
1604
-
1605
  /**
1606
  * Checks if attribute exists
1607
  * If supplied, the attribute's value is also validated
@@ -1630,7 +1681,7 @@ class SLB_Lightbox extends SLB_Base {
1630
  }
1631
  return $ret;
1632
  }
1633
-
1634
  /**
1635
  * Build JS object of UI strings when initializing lightbox
1636
  * @return array UI strings
1
+ <?php
2
  /**
3
  * Controller
4
  * @package Simple Lightbox
5
  * @author Archetyped
6
  */
7
  class SLB_Lightbox extends SLB_Base {
8
+
9
  /*-** Properties **-*/
10
+
11
  protected $model = true;
12
+
13
  /**
14
  * Fields
15
  * @var SLB_Fields
16
  */
17
  public $fields = null;
18
+
19
  /**
20
  * Themes collection
21
  * @var SLB_Themes
22
  */
23
  var $themes = null;
24
+
25
  /**
26
  * Content types
27
  * @var SLB_Content_Handlers
28
  */
29
  var $handlers = null;
30
+
31
  /**
32
  * Template tags
33
  * @var SLB_Template_Tags
35
  var $template_tags = null;
36
 
37
  /**
38
+ * Media item template.
39
+ *
40
+ * @var array {
41
+ * Media item properties.
42
+ *
43
+ * @type int $id WP post ID. Default null.
44
+ * @type string $type Item type. Default null.
45
+ * @type string $source Source URI.
46
+ * @type bool $internal Internal resource. Default false.
47
+ * @type string $title Item title.
48
+ * @type string $caption Item caption.
49
+ * @type string $description Item description.
50
+ * @type array $media {
51
+ * Media properties (indexed by size name).
52
+ * Original size = 'full'.
53
+ *
54
+ * @type string $file File URI.
55
+ * @type int $width File width in pixels.
56
+ * @type int $height File height in pixels.
57
+ * }
58
+ * @type array $meta {
59
+ * Item metadata.
60
+ * }
61
+ * }
62
+ */
63
+ private $media_item_template = [
64
+ 'id' => null,
65
+ 'type' => null,
66
+ 'internal' => false,
67
+ 'source' => '',
68
+ /* @future: Metadata
69
+ 'media' => [],
70
+ 'meta' => []
71
+ END @future: Metadata */
72
+ ];
73
+
74
+ /**
75
+ * Processed media items for output to client.
76
+ *
77
+ * @var object[string] {
78
+ * Media item properties.
79
+ *
80
+ * @index string Unique ID (system-generated).
81
+ *
82
+ * @see $media_item_template.
83
+ * }
84
  */
85
+ private $media_items = [];
86
+
87
+ /**
88
+ * Collection of unprocessed media items.
89
+ *
90
+ * @var array {
91
+ * @type object[string] $props {
92
+ * Media item properties.
93
+ *
94
+ * @index string Unique ID (system-generated).
95
+ *
96
+ * @see $media_item_template
97
+ * }
98
+ * @type string[string] $uri {
99
+ * Cached URIs.
100
+ *
101
+ * @index string URI.
102
+ *
103
+ * @type string Item ID (points to item in `props` array)
104
+ * }
105
+ * }
106
  */
107
+ private $media_items_raw = [ 'props' => [], 'uri' => [] ];
108
+
109
  /**
110
  * Manage excluded content
111
  * @var object
112
  */
113
  private $exclude = null;
114
+
115
  private $groups = array (
116
  'auto' => 0,
117
  'manual' => array(),
118
  );
119
+
120
  /**
121
  * Validated URIs
122
  * Caches validation of parsed URIs
125
  * @var array
126
  */
127
  private $validated_uris = array();
128
+
129
  /* Widget properties */
130
+
131
  /**
132
  * Used to track if widget is currently being processed or not
133
  * Set to Widget ID currently being processed
134
  * @var bool|string
135
  */
136
  private $widget_processing = false;
137
+
138
  /**
139
  * Parameters for widget being processed
140
  * @param array
141
  */
142
  private $widget_processing_params = null;
143
+
144
  /**
145
  * Manage nested widget processing
146
  * Used to avoid premature widget output
150
 
151
  /**
152
  * Constructor
153
+ */
154
  public function __construct() {
155
  parent::__construct();
156
  // Init instances
160
  $this->template_tags = new SLB_Template_Tags($this);
161
  }
162
  }
163
+
164
  /* Init */
165
+
166
  public function _init() {
167
  parent::_init();
168
  $this->util->do_action('init');
169
  }
170
+
171
  /**
172
  * Declare client files (scripts, styles)
173
  * @uses parent::_client_files()
200
  );
201
  parent::_client_files($files);
202
  }
203
+
204
  /**
205
  * Register hooks
206
  * @uses parent::_hooks()
211
  /* Admin */
212
  add_action('admin_menu', $this->m('admin_menus'));
213
  $this->util->add_filter('admin_plugin_row_meta_support', $this->m('admin_plugin_row_meta_support'));
214
+
215
  /* Init */
216
  add_action('wp', $this->m('_hooks_init'));
217
  }
218
+
219
  /**
220
  * Init Hooks
221
  */
222
  public function _hooks_init() {
223
  if ( $this->is_enabled() ) {
224
  $priority = $this->util->priority('low');
225
+
226
  // Init lightbox
227
  add_action('wp_footer', $this->m('client_footer'));
228
  $this->util->add_action('footer_script', $this->m('client_init'), 1);
236
  $this->util->add_filter('pre_process_links', $this->m('exclude_content'));
237
  $this->util->add_filter('pre_exclude_content', $this->m('exclude_shortcodes'));
238
  $this->util->add_filter('post_process_links', $this->m('restore_excluded_content'));
239
+
240
  // Grouping
241
  if ( $this->options->get_bool('group_post') ) {
242
+ $this->util->add_filter('get_group_id', $this->m('post_group_id'), 1);
243
  }
244
+
245
  // Shortcode grouping
246
  if ( $this->options->get_bool('group_gallery') ) {
247
  add_filter('the_content', $this->m('group_shortcodes'), 1);
248
  }
249
+
250
  // Widgets
251
  if ( $this->options->get_bool('enabled_widget') ) {
252
  add_action('dynamic_sidebar_before', $this->m('widget_process_nested'));
258
  add_action('dynamic_sidebar_before', $this->m('widget_block_start'));
259
  add_action('dynamic_sidebar_after', $this->m('widget_block_finish'));
260
  }
261
+
262
  // Menus
263
  if ( $this->options->get_bool('enabled_menu') ) {
264
  add_filter('wp_nav_menu', $this->m('menu_process'), $priority, 2);
282
  }
283
  return $group_segments;
284
  }
285
+
286
  /**
287
  * Init options
288
  */
314
  'slideshow_duration' => array('title' => __('Slide Duration (Seconds)', 'simple-lightbox'), 'default' => '6', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => array('ui', 40), 'in_client' => true),
315
  'group_loop' => array('title' => __('Loop through items', 'simple-lightbox'),'default' => true, 'group' => array('ui', 50), 'in_client' => true),
316
  'ui_overlay_opacity' => array('title' => __('Overlay Opacity (0 - 1)', 'simple-lightbox'), 'default' => '0.8', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => array('ui', 60), 'in_client' => true),
317
+ 'ui_title_default' => array('title' => __('Enable default title', 'simple-lightbox'), 'default' => false, 'group' => array('ui', 70), 'in_client' => true),
318
  'txt_loading' => array('title' => __('Loading indicator', 'simple-lightbox'), 'default' => 'Loading', 'group' => array('labels', 20)),
319
  'txt_close' => array('title' => __('Close button', 'simple-lightbox'), 'default' => 'Close', 'group' => array('labels', 10)),
320
  'txt_nav_next' => array('title' => __('Next Item button', 'simple-lightbox'), 'default' => 'Next', 'group' => array('labels', 30)),
348
  'txt_closeLink' => 'txt_link_close',
349
  'txt_nextLink' => 'txt_link_next',
350
  'txt_prevLink' => 'txt_link_prev',
351
+ 'txt_startSlideshow' => 'txt_slideshow_start',
352
  'txt_stopSlideshow' => 'txt_slideshow_stop',
353
  'txt_loadingMsg' => 'txt_loading',
354
  'txt_link_next' => 'txt_nav_next',
356
  'txt_link_close' => 'txt_close',
357
  )
358
  );
359
+
360
  parent::_set_options($opts);
361
  }
362
 
363
  /* Methods */
364
+
365
  /*-** Admin **-*/
366
 
367
  /**
378
  $pg_opts = $this->admin->add_theme_page('options', $lbls_opts)
379
  ->require_form()
380
  ->add_content('options', 'Options', $this->options);
381
+
382
  // Add Support information
383
  $support = $this->util->get_plugin_info('SupportURI');
384
  if ( !empty($support) ) {
385
  $pg_opts->add_content('support', __('Feedback & Support', 'simple-lightbox'), $this->m('theme_page_callback_support'), 'secondary');
386
  }
387
+
388
  // Add Actions
389
  $lbls_reset = array (
390
  'title' => __('Reset', 'simple-lightbox'),
394
  );
395
  $this->admin->add_action('reset', $lbls_reset, $this->options);
396
  }
397
+
398
  /**
399
  * Support information
400
  */
407
  $lnk_txt = __('Get Support &amp; Provide Feedback', 'simple-lightbox');
408
  echo $this->util->build_html_link($lnk_uri, $lnk_txt, array('target' => '_blank', 'class' => 'button'));
409
  }
410
+
411
  /**
412
  * Filter support link text in plugin metadata
413
  * @param string $text Original link text
418
  }
419
 
420
  /*-** Functionality **-*/
421
+
422
  /**
423
  * Checks whether lightbox is currently enabled/disabled
424
  * @return bool TRUE if lightbox is currently enabled, FALSE otherwise
452
  // Return value (force boolean)
453
  return !!$ret;
454
  }
455
+
456
  /**
457
  * Make sure content is valid for processing/activation
458
+ *
459
  * @param string $content Content to validate
460
  * @return bool TRUE if content is valid (FALSE otherwise)
461
  */
467
  // Non-string value
468
  if ( !is_string($content) )
469
  return false;
470
+
471
  // Empty string
472
  $content = trim($content);
473
  if ( empty($content) )
474
  return false;
475
+
476
  // Content is valid
477
  return $this->util->apply_filters('is_content_valid', true, $content);
478
  }
479
+
480
  /**
481
  * Activates galleries extracted from post
482
  * @see get_post_galleries()
493
  if ( is_array($gallery) ) {
494
  return $galleries;
495
  }
496
+
497
  // Activate galleries
498
  $group = ( $this->options->get_bool('group_gallery') ) ? true : null;
499
  foreach ( $galleries as $key => $val ) {
502
  }
503
  // Activate links in gallery
504
  $gallery = $this->process_links($val, $group);
505
+
506
  // Save modified gallery
507
  $galleries[$key] = $gallery;
508
  }
509
+
510
  return $galleries;
511
  }
512
+
513
  /**
514
  * Scans post content for image links and activates them
515
+ *
516
  * Lightbox will not be activated for feeds
517
  * @param string $content Content to activate
518
  * @param string (optonal) $group Group ID for content
525
  }
526
  // Filter content before processing links
527
  $content = $this->util->apply_filters('pre_process_links', $content);
528
+
529
  // Process links
530
  $content = $this->process_links($content, $group);
531
+
532
  // Filter content after processing links
533
  $content = $this->util->apply_filters('post_process_links', $content);
534
+
535
  return $content;
536
  }
537
+
538
  /**
539
  * Process links in content
540
  * @global obj $wpdb DB instance
541
  * @global obj $post Current post
542
  * @param string $content Text containing links
543
  * @param string (optional) $group Group to add links to (Default: none)
544
+ * @return string Content with processed links
545
  */
546
  protected function process_links($content, $group = null) {
547
  // Extract links
563
  $uri_proto = (object) array('raw' => '', 'source' => '', 'parts' => '');
564
  }
565
  $uri_parts_required = array('host' => '');
566
+
567
  // Setup group properties
568
  $g_props = (object) array(
569
  'enabled' => $this->options->get_bool('group_links'),
575
  if ( $g_props->enabled ) {
576
  $g_props->base = ( is_scalar($group) ) ? trim(strval($group)) : '';
577
  }
578
+
579
  // Initialize content handlers
580
  if ( !( $this->handlers instanceof SLB_Content_Handlers ) ) {
581
  $this->handlers = new SLB_Content_Handlers($this);
582
  }
583
+
584
  // Iterate through and activate supported links
585
+
586
  foreach ( $links as $link ) {
587
  // Init vars
588
  $pid = 0;
592
  $props_extra = array();
593
  $key = null;
594
  $internal = false;
595
+
596
  // Parse link attributes
597
  $attrs = $this->util->parse_attribute_string($link_new, array('href' => ''));
598
  // Get URI
599
  $uri->raw = $attrs['href'];
600
+
601
  // Stop processing invalid links
602
  if ( !$this->validate_uri($uri->raw)
603
  || $this->has_attribute($attrs, 'active', false) // Previously-processed
604
  ) {
605
  continue;
606
  }
607
+
608
  // Normalize URI (make absolute)
609
  $uri->source = WP_HTTP::make_absolute_url($uri->raw, $uri_origin['scheme'] . '://' . $uri_origin['host']);
610
+
611
  // URI cached?
612
  $key = $this->get_media_item_id($uri->source);
613
+
614
  // Internal URI? (e.g. attachments)
615
  if ( !$key ) {
616
  $uri->parts = array_merge( $uri_parts_required, (array) parse_url($uri->source) );
617
  $internal = ( $uri->parts['host'] === $uri_origin['host'] ) ? true : false;
618
+
619
  // Attachment?
620
  if ( $internal && is_local_attachment($uri->source) ) {
621
  $pid = url_to_postid($uri->source);
629
  unset($src);
630
  }
631
  }
632
+
633
  // Determine content type
634
  if ( !$key ) {
635
  // Get handler match
643
  unset($props_extra['uri']);
644
  }
645
  }
646
+
647
  // Cache valid item
648
  if ( !!$type ) {
649
  $key = $this->cache_media_item($uri, $type, $internal, $props_extra);
650
  }
651
  }
652
+
653
  // Stop processing invalid links
654
  if ( !$key ) {
655
  // Cache invalid URI
656
  $this->validated_uris[$uri->source] = false;
657
  if ( $uri->raw !== $uri->source ) {
658
+ $this->validated_uris[$uri->raw] = false;
659
  }
660
  continue;
661
  }
662
+
663
  // Activate link
664
  $this->set_attribute($attrs, 'active');
665
  $this->set_attribute($attrs, 'asset', $key);
667
  if ( $internal ) {
668
  $this->set_attribute($attrs, 'internal', $pid);
669
  }
670
+
671
  // Set group (if enabled)
672
  if ( $g_props->enabled ) {
673
  $group = array();
678
  } elseif ( !empty($g_props->base) ) {
679
  $group[] = $g_props->base;
680
  }
681
+
682
  /**
683
  * Filter group ID components
684
+ *
685
  * @see process_links()
686
+ *
687
  * @param array $group Components used to build group ID
688
  */
689
  $group = $this->util->apply_filters('get_group_id', $group);
690
+
691
  // Default group
692
  if ( empty($group) || !is_array($group) ) {
693
  $group = $this->get_prefix();
694
  } else {
695
  $group = implode('_', $group);
696
  }
697
+
698
  // Set group attribute
699
  $this->set_attribute($attrs, $g_props->attr, $group);
700
  unset($g);
701
  }
702
+
703
  // Filter attributes
704
  $attrs = $this->util->apply_filters('process_link_attributes', $attrs);
705
+
706
  // Update link in content
707
  $link_new = '<a ' . $this->util->build_attribute_string($attrs) . '>';
708
  $content = str_replace($link, $link_new, $content);
712
  if ( !!$this->widget_processing && 'the_content' == current_filter() ) {
713
  $content = $this->exclude_wrap($content);
714
  }
715
+
716
  return $content;
717
  }
718
 
723
  * @return array Links in content
724
  */
725
  function get_links($content, $unique = false) {
726
+ $rgx = "/\<a\b(?:(?!\shref=|\>).)*\shref=[^\>\<]++\>/i";
727
+ $links = [];
728
  preg_match_all($rgx, $content, $links);
729
  $links = $links[0];
730
  if ( $unique )
731
  $links = array_unique($links);
732
  return $links;
733
  }
734
+
735
  /**
736
  * Validate URI
737
  * Matches specified URI against internal & external regex patterns
738
  * URI is **invalid** if it matches a regex
739
+ *
740
  * @param string $uri URI to validate
741
  * @return bool TRUE if URI is valid
742
  */
758
  // Get patterns
759
  if ( is_null($patterns) ) {
760
  $patterns = $this->util->apply_filters('validate_uri_regex', array());
761
+ }
762
  // Iterate through patterns until match found
763
  foreach ( $patterns as $pattern ) {
764
  if ( 1 === preg_match($pattern, $uri) ) {
767
  }
768
  }
769
  }
770
+
771
  // Cache
772
  $this->validated_uris[$uri] = $valid;
773
  return $valid;
774
  }
775
+
776
  /**
777
  * Add URI validation regex pattern
778
+ * @param
779
  */
780
  public function validate_uri_regex_default($patterns) {
781
  $patterns[] = '@^https?://[^/]*(wikipedia|wikimedia)\.org/wiki/file:.*$@i';
782
  return $patterns;
783
+ }
784
+
785
  /* Client */
786
+
787
  /**
788
  * Checks if output should be loaded in current request
789
  * @uses `is_enabled()`
793
  public function is_request_valid() {
794
  return ( $this->is_enabled() && $this->has_cached_media_items() ) ? true : false;
795
  }
796
+
797
  /**
798
  * Sets options/settings to initialize lightbox functionality on page load
799
  * @return void
801
  function client_init($client_script) {
802
  // Get options
803
  $options = $this->options->build_client_output();
804
+
805
  // Load UI Strings
806
  if ( ($labels = $this->build_labels()) && !empty($labels) ) {
807
  $options['ui_labels'] = $labels;
808
  }
809
+
810
  // Build client output
811
  $client_script[] = $this->util->call_client_method('View.init', $options);
812
  return $client_script;
813
  }
814
+
815
  /**
816
  * Output code in footer
817
  * > Media attachment URLs
821
  function client_footer() {
822
  if ( !$this->has_cached_media_items() )
823
  return false;
824
+
825
  // Set up hooks
826
  add_action('wp_print_footer_scripts', $this->m('client_footer_script'));
827
+
828
  // Build client output
829
  $this->util->do_action('footer');
830
  }
831
+
832
  /**
833
  * Output client footer scripts
834
  */
838
  echo $this->util->build_script_element($client_script, 'footer', true, true);
839
  }
840
  }
841
+
842
  /**
843
  * Add media information to client output
844
+ *
845
+ * @param array $client_script Client script commands.
846
+ * @return array Modified script commands.
847
  * TODO Refactor
848
  */
849
+ public function client_script_media($client_script) {
850
  global $wpdb;
851
+
852
+ // Init.
853
+ $this->media_items = $this->get_cached_media_items();
854
+
855
+ // Extract internal links for additional processing.
856
+ $m_internals = [];
857
+ foreach ( $this->media_items as $key => $p ) {
858
+ if ( $p->internal ) {
859
+ $m_internals[$key] =& $this->media_items[$key];
 
 
 
 
 
 
 
860
  }
861
  }
862
+ // Cleanup.
863
  unset($key, $p);
864
+
865
+ // Process internal links.
866
  if ( !empty($m_internals) ) {
867
+ $uris_base = [];
868
  $uri_prefix = wp_upload_dir();
869
  $uri_prefix = $this->util->normalize_path($uri_prefix['baseurl'], true);
870
  foreach ( $m_internals as $key => $p ) {
871
+ // Prepare internal links.
872
+ // Create relative URIs for attachment data retrieval.
873
  if ( !$p->id && strpos($p->source, $uri_prefix) === 0 ) {
874
  $uris_base[str_replace($uri_prefix, '', $p->source)] = $key;
875
  }
876
  }
877
+ // Cleanup.
878
  unset($key, $p);
879
+
880
+ // Retrieve attachment IDs.
881
  $uris_flat = "('" . implode("','", array_keys($uris_base)) . "')";
882
  $q = $wpdb->prepare("SELECT post_id, meta_value FROM $wpdb->postmeta WHERE `meta_key` = %s AND LOWER(`meta_value`) IN $uris_flat LIMIT %d", '_wp_attached_file', count($uris_base));
883
  $pids = $wpdb->get_results($q);
884
+ // Match IDs to URIs.
885
  if ( $pids ) {
886
  foreach ( $pids as $pd ) {
887
  $file =& $pd->meta_value;
888
  if ( isset($uris_base[$file]) ) {
889
+ $m_internals[ $uris_base[$file] ]->id = absint($pd->post_id);
890
  }
891
  }
892
  }
893
+ // Cleanup.
894
  unset($uris_base, $uris_flat, $q, $pids, $pd, $file);
895
  }
896
+
897
+ // Process items with attachment IDs.
898
+ $pids = [];
899
+ foreach ( $this->media_items as $key => $p ) {
900
+ // Add post ID to query.
901
  if ( !!$p->id ) {
902
+ // Create array for ID (support multiple URIs per ID).
903
  if ( !isset($pids[$p->id]) ) {
904
+ $pids[$p->id] = [];
905
  }
906
+ // Add URI to ID.
907
  $pids[$p->id][] = $key;
908
  }
909
  }
910
+ // Cleanup.
911
  unset($key, $p);
912
+
913
+ // Retrieve attachment properties.
914
  if ( !empty($pids) ) {
915
  $pids_flat = array_keys($pids);
916
+ // Retrieve attachment post data.
917
  $atts = get_posts(array('post_type' => 'attachment', 'include' => $pids_flat));
918
+
919
+ // Process attachments.
920
  if ( $atts ) {
921
+ /* @future: Metadata
922
+ // Retrieve attachment metadata.
923
  $pids_flat = "('" . implode("','", $pids_flat) . "')";
924
  $atts_meta = $wpdb->get_results($wpdb->prepare("SELECT `post_id`,`meta_value` FROM $wpdb->postmeta WHERE `post_id` IN $pids_flat AND `meta_key` = %s LIMIT %d", '_wp_attachment_metadata', count($atts)));
925
+ // Reindex metadata array by attachment ID.
926
  if ( $atts_meta ) {
927
+ $meta = [];
928
  foreach ( $atts_meta as $att_meta ) {
929
  $meta[$att_meta->post_id] = $att_meta->meta_value;
930
  }
931
  $atts_meta = $meta;
932
+ // Cleanup.
933
  unset($meta);
934
  } else {
935
+ $atts_meta = [];
936
  }
937
+ END @future: Metadata */
938
+
939
+ /* @future: Metadata
940
+ // Process attachment data.
941
+ $media_props = array('file', 'width', 'height');
942
+ $media_original_name = 'full';
943
+ END @future: Metadata */
944
+
945
+ $props_post_map = [ 'title' => 'post_title', 'caption' => 'post_excerpt', 'description' => 'post_content' ];
946
+
947
  foreach ( $atts as $att ) {
948
+ $data = [];
949
+ /* @future: Metadata
950
+ $data = [ 'meta' => [], 'media' => [ $media_original_name => [] ] ];
951
+ END @future: Metadata */
952
+ // Remap post data to metadata.
953
+ foreach ( $props_post_map as $props_post_key => $props_post_source ) {
954
+ $data[$props_post_key] = $att->{$props_post_source};
955
  }
956
+ // Cleanup.
957
+ unset($props_post_key, $props_post_source);
 
 
 
 
 
 
 
 
 
 
958
 
959
+ /* @future: Metadata
960
+ // Process metadata.
961
+ if ( isset( $atts_meta[$att->ID] ) && ( $a = unserialize( $atts_meta[$att->ID] ) ) && is_array( $a ) ) {
962
+ // Media properties.
963
+ // Source file.
964
+ foreach ( $media_props as $d ) {
965
  if ( isset($a[$d]) ) {
966
+ $data['media'][$media_original_name][$d] = $a[$d];
967
  }
968
  }
969
+ // Cleanup.
970
+ unset( $a, $d );
 
 
 
971
  }
972
+ END @future: Metadata */
973
+ // Save data to corresponding media item(s).
974
  if ( isset($pids[$att->ID]) ) {
975
  foreach ( $pids[$att->ID] as $key ) {
976
+ $this->media_items[$key] = (object) array_merge( (array) $this->media_items[$key], $data );
977
  }
978
  }
979
  }
980
+ // Cleanup.
981
+ unset($att, $data);
982
  }
983
+ // Cleanup.
984
  unset($atts, $atts_meta, $m, $a, $uri, $pids, $pids_flat);
985
  }
986
 
987
+ // Filter media items.
988
+ $this->media_items = $this->util->apply_filters('media_items', $this->media_items);
 
 
989
 
990
+ // Build client output.
991
  $obj = 'View.assets';
992
  $client_script[] = $this->util->extend_client_object($obj, $this->media_items);
993
  return $client_script;
994
  }
995
 
996
  /*-** Media **-*/
997
+
998
  /**
999
  * Cache media properties for later processing
1000
  * @uses array self::$media_items_raw Stores media items for output
1008
  * @return string Unique ID for cached media item
1009
  */
1010
  private function cache_media_item($uri, $type, $internal, $props = null) {
1011
+ // Validate.
1012
  if ( !is_object($uri) || !is_string($type) ) {
1013
  return false;
1014
  }
1015
+ // Check if URI already cached.
1016
  $key = $this->get_media_item_id($uri->source);
1017
+ // Cache new item.
1018
  if ( null == $key ) {
1019
+ // Generate Unique ID.
1020
  do {
1021
  $key = (string) mt_rand();
1022
  } while ( isset($this->media_items_raw['props'][$key]) );
1023
+ // Build properties object.
1024
+ $i = $this->media_item_template;
1025
  if ( is_array($props) && !empty($props) ) {
1026
  $i = array_merge($i, $props);
1027
  }
1028
+ $i = array_merge( $i, [
1029
+ 'type' => $type,
1030
+ 'source' => $uri->source,
1031
+ 'internal' => $internal,
1032
+ ] );
1033
+ // Cache item properties.
1034
  $this->media_items_raw['props'][$key] = (object) $i;
1035
+ // Cache Source URI (point to properties object).
1036
  $this->media_items_raw['uri'][$uri->source] = $key;
1037
  }
1038
  return $key;
1039
  }
1040
+
1041
  /**
1042
  * Retrieve ID for media item
1043
  * @uses self::$media_items_raw
1050
  }
1051
  return null;
1052
  }
1053
+
1054
  /**
1055
  * Checks if media item has already been cached
1056
  * @param string $uri URI of media item
1059
  private function media_item_cached($uri) {
1060
  return ( is_string($uri) && !empty($uri) && isset($this->media_items_raw['uri'][$uri]) ) ? true : false;
1061
  }
1062
+
1063
  /**
1064
  * Retrieve cached media item
1065
  * @param string $uri Media item URI
1072
  }
1073
  return null;
1074
  }
1075
+
1076
  /**
1077
  * Retrieve cached media items (properties)
1078
  * @uses self::$media_items_raw
1081
  private function &get_cached_media_items() {
1082
  return $this->media_items_raw['props'];
1083
  }
1084
+
1085
  /**
1086
  * Check if media items have been cached
1087
  * @return boolean
1088
  */
1089
  private function has_cached_media_items() {
1090
+ return ( empty($this->media_items_raw['props']) ) ? false : true;
1091
  }
1092
+
1093
  /*-** Exclusion **-*/
1094
+
1095
  /**
1096
  * Retrieve exclude object
1097
  * Initialize object properties if necessary
1109
  }
1110
  return $this->exclude;
1111
  }
1112
+
1113
  /**
1114
  * Get exclusion tags (open/close)
1115
  * Example: open => [slb_exclude], close => [/slb_exclude]
1116
+ *
1117
  * @return object Exclusion tags
1118
  */
1119
  private function get_exclude_tags() {
1129
  }
1130
  return $tags;
1131
  }
1132
+
1133
  /**
1134
  * Get exclusion tag ("[slb_exclude]")
1135
  * @uses `get_exclude_tags()` to retrieve tag
1136
+ *
1137
  * @param string $type (optional) Tag to retrieve (open or close)
1138
  * @return string Exclusion tag
1139
  */
1145
  }
1146
  return $tags->{$type};
1147
  }
1148
+
1149
  /**
1150
  * Build exclude placeholder
1151
  * @return object Exclude placeholder properties
1172
  }
1173
  return $ph;
1174
  }
1175
+
1176
  /**
1177
  * Wrap content in exclusion tags
1178
  * @uses `get_exclude_tag()` to wrap content with exclusion tag
1188
  $tags = $this->get_exclude_tags();
1189
  return $tags->open . $content . $tags->close;
1190
  }
1191
+
1192
  /**
1193
  * Remove excluded content
1194
  * Caches content for restoring later
1207
  $cache =& $ex->cache[$group];
1208
 
1209
  $content = $this->util->apply_filters('pre_exclude_content', $content);
1210
+
1211
  // Search content
1212
  $matches = null;
1213
  if ( false !== strpos($content, $ex->tags->open) && preg_match_all($ex->tags->search, $content, $matches) ) {
1225
  unset($midx, $match);
1226
  // Replace content with placeholder
1227
  $content = str_replace($matches[0], $ph, $content);
1228
+
1229
  // Cleanup
1230
  unset($matches, $ph);
1231
  }
1232
+
1233
  return $content;
1234
  }
1235
+
1236
  /**
1237
  * Exclude shortcodes from link activation
1238
  * @param string $content Content to exclude shortcodes from
1245
  $shortcodes = array_fill_keys($shortcodes, $this->m('exclude_shortcodes_handler'));
1246
  return $this->util->do_shortcode($content, $shortcodes);
1247
  }
1248
+
1249
  /**
1250
  * Wrap shortcode in exclude tags
1251
  * @uses Util->make_shortcode() to rebuild original shortcode
1252
+ *
1253
  * @param array $attr Shortcode attributes
1254
  * @param string $content Content enclosed in shortcode
1255
  * @param string $tag Shortcode name
1260
  // Exclude shortcode
1261
  return $this->exclude_wrap($code);
1262
  }
1263
+
1264
  /**
1265
  * Restore excluded content
1266
  * @param string $content Content to restore excluded content to
1277
  return $content;
1278
  }
1279
  $cache =& $ex->cache[$group];
1280
+
1281
  // Search content for placeholders
1282
  $matches = null;
1283
  if ( false !== strpos($content, $ex->ph->open . $ex->ph->base) && preg_match_all($ex->ph->search, $content, $matches) ) {
1298
  // Cleanup
1299
  unset($idx, $ph, $matches, $key);
1300
  }
1301
+
1302
  return $content;
1303
  }
1304
+
1305
  /*-** Grouping **-*/
1306
+
1307
  /**
1308
  * Builds wrapper for grouping
1309
  * @return string Format for wrapping content in group
1315
  }
1316
  return $fmt;
1317
  }
1318
+
1319
  /**
1320
  * Wraps shortcodes for automatic grouping
1321
  * @uses `the_content` Filter hook
1334
  // Process gallery shortcodes
1335
  return $this->util->do_shortcode($content, $shortcodes);
1336
  }
1337
+
1338
  /**
1339
  * Groups shortcodes for later processing
1340
  * @param array $attr Shortcode attributes
1347
  // Wrap shortcode
1348
  return sprintf( $this->group_get_wrapper(), $code);
1349
  }
1350
+
1351
  /**
1352
  * Activate groups in content
1353
  * @param string $content Content to activate
1377
  }
1378
  return $this->process_links($content, $group);
1379
  }
1380
+
1381
  /*-** Widgets **-*/
1382
+
1383
  /**
1384
  * Set widget up for processing/activation
1385
  * Buffers widget output for further processing
1401
  // Begin output buffer
1402
  ob_start();
1403
  }
1404
+
1405
  /**
1406
  * Handles inter-widget processing
1407
  * After widget output generated, Before next widget starts
1411
  $this->widget_process_finish();
1412
  return $params;
1413
  }
1414
+
1415
  /**
1416
  * Complete widget processing
1417
  * Activate widget output
1431
  }
1432
  // Activate widget output
1433
  $out = $this->activate_links(ob_get_clean());
1434
+
1435
  // Clear grouping callback
1436
  if ( $this->options->get_bool('group_widget') ) {
1437
  $this->util->remove_filter('get_group_id', $this->m('widget_group_id'));
1442
  // Output widget
1443
  echo $out;
1444
  }
1445
+
1446
  /**
1447
  * Add widget ID to link group ID
1448
  * Widget ID precedes all other group segments
1457
  }
1458
  return $group_segments;
1459
  }
1460
+
1461
  /**
1462
  * Handles nested activation in widgets
1463
  * @uses widget_processing
1469
  if ( !$this->widget_processing ) {
1470
  return;
1471
  }
1472
+
1473
  // Increment nesting level
1474
  $this->widget_processing_level++;
1475
  }
1476
+
1477
  /**
1478
  * Mark the end of a nested widget
1479
  * @uses $widget_processing_level
1484
  $this->widget_processing_level--;
1485
  }
1486
  }
1487
+
1488
  /**
1489
  * Begin blocking widget activation
1490
  * @return void
1492
  public function widget_block_start() {
1493
  $this->util->add_filter('is_content_valid', $this->m('widget_block_handle'));
1494
  }
1495
+
1496
  /**
1497
  * Stop blocking widget activation
1498
  * @return void
1500
  public function widget_block_finish() {
1501
  $this->util->remove_filter('is_content_valid', $this->m('widget_block_handle'));
1502
  }
1503
+
1504
  /**
1505
  * Handle widget activation blocking
1506
  */
1507
  public function widget_block_handle($is_content_valid) {
1508
  return false;
1509
  }
1510
+
1511
  /*-** Menus **-*/
1512
+
1513
  /**
1514
  * Process navigation menu links
1515
  *
1533
  } else {
1534
  $group = null;
1535
  }
1536
+
1537
  // Process menu
1538
  $nav_menu = $this->activate_links($nav_menu, $group);
1539
+
1540
  return $nav_menu;
1541
  }
1542
+
1543
  /**
1544
  * Generate unique group ID
1545
+ *
1546
  * @param string $group Group ID to check
1547
  * @return string Unique group ID
1548
  */
1557
  }
1558
  return $group;
1559
  }
1560
+
1561
  /*-** Helpers **-*/
1562
 
1563
  /**
1602
  }
1603
  // Add attribute
1604
  $attrs = array_merge($attrs, array( $this->make_attribute_name($name) => strval($value) ));
1605
+
1606
  return $attrs;
1607
  }
1608
+
1609
  /**
1610
  * Convert attribute string into array
1611
  * @param string $attr_string Attribute string
1629
  $ret = $ret_f;
1630
  }
1631
  }
1632
+
1633
  return $ret;
1634
  }
1635
+
1636
  /**
1637
  * Retrieve attribute value
1638
  * @param string|array $attrs Attributes to retrieve attribute value from
1652
  }
1653
  return $ret;
1654
  }
1655
+
1656
  /**
1657
  * Checks if attribute exists
1658
  * If supplied, the attribute's value is also validated
1681
  }
1682
  return $ret;
1683
  }
1684
+
1685
  /**
1686
  * Build JS object of UI strings when initializing lightbox
1687
  * @return array UI strings
functions.php CHANGED
@@ -7,7 +7,7 @@
7
  */
8
 
9
  /* Template Tags */
10
-
11
  /**
12
  * Activate links in user-defined content
13
  * @param string $content
7
  */
8
 
9
  /* Template Tags */
10
+
11
  /**
12
  * Activate links in user-defined content
13
  * @param string $content
grunt/phplint.js CHANGED
@@ -1,9 +1,9 @@
1
  module.exports = function(grunt) {
2
-
3
  grunt.config('phplint', {
4
  options : {
5
  phpArgs : {
6
- '-lf': null
7
  }
8
  },
9
  all : {
1
  module.exports = function(grunt) {
2
+
3
  grunt.config('phplint', {
4
  options : {
5
  phpArgs : {
6
+ '-f': null
7
  }
8
  },
9
  all : {
grunt/sass.js CHANGED
@@ -1,7 +1,10 @@
1
  module.exports = function(grunt) {
2
 
 
 
3
  grunt.config('sass', {
4
  options : {
 
5
  outputStyle : 'compressed',
6
  },
7
  core : {
1
  module.exports = function(grunt) {
2
 
3
+ const sass = require('node-sass');
4
+
5
  grunt.config('sass', {
6
  options : {
7
+ implementation: sass,
8
  outputStyle : 'compressed',
9
  },
10
  core : {
includes/class.admin.php CHANGED
@@ -8,18 +8,18 @@
8
  */
9
  class SLB_Admin extends SLB_Base {
10
  /* Configuration */
11
-
12
  protected $mode = 'sub';
13
 
14
  /* Properties */
15
-
16
  /**
17
  * Parent object
18
  * Set on initialization
19
  * @var obj
20
  */
21
  protected $parent = null;
22
-
23
  /**
24
  * Messages
25
  * @var array
@@ -29,9 +29,9 @@ class SLB_Admin extends SLB_Base {
29
  'beta' => '<strong class="%1$s">Notice:</strong> This update is a <strong class="%1$s">Beta version</strong>. It is highly recommended that you test the update on a test server before updating the plugin on a production server.',
30
  'access_denied' => 'You do not have sufficient permissions'
31
  );
32
-
33
  /* Views */
34
-
35
  /**
36
  * Custom admin top-level menus
37
  * Associative Array
@@ -40,7 +40,7 @@ class SLB_Admin extends SLB_Base {
40
  * @var array
41
  */
42
  protected $menus = array();
43
-
44
  /**
45
  * Custom admin pages
46
  * Associative Array
@@ -49,16 +49,16 @@ class SLB_Admin extends SLB_Base {
49
  * @var array
50
  */
51
  protected $pages = array();
52
-
53
  /**
54
  * Custom admin sections
55
  * Associative Array
56
  * > Key: Section ID
57
- * > Val: Section properties
58
  * @var array
59
  */
60
  protected $sections = array();
61
-
62
  /**
63
  * Actions
64
  * Index Array
@@ -67,34 +67,34 @@ class SLB_Admin extends SLB_Base {
67
  protected $actions = array();
68
 
69
  /* Constructor */
70
-
71
  public function __construct(&$parent) {
72
  parent::__construct();
73
  // Set parent
74
  if ( is_object($parent) )
75
  $this->parent = $parent;
76
  }
77
-
78
  /* Init */
79
-
80
  protected function _hooks() {
81
  parent::_hooks();
82
  // Init
83
  add_action('admin_menu', $this->m('init_menus'), 11);
84
-
85
  // Plugin actions
86
  add_action('admin_action_' . $this->add_prefix('admin'), $this->m('handle_action'));
87
-
88
  // Notices
89
  add_action('admin_notices', $this->m('handle_notices'));
90
-
91
  // Plugin listing
92
  add_filter('plugin_action_links_' . $this->util->get_plugin_base_name(), $this->m('plugin_action_links'), 10, 4);
93
  add_filter('plugin_row_meta', $this->m('plugin_row_meta'), 10, 4);
94
  add_action('in_plugin_update_message-' . $this->util->get_plugin_base_name(), $this->m('plugin_update_message'), 10, 2);
95
  add_filter('site_transient_update_plugins', $this->m('plugin_update_transient'));
96
  }
97
-
98
  /**
99
  * Declare client files (scripts, styles)
100
  * @uses parent::_client_files()
@@ -122,9 +122,9 @@ class SLB_Admin extends SLB_Base {
122
  );
123
  parent::_client_files($files);
124
  }
125
-
126
  /* Handlers */
127
-
128
  /**
129
  * Handle routing of internal action to appropriate handler
130
  */
@@ -137,7 +137,7 @@ class SLB_Admin extends SLB_Base {
137
  $this->add_prefix_ref($g);
138
  $this->add_prefix_ref($o);
139
  $r =& $_REQUEST;
140
-
141
  // Retrieve view that initiated the action
142
  if ( isset($r[$t]) && 'view' == $r[$t] ) {
143
  if ( isset($r[$g]) && ( $prop = $r[$g] . 's' ) && property_exists($this, $prop) && is_array($this->{$prop}) && isset($r[$o]) && isset($this->{$prop}[$r[$o]]) ) {
@@ -147,7 +147,7 @@ class SLB_Admin extends SLB_Base {
147
  }
148
  }
149
  }
150
-
151
  /**
152
  * Display notices
153
  * Messages are localized upon display
@@ -170,9 +170,9 @@ class SLB_Admin extends SLB_Base {
170
  <?php
171
  }
172
  }
173
-
174
  /* Views */
175
-
176
  /**
177
  * Adds settings section for plugin functionality
178
  * Section is added to specified admin section/menu
@@ -188,7 +188,7 @@ class SLB_Admin extends SLB_Base {
188
  $menu->set_hookname($hook);
189
  $this->menus[$menu->get_id_raw()] =& $menu;
190
  }
191
-
192
  $page;
193
  // Add subpages
194
  foreach ( $this->pages as $page ) {
@@ -199,20 +199,20 @@ class SLB_Admin extends SLB_Base {
199
  if ( $page->is_parent_wp() ) {
200
  $f = 'add_' . $page->get_parent() . '_page';
201
  }
202
-
203
  // Handle pages for custom menus
204
  if ( ! function_exists($f) ) {
205
  array_unshift( $args, $page->get_parent() );
206
  $f = 'add_submenu_page';
207
  }
208
-
209
  // Add admin page
210
  $hook = call_user_func_array($f, $args);
211
  // Save hook to page properties
212
  $page->set_hookname($hook);
213
  $this->pages[$page->get_id_raw()] =& $page;
214
  }
215
-
216
  // Add sections
217
  $section;
218
  foreach ( $this->sections as $section ) {
@@ -222,7 +222,7 @@ class SLB_Admin extends SLB_Base {
222
 
223
 
224
  /* Methods */
225
-
226
  /**
227
  * Add a new view
228
  * @param string $type View type
@@ -246,7 +246,7 @@ class SLB_Admin extends SLB_Base {
246
  unset($r);
247
  return $view;
248
  }
249
-
250
  /**
251
  * Add plugin action link
252
  * @uses `add_view()` to init/attach action instance
@@ -263,9 +263,9 @@ class SLB_Admin extends SLB_Base {
263
  $args = func_get_args();
264
  return $this->add_view('action', $id, $args);
265
  }
266
-
267
  /*-** Menus **-*/
268
-
269
  /**
270
  * Adds custom admin panel
271
  * @param string $id Menu ID
@@ -277,9 +277,9 @@ class SLB_Admin extends SLB_Base {
277
  $args = array ( $id, $labels, null, null, null, $position );
278
  return $this->add_view('menu', $id, $args);
279
  }
280
-
281
  /* Page */
282
-
283
  /**
284
  * Add admin page
285
  * @uses this->pages
@@ -295,9 +295,9 @@ class SLB_Admin extends SLB_Base {
295
  $args = func_get_args();
296
  return $this->add_view('page', $id, $args);
297
  }
298
-
299
  /* WP Pages */
300
-
301
  /**
302
  * Add admin page to a standard WP menu
303
  * @uses this->add_page()
@@ -318,7 +318,7 @@ class SLB_Admin extends SLB_Base {
318
  }
319
  return $pg;
320
  }
321
-
322
  /**
323
  * Add admin page to Dashboard menu
324
  * @see add_dashboard_page()
@@ -344,7 +344,7 @@ class SLB_Admin extends SLB_Base {
344
  public function add_comments_page($id, $labels, $callback = null, $capability = null) {
345
  return $this->add_wp_page($id, 'comments', $labels, $capability);
346
  }
347
-
348
  /**
349
  * Add admin page to Links menu
350
  * @see add_links_page()
@@ -358,7 +358,7 @@ class SLB_Admin extends SLB_Base {
358
  return $this->add_wp_page($id, 'links', $labels, $capability);
359
  }
360
 
361
-
362
  /**
363
  * Add admin page to Posts menu
364
  * @see add_posts_page()
@@ -371,7 +371,7 @@ class SLB_Admin extends SLB_Base {
371
  public function add_posts_page($id, $labels, $callback = null, $capability = null) {
372
  return $this->add_wp_page($id, 'posts', $labels, $capability);
373
  }
374
-
375
  /**
376
  * Add admin page to Pages menu
377
  * @see add_pages_page()
@@ -384,7 +384,7 @@ class SLB_Admin extends SLB_Base {
384
  public function add_pages_page($id, $labels, $callback = null, $capability = null) {
385
  return $this->add_wp_page($id, 'pages', $labels, $capability);
386
  }
387
-
388
  /**
389
  * Add admin page to Media menu
390
  * @see add_media_page()
@@ -397,7 +397,7 @@ class SLB_Admin extends SLB_Base {
397
  public function add_media_page($id, $labels, $callback = null, $capability = null) {
398
  return $this->add_wp_page($id, 'media', $labels, $capability);
399
  }
400
-
401
  /**
402
  * Add admin page to Themes menu
403
  * @see add_theme_page()
@@ -410,7 +410,7 @@ class SLB_Admin extends SLB_Base {
410
  public function add_theme_page($id, $labels, $callback = null, $capability = null) {
411
  return $this->add_wp_page($id, 'theme', $labels, $capability);
412
  }
413
-
414
  /**
415
  * Add admin page to Plugins menu
416
  * @see add_plugins_page()
@@ -423,7 +423,7 @@ class SLB_Admin extends SLB_Base {
423
  public function add_plugins_page($id, $labels, $callback = null, $capability = null) {
424
  return $this->add_wp_page($id, 'plugins', $labels, $capability);
425
  }
426
-
427
  /**
428
  * Add admin page to Options menu
429
  * @see add_options_page()
@@ -436,7 +436,7 @@ class SLB_Admin extends SLB_Base {
436
  public function add_options_page($id, $labels, $callback = null, $capability = null) {
437
  return $this->add_wp_page($id, 'options', $labels, $capability);
438
  }
439
-
440
  /**
441
  * Add admin page to Tools menu
442
  * @see add_management_page()
@@ -449,7 +449,7 @@ class SLB_Admin extends SLB_Base {
449
  public function add_management_page($id, $labels, $callback = null, $capability = null) {
450
  return $this->add_wp_page($id, 'management', $labels, $capability);
451
  }
452
-
453
  /**
454
  * Add admin page to Users menu
455
  * @uses this->add_wp_page()
@@ -461,9 +461,9 @@ class SLB_Admin extends SLB_Base {
461
  public function add_users_page($id, $labels, $callback = null, $capability = null) {
462
  return $this->add_wp_page($id, 'users', $labels, $capability);
463
  }
464
-
465
  /* Section */
466
-
467
  /**
468
  * Add section
469
  * @uses this->sections
@@ -475,16 +475,16 @@ class SLB_Admin extends SLB_Base {
475
  public function add_section($id, $parent, $labels) {
476
  $args = func_get_args();
477
  $section = $this->add_view('section', $id, $args);
478
-
479
  // Add Section
480
  if ( $section->is_valid() )
481
  $this->sections[$id] = $section;
482
-
483
  return $section;
484
  }
485
-
486
  /* Operations */
487
-
488
  /**
489
  * Adds custom links below plugin on plugin listing page
490
  * @uses `plugin_action_links_$plugin-name` Filter hook
@@ -498,10 +498,10 @@ class SLB_Admin extends SLB_Base {
498
  // Add link to settings (only if active)
499
  if ( is_plugin_active($this->util->get_plugin_base_name()) ) {
500
  /* Get Actions */
501
-
502
  $acts = array();
503
  $type = 'plugin_action';
504
-
505
  /* Get view links */
506
  foreach ( array('menus', 'pages', 'sections') as $views ) {
507
  foreach ( $this->{$views} as $view ) {
@@ -515,7 +515,7 @@ class SLB_Admin extends SLB_Base {
515
  );
516
  }
517
  }
518
-
519
  /* Get action links */
520
  $type = 'title';
521
  foreach ( $this->actions as $a ) {
@@ -530,13 +530,13 @@ class SLB_Admin extends SLB_Base {
530
  );
531
  }
532
  unset($a);
533
-
534
  // Add links
535
  $links = array();
536
  foreach ( $acts as $act ) {
537
  $links[$act->id] = $this->util->build_html_link($act->uri, $act->label, $act->attributes);
538
  }
539
-
540
  // Add links
541
  $actions = array_merge($links, $actions);
542
  }
@@ -565,7 +565,7 @@ class SLB_Admin extends SLB_Base {
565
  }
566
  return $plugin_meta;
567
  }
568
-
569
  /**
570
  * Adds additional message for plugin updates
571
  * @uses `in_plugin_update_message-$plugin-name` Action hook
@@ -581,7 +581,7 @@ class SLB_Admin extends SLB_Base {
581
  echo '<br />' . $this->plugin_update_get_message($r);
582
  }
583
  }
584
-
585
  /**
586
  * Modify update plugins response data if necessary
587
  * @uses `site_transient_update_plugins` Filter hook
@@ -597,7 +597,7 @@ class SLB_Admin extends SLB_Base {
597
  }
598
  return $transient;
599
  }
600
-
601
  /**
602
  * Retrieve custom update message
603
  * @uses this->get_message()
@@ -614,9 +614,9 @@ class SLB_Admin extends SLB_Base {
614
  }
615
  return $msg;
616
  }
617
-
618
  /*-** Messages **-*/
619
-
620
  /**
621
  * Retrieve stored messages
622
  * @param string $msg_id Message ID
@@ -630,7 +630,7 @@ class SLB_Admin extends SLB_Base {
630
  }
631
  return $msg;
632
  }
633
-
634
  /**
635
  * Retrieve all messages
636
  * Initializes messages if necessary
@@ -648,7 +648,7 @@ class SLB_Admin extends SLB_Base {
648
  }
649
  return $this->messages;
650
  }
651
-
652
  /**
653
  * Set message text
654
  * @uses this->messages
8
  */
9
  class SLB_Admin extends SLB_Base {
10
  /* Configuration */
11
+
12
  protected $mode = 'sub';
13
 
14
  /* Properties */
15
+
16
  /**
17
  * Parent object
18
  * Set on initialization
19
  * @var obj
20
  */
21
  protected $parent = null;
22
+
23
  /**
24
  * Messages
25
  * @var array
29
  'beta' => '<strong class="%1$s">Notice:</strong> This update is a <strong class="%1$s">Beta version</strong>. It is highly recommended that you test the update on a test server before updating the plugin on a production server.',
30
  'access_denied' => 'You do not have sufficient permissions'
31
  );
32
+
33
  /* Views */
34
+
35
  /**
36
  * Custom admin top-level menus
37
  * Associative Array
40
  * @var array
41
  */
42
  protected $menus = array();
43
+
44
  /**
45
  * Custom admin pages
46
  * Associative Array
49
  * @var array
50
  */
51
  protected $pages = array();
52
+
53
  /**
54
  * Custom admin sections
55
  * Associative Array
56
  * > Key: Section ID
57
+ * > Val: Section properties
58
  * @var array
59
  */
60
  protected $sections = array();
61
+
62
  /**
63
  * Actions
64
  * Index Array
67
  protected $actions = array();
68
 
69
  /* Constructor */
70
+
71
  public function __construct(&$parent) {
72
  parent::__construct();
73
  // Set parent
74
  if ( is_object($parent) )
75
  $this->parent = $parent;
76
  }
77
+
78
  /* Init */
79
+
80
  protected function _hooks() {
81
  parent::_hooks();
82
  // Init
83
  add_action('admin_menu', $this->m('init_menus'), 11);
84
+
85
  // Plugin actions
86
  add_action('admin_action_' . $this->add_prefix('admin'), $this->m('handle_action'));
87
+
88
  // Notices
89
  add_action('admin_notices', $this->m('handle_notices'));
90
+
91
  // Plugin listing
92
  add_filter('plugin_action_links_' . $this->util->get_plugin_base_name(), $this->m('plugin_action_links'), 10, 4);
93
  add_filter('plugin_row_meta', $this->m('plugin_row_meta'), 10, 4);
94
  add_action('in_plugin_update_message-' . $this->util->get_plugin_base_name(), $this->m('plugin_update_message'), 10, 2);
95
  add_filter('site_transient_update_plugins', $this->m('plugin_update_transient'));
96
  }
97
+
98
  /**
99
  * Declare client files (scripts, styles)
100
  * @uses parent::_client_files()
122
  );
123
  parent::_client_files($files);
124
  }
125
+
126
  /* Handlers */
127
+
128
  /**
129
  * Handle routing of internal action to appropriate handler
130
  */
137
  $this->add_prefix_ref($g);
138
  $this->add_prefix_ref($o);
139
  $r =& $_REQUEST;
140
+
141
  // Retrieve view that initiated the action
142
  if ( isset($r[$t]) && 'view' == $r[$t] ) {
143
  if ( isset($r[$g]) && ( $prop = $r[$g] . 's' ) && property_exists($this, $prop) && is_array($this->{$prop}) && isset($r[$o]) && isset($this->{$prop}[$r[$o]]) ) {
147
  }
148
  }
149
  }
150
+
151
  /**
152
  * Display notices
153
  * Messages are localized upon display
170
  <?php
171
  }
172
  }
173
+
174
  /* Views */
175
+
176
  /**
177
  * Adds settings section for plugin functionality
178
  * Section is added to specified admin section/menu
188
  $menu->set_hookname($hook);
189
  $this->menus[$menu->get_id_raw()] =& $menu;
190
  }
191
+
192
  $page;
193
  // Add subpages
194
  foreach ( $this->pages as $page ) {
199
  if ( $page->is_parent_wp() ) {
200
  $f = 'add_' . $page->get_parent() . '_page';
201
  }
202
+
203
  // Handle pages for custom menus
204
  if ( ! function_exists($f) ) {
205
  array_unshift( $args, $page->get_parent() );
206
  $f = 'add_submenu_page';
207
  }
208
+
209
  // Add admin page
210
  $hook = call_user_func_array($f, $args);
211
  // Save hook to page properties
212
  $page->set_hookname($hook);
213
  $this->pages[$page->get_id_raw()] =& $page;
214
  }
215
+
216
  // Add sections
217
  $section;
218
  foreach ( $this->sections as $section ) {
222
 
223
 
224
  /* Methods */
225
+
226
  /**
227
  * Add a new view
228
  * @param string $type View type
246
  unset($r);
247
  return $view;
248
  }
249
+
250
  /**
251
  * Add plugin action link
252
  * @uses `add_view()` to init/attach action instance
263
  $args = func_get_args();
264
  return $this->add_view('action', $id, $args);
265
  }
266
+
267
  /*-** Menus **-*/
268
+
269
  /**
270
  * Adds custom admin panel
271
  * @param string $id Menu ID
277
  $args = array ( $id, $labels, null, null, null, $position );
278
  return $this->add_view('menu', $id, $args);
279
  }
280
+
281
  /* Page */
282
+
283
  /**
284
  * Add admin page
285
  * @uses this->pages
295
  $args = func_get_args();
296
  return $this->add_view('page', $id, $args);
297
  }
298
+
299
  /* WP Pages */
300
+
301
  /**
302
  * Add admin page to a standard WP menu
303
  * @uses this->add_page()
318
  }
319
  return $pg;
320
  }
321
+
322
  /**
323
  * Add admin page to Dashboard menu
324
  * @see add_dashboard_page()
344
  public function add_comments_page($id, $labels, $callback = null, $capability = null) {
345
  return $this->add_wp_page($id, 'comments', $labels, $capability);
346
  }
347
+
348
  /**
349
  * Add admin page to Links menu
350
  * @see add_links_page()
358
  return $this->add_wp_page($id, 'links', $labels, $capability);
359
  }
360
 
361
+
362
  /**
363
  * Add admin page to Posts menu
364
  * @see add_posts_page()
371
  public function add_posts_page($id, $labels, $callback = null, $capability = null) {
372
  return $this->add_wp_page($id, 'posts', $labels, $capability);
373
  }
374
+
375
  /**
376
  * Add admin page to Pages menu
377
  * @see add_pages_page()
384
  public function add_pages_page($id, $labels, $callback = null, $capability = null) {
385
  return $this->add_wp_page($id, 'pages', $labels, $capability);
386
  }
387
+
388
  /**
389
  * Add admin page to Media menu
390
  * @see add_media_page()
397
  public function add_media_page($id, $labels, $callback = null, $capability = null) {
398
  return $this->add_wp_page($id, 'media', $labels, $capability);
399
  }
400
+
401
  /**
402
  * Add admin page to Themes menu
403
  * @see add_theme_page()
410
  public function add_theme_page($id, $labels, $callback = null, $capability = null) {
411
  return $this->add_wp_page($id, 'theme', $labels, $capability);
412
  }
413
+
414
  /**
415
  * Add admin page to Plugins menu
416
  * @see add_plugins_page()
423
  public function add_plugins_page($id, $labels, $callback = null, $capability = null) {
424
  return $this->add_wp_page($id, 'plugins', $labels, $capability);
425
  }
426
+
427
  /**
428
  * Add admin page to Options menu
429
  * @see add_options_page()
436
  public function add_options_page($id, $labels, $callback = null, $capability = null) {
437
  return $this->add_wp_page($id, 'options', $labels, $capability);
438
  }
439
+
440
  /**
441
  * Add admin page to Tools menu
442
  * @see add_management_page()
449
  public function add_management_page($id, $labels, $callback = null, $capability = null) {
450
  return $this->add_wp_page($id, 'management', $labels, $capability);
451
  }
452
+
453
  /**
454
  * Add admin page to Users menu
455
  * @uses this->add_wp_page()
461
  public function add_users_page($id, $labels, $callback = null, $capability = null) {
462
  return $this->add_wp_page($id, 'users', $labels, $capability);
463
  }
464
+
465
  /* Section */
466
+
467
  /**
468
  * Add section
469
  * @uses this->sections
475
  public function add_section($id, $parent, $labels) {
476
  $args = func_get_args();
477
  $section = $this->add_view('section', $id, $args);
478
+
479
  // Add Section
480
  if ( $section->is_valid() )
481
  $this->sections[$id] = $section;
482
+
483
  return $section;
484
  }
485
+
486
  /* Operations */
487
+
488
  /**
489
  * Adds custom links below plugin on plugin listing page
490
  * @uses `plugin_action_links_$plugin-name` Filter hook
498
  // Add link to settings (only if active)
499
  if ( is_plugin_active($this->util->get_plugin_base_name()) ) {
500
  /* Get Actions */
501
+
502
  $acts = array();
503
  $type = 'plugin_action';
504
+
505
  /* Get view links */
506
  foreach ( array('menus', 'pages', 'sections') as $views ) {
507
  foreach ( $this->{$views} as $view ) {
515
  );
516
  }
517
  }
518
+
519
  /* Get action links */
520
  $type = 'title';
521
  foreach ( $this->actions as $a ) {
530
  );
531
  }
532
  unset($a);
533
+
534
  // Add links
535
  $links = array();
536
  foreach ( $acts as $act ) {
537
  $links[$act->id] = $this->util->build_html_link($act->uri, $act->label, $act->attributes);
538
  }
539
+
540
  // Add links
541
  $actions = array_merge($links, $actions);
542
  }
565
  }
566
  return $plugin_meta;
567
  }
568
+
569
  /**
570
  * Adds additional message for plugin updates
571
  * @uses `in_plugin_update_message-$plugin-name` Action hook
581
  echo '<br />' . $this->plugin_update_get_message($r);
582
  }
583
  }
584
+
585
  /**
586
  * Modify update plugins response data if necessary
587
  * @uses `site_transient_update_plugins` Filter hook
597
  }
598
  return $transient;
599
  }
600
+
601
  /**
602
  * Retrieve custom update message
603
  * @uses this->get_message()
614
  }
615
  return $msg;
616
  }
617
+
618
  /*-** Messages **-*/
619
+
620
  /**
621
  * Retrieve stored messages
622
  * @param string $msg_id Message ID
630
  }
631
  return $msg;
632
  }
633
+
634
  /**
635
  * Retrieve all messages
636
  * Initializes messages if necessary
648
  }
649
  return $this->messages;
650
  }
651
+
652
  /**
653
  * Set message text
654
  * @uses this->messages
includes/class.admin_action.php CHANGED
@@ -9,13 +9,13 @@
9
  */
10
  class SLB_Admin_Action extends SLB_Admin_View {
11
  /* Properties */
12
-
13
  protected $parent_required = false;
14
-
15
  public $hook_prefix = 'admin_action';
16
-
17
  /* Init */
18
-
19
  /**
20
  * Init
21
  * @param string $id ID
@@ -31,9 +31,9 @@ class SLB_Admin_Action extends SLB_Admin_View {
31
  }
32
  return $this;
33
  }
34
-
35
  /* Handlers */
36
-
37
  /**
38
  * Default handler
39
  * Handles action
@@ -43,12 +43,12 @@ class SLB_Admin_Action extends SLB_Admin_View {
43
  // Validate user
44
  if ( ! current_user_can('activate_plugins') || ! check_admin_referer($this->get_id()) )
45
  wp_die(__('Access Denied', 'simple-lightbox'));
46
-
47
  // Get data
48
  $content = $this->get_content();
49
-
50
  $success = true;
51
-
52
  // Iterate through data
53
  $hook = $this->util->get_hook($this->get_id_raw());
54
  foreach ( $content as $c ) {
@@ -59,12 +59,12 @@ class SLB_Admin_Action extends SLB_Admin_View {
59
  $success = $res;
60
  }
61
  }
62
-
63
  // Set Status Message
64
  $lbl = ( $success ) ? 'success' : 'failure';
65
  $this->set_message($this->get_label($lbl));
66
  }
67
-
68
  /**
69
  * Get URI
70
  * @see Admin_View::get_uri()
@@ -72,7 +72,7 @@ class SLB_Admin_Action extends SLB_Admin_View {
72
  public function get_uri($file = null, $format = null) {
73
  return wp_nonce_url(add_query_arg($this->get_query_args(), remove_query_arg($this->get_query_args_remove(), $_SERVER['REQUEST_URI'])), $this->get_id());
74
  }
75
-
76
  protected function get_query_args() {
77
  return array (
78
  'action' => $this->add_prefix('admin'),
@@ -81,25 +81,25 @@ class SLB_Admin_Action extends SLB_Admin_View {
81
  $this->add_prefix('obj') => $this->get_id_raw()
82
  );
83
  }
84
-
85
  protected function get_query_args_remove() {
86
  $args_r = array (
87
  '_wpnonce',
88
  $this->add_prefix('action')
89
  );
90
-
91
  return array_unique( array_merge( array_keys( $this->get_query_args() ), $args_r ) );
92
  }
93
-
94
  public function get_link_attr() {
95
  return array (
96
  'class' => $this->util->get_hook($this->get_id_raw()),
97
  'onclick' => "return confirm('" . esc_js( $this->get_label('confirm') ) . "')"
98
  );
99
  }
100
-
101
  /* Content */
102
-
103
  /**
104
  * Save options
105
  */
9
  */
10
  class SLB_Admin_Action extends SLB_Admin_View {
11
  /* Properties */
12
+
13
  protected $parent_required = false;
14
+
15
  public $hook_prefix = 'admin_action';
16
+
17
  /* Init */
18
+
19
  /**
20
  * Init
21
  * @param string $id ID
31
  }
32
  return $this;
33
  }
34
+
35
  /* Handlers */
36
+
37
  /**
38
  * Default handler
39
  * Handles action
43
  // Validate user
44
  if ( ! current_user_can('activate_plugins') || ! check_admin_referer($this->get_id()) )
45
  wp_die(__('Access Denied', 'simple-lightbox'));
46
+
47
  // Get data
48
  $content = $this->get_content();
49
+
50
  $success = true;
51
+
52
  // Iterate through data
53
  $hook = $this->util->get_hook($this->get_id_raw());
54
  foreach ( $content as $c ) {
59
  $success = $res;
60
  }
61
  }
62
+
63
  // Set Status Message
64
  $lbl = ( $success ) ? 'success' : 'failure';
65
  $this->set_message($this->get_label($lbl));
66
  }
67
+
68
  /**
69
  * Get URI
70
  * @see Admin_View::get_uri()
72
  public function get_uri($file = null, $format = null) {
73
  return wp_nonce_url(add_query_arg($this->get_query_args(), remove_query_arg($this->get_query_args_remove(), $_SERVER['REQUEST_URI'])), $this->get_id());
74
  }
75
+
76
  protected function get_query_args() {
77
  return array (
78
  'action' => $this->add_prefix('admin'),
81
  $this->add_prefix('obj') => $this->get_id_raw()
82
  );
83
  }
84
+
85
  protected function get_query_args_remove() {
86
  $args_r = array (
87
  '_wpnonce',
88
  $this->add_prefix('action')
89
  );
90
+
91
  return array_unique( array_merge( array_keys( $this->get_query_args() ), $args_r ) );
92
  }
93
+
94
  public function get_link_attr() {
95
  return array (
96
  'class' => $this->util->get_hook($this->get_id_raw()),
97
  'onclick' => "return confirm('" . esc_js( $this->get_label('confirm') ) . "')"
98
  );
99
  }
100
+
101
  /* Content */
102
+
103
  /**
104
  * Save options
105
  */
includes/class.admin_menu.php CHANGED
@@ -9,15 +9,15 @@
9
  */
10
  class SLB_Admin_Menu extends SLB_Admin_View {
11
  /* Properties */
12
-
13
  /**
14
  * Menu position
15
  * @var int
16
  */
17
  protected $position = null;
18
-
19
  /* Init */
20
-
21
  public function __construct($id, $labels, $callback = null, $capability = null, $icon = null, $position = null) {
22
  // Default
23
  parent::__construct($id, $labels, $callback, $capability, $icon);
@@ -25,9 +25,9 @@ class SLB_Admin_Menu extends SLB_Admin_View {
25
  $this->set_position($position);
26
  return $this;
27
  }
28
-
29
  /* Getters/Setters */
30
-
31
  /**
32
  * Set menu position
33
  * @return obj Current instance
9
  */
10
  class SLB_Admin_Menu extends SLB_Admin_View {
11
  /* Properties */
12
+
13
  /**
14
  * Menu position
15
  * @var int
16
  */
17
  protected $position = null;
18
+
19
  /* Init */
20
+
21
  public function __construct($id, $labels, $callback = null, $capability = null, $icon = null, $position = null) {
22
  // Default
23
  parent::__construct($id, $labels, $callback, $capability, $icon);
25
  $this->set_position($position);
26
  return $this;
27
  }
28
+
29
  /* Getters/Setters */
30
+
31
  /**
32
  * Set menu position
33
  * @return obj Current instance
includes/class.admin_page.php CHANGED
@@ -9,18 +9,18 @@
9
  */
10
  class SLB_Admin_Page extends SLB_Admin_View {
11
  /* Properties */
12
-
13
  protected $parent_required = true;
14
-
15
  public $hook_prefix = 'admin_page';
16
-
17
  /**
18
  * Required features/elements
19
  */
20
  private $_required = array();
21
-
22
  /* Init */
23
-
24
  public function __construct($id, $parent, $labels, $callback = null, $capability = null) {
25
  // Default
26
  parent::__construct($id, $labels, $callback, $capability);
@@ -28,9 +28,9 @@ class SLB_Admin_Page extends SLB_Admin_View {
28
  $this->set_parent($parent);
29
  return $this;
30
  }
31
-
32
  /* Operations */
33
-
34
  /**
35
  * Add content to page
36
  * @uses parent::add_content()
@@ -53,7 +53,7 @@ class SLB_Admin_Page extends SLB_Admin_View {
53
  )
54
  );
55
  }
56
-
57
  /**
58
  * Parse content by parameters
59
  * Sets content value
@@ -73,7 +73,7 @@ class SLB_Admin_Page extends SLB_Admin_View {
73
  }
74
  return $content;
75
  }
76
-
77
  /**
78
  * Render content blocks
79
  * @param string $context (optional) Context to render
@@ -110,7 +110,7 @@ class SLB_Admin_Page extends SLB_Admin_View {
110
  </div>
111
  <?php
112
  }
113
-
114
  /**
115
  * Require form submission support
116
  * @return obj Page instance
@@ -119,7 +119,7 @@ class SLB_Admin_Page extends SLB_Admin_View {
119
  $this->_require('form_submit');
120
  return $this;
121
  }
122
-
123
  /**
124
  * Check if form submission is required
125
  * @return bool TRUE if form submission required
@@ -127,9 +127,9 @@ class SLB_Admin_Page extends SLB_Admin_View {
127
  private function is_required_form() {
128
  return $this->_is_required('form_submit');
129
  }
130
-
131
  /* Handlers */
132
-
133
  /**
134
  * Default Page handler
135
  * Builds content blocks
@@ -149,9 +149,14 @@ class SLB_Admin_Page extends SLB_Admin_View {
149
  if ( $this->is_required_form() ) {
150
  // Build form output
151
  $form_id = $this->add_prefix('admin_form_' . $this->get_id_raw());
 
 
 
 
152
  ?>
153
  <form id="<?php esc_attr_e($form_id); ?>" name="<?php esc_attr_e($form_id); ?>" action="" method="post">
154
  <?php
 
155
  }
156
  ?>
157
  <div class="metabox-holder columns-2">
9
  */
10
  class SLB_Admin_Page extends SLB_Admin_View {
11
  /* Properties */
12
+
13
  protected $parent_required = true;
14
+
15
  public $hook_prefix = 'admin_page';
16
+
17
  /**
18
  * Required features/elements
19
  */
20
  private $_required = array();
21
+
22
  /* Init */
23
+
24
  public function __construct($id, $parent, $labels, $callback = null, $capability = null) {
25
  // Default
26
  parent::__construct($id, $labels, $callback, $capability);
28
  $this->set_parent($parent);
29
  return $this;
30
  }
31
+
32
  /* Operations */
33
+
34
  /**
35
  * Add content to page
36
  * @uses parent::add_content()
53
  )
54
  );
55
  }
56
+
57
  /**
58
  * Parse content by parameters
59
  * Sets content value
73
  }
74
  return $content;
75
  }
76
+
77
  /**
78
  * Render content blocks
79
  * @param string $context (optional) Context to render
110
  </div>
111
  <?php
112
  }
113
+
114
  /**
115
  * Require form submission support
116
  * @return obj Page instance
119
  $this->_require('form_submit');
120
  return $this;
121
  }
122
+
123
  /**
124
  * Check if form submission is required
125
  * @return bool TRUE if form submission required
127
  private function is_required_form() {
128
  return $this->_is_required('form_submit');
129
  }
130
+
131
  /* Handlers */
132
+
133
  /**
134
  * Default Page handler
135
  * Builds content blocks
149
  if ( $this->is_required_form() ) {
150
  // Build form output
151
  $form_id = $this->add_prefix('admin_form_' . $this->get_id_raw());
152
+ $nonce = (object) [
153
+ 'action' => $this->get_id(),
154
+ 'name' => $this->get_id() . '_nonce',
155
+ ];
156
  ?>
157
  <form id="<?php esc_attr_e($form_id); ?>" name="<?php esc_attr_e($form_id); ?>" action="" method="post">
158
  <?php
159
+ wp_nonce_field( $nonce->action, $nonce->name );
160
  }
161
  ?>
162
  <div class="metabox-holder columns-2">
includes/class.admin_section.php CHANGED
@@ -9,12 +9,12 @@
9
  */
10
  class SLB_Admin_Section extends SLB_Admin_View {
11
  /* Properties */
12
-
13
  protected $parent_required = true;
14
  protected $parent_custom = false;
15
-
16
  /* Init */
17
-
18
  public function __construct($id, $parent, $labels, $callback = null, $capability = null) {
19
  // Default
20
  parent::__construct($id, $labels, $callback, $capability);
@@ -22,9 +22,9 @@ class SLB_Admin_Section extends SLB_Admin_View {
22
  $this->set_parent($parent);
23
  return $this;
24
  }
25
-
26
  /* Getters/Setters */
27
-
28
  /**
29
  * Retrieve URI
30
  * @uses Admin_View::get_uri()
9
  */
10
  class SLB_Admin_Section extends SLB_Admin_View {
11
  /* Properties */
12
+
13
  protected $parent_required = true;
14
  protected $parent_custom = false;
15
+
16
  /* Init */
17
+
18
  public function __construct($id, $parent, $labels, $callback = null, $capability = null) {
19
  // Default
20
  parent::__construct($id, $labels, $callback, $capability);
22
  $this->set_parent($parent);
23
  return $this;
24
  }
25
+
26
  /* Getters/Setters */
27
+
28
  /**
29
  * Retrieve URI
30
  * @uses Admin_View::get_uri()
includes/class.admin_view.php CHANGED
@@ -2,62 +2,62 @@
2
 
3
  /**
4
  * Admin View Base
5
- * Core functionality Admin UI components
6
  * @package Simple Lightbox
7
  * @subpackage Admin
8
  * @author Archetyped
9
  */
10
  class SLB_Admin_View extends SLB_Base_Object {
11
  /* Properties */
12
-
13
  /**
14
  * Labels
15
  * @var array (Associative)
16
  */
17
  protected $labels = array();
18
-
19
  /**
20
  * Function to handle building UI
21
  * @var callback
22
  */
23
  protected $callback = null;
24
-
25
  /**
26
  * Capability for access control
27
- * @var string
28
  */
29
  protected $capability = 'manage_options';
30
-
31
  /**
32
  * Icon to use
33
  * @var string
34
  */
35
  protected $icon = null;
36
-
37
  /**
38
  * View parent ID/Slug
39
  * @var string
40
  */
41
  protected $parent = null;
42
-
43
  /**
44
  * Whether parent is a custom view or a default WP one
45
  * @var bool
46
  */
47
  protected $parent_custom = true;
48
-
49
  /**
50
  * If view requires a parent
51
  * @var bool
52
  */
53
  protected $parent_required = false;
54
-
55
  /**
56
  * WP-Generated hook name for view
57
  * @var string
58
  */
59
  protected $hookname = null;
60
-
61
  /**
62
  * Raw content parameters
63
  * Stores pre-rendered content parameters
@@ -65,20 +65,20 @@ class SLB_Admin_View extends SLB_Base_Object {
65
  * @var array
66
  */
67
  protected $content_raw = array();
68
-
69
  /**
70
  * Parsed content parameters
71
  * @var array
72
  */
73
  protected $content = array();
74
-
75
  /**
76
  * Messages to be displayed
77
  * Indexed Array
78
  * @var array
79
  */
80
  protected $messages = array();
81
-
82
  /**
83
  * Required properties
84
  * Associative array
@@ -87,7 +87,7 @@ class SLB_Admin_View extends SLB_Base_Object {
87
  * @var array
88
  */
89
  private $required = array();
90
-
91
  /**
92
  * Default required properties
93
  * Merged into $required array with this->init_required()
@@ -95,9 +95,9 @@ class SLB_Admin_View extends SLB_Base_Object {
95
  * @var array
96
  */
97
  private $_required = array ( 'id' => 'string', 'labels' => 'array' );
98
-
99
  /* Init */
100
-
101
  /**
102
  * Constructor
103
  * @return obj Current instance
@@ -113,14 +113,14 @@ class SLB_Admin_View extends SLB_Base_Object {
113
  $this->init_required();
114
  return $this;
115
  }
116
-
117
  protected function init_required() {
118
  $this->required = array_merge($this->_required, $this->required);
119
  // Check for parent requirement
120
  if ( $this->parent_required )
121
  $this->required['parent'] = 'string';
122
  }
123
-
124
  /**
125
  * Set required feature
126
  * @param string $feature Required feature
@@ -131,7 +131,7 @@ class SLB_Admin_View extends SLB_Base_Object {
131
  }
132
  return $this;
133
  }
134
-
135
  /**
136
  * Check if feature is required
137
  * @param string $feature Feature to check for
@@ -140,9 +140,9 @@ class SLB_Admin_View extends SLB_Base_Object {
140
  protected function _is_required($feature) {
141
  return ( isset($this->_required[$feature]) ) ? true : false;
142
  }
143
-
144
  /* Property Methods */
145
-
146
  /**
147
  * Retrieve ID (Formatted by default)
148
  * @param bool $formatted (optional) Whether ID should be formatted for external use or not
@@ -154,7 +154,7 @@ class SLB_Admin_View extends SLB_Base_Object {
154
  $this->add_prefix_ref($id);
155
  return $id;
156
  }
157
-
158
  /**
159
  * Retrieve raw ID
160
  * @return string Raw ID
@@ -162,7 +162,7 @@ class SLB_Admin_View extends SLB_Base_Object {
162
  public function get_id_raw() {
163
  return $this->get_id(false);
164
  }
165
-
166
  /**
167
  * Retrieve label
168
  * Uses first label (or default if defined) if specified type does not exist
@@ -179,10 +179,10 @@ class SLB_Admin_View extends SLB_Base_Object {
179
  reset($this->labels);
180
  $default = current($this->labels);
181
  }
182
-
183
  return ( empty($default) ) ? '' : $default;
184
  }
185
-
186
  /**
187
  * Set text labels
188
  * @param array|string $labels
@@ -194,8 +194,8 @@ class SLB_Admin_View extends SLB_Base_Object {
194
  // Single string
195
  if ( is_string($labels) ) {
196
  $labels = array ( $labels );
197
- }
198
-
199
  // Array
200
  if ( is_array($labels) ) {
201
  // Merge with existing labels
@@ -206,7 +206,7 @@ class SLB_Admin_View extends SLB_Base_Object {
206
  }
207
  return $this;
208
  }
209
-
210
  /**
211
  * Set single text label
212
  * @uses this->set_labels()
@@ -221,7 +221,7 @@ class SLB_Admin_View extends SLB_Base_Object {
221
  }
222
  return $this;
223
  }
224
-
225
  /**
226
  * Checks if specified label is set on view
227
  * @param string $type Label type
@@ -230,9 +230,9 @@ class SLB_Admin_View extends SLB_Base_Object {
230
  public function has_label($type) {
231
  return ( isset($this->labels[$type]) );
232
  }
233
-
234
  /* Content */
235
-
236
  /**
237
  * Add content block to view
238
  * Child classes define method functionality
@@ -248,7 +248,7 @@ class SLB_Admin_View extends SLB_Base_Object {
248
  // Return instance reference
249
  return $this;
250
  }
251
-
252
  /**
253
  * Retrieve content
254
  */
@@ -266,7 +266,7 @@ class SLB_Admin_View extends SLB_Base_Object {
266
  }
267
  return $content;
268
  }
269
-
270
  /**
271
  * Parse content
272
  * Child classes define functionality
@@ -275,7 +275,7 @@ class SLB_Admin_View extends SLB_Base_Object {
275
  protected function parse_content() {
276
  return $this->get_content(false);
277
  }
278
-
279
  /**
280
  * Check if content has been added to view
281
  * @return bool TRUE if content added
@@ -284,12 +284,12 @@ class SLB_Admin_View extends SLB_Base_Object {
284
  $raw = $this->get_content(false);
285
  return !empty($raw);
286
  }
287
-
288
  /**
289
  * Render content
290
  */
291
  protected function render_content($context = 'default') {}
292
-
293
  /**
294
  * Retrieve view messages
295
  * @return array Messages
@@ -299,7 +299,7 @@ class SLB_Admin_View extends SLB_Base_Object {
299
  $this->messages = array();
300
  return $this->messages;
301
  }
302
-
303
  /**
304
  * Save message
305
  * @param string $text Message text
@@ -313,7 +313,7 @@ class SLB_Admin_View extends SLB_Base_Object {
313
  $msgs[] = $text;
314
  return $this;
315
  }
316
-
317
  /**
318
  * Add messages to array
319
  * Called by internal `admin_messages` filter hook
@@ -326,7 +326,7 @@ class SLB_Admin_View extends SLB_Base_Object {
326
  $msgs = array_merge($msgs, $m);
327
  return $msgs;
328
  }
329
-
330
  /**
331
  * Retrieve view callback
332
  * @return callback Callback (Default: standard handler method)
@@ -334,7 +334,7 @@ class SLB_Admin_View extends SLB_Base_Object {
334
  public function get_callback() {
335
  return ( $this->has_callback() ) ? $this->callback : $this->m('handle');
336
  }
337
-
338
  /**
339
  * Set callback function for building item
340
  * @param callback $callback Callback function to use
@@ -344,7 +344,7 @@ class SLB_Admin_View extends SLB_Base_Object {
344
  $this->callback = ( is_callable($callback) ) ? $callback : null;
345
  return $this;
346
  }
347
-
348
  /**
349
  * Check if callback set
350
  * @return bool TRUE if callback is set
@@ -352,14 +352,14 @@ class SLB_Admin_View extends SLB_Base_Object {
352
  protected function has_callback() {
353
  return ( !empty($this->callback) ) ? true : false;
354
  }
355
-
356
  /**
357
  * Run callback
358
  */
359
  public function do_callback() {
360
  call_user_func($this->get_callback());
361
  }
362
-
363
  /**
364
  * Retrieve capability
365
  * @return string Capability
@@ -367,7 +367,7 @@ class SLB_Admin_View extends SLB_Base_Object {
367
  public function get_capability() {
368
  return $this->capability;
369
  }
370
-
371
  /**
372
  * Set capability for access control
373
  * @param string $capability Capability
@@ -378,7 +378,7 @@ class SLB_Admin_View extends SLB_Base_Object {
378
  $this->capability = $capability;
379
  return $this;
380
  }
381
-
382
  /**
383
  * Set icon
384
  * @param string $icon Icon URI
@@ -389,11 +389,11 @@ class SLB_Admin_View extends SLB_Base_Object {
389
  $this->icon = $icon;
390
  return $this;
391
  }
392
-
393
  protected function get_hookname() {
394
  return ( empty($this->hookname) ) ? '' : $this->hookname;
395
  }
396
-
397
  /**
398
  * Set hookname
399
  * @param string $hookname Hookname value
@@ -404,7 +404,7 @@ class SLB_Admin_View extends SLB_Base_Object {
404
  $this->hookname = $hookname;
405
  return $this;
406
  }
407
-
408
  /**
409
  * Retrieve parent
410
  * Formats parent ID for custom parents
@@ -415,7 +415,7 @@ class SLB_Admin_View extends SLB_Base_Object {
415
  $parent = parent::get_parent();
416
  return ( $this->is_parent_custom() ) ? $this->add_prefix($parent) : $parent;
417
  }
418
-
419
  /**
420
  * Set parent for view
421
  * @param string $parent Parent ID
@@ -430,7 +430,7 @@ class SLB_Admin_View extends SLB_Base_Object {
430
  }
431
  return $this;
432
  }
433
-
434
  /**
435
  * Specify whether parent is a custom view or a WP view
436
  * @param bool $custom (optional) TRUE if custom, FALSE if WP
@@ -442,7 +442,7 @@ class SLB_Admin_View extends SLB_Base_Object {
442
  }
443
  return $this;
444
  }
445
-
446
  /**
447
  * Set parent as WP view
448
  * @uses this->set_parent_custom()
@@ -452,18 +452,18 @@ class SLB_Admin_View extends SLB_Base_Object {
452
  $this->set_parent_custom(false);
453
  return $this;
454
  }
455
-
456
  /**
457
  * Get view URI
458
  * URI Structures:
459
  * > Top Level Menus: admin.php?page={menu_id}
460
  * > Pages: [parent_page_file.php|admin.php]?page={page_id}
461
  * > Section: [parent_menu_uri]#{section_id}
462
- *
463
  * @uses $admin_page_hooks to determine if page is child of default WP page
464
  * @param string $file (optional) Base file name
465
  * @param string $format (optional) Format string for URI
466
- * @return string Object URI
467
  */
468
  public function get_uri($file = null, $format = null) {
469
  static $page_hooks = null;
@@ -478,7 +478,7 @@ class SLB_Admin_View extends SLB_Base_Object {
478
  if ( isset($page_hooks[$parent]) )
479
  $file = $page_hooks[$parent];
480
  }
481
-
482
  if ( empty($format) ) {
483
  $delim = ( strpos($file, '?') === false ) ? '?' : '&amp;';
484
  $format = '%1$s' . $delim . 'page=%2$s';
@@ -487,20 +487,20 @@ class SLB_Admin_View extends SLB_Base_Object {
487
 
488
  return $uri;
489
  }
490
-
491
  /* Handlers */
492
-
493
  /**
494
  * Default View handler
495
  * Used as callback when none set
496
  */
497
  public function handle() {}
498
-
499
  /* Validation */
500
-
501
  /**
502
  * Check if instance is valid based on required properties/data types
503
- * @return bool TRUE if valid, FALSE if not valid
504
  */
505
  public function is_valid() {
506
  $valid = true;
@@ -513,17 +513,17 @@ class SLB_Admin_View extends SLB_Base_Object {
513
  }
514
  return $valid;
515
  }
516
-
517
  protected function is_child() {
518
  return $this->parent_required;
519
  }
520
-
521
  protected function is_parent_custom() {
522
  return ( $this->is_child() && $this->parent_custom ) ? true : false;
523
  }
524
-
525
  public function is_parent_wp() {
526
  return ( $this->is_child() && !$this->parent_custom ) ? true : false;
527
  }
528
-
529
  }
2
 
3
  /**
4
  * Admin View Base
5
+ * Core functionality Admin UI components
6
  * @package Simple Lightbox
7
  * @subpackage Admin
8
  * @author Archetyped
9
  */
10
  class SLB_Admin_View extends SLB_Base_Object {
11
  /* Properties */
12
+
13
  /**
14
  * Labels
15
  * @var array (Associative)
16
  */
17
  protected $labels = array();
18
+
19
  /**
20
  * Function to handle building UI
21
  * @var callback
22
  */
23
  protected $callback = null;
24
+
25
  /**
26
  * Capability for access control
27
+ * @var string
28
  */
29
  protected $capability = 'manage_options';
30
+
31
  /**
32
  * Icon to use
33
  * @var string
34
  */
35
  protected $icon = null;
36
+
37
  /**
38
  * View parent ID/Slug
39
  * @var string
40
  */
41
  protected $parent = null;
42
+
43
  /**
44
  * Whether parent is a custom view or a default WP one
45
  * @var bool
46
  */
47
  protected $parent_custom = true;
48
+
49
  /**
50
  * If view requires a parent
51
  * @var bool
52
  */
53
  protected $parent_required = false;
54
+
55
  /**
56
  * WP-Generated hook name for view
57
  * @var string
58
  */
59
  protected $hookname = null;
60
+
61
  /**
62
  * Raw content parameters
63
  * Stores pre-rendered content parameters
65
  * @var array
66
  */
67
  protected $content_raw = array();
68
+
69
  /**
70
  * Parsed content parameters
71
  * @var array
72
  */
73
  protected $content = array();
74
+
75
  /**
76
  * Messages to be displayed
77
  * Indexed Array
78
  * @var array
79
  */
80
  protected $messages = array();
81
+
82
  /**
83
  * Required properties
84
  * Associative array
87
  * @var array
88
  */
89
  private $required = array();
90
+
91
  /**
92
  * Default required properties
93
  * Merged into $required array with this->init_required()
95
  * @var array
96
  */
97
  private $_required = array ( 'id' => 'string', 'labels' => 'array' );
98
+
99
  /* Init */
100
+
101
  /**
102
  * Constructor
103
  * @return obj Current instance
113
  $this->init_required();
114
  return $this;
115
  }
116
+
117
  protected function init_required() {
118
  $this->required = array_merge($this->_required, $this->required);
119
  // Check for parent requirement
120
  if ( $this->parent_required )
121
  $this->required['parent'] = 'string';
122
  }
123
+
124
  /**
125
  * Set required feature
126
  * @param string $feature Required feature
131
  }
132
  return $this;
133
  }
134
+
135
  /**
136
  * Check if feature is required
137
  * @param string $feature Feature to check for
140
  protected function _is_required($feature) {
141
  return ( isset($this->_required[$feature]) ) ? true : false;
142
  }
143
+
144
  /* Property Methods */
145
+
146
  /**
147
  * Retrieve ID (Formatted by default)
148
  * @param bool $formatted (optional) Whether ID should be formatted for external use or not
154
  $this->add_prefix_ref($id);
155
  return $id;
156
  }
157
+
158
  /**
159
  * Retrieve raw ID
160
  * @return string Raw ID
162
  public function get_id_raw() {
163
  return $this->get_id(false);
164
  }
165
+
166
  /**
167
  * Retrieve label
168
  * Uses first label (or default if defined) if specified type does not exist
179
  reset($this->labels);
180
  $default = current($this->labels);
181
  }
182
+
183
  return ( empty($default) ) ? '' : $default;
184
  }
185
+
186
  /**
187
  * Set text labels
188
  * @param array|string $labels
194
  // Single string
195
  if ( is_string($labels) ) {
196
  $labels = array ( $labels );
197
+ }
198
+
199
  // Array
200
  if ( is_array($labels) ) {
201
  // Merge with existing labels
206
  }
207
  return $this;
208
  }
209
+
210
  /**
211
  * Set single text label
212
  * @uses this->set_labels()
221
  }
222
  return $this;
223
  }
224
+
225
  /**
226
  * Checks if specified label is set on view
227
  * @param string $type Label type
230
  public function has_label($type) {
231
  return ( isset($this->labels[$type]) );
232
  }
233
+
234
  /* Content */
235
+
236
  /**
237
  * Add content block to view
238
  * Child classes define method functionality
248
  // Return instance reference
249
  return $this;
250
  }
251
+
252
  /**
253
  * Retrieve content
254
  */
266
  }
267
  return $content;
268
  }
269
+
270
  /**
271
  * Parse content
272
  * Child classes define functionality
275
  protected function parse_content() {
276
  return $this->get_content(false);
277
  }
278
+
279
  /**
280
  * Check if content has been added to view
281
  * @return bool TRUE if content added
284
  $raw = $this->get_content(false);
285
  return !empty($raw);
286
  }
287
+
288
  /**
289
  * Render content
290
  */
291
  protected function render_content($context = 'default') {}
292
+
293
  /**
294
  * Retrieve view messages
295
  * @return array Messages
299
  $this->messages = array();
300
  return $this->messages;
301
  }
302
+
303
  /**
304
  * Save message
305
  * @param string $text Message text
313
  $msgs[] = $text;
314
  return $this;
315
  }
316
+
317
  /**
318
  * Add messages to array
319
  * Called by internal `admin_messages` filter hook
326
  $msgs = array_merge($msgs, $m);
327
  return $msgs;
328
  }
329
+
330
  /**
331
  * Retrieve view callback
332
  * @return callback Callback (Default: standard handler method)
334
  public function get_callback() {
335
  return ( $this->has_callback() ) ? $this->callback : $this->m('handle');
336
  }
337
+
338
  /**
339
  * Set callback function for building item
340
  * @param callback $callback Callback function to use
344
  $this->callback = ( is_callable($callback) ) ? $callback : null;
345
  return $this;
346
  }
347
+
348
  /**
349
  * Check if callback set
350
  * @return bool TRUE if callback is set
352
  protected function has_callback() {
353
  return ( !empty($this->callback) ) ? true : false;
354
  }
355
+
356
  /**
357
  * Run callback
358
  */
359
  public function do_callback() {
360
  call_user_func($this->get_callback());
361
  }
362
+
363
  /**
364
  * Retrieve capability
365
  * @return string Capability
367
  public function get_capability() {
368
  return $this->capability;
369
  }
370
+
371
  /**
372
  * Set capability for access control
373
  * @param string $capability Capability
378
  $this->capability = $capability;
379
  return $this;
380
  }
381
+
382
  /**
383
  * Set icon
384
  * @param string $icon Icon URI
389
  $this->icon = $icon;
390
  return $this;
391
  }
392
+
393
  protected function get_hookname() {
394
  return ( empty($this->hookname) ) ? '' : $this->hookname;
395
  }
396
+
397
  /**
398
  * Set hookname
399
  * @param string $hookname Hookname value
404
  $this->hookname = $hookname;
405
  return $this;
406
  }
407
+
408
  /**
409
  * Retrieve parent
410
  * Formats parent ID for custom parents
415
  $parent = parent::get_parent();
416
  return ( $this->is_parent_custom() ) ? $this->add_prefix($parent) : $parent;
417
  }
418
+
419
  /**
420
  * Set parent for view
421
  * @param string $parent Parent ID
430
  }
431
  return $this;
432
  }
433
+
434
  /**
435
  * Specify whether parent is a custom view or a WP view
436
  * @param bool $custom (optional) TRUE if custom, FALSE if WP
442
  }
443
  return $this;
444
  }
445
+
446
  /**
447
  * Set parent as WP view
448
  * @uses this->set_parent_custom()
452
  $this->set_parent_custom(false);
453
  return $this;
454
  }
455
+
456
  /**
457
  * Get view URI
458
  * URI Structures:
459
  * > Top Level Menus: admin.php?page={menu_id}
460
  * > Pages: [parent_page_file.php|admin.php]?page={page_id}
461
  * > Section: [parent_menu_uri]#{section_id}
462
+ *
463
  * @uses $admin_page_hooks to determine if page is child of default WP page
464
  * @param string $file (optional) Base file name
465
  * @param string $format (optional) Format string for URI
466
+ * @return string Object URI
467
  */
468
  public function get_uri($file = null, $format = null) {
469
  static $page_hooks = null;
478
  if ( isset($page_hooks[$parent]) )
479
  $file = $page_hooks[$parent];
480
  }
481
+
482
  if ( empty($format) ) {
483
  $delim = ( strpos($file, '?') === false ) ? '?' : '&amp;';
484
  $format = '%1$s' . $delim . 'page=%2$s';
487
 
488
  return $uri;
489
  }
490
+
491
  /* Handlers */
492
+
493
  /**
494
  * Default View handler
495
  * Used as callback when none set
496
  */
497
  public function handle() {}
498
+
499
  /* Validation */
500
+
501
  /**
502
  * Check if instance is valid based on required properties/data types
503
+ * @return bool TRUE if valid, FALSE if not valid
504
  */
505
  public function is_valid() {
506
  $valid = true;
513
  }
514
  return $valid;
515
  }
516
+
517
  protected function is_child() {
518
  return $this->parent_required;
519
  }
520
+
521
  protected function is_parent_custom() {
522
  return ( $this->is_child() && $this->parent_custom ) ? true : false;
523
  }
524
+
525
  public function is_parent_wp() {
526
  return ( $this->is_child() && !$this->parent_custom ) ? true : false;
527
  }
528
+
529
  }
includes/class.base.php CHANGED
@@ -8,7 +8,7 @@
8
  */
9
  class SLB_Base {
10
  /* Configuration */
11
-
12
  /**
13
  * Class type
14
  * Controls initialization, etc.
@@ -18,53 +18,53 @@ class SLB_Base {
18
  * @var string
19
  */
20
  protected $mode = 'full';
21
-
22
  /**
23
  * Indicates that instance is model (main controller)
24
  * @var bool
25
  */
26
  protected $model = false;
27
-
28
  /* Properties */
29
-
30
  /**
31
  * Variable name of base object in global scope
32
  * @var string
33
  */
34
  protected $base = 'slb';
35
-
36
  /**
37
  * Prefix for plugin-related data (attributes, DB tables, etc.)
38
  * @var string
39
  */
40
  public $prefix = 'slb';
41
-
42
  /**
43
  * Prefix to be added when creating internal hook (action/filter) tags
44
  * Used by Utilities
45
  * @var string
46
  */
47
  public $hook_prefix = '';
48
-
49
  /**
50
  * Global data
51
  * Facilitates sharing between decoupled objects
52
  * @var array
53
  */
54
  private static $globals = array();
55
-
56
  protected $shared = array('options', 'admin');
57
-
58
  /**
59
  * Capabilities
60
  * @var array
61
  */
62
  protected $caps = null;
63
-
64
  protected $_init = false;
65
-
66
  private static $_init_passed = false;
67
-
68
  /* Client */
69
 
70
  /**
@@ -80,36 +80,36 @@ class SLB_Base {
80
  * > Context in which the script should be included
81
  * > in_footer (bool) optional [Default: FALSE]
82
  * > If TRUE, file will be included in footer of page, otherwise it will be included in the header
83
- *
84
  * Array is processed and converted to an object on init
85
  */
86
  private $client_files = array (
87
  'scripts' => array(),
88
  'styles' => array()
89
  );
90
-
91
  /*-** Instances **-*/
92
-
93
  /**
94
  * Utilities
95
  * @var SLB_Utilities
96
  */
97
  var $util = null;
98
-
99
  /**
100
  * Options
101
  * @var SLB_Options
102
  */
103
  protected $options = null;
104
-
105
  /**
106
  * Admin
107
  * @var SLB_Admin
108
  */
109
  var $admin = null;
110
-
111
  /*-** Initialization **-*/
112
-
113
  /**
114
  * Constructor
115
  */
@@ -124,7 +124,7 @@ class SLB_Base {
124
  }
125
  }
126
  }
127
-
128
  /**
129
  * Default initialization method
130
  * @uses _init_passed
@@ -145,7 +145,7 @@ class SLB_Base {
145
  if ( $this->can('control') ) {
146
  // Options
147
  $this->_options();
148
-
149
  // Admin
150
  if ( is_admin() )
151
  $this->_admin();
@@ -153,11 +153,11 @@ class SLB_Base {
153
 
154
  // Hooks
155
  $this->_hooks();
156
-
157
  // Client files
158
  $this->_client_files();
159
  }
160
-
161
  /**
162
  * Initialize environment (Localization, etc.)
163
  */
@@ -172,17 +172,17 @@ class SLB_Base {
172
  if ( is_dir($lpath_abs) ) {
173
  load_plugin_textdomain('simple-lightbox', false, $lpath);
174
  }
175
-
176
  // Context
177
  add_action( ( is_admin() ) ? 'admin_print_footer_scripts' : 'wp_footer', $this->util->m('set_client_context'), $this->util->priority('client_footer_output') );
178
  }
179
-
180
  /**
181
  * Initialize options
182
  * To be implemented in child classes
183
  */
184
  protected function _options() {}
185
-
186
  /**
187
  * Initialize options
188
  * To be called by child class
@@ -206,7 +206,7 @@ class SLB_Base {
206
  // Set instance property
207
  $this->options = $opts;
208
  }
209
-
210
  /**
211
  * Initialize admin
212
  * To be called by child class
@@ -229,7 +229,7 @@ class SLB_Base {
229
  // Set instance property
230
  $this->admin = $adm;
231
  }
232
-
233
  /**
234
  * Register default hooks
235
  */
@@ -239,13 +239,13 @@ class SLB_Base {
239
  $func_activate = '_activate';
240
  if ( method_exists($this, $func_activate) )
241
  register_activation_hook($base, $this->m($func_activate));
242
-
243
  // Deactivation
244
  $func_deactivate = '_deactivate';
245
  if ( method_exists($this, $func_deactivate) )
246
  register_deactivation_hook($base, $this->m($func_deactivate));
247
  }
248
-
249
  /**
250
  * Initialize client files
251
  */
@@ -253,7 +253,7 @@ class SLB_Base {
253
  // Validation
254
  if ( !is_array($files) || empty($files) ) {
255
  return false;
256
- }
257
  foreach ( $this->client_files as $key => $val ) {
258
  if ( isset($files[$key]) && is_array($files[$key]) || !empty($files[$key]) ) {
259
  $this->client_files[$key] = $this->util->parse_client_files($files[$key], $key);
@@ -263,16 +263,16 @@ class SLB_Base {
263
  unset($this->client_files[$key]);
264
  }
265
  }
266
-
267
-
268
  // Stop if no files are set for registration
269
  if ( empty($this->client_files) ) {
270
  return false;
271
  }
272
-
273
  // Register
274
  add_action('init', $this->m('register_client_files'));
275
-
276
  // Enqueue
277
  $hk_prfx = ( ( is_admin() ) ? 'admin' : 'wp' );
278
  $hk_enqueue = $hk_prfx . '_enqueue_scripts' ;
@@ -280,7 +280,7 @@ class SLB_Base {
280
  add_action($hk_enqueue, $this->m('enqueue_client_files'), 10, 0);
281
  add_action($hk_enqueue_ft, $this->m('enqueue_client_files_footer'), 1);
282
  }
283
-
284
  /**
285
  * Register client files
286
  * @see enqueue_client_files() for actual loading of files based on context
@@ -311,7 +311,7 @@ class SLB_Base {
311
  }
312
  }
313
  }
314
-
315
  /**
316
  * Enqueues files for client output (scripts/styles) based on context
317
  * @uses `admin_enqueue_scripts` Action hook depending on context
@@ -384,7 +384,7 @@ class SLB_Base {
384
  public function enqueue_client_files_footer() {
385
  $this->enqueue_client_files(true);
386
  }
387
-
388
  /**
389
  * Build function name for handling client operations
390
  */
@@ -394,9 +394,9 @@ class SLB_Base {
394
  $func = false;
395
  return $func;
396
  }
397
-
398
  /*-** Reflection **-*/
399
-
400
  /**
401
  * Retrieve base object
402
  * @return object|bool Base object (FALSE if object does not exist)
@@ -404,12 +404,12 @@ class SLB_Base {
404
  function &get_base() {
405
  $base = false;
406
  if ( isset($GLOBALS[$this->base]) )
407
- $base =& $GLOBALS[$this->base];
408
  return $base;
409
  }
410
-
411
  /*-** Method/Function calling **-*/
412
-
413
  /**
414
  * Returns callback to instance method
415
  * @param string $method Method name
@@ -418,9 +418,9 @@ class SLB_Base {
418
  function m($method) {
419
  return $this->util->m($this, $method);
420
  }
421
-
422
  /*-** Prefix **-*/
423
-
424
  /**
425
  * Retrieve class prefix (with separator if set)
426
  * @param bool|string $sep Separator to append to class prefix (Default: no separator)
@@ -430,7 +430,7 @@ class SLB_Base {
430
  $args = func_get_args();
431
  return call_user_func_array($this->util->m($this->util, 'get_prefix'), $args);
432
  }
433
-
434
  /**
435
  * Check if a string is prefixed
436
  * @param string $text Text to check for prefix
@@ -440,7 +440,7 @@ class SLB_Base {
440
  $args = func_get_args();
441
  return call_user_func_array($this->util->m($this->util, 'has_prefix'), $args);
442
  }
443
-
444
  /**
445
  * Prepend plugin prefix to some text
446
  * @param string $text Text to add to prefix
@@ -452,7 +452,7 @@ class SLB_Base {
452
  $args = func_get_args();
453
  return call_user_func_array($this->util->m($this->util, 'add_prefix'), $args);
454
  }
455
-
456
  /**
457
  * Prepend uppercased plugin prefix to some text
458
  * @param string $text Text to add to prefix
@@ -464,7 +464,7 @@ class SLB_Base {
464
  $args = func_get_args();
465
  return call_user_func_array($this->util->m($this->util, 'add_prefix_uc'), $args);
466
  }
467
-
468
  /**
469
  * Add prefix to variable reference
470
  * Updates actual variable rather than return value
@@ -479,7 +479,7 @@ class SLB_Base {
479
  $args[0] =& $var;
480
  call_user_func_array($this->util->m($this->util, 'add_prefix_ref'), $args);
481
  }
482
-
483
  /**
484
  * Remove prefix from specified string
485
  * @param string $text String to remove prefix from
@@ -489,9 +489,9 @@ class SLB_Base {
489
  $args = func_get_args();
490
  return call_user_func_array($this->util->m($this->util, 'remove_prefix'), $args);
491
  }
492
-
493
  /*-** Capabilities **-*/
494
-
495
  protected function can($cap) {
496
  if ( is_null($this->caps) ) {
497
  // Build capabilities based on instance properties
@@ -503,9 +503,9 @@ class SLB_Base {
503
  }
504
  return ( isset($this->caps[$cap]) ) ? $this->caps[$cap] : false;
505
  }
506
-
507
  /*-** Globals **-*/
508
-
509
  /**
510
  * Get/Set (internal) global variables
511
  * @uses $globals to get/set global variables
@@ -531,13 +531,13 @@ class SLB_Base {
531
  }
532
  return $ret;
533
  }
534
-
535
  private function shares($name) {
536
  return ( !empty($this->shared) && in_array($name, $this->shared) ) ? true : false;
537
  }
538
-
539
  /*-** Options **-*/
540
-
541
  /**
542
  * Checks if options are valid
543
  * @param array $data Data to be used on options
8
  */
9
  class SLB_Base {
10
  /* Configuration */
11
+
12
  /**
13
  * Class type
14
  * Controls initialization, etc.
18
  * @var string
19
  */
20
  protected $mode = 'full';
21
+
22
  /**
23
  * Indicates that instance is model (main controller)
24
  * @var bool
25
  */
26
  protected $model = false;
27
+
28
  /* Properties */
29
+
30
  /**
31
  * Variable name of base object in global scope
32
  * @var string
33
  */
34
  protected $base = 'slb';
35
+
36
  /**
37
  * Prefix for plugin-related data (attributes, DB tables, etc.)
38
  * @var string
39
  */
40
  public $prefix = 'slb';
41
+
42
  /**
43
  * Prefix to be added when creating internal hook (action/filter) tags
44
  * Used by Utilities
45
  * @var string
46
  */
47
  public $hook_prefix = '';
48
+
49
  /**
50
  * Global data
51
  * Facilitates sharing between decoupled objects
52
  * @var array
53
  */
54
  private static $globals = array();
55
+
56
  protected $shared = array('options', 'admin');
57
+
58
  /**
59
  * Capabilities
60
  * @var array
61
  */
62
  protected $caps = null;
63
+
64
  protected $_init = false;
65
+
66
  private static $_init_passed = false;
67
+
68
  /* Client */
69
 
70
  /**
80
  * > Context in which the script should be included
81
  * > in_footer (bool) optional [Default: FALSE]
82
  * > If TRUE, file will be included in footer of page, otherwise it will be included in the header
83
+ *
84
  * Array is processed and converted to an object on init
85
  */
86
  private $client_files = array (
87
  'scripts' => array(),
88
  'styles' => array()
89
  );
90
+
91
  /*-** Instances **-*/
92
+
93
  /**
94
  * Utilities
95
  * @var SLB_Utilities
96
  */
97
  var $util = null;
98
+
99
  /**
100
  * Options
101
  * @var SLB_Options
102
  */
103
  protected $options = null;
104
+
105
  /**
106
  * Admin
107
  * @var SLB_Admin
108
  */
109
  var $admin = null;
110
+
111
  /*-** Initialization **-*/
112
+
113
  /**
114
  * Constructor
115
  */
124
  }
125
  }
126
  }
127
+
128
  /**
129
  * Default initialization method
130
  * @uses _init_passed
145
  if ( $this->can('control') ) {
146
  // Options
147
  $this->_options();
148
+
149
  // Admin
150
  if ( is_admin() )
151
  $this->_admin();
153
 
154
  // Hooks
155
  $this->_hooks();
156
+
157
  // Client files
158
  $this->_client_files();
159
  }
160
+
161
  /**
162
  * Initialize environment (Localization, etc.)
163
  */
172
  if ( is_dir($lpath_abs) ) {
173
  load_plugin_textdomain('simple-lightbox', false, $lpath);
174
  }
175
+
176
  // Context
177
  add_action( ( is_admin() ) ? 'admin_print_footer_scripts' : 'wp_footer', $this->util->m('set_client_context'), $this->util->priority('client_footer_output') );
178
  }
179
+
180
  /**
181
  * Initialize options
182
  * To be implemented in child classes
183
  */
184
  protected function _options() {}
185
+
186
  /**
187
  * Initialize options
188
  * To be called by child class
206
  // Set instance property
207
  $this->options = $opts;
208
  }
209
+
210
  /**
211
  * Initialize admin
212
  * To be called by child class
229
  // Set instance property
230
  $this->admin = $adm;
231
  }
232
+
233
  /**
234
  * Register default hooks
235
  */
239
  $func_activate = '_activate';
240
  if ( method_exists($this, $func_activate) )
241
  register_activation_hook($base, $this->m($func_activate));
242
+
243
  // Deactivation
244
  $func_deactivate = '_deactivate';
245
  if ( method_exists($this, $func_deactivate) )
246
  register_deactivation_hook($base, $this->m($func_deactivate));
247
  }
248
+
249
  /**
250
  * Initialize client files
251
  */
253
  // Validation
254
  if ( !is_array($files) || empty($files) ) {
255
  return false;
256
+ }
257
  foreach ( $this->client_files as $key => $val ) {
258
  if ( isset($files[$key]) && is_array($files[$key]) || !empty($files[$key]) ) {
259
  $this->client_files[$key] = $this->util->parse_client_files($files[$key], $key);
263
  unset($this->client_files[$key]);
264
  }
265
  }
266
+
267
+
268
  // Stop if no files are set for registration
269
  if ( empty($this->client_files) ) {
270
  return false;
271
  }
272
+
273
  // Register
274
  add_action('init', $this->m('register_client_files'));
275
+
276
  // Enqueue
277
  $hk_prfx = ( ( is_admin() ) ? 'admin' : 'wp' );
278
  $hk_enqueue = $hk_prfx . '_enqueue_scripts' ;
280
  add_action($hk_enqueue, $this->m('enqueue_client_files'), 10, 0);
281
  add_action($hk_enqueue_ft, $this->m('enqueue_client_files_footer'), 1);
282
  }
283
+
284
  /**
285
  * Register client files
286
  * @see enqueue_client_files() for actual loading of files based on context
311
  }
312
  }
313
  }
314
+
315
  /**
316
  * Enqueues files for client output (scripts/styles) based on context
317
  * @uses `admin_enqueue_scripts` Action hook depending on context
384
  public function enqueue_client_files_footer() {
385
  $this->enqueue_client_files(true);
386
  }
387
+
388
  /**
389
  * Build function name for handling client operations
390
  */
394
  $func = false;
395
  return $func;
396
  }
397
+
398
  /*-** Reflection **-*/
399
+
400
  /**
401
  * Retrieve base object
402
  * @return object|bool Base object (FALSE if object does not exist)
404
  function &get_base() {
405
  $base = false;
406
  if ( isset($GLOBALS[$this->base]) )
407
+ $base =& $GLOBALS[$this->base];
408
  return $base;
409
  }
410
+
411
  /*-** Method/Function calling **-*/
412
+
413
  /**
414
  * Returns callback to instance method
415
  * @param string $method Method name
418
  function m($method) {
419
  return $this->util->m($this, $method);
420
  }
421
+
422
  /*-** Prefix **-*/
423
+
424
  /**
425
  * Retrieve class prefix (with separator if set)
426
  * @param bool|string $sep Separator to append to class prefix (Default: no separator)
430
  $args = func_get_args();
431
  return call_user_func_array($this->util->m($this->util, 'get_prefix'), $args);
432
  }
433
+
434
  /**
435
  * Check if a string is prefixed
436
  * @param string $text Text to check for prefix
440
  $args = func_get_args();
441
  return call_user_func_array($this->util->m($this->util, 'has_prefix'), $args);
442
  }
443
+
444
  /**
445
  * Prepend plugin prefix to some text
446
  * @param string $text Text to add to prefix
452
  $args = func_get_args();
453
  return call_user_func_array($this->util->m($this->util, 'add_prefix'), $args);
454
  }
455
+
456
  /**
457
  * Prepend uppercased plugin prefix to some text
458
  * @param string $text Text to add to prefix
464
  $args = func_get_args();
465
  return call_user_func_array($this->util->m($this->util, 'add_prefix_uc'), $args);
466
  }
467
+
468
  /**
469
  * Add prefix to variable reference
470
  * Updates actual variable rather than return value
479
  $args[0] =& $var;
480
  call_user_func_array($this->util->m($this->util, 'add_prefix_ref'), $args);
481
  }
482
+
483
  /**
484
  * Remove prefix from specified string
485
  * @param string $text String to remove prefix from
489
  $args = func_get_args();
490
  return call_user_func_array($this->util->m($this->util, 'remove_prefix'), $args);
491
  }
492
+
493
  /*-** Capabilities **-*/
494
+
495
  protected function can($cap) {
496
  if ( is_null($this->caps) ) {
497
  // Build capabilities based on instance properties
503
  }
504
  return ( isset($this->caps[$cap]) ) ? $this->caps[$cap] : false;
505
  }
506
+
507
  /*-** Globals **-*/
508
+
509
  /**
510
  * Get/Set (internal) global variables
511
  * @uses $globals to get/set global variables
531
  }
532
  return $ret;
533
  }
534
+
535
  private function shares($name) {
536
  return ( !empty($this->shared) && in_array($name, $this->shared) ) ? true : false;
537
  }
538
+
539
  /*-** Options **-*/
540
+
541
  /**
542
  * Checks if options are valid
543
  * @param array $data Data to be used on options
includes/class.base_collection.php CHANGED
@@ -8,7 +8,7 @@
8
  */
9
  class SLB_Base_Collection extends SLB_Base {
10
  /* Configuration */
11
-
12
  /**
13
  * Set object mode
14
  * @var string
@@ -20,28 +20,28 @@ class SLB_Base_Collection extends SLB_Base {
20
  * @var string
21
  */
22
  protected $item_type = null;
23
-
24
  /**
25
  * Property to use for item key
26
  * Example: A property or method of the item
27
  * @var string
28
  */
29
  protected $key_prop = null;
30
-
31
  /**
32
  * Should $key_prop be called or retrieved?
33
  * Default: Retrieved (FALSE)
34
  * @var bool
35
  */
36
  protected $key_call = false;
37
-
38
  /**
39
  * Items in collection unique?
40
  * Default: FALSE
41
  * @var bool
42
  */
43
  protected $unique = false;
44
-
45
  /* Properties */
46
 
47
  /**
@@ -49,16 +49,16 @@ class SLB_Base_Collection extends SLB_Base {
49
  * @var array
50
  */
51
  protected $items = null;
52
-
53
  /**
54
  * Item metadata
55
  * Indexed by item key
56
  * @var array
57
  */
58
  protected $items_meta = array();
59
-
60
  /* Item Management */
61
-
62
  /**
63
  * Initialize collections
64
  * Calls `init` action if collection has a hook prefix
@@ -72,7 +72,7 @@ class SLB_Base_Collection extends SLB_Base {
72
  }
73
  }
74
  }
75
-
76
  /**
77
  * Normalize/Validate item(s)
78
  * TODO: If no items are specified, then collection is normalized
@@ -98,12 +98,12 @@ class SLB_Base_Collection extends SLB_Base {
98
  }
99
  return $items;
100
  }
101
-
102
  protected function item_valid($item) {
103
- // Validate item type
104
  return ( empty($this->item_type) || ( $item instanceof $this->item_type ) ) ? true : false;
105
  }
106
-
107
  /**
108
  * Validate item key
109
  * Checks collection for existence of key as well
@@ -114,7 +114,7 @@ class SLB_Base_Collection extends SLB_Base {
114
  $this->init();
115
  return ( ( ( is_string($key) && !empty($key) ) || is_int($key) ) && isset($this->items[$key]) ) ? true : false;
116
  }
117
-
118
  /**
119
  * Generate key for item (for storing in collection, etc.)
120
  * @param mixed $item Item to generate key for
@@ -141,7 +141,7 @@ class SLB_Base_Collection extends SLB_Base {
141
  }
142
  return $ret;
143
  }
144
-
145
  /**
146
  * Add item to collection
147
  * @param mixed $item Item to add to collection
@@ -167,11 +167,11 @@ class SLB_Base_Collection extends SLB_Base {
167
  }
168
  return $this;
169
  }
170
-
171
  /**
172
  * Remove item from collection
173
  * @param int|string $item Key of item to remove
174
- * @return Current instance
175
  */
176
  public function remove($item) {
177
  if ( $this->key_valid($item) ) {
@@ -179,7 +179,7 @@ class SLB_Base_Collection extends SLB_Base {
179
  }
180
  return $this;
181
  }
182
-
183
  /**
184
  * Clear collection
185
  * @return Current instance
@@ -188,7 +188,7 @@ class SLB_Base_Collection extends SLB_Base {
188
  $this->items = array();
189
  return $this;
190
  }
191
-
192
  /**
193
  * Checks if item exists in the collection
194
  * @param mixed $item Item(s) to check for
@@ -198,7 +198,7 @@ class SLB_Base_Collection extends SLB_Base {
198
  // Attempt to locate item
199
  return false;
200
  }
201
-
202
  /**
203
  * Retrieve item(s) from collection
204
  * If no items specified, entire collection returned
@@ -215,9 +215,9 @@ class SLB_Base_Collection extends SLB_Base {
215
  'exclude' => array(),
216
  );
217
  $r = wp_parse_args($args, $args_default);
218
-
219
  $items = $this->items;
220
-
221
  /* Sort */
222
  if ( !is_null($r['orderby']) ) {
223
  // Validate
@@ -260,9 +260,9 @@ class SLB_Base_Collection extends SLB_Base {
260
  }
261
  return $items;
262
  }
263
-
264
  /* Metadata */
265
-
266
  /**
267
  * Add metadata for item
268
  * @param string|int $item Item key
@@ -291,7 +291,7 @@ class SLB_Base_Collection extends SLB_Base {
291
  }
292
  return $this;
293
  }
294
-
295
  /**
296
  * Remove item metadata
297
  * @param string $item Item key
@@ -309,7 +309,7 @@ class SLB_Base_Collection extends SLB_Base {
309
  }
310
  return $this;
311
  }
312
-
313
  /**
314
  * Retrieve metadata
315
  * @param string $item Item key
@@ -327,9 +327,9 @@ class SLB_Base_Collection extends SLB_Base {
327
  }
328
  return $ret;
329
  }
330
-
331
  /* Collection */
332
-
333
  /**
334
  * Build entire collection of items
335
  * Prints output
@@ -345,7 +345,7 @@ class SLB_Base_Collection extends SLB_Base {
345
  // Post-build output
346
  $this->util->do_action_ref_array('build_post', array($this));
347
  }
348
-
349
  /**
350
  * Parses build variables prior to use
351
  * @uses this->reset_build_vars() to reset build variables for each request
@@ -353,9 +353,9 @@ class SLB_Base_Collection extends SLB_Base {
353
  */
354
  function parse_build_vars($build_vars = array()) {
355
  $this->reset_build_vars();
356
- $this->build_vars = $this->util->apply_filters('parse_build_vars', wp_parse_args($build_vars, $this->build_vars), $this);
357
  }
358
-
359
  /**
360
  * Reset build variables to defaults
361
  * Default Variables
8
  */
9
  class SLB_Base_Collection extends SLB_Base {
10
  /* Configuration */
11
+
12
  /**
13
  * Set object mode
14
  * @var string
20
  * @var string
21
  */
22
  protected $item_type = null;
23
+
24
  /**
25
  * Property to use for item key
26
  * Example: A property or method of the item
27
  * @var string
28
  */
29
  protected $key_prop = null;
30
+
31
  /**
32
  * Should $key_prop be called or retrieved?
33
  * Default: Retrieved (FALSE)
34
  * @var bool
35
  */
36
  protected $key_call = false;
37
+
38
  /**
39
  * Items in collection unique?
40
  * Default: FALSE
41
  * @var bool
42
  */
43
  protected $unique = false;
44
+
45
  /* Properties */
46
 
47
  /**
49
  * @var array
50
  */
51
  protected $items = null;
52
+
53
  /**
54
  * Item metadata
55
  * Indexed by item key
56
  * @var array
57
  */
58
  protected $items_meta = array();
59
+
60
  /* Item Management */
61
+
62
  /**
63
  * Initialize collections
64
  * Calls `init` action if collection has a hook prefix
72
  }
73
  }
74
  }
75
+
76
  /**
77
  * Normalize/Validate item(s)
78
  * TODO: If no items are specified, then collection is normalized
98
  }
99
  return $items;
100
  }
101
+
102
  protected function item_valid($item) {
103
+ // Validate item type
104
  return ( empty($this->item_type) || ( $item instanceof $this->item_type ) ) ? true : false;
105
  }
106
+
107
  /**
108
  * Validate item key
109
  * Checks collection for existence of key as well
114
  $this->init();
115
  return ( ( ( is_string($key) && !empty($key) ) || is_int($key) ) && isset($this->items[$key]) ) ? true : false;
116
  }
117
+
118
  /**
119
  * Generate key for item (for storing in collection, etc.)
120
  * @param mixed $item Item to generate key for
141
  }
142
  return $ret;
143
  }
144
+
145
  /**
146
  * Add item to collection
147
  * @param mixed $item Item to add to collection
167
  }
168
  return $this;
169
  }
170
+
171
  /**
172
  * Remove item from collection
173
  * @param int|string $item Key of item to remove
174
+ * @return Current instance
175
  */
176
  public function remove($item) {
177
  if ( $this->key_valid($item) ) {
179
  }
180
  return $this;
181
  }
182
+
183
  /**
184
  * Clear collection
185
  * @return Current instance
188
  $this->items = array();
189
  return $this;
190
  }
191
+
192
  /**
193
  * Checks if item exists in the collection
194
  * @param mixed $item Item(s) to check for
198
  // Attempt to locate item
199
  return false;
200
  }
201
+
202
  /**
203
  * Retrieve item(s) from collection
204
  * If no items specified, entire collection returned
215
  'exclude' => array(),
216
  );
217
  $r = wp_parse_args($args, $args_default);
218
+
219
  $items = $this->items;
220
+
221
  /* Sort */
222
  if ( !is_null($r['orderby']) ) {
223
  // Validate
260
  }
261
  return $items;
262
  }
263
+
264
  /* Metadata */
265
+
266
  /**
267
  * Add metadata for item
268
  * @param string|int $item Item key
291
  }
292
  return $this;
293
  }
294
+
295
  /**
296
  * Remove item metadata
297
  * @param string $item Item key
309
  }
310
  return $this;
311
  }
312
+
313
  /**
314
  * Retrieve metadata
315
  * @param string $item Item key
327
  }
328
  return $ret;
329
  }
330
+
331
  /* Collection */
332
+
333
  /**
334
  * Build entire collection of items
335
  * Prints output
345
  // Post-build output
346
  $this->util->do_action_ref_array('build_post', array($this));
347
  }
348
+
349
  /**
350
  * Parses build variables prior to use
351
  * @uses this->reset_build_vars() to reset build variables for each request
353
  */
354
  function parse_build_vars($build_vars = array()) {
355
  $this->reset_build_vars();
356
+ $this->build_vars = $this->util->apply_filters('parse_build_vars', wp_parse_args($build_vars, $this->build_vars), $this);
357
  }
358
+
359
  /**
360
  * Reset build variables to defaults
361
  * Default Variables
includes/class.base_object.php CHANGED
@@ -8,27 +8,27 @@
8
  */
9
  class SLB_Base_Object extends SLB_Base {
10
  /* Configuration */
11
-
12
  /**
13
  * @var string
14
  * @see Base::$mode
15
  */
16
  protected $mode = 'object';
17
-
18
  /*-** Properties **-*/
19
-
20
  /**
21
  * Unique ID
22
  * @var string
23
  */
24
  protected $id = '';
25
-
26
  /**
27
  * Parent object
28
  * @var Base_Object
29
  */
30
  protected $parent = null;
31
-
32
  /**
33
  * Attached files
34
  * @var array
@@ -39,15 +39,15 @@ class SLB_Base_Object extends SLB_Base {
39
  'scripts' => array(),
40
  'styles' => array()
41
  );
42
-
43
  /**
44
  * Properties that can be inherited from parent
45
  * @var array
46
  */
47
  protected $parent_props = array();
48
-
49
  /*-** Methods **-*/
50
-
51
  /**
52
  * Constructor
53
  * @param string $id Unique ID for content type
@@ -59,7 +59,7 @@ class SLB_Base_Object extends SLB_Base {
59
  ->set_id($id)
60
  ->set_props($props);
61
  }
62
-
63
  /**
64
  * Checks if object is valid
65
  * To be overriden by child classes
@@ -67,9 +67,9 @@ class SLB_Base_Object extends SLB_Base {
67
  public function is_valid() {
68
  return true;
69
  }
70
-
71
  /*-** Getters/Setters **-*/
72
-
73
  /**
74
  * Get ID
75
  * @return string ID
@@ -77,7 +77,7 @@ class SLB_Base_Object extends SLB_Base {
77
  public function get_id() {
78
  return $this->id;
79
  }
80
-
81
  /**
82
  * Set ID
83
  * @param string $id ID
@@ -90,7 +90,7 @@ class SLB_Base_Object extends SLB_Base {
90
  }
91
  return $this;
92
  }
93
-
94
  /**
95
  * Set type properties
96
  * @param array $props Type properties to set
@@ -107,7 +107,7 @@ class SLB_Base_Object extends SLB_Base {
107
  }
108
  return $this;
109
  }
110
-
111
  /**
112
  * Get parent
113
  * @return object|null Parent
@@ -115,7 +115,7 @@ class SLB_Base_Object extends SLB_Base {
115
  public function get_parent() {
116
  return $this->parent;
117
  }
118
-
119
  /**
120
  * Set parent
121
  * @param object $parent Parent object
@@ -133,7 +133,7 @@ class SLB_Base_Object extends SLB_Base {
133
  public function has_parent() {
134
  return ( is_null($this->parent) ) ? false : true;
135
  }
136
-
137
  /**
138
  * Retrieve all ancestors
139
  * @return array Ancestors
@@ -149,9 +149,9 @@ class SLB_Base_Object extends SLB_Base {
149
  }
150
  return $ret;
151
  }
152
-
153
  /* Files */
154
-
155
  /**
156
  * Add file
157
  * @param string $type Group to add file to
@@ -170,11 +170,11 @@ class SLB_Base_Object extends SLB_Base {
170
  $this->files[$type] = array();
171
  }
172
  // Add file to group
173
- $this->files[$type][$handle] = array('handle' => $handle, 'uri' => $src, 'deps' => $deps);
174
  }
175
  return $this;
176
  }
177
-
178
  /**
179
  * Add multiple files
180
  * @param string $type Group to add files to
@@ -195,7 +195,7 @@ class SLB_Base_Object extends SLB_Base {
195
  }
196
  return $this;
197
  }
198
-
199
  /**
200
  * Retrieve files
201
  * All files or a specific group of files can be retrieved
@@ -212,7 +212,7 @@ class SLB_Base_Object extends SLB_Base {
212
  }
213
  return $ret;
214
  }
215
-
216
  /**
217
  * Retrieve file
218
  * @param string $type Group to retrieve file from
@@ -258,7 +258,7 @@ class SLB_Base_Object extends SLB_Base {
258
  }
259
  return $ret;
260
  }
261
-
262
  /**
263
  * Add stylesheet
264
  * @param string $handle Name of the stylesheet
@@ -268,7 +268,7 @@ class SLB_Base_Object extends SLB_Base {
268
  public function add_style($handle, $src, $deps = array()) {
269
  return $this->add_file('styles', $handle, $src, $deps);
270
  }
271
-
272
  /**
273
  * Retrieve stylesheet files
274
  * @return array Stylesheet files
@@ -295,7 +295,7 @@ class SLB_Base_Object extends SLB_Base {
295
  }
296
  return $files;
297
  }
298
-
299
  /**
300
  * Retrieve stylesheet file
301
  * @param string $handle Name of stylesheet
@@ -305,7 +305,7 @@ class SLB_Base_Object extends SLB_Base {
305
  public function get_style($handle, $format = null) {
306
  return $this->get_file('styles', $handle, $format);
307
  }
308
-
309
  /**
310
  * Add script
311
  * @param string $handle Name of the script
@@ -315,7 +315,7 @@ class SLB_Base_Object extends SLB_Base {
315
  public function add_script($handle, $src, $deps = array()) {
316
  return $this->add_file('scripts', $handle, $src, $deps);
317
  }
318
-
319
  /**
320
  * Retrieve script files
321
  * @return array Script files
@@ -323,7 +323,7 @@ class SLB_Base_Object extends SLB_Base {
323
  public function get_scripts() {
324
  return $this->get_files('scripts');
325
  }
326
-
327
  /**
328
  * Retrieve script file
329
  * @param string $handle Name of script
@@ -333,5 +333,5 @@ class SLB_Base_Object extends SLB_Base {
333
  public function get_script($handle, $format = null) {
334
  return $this->get_file('scripts', $handle, $format);
335
  }
336
-
337
  }
8
  */
9
  class SLB_Base_Object extends SLB_Base {
10
  /* Configuration */
11
+
12
  /**
13
  * @var string
14
  * @see Base::$mode
15
  */
16
  protected $mode = 'object';
17
+
18
  /*-** Properties **-*/
19
+
20
  /**
21
  * Unique ID
22
  * @var string
23
  */
24
  protected $id = '';
25
+
26
  /**
27
  * Parent object
28
  * @var Base_Object
29
  */
30
  protected $parent = null;
31
+
32
  /**
33
  * Attached files
34
  * @var array
39
  'scripts' => array(),
40
  'styles' => array()
41
  );
42
+
43
  /**
44
  * Properties that can be inherited from parent
45
  * @var array
46
  */
47
  protected $parent_props = array();
48
+
49
  /*-** Methods **-*/
50
+
51
  /**
52
  * Constructor
53
  * @param string $id Unique ID for content type
59
  ->set_id($id)
60
  ->set_props($props);
61
  }
62
+
63
  /**
64
  * Checks if object is valid
65
  * To be overriden by child classes
67
  public function is_valid() {
68
  return true;
69
  }
70
+
71
  /*-** Getters/Setters **-*/
72
+
73
  /**
74
  * Get ID
75
  * @return string ID
77
  public function get_id() {
78
  return $this->id;
79
  }
80
+
81
  /**
82
  * Set ID
83
  * @param string $id ID
90
  }
91
  return $this;
92
  }
93
+
94
  /**
95
  * Set type properties
96
  * @param array $props Type properties to set
107
  }
108
  return $this;
109
  }
110
+
111
  /**
112
  * Get parent
113
  * @return object|null Parent
115
  public function get_parent() {
116
  return $this->parent;
117
  }
118
+
119
  /**
120
  * Set parent
121
  * @param object $parent Parent object
133
  public function has_parent() {
134
  return ( is_null($this->parent) ) ? false : true;
135
  }
136
+
137
  /**
138
  * Retrieve all ancestors
139
  * @return array Ancestors
149
  }
150
  return $ret;
151
  }
152
+
153
  /* Files */
154
+
155
  /**
156
  * Add file
157
  * @param string $type Group to add file to
170
  $this->files[$type] = array();
171
  }
172
  // Add file to group
173
+ $this->files[$type][$handle] = array('handle' => $handle, 'uri' => $src, 'deps' => $deps);
174
  }
175
  return $this;
176
  }
177
+
178
  /**
179
  * Add multiple files
180
  * @param string $type Group to add files to
195
  }
196
  return $this;
197
  }
198
+
199
  /**
200
  * Retrieve files
201
  * All files or a specific group of files can be retrieved
212
  }
213
  return $ret;
214
  }
215
+
216
  /**
217
  * Retrieve file
218
  * @param string $type Group to retrieve file from
258
  }
259
  return $ret;
260
  }
261
+
262
  /**
263
  * Add stylesheet
264
  * @param string $handle Name of the stylesheet
268
  public function add_style($handle, $src, $deps = array()) {
269
  return $this->add_file('styles', $handle, $src, $deps);
270
  }
271
+
272
  /**
273
  * Retrieve stylesheet files
274
  * @return array Stylesheet files
295
  }
296
  return $files;
297
  }
298
+
299
  /**
300
  * Retrieve stylesheet file
301
  * @param string $handle Name of stylesheet
305
  public function get_style($handle, $format = null) {
306
  return $this->get_file('styles', $handle, $format);
307
  }
308
+
309
  /**
310
  * Add script
311
  * @param string $handle Name of the script
315
  public function add_script($handle, $src, $deps = array()) {
316
  return $this->add_file('scripts', $handle, $src, $deps);
317
  }
318
+
319
  /**
320
  * Retrieve script files
321
  * @return array Script files
323
  public function get_scripts() {
324
  return $this->get_files('scripts');
325
  }
326
+
327
  /**
328
  * Retrieve script file
329
  * @param string $handle Name of script
333
  public function get_script($handle, $format = null) {
334
  return $this->get_file('scripts', $handle, $format);
335
  }
336
+
337
  }
includes/class.collection_controller.php CHANGED
@@ -8,26 +8,26 @@
8
  */
9
  class SLB_Collection_Controller extends SLB_Base_Collection {
10
  /* Configuration */
11
-
12
  protected $mode = 'full';
13
-
14
  protected $unique = true;
15
-
16
  /* Properties */
17
-
18
  protected $parent = null;
19
-
20
  /* Methods */
21
 
22
  public function __construct($parent = null) {
23
  $this->set_parent($parent);
24
  parent::__construct();
25
  }
26
-
27
  /* Initialization */
28
-
29
  /* Parent */
30
-
31
  /**
32
  * Set parent instance
33
  * @param SLB_Base $parent (optional) Parent instance
@@ -37,7 +37,7 @@ class SLB_Collection_Controller extends SLB_Base_Collection {
37
  $this->parent = ( $parent instanceof SLB_Base ) ? $parent : null;
38
  return $this;
39
  }
40
-
41
  /**
42
  * Check if parent set
43
  * @return bool TRUE if parent set
@@ -45,7 +45,7 @@ class SLB_Collection_Controller extends SLB_Base_Collection {
45
  protected function has_parent() {
46
  return ( is_object($this->get_parent()) ) ? true : false;
47
  }
48
-
49
  /**
50
  * Retrieve parent
51
  * @uses $parent
8
  */
9
  class SLB_Collection_Controller extends SLB_Base_Collection {
10
  /* Configuration */
11
+
12
  protected $mode = 'full';
13
+
14
  protected $unique = true;
15
+
16
  /* Properties */
17
+
18
  protected $parent = null;
19
+
20
  /* Methods */
21
 
22
  public function __construct($parent = null) {
23
  $this->set_parent($parent);
24
  parent::__construct();
25
  }
26
+
27
  /* Initialization */
28
+
29
  /* Parent */
30
+
31
  /**
32
  * Set parent instance
33
  * @param SLB_Base $parent (optional) Parent instance
37
  $this->parent = ( $parent instanceof SLB_Base ) ? $parent : null;
38
  return $this;
39
  }
40
+
41
  /**
42
  * Check if parent set
43
  * @return bool TRUE if parent set
45
  protected function has_parent() {
46
  return ( is_object($this->get_parent()) ) ? true : false;
47
  }
48
+
49
  /**
50
  * Retrieve parent
51
  * @uses $parent
includes/class.component.php CHANGED
@@ -8,19 +8,19 @@
8
  */
9
  class SLB_Component extends SLB_Base_Object {
10
  /* Properties */
11
-
12
  /**
13
  * Pretty name
14
  * @var string
15
  */
16
  protected $name = '';
17
-
18
  protected $props_required = array();
19
-
20
  private $props_required_base = array('id');
21
-
22
  /* Get/Set */
23
-
24
  /**
25
  * Set name
26
  * @param string $name Name
@@ -35,21 +35,21 @@ class SLB_Component extends SLB_Base_Object {
35
  }
36
  return $this;
37
  }
38
-
39
  public function get_name() {
40
  return $this->name;
41
  }
42
-
43
  public function set_scripts($scripts) {
44
  $this->add_files('scripts', $scripts);
45
  }
46
-
47
  public function set_styles($styles) {
48
  $this->add_files('styles', $styles);
49
  }
50
-
51
  /* Assets */
52
-
53
  /**
54
  * Get formatted handle for file
55
  * @param string $base_handle Base handle to format
@@ -58,7 +58,7 @@ class SLB_Component extends SLB_Base_Object {
58
  public function get_handle($base_handle) {
59
  return $this->add_prefix( array('asset', $this->get_id(), $base_handle), '-');
60
  }
61
-
62
  /**
63
  * Enqueue files in client
64
  * @param string $type (optional) Type of file to load (singular) (Default: All client file types)
@@ -82,7 +82,7 @@ class SLB_Component extends SLB_Base_Object {
82
  $f = (object) $f;
83
  // Format handle
84
  $handle = $this->get_handle($f->handle);
85
-
86
  // Format dependencies
87
  $deps = array();
88
  foreach ( $f->deps as $dep ) {
@@ -96,7 +96,7 @@ class SLB_Component extends SLB_Base_Object {
96
  unset($files, $f, $param_final, $handle, $deps, $dep);
97
  }
98
  }
99
-
100
  /**
101
  * Enqueue scripts
102
  */
@@ -110,9 +110,9 @@ class SLB_Component extends SLB_Base_Object {
110
  public function enqueue_styles() {
111
  $this->enqueue_client_files('style');
112
  }
113
-
114
  /* Helpers */
115
-
116
  /**
117
  * Validate instance
118
  * @see `Base_Object::is_valid()`
8
  */
9
  class SLB_Component extends SLB_Base_Object {
10
  /* Properties */
11
+
12
  /**
13
  * Pretty name
14
  * @var string
15
  */
16
  protected $name = '';
17
+
18
  protected $props_required = array();
19
+
20
  private $props_required_base = array('id');
21
+
22
  /* Get/Set */
23
+
24
  /**
25
  * Set name
26
  * @param string $name Name
35
  }
36
  return $this;
37
  }
38
+
39
  public function get_name() {
40
  return $this->name;
41
  }
42
+
43
  public function set_scripts($scripts) {
44
  $this->add_files('scripts', $scripts);
45
  }
46
+
47
  public function set_styles($styles) {
48
  $this->add_files('styles', $styles);
49
  }
50
+
51
  /* Assets */
52
+
53
  /**
54
  * Get formatted handle for file
55
  * @param string $base_handle Base handle to format
58
  public function get_handle($base_handle) {
59
  return $this->add_prefix( array('asset', $this->get_id(), $base_handle), '-');
60
  }
61
+
62
  /**
63
  * Enqueue files in client
64
  * @param string $type (optional) Type of file to load (singular) (Default: All client file types)
82
  $f = (object) $f;
83
  // Format handle
84
  $handle = $this->get_handle($f->handle);
85
+
86
  // Format dependencies
87
  $deps = array();
88
  foreach ( $f->deps as $dep ) {
96
  unset($files, $f, $param_final, $handle, $deps, $dep);
97
  }
98
  }
99
+
100
  /**
101
  * Enqueue scripts
102
  */
110
  public function enqueue_styles() {
111
  $this->enqueue_client_files('style');
112
  }
113
+
114
  /* Helpers */
115
+
116
  /**
117
  * Validate instance
118
  * @see `Base_Object::is_valid()`
includes/class.content_handler.php CHANGED
@@ -8,21 +8,21 @@
8
  */
9
  class SLB_Content_Handler extends SLB_Component {
10
  /* Properties */
11
-
12
  /**
13
  * Match handler
14
  * @var callback
15
  */
16
  protected $match;
17
-
18
  /**
19
  * Custom attributes
20
  * @var callback
21
  */
22
  protected $attributes;
23
-
24
  /* Matching */
25
-
26
  /**
27
  * Set matching handler
28
  * @param callback $callback Handler callback
@@ -32,7 +32,7 @@ class SLB_Content_Handler extends SLB_Component {
32
  $this->match = ( is_callable($callback) ) ? $callback : null;
33
  return $this;
34
  }
35
-
36
  /**
37
  * Retrieve match handler
38
  * @return callback|null Match handler
@@ -40,14 +40,14 @@ class SLB_Content_Handler extends SLB_Component {
40
  protected function get_match() {
41
  return $this->match;
42
  }
43
-
44
  /**
45
  * Check if valid match set
46
  */
47
  protected function has_match() {
48
  return ( is_null($this->match) ) ? false : true;
49
  }
50
-
51
  /**
52
  * Match handler against URI
53
  * @param string $uri URI to check for match
@@ -60,14 +60,14 @@ class SLB_Content_Handler extends SLB_Component {
60
  }
61
  return $ret;
62
  }
63
-
64
  /* Attributes */
65
-
66
  public function set_attributes($callback) {
67
  $this->attributes = ( is_callable($callback) ) ? $callback : null;
68
  return $this;
69
  }
70
-
71
  public function get_attributes() {
72
  $ret = array();
73
  // Callback
8
  */
9
  class SLB_Content_Handler extends SLB_Component {
10
  /* Properties */
11
+
12
  /**
13
  * Match handler
14
  * @var callback
15
  */
16
  protected $match;
17
+
18
  /**
19
  * Custom attributes
20
  * @var callback
21
  */
22
  protected $attributes;
23
+
24
  /* Matching */
25
+
26
  /**
27
  * Set matching handler
28
  * @param callback $callback Handler callback
32
  $this->match = ( is_callable($callback) ) ? $callback : null;
33
  return $this;
34
  }
35
+
36
  /**
37
  * Retrieve match handler
38
  * @return callback|null Match handler
40
  protected function get_match() {
41
  return $this->match;
42
  }
43
+
44
  /**
45
  * Check if valid match set
46
  */
47
  protected function has_match() {
48
  return ( is_null($this->match) ) ? false : true;
49
  }
50
+
51
  /**
52
  * Match handler against URI
53
  * @param string $uri URI to check for match
60
  }
61
  return $ret;
62
  }
63
+
64
  /* Attributes */
65
+
66
  public function set_attributes($callback) {
67
  $this->attributes = ( is_callable($callback) ) ? $callback : null;
68
  return $this;
69
  }
70
+
71
  public function get_attributes() {
72
  $ret = array();
73
  // Callback
includes/class.content_handlers.php CHANGED
@@ -8,36 +8,36 @@
8
  */
9
  class SLB_Content_Handlers extends SLB_Collection_Controller {
10
  /* Configuration */
11
-
12
  protected $item_type = 'SLB_Content_Handler';
13
-
14
  public $hook_prefix = 'content_handlers';
15
-
16
  protected $key_prop = 'get_id';
17
-
18
  protected $key_call = true;
19
-
20
  /* Properties */
21
-
22
  protected $request_matches = array();
23
-
24
  /**
25
  * Cache properties (key, group)
26
  * @var object
27
  */
28
  protected $cache_props = null;
29
-
30
  /* Initialization */
31
-
32
  protected function _hooks() {
33
  parent::_hooks();
34
  $this->util->add_action('init', $this->m('init_defaults'), 5);
35
  $this->util->add_action('footer', $this->m('client_output'), 1, 0, false);
36
  $this->util->add_filter('footer_script', $this->m('client_output_script'), $this->util->priority('client_footer_output'), 1, false);
37
  }
38
-
39
  /* Collection Management */
40
-
41
  /**
42
  * Add content type handler
43
  * Accepts properties to create new handler OR previously-initialized handler instance
@@ -65,7 +65,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
65
  // Add to collection
66
  return parent::add($handler, array('priority' => $priority));
67
  }
68
-
69
  /**
70
  * Remove item
71
  * @uses clear_cache()
@@ -76,7 +76,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
76
  $this->clear_cache();
77
  return parent::remove($item);
78
  }
79
-
80
  /**
81
  * Clear collection
82
  * @uses clear_cache()
@@ -87,7 +87,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
87
  $this->clear_cache();
88
  return parent::clear();
89
  }
90
-
91
  /**
92
  * Retrieves handlers sorted by priority
93
  * @see parent::get()
@@ -104,7 +104,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
104
  }
105
  return $items;
106
  }
107
-
108
  /**
109
  * Get matching handler for URI
110
  * @param string $uri URI to find match for
@@ -133,9 +133,9 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
133
  }
134
  return $ret;
135
  }
136
-
137
  /* Cache */
138
-
139
  /**
140
  * Retrieve cached items
141
  * @uses get_cache_props()
@@ -147,7 +147,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
147
  $items = wp_cache_get($cprops->key, $cprops->group);
148
  return ( is_array($items) ) ? $items : array();
149
  }
150
-
151
  /**
152
  * Update cached items
153
  * Cache is cleared if no items specified
@@ -159,7 +159,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
159
  $props = $this->get_cache_props();
160
  wp_cache_set($props->key, $data, $props->group);
161
  }
162
-
163
  /**
164
  * Clear cache
165
  * @uses update_cache()
@@ -167,7 +167,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
167
  protected function clear_cache() {
168
  $this->update_cache();
169
  }
170
-
171
  /**
172
  * Retrieve cache properites (key, group)
173
  * @return object Cache properties
@@ -179,11 +179,11 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
179
  'group' => $this->get_prefix(),
180
  );
181
  }
182
- return $this->cache_props;
183
  }
184
-
185
  /* Handlers */
186
-
187
  /**
188
  * Initialize default handlers
189
  * @param SLB_Content_Handlers $handlers Handlers controller
@@ -204,7 +204,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
204
  $handlers->add($id, $props);
205
  }
206
  }
207
-
208
  /**
209
  * Matches image URIs
210
  * @param string $uri URI to match
@@ -213,22 +213,22 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
213
  public function match_image($uri, $handlers) {
214
  // Basic matching
215
  $match = ( $this->util->has_file_extension($uri, array('jpg', 'jpeg', 'jpe', 'jfif', 'jif', 'gif', 'png')) ) ? true : false;
216
-
217
  // Filter result
218
  $extra = new stdClass();
219
  $match = $this->util->apply_filters('image_match', $match, $uri, $extra);
220
-
221
  // Handle extra data passed from filters
222
  // Currently only `uri` supported
223
  if ( $match && isset($extra->uri) && is_string($extra->uri) ) {
224
  $match = array('uri' => $extra->uri);
225
  }
226
-
227
  return $match;
228
  }
229
-
230
  /* Output */
231
-
232
  /**
233
  * Build client output
234
  * Load handler files in client
@@ -239,7 +239,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
239
  $handler->enqueue_scripts();
240
  }
241
  }
242
-
243
  /**
244
  * Client output script
245
  * @param array $commands Client script commands
@@ -248,7 +248,7 @@ class SLB_Content_Handlers extends SLB_Collection_Controller {
248
  public function client_output_script($commands) {
249
  $out = array('/* CHDL */');
250
  $code = array();
251
-
252
  foreach ( $this->request_matches as $handler ) {
253
  // Attributes
254
  $attrs = $handler->get_attributes();
8
  */
9
  class SLB_Content_Handlers extends SLB_Collection_Controller {
10
  /* Configuration */
11
+
12
  protected $item_type = 'SLB_Content_Handler';
13
+
14
  public $hook_prefix = 'content_handlers';
15
+
16
  protected $key_prop = 'get_id';
17
+
18
  protected $key_call = true;
19
+
20
  /* Properties */
21
+
22
  protected $request_matches = array();
23
+
24
  /**
25
  * Cache properties (key, group)
26
  * @var object
27
  */
28
  protected $cache_props = null;
29
+
30
  /* Initialization */
31
+
32
  protected function _hooks() {
33
  parent::_hooks();
34
  $this->util->add_action('init', $this->m('init_defaults'), 5);
35
  $this->util->add_action('footer', $this->m('client_output'), 1, 0, false);
36
  $this->util->add_filter('footer_script', $this->m('client_output_script'), $this->util->priority('client_footer_output'), 1, false);
37
  }
38
+
39
  /* Collection Management */
40
+
41
  /**
42
  * Add content type handler
43
  * Accepts properties to create new handler OR previously-initialized handler instance
65
  // Add to collection
66
  return parent::add($handler, array('priority' => $priority));
67
  }
68
+
69
  /**
70
  * Remove item
71
  * @uses clear_cache()
76
  $this->clear_cache();
77
  return parent::remove($item);
78
  }
79
+
80
  /**
81
  * Clear collection
82
  * @uses clear_cache()
87
  $this->clear_cache();
88
  return parent::clear();
89
  }
90
+
91
  /**
92
  * Retrieves handlers sorted by priority
93
  * @see parent::get()
104
  }
105
  return $items;
106
  }
107
+
108
  /**
109
  * Get matching handler for URI
110
  * @param string $uri URI to find match for
133
  }
134
  return $ret;
135
  }
136
+
137
  /* Cache */
138
+
139
  /**
140
  * Retrieve cached items
141
  * @uses get_cache_props()
147
  $items = wp_cache_get($cprops->key, $cprops->group);
148
  return ( is_array($items) ) ? $items : array();
149
  }
150
+
151
  /**
152
  * Update cached items
153
  * Cache is cleared if no items specified
159
  $props = $this->get_cache_props();
160
  wp_cache_set($props->key, $data, $props->group);
161
  }
162
+
163
  /**
164
  * Clear cache
165
  * @uses update_cache()
167
  protected function clear_cache() {
168
  $this->update_cache();
169
  }
170
+
171
  /**
172
  * Retrieve cache properites (key, group)
173
  * @return object Cache properties
179
  'group' => $this->get_prefix(),
180
  );
181
  }
182
+ return $this->cache_props;
183
  }
184
+
185
  /* Handlers */
186
+
187
  /**
188
  * Initialize default handlers
189
  * @param SLB_Content_Handlers $handlers Handlers controller
204
  $handlers->add($id, $props);
205
  }
206
  }
207
+
208
  /**
209
  * Matches image URIs
210
  * @param string $uri URI to match
213
  public function match_image($uri, $handlers) {
214
  // Basic matching
215
  $match = ( $this->util->has_file_extension($uri, array('jpg', 'jpeg', 'jpe', 'jfif', 'jif', 'gif', 'png')) ) ? true : false;
216
+
217
  // Filter result
218
  $extra = new stdClass();
219
  $match = $this->util->apply_filters('image_match', $match, $uri, $extra);
220
+
221
  // Handle extra data passed from filters
222
  // Currently only `uri` supported
223
  if ( $match && isset($extra->uri) && is_string($extra->uri) ) {
224
  $match = array('uri' => $extra->uri);
225
  }
226
+
227
  return $match;
228
  }
229
+
230
  /* Output */
231
+
232
  /**
233
  * Build client output
234
  * Load handler files in client
239
  $handler->enqueue_scripts();
240
  }
241
  }
242
+
243
  /**
244
  * Client output script
245
  * @param array $commands Client script commands
248
  public function client_output_script($commands) {
249
  $out = array('/* CHDL */');
250
  $code = array();
251
+
252
  foreach ( $this->request_matches as $handler ) {
253
  // Attributes
254
  $attrs = $handler->get_attributes();
includes/class.field_base.php CHANGED
@@ -11,42 +11,28 @@ class SLB_Field_Base extends SLB_Base {
11
  /*-** Config **-*/
12
  protected $mode = 'object';
13
  protected $shared = false;
14
-
15
  /*-** Properties **-*/
16
-
17
  /**
18
  * @var string Unique name
19
  */
20
  var $id = '';
21
-
22
  /**
23
- * ID formatting options
24
- * Merged with defaults during initialization
25
- * @see $id_formats_default
26
- * @var array
27
  */
28
- var $id_formats = null;
29
-
30
  /**
31
- * Default ID Formatting options
32
- * Structure:
33
- * > Key (string): Format name
34
- * > Val (array): Options
35
- * @var array
36
  */
37
- var $id_formats_default = array(
38
- 'attr_id' => array(
39
- 'wrap' => array('open' => '_', 'segment_open' => '_'),
40
- 'prefix' => array('get_container', 'get_id', 'add_prefix'),
41
- 'recursive' => true
42
- ),
43
- 'attr_name' => array(
44
- 'wrap' => array('open' => '[', 'close' => ']', 'segment_open' => '[', 'segment_close' => ']'),
45
- 'recursive' => true,
46
- 'prefix' => array('get_container', 'get_id', 'add_prefix')
47
- )
48
- );
49
-
50
  /**
51
  * Special characters/phrases
52
  * Used for preserving special characters during formatting
@@ -57,7 +43,7 @@ class SLB_Field_Base extends SLB_Base {
57
  * @var array
58
  */
59
  var $special_chars = null;
60
-
61
  var $special_chars_default = array(
62
  '{' => '%SQB_L%',
63
  '}' => '%SQB_R%',
@@ -84,13 +70,13 @@ class SLB_Field_Base extends SLB_Base {
84
  * @var array Object Properties
85
  */
86
  var $properties = array();
87
-
88
  /**
89
  * Initialization properties
90
  * @var array
91
  */
92
  protected $properties_init = null;
93
-
94
  /**
95
  * Structure: Property names stored as keys in group
96
  * Root
@@ -100,33 +86,33 @@ class SLB_Field_Base extends SLB_Base {
100
  * @var array Groupings of Properties
101
  */
102
  var $property_groups = array();
103
-
104
  /**
105
  * Keys to filter out of properties array before setting properties
106
  * @var array
107
  */
108
  var $property_filter = array('group');
109
-
110
  /**
111
  * Define order of properties
112
  * Useful when processing order is important (e.g. one property depends on another)
113
  * @var array
114
  */
115
  var $property_priority = array();
116
-
117
  /**
118
  * Data for object
119
  * May also contain data for nested objects
120
  * @var mixed
121
  */
122
  var $data = null;
123
-
124
  /**
125
  * Whether data has been fetched or not
126
  * @var bool
127
  */
128
- var $data_loaded = false;
129
-
130
  /**
131
  * @var array Script resources to include for object
132
  */
@@ -142,7 +128,7 @@ class SLB_Field_Base extends SLB_Base {
142
  * @var array
143
  */
144
  var $hooks = array();
145
-
146
  /**
147
  * Mapping of child properties to parent members
148
  * Allows more flexibility when creating new instances of child objects using property arrays
@@ -152,7 +138,7 @@ class SLB_Field_Base extends SLB_Base {
152
  * @var array
153
  */
154
  var $map = null;
155
-
156
  /**
157
  * Options used when building collection (callbacks, etc.)
158
  * Associative array
@@ -161,9 +147,9 @@ class SLB_Field_Base extends SLB_Base {
161
  * @var array
162
  */
163
  var $build_vars = array();
164
-
165
  var $build_vars_default = array();
166
-
167
  /**
168
  * Constructor
169
  */
@@ -180,7 +166,7 @@ class SLB_Field_Base extends SLB_Base {
180
  }
181
 
182
  /* Getters/Setters */
183
-
184
  /**
185
  * Checks if the specified path exists in the object
186
  * @param array $path Path to check for
@@ -203,7 +189,7 @@ class SLB_Field_Base extends SLB_Base {
203
  return false;
204
  }
205
  }
206
- return true;
207
  }
208
 
209
  /**
@@ -303,7 +289,7 @@ class SLB_Field_Base extends SLB_Base {
303
  if ( 'parent' == $dir )
304
  $ex_val = $this->get_parent_value($member, $name, $default);
305
  elseif ( method_exists($this, 'get_container_value') )
306
- $ex_val = $this->get_container_value($member, $name, $default);
307
  // Handle inheritance
308
  if ( is_array($val) ) {
309
  // Combine Arrays
@@ -336,7 +322,7 @@ class SLB_Field_Base extends SLB_Base {
336
  $ret = $object->get_member_value($member, $name, $default, $dir);
337
  return $ret;
338
  }
339
-
340
  /**
341
  * Set item ID
342
  * @param string $id Unique item ID
@@ -346,7 +332,7 @@ class SLB_Field_Base extends SLB_Base {
346
  return false;
347
  $this->id = trim($id);
348
  }
349
-
350
  /**
351
  * Retrieves field ID
352
  * @param array|string $options (optional) Options or ID of format to use
@@ -355,10 +341,9 @@ class SLB_Field_Base extends SLB_Base {
355
  function get_id($options = array()) {
356
  $item_id = trim($this->id);
357
  $formats = $this->get_id_formats();
358
-
359
  // Setup options
360
  $wrap_default = array('open' => '', 'close' => '', 'segment_open' => '', 'segment_close' => '');
361
-
362
  $options_default = array(
363
  'format' => null,
364
  'wrap' => array(),
@@ -366,7 +351,7 @@ class SLB_Field_Base extends SLB_Base {
366
  'prefix' => '',
367
  'recursive' => false
368
  );
369
-
370
  // Load options based on format
371
  if ( !is_array($options) )
372
  $options = array('format' => $options);
@@ -380,15 +365,15 @@ class SLB_Field_Base extends SLB_Base {
380
 
381
  // Validate options
382
  $wrap = wp_parse_args($wrap, $wrap_default);
383
-
384
  if ( !is_array($segments_pre) )
385
  $segments_pre = array($segments_pre);
386
  $segments_pre = array_reverse($segments_pre);
387
-
388
  // Format ID based on options
389
  $item_id = array($item_id);
390
 
391
- // Add parent objects to ID
392
  if ( !!$recursive ) {
393
  // Create array of ID components
394
  $m = 'get_caller';
@@ -403,7 +388,7 @@ class SLB_Field_Base extends SLB_Base {
403
  }
404
  unset($c);
405
  }
406
-
407
  // Additional segments (Pre)
408
  foreach ( $segments_pre as $seg ) {
409
  if ( is_null($seg) )
@@ -415,7 +400,7 @@ class SLB_Field_Base extends SLB_Base {
415
  elseif ( '' != strval($seg) )
416
  $item_id[] = strval($seg);
417
  }
418
-
419
  // Prefix
420
  if ( is_array($prefix) ) {
421
  // Array is sequence of instance methods to call on object
@@ -430,7 +415,7 @@ class SLB_Field_Base extends SLB_Base {
430
  continue;
431
  // Build callback
432
  $m = $this->util->m($p, $m);
433
- // Call callback
434
  $val = call_user_func_array($m, $args);
435
  // Returned value may be an instance object
436
  if ( is_object($val) )
@@ -444,27 +429,81 @@ class SLB_Field_Base extends SLB_Base {
444
  if ( is_numeric($prefix) )
445
  $prefix = strval($prefix);
446
  if ( empty($prefix) || !is_string($prefix) )
447
- $prefix = '';
448
 
449
  // Convert array to string
450
  $item_id = $prefix . $wrap['open'] . implode($wrap['segment_close'] . $wrap['segment_open'], array_reverse($item_id)) . $wrap['close'];
451
  return $item_id;
452
  }
453
-
454
  /**
455
- * Retrieve ID formatting options for class
456
- * Format options arrays are merged together and saved to $id_formats
457
- * @uses $id_formats
458
- * @uses $id_formats_default
459
- * @return array ID Formatting options
460
  */
461
- function &get_id_formats() {
462
- if ( is_null($this->id_formats) ) {
463
- $this->id_formats = wp_parse_args($this->id_formats, $this->id_formats_default);
464
- }
465
  return $this->id_formats;
466
  }
467
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
  /**
469
  * Retrieve value from data member
470
  * @param string $context Context to format data for
@@ -480,7 +519,7 @@ class SLB_Field_Base extends SLB_Base {
480
  $args = wp_parse_args($args[0], $opt_d);
481
  extract($args);
482
  }
483
-
484
  if ( is_string($top) ) {
485
  if ( 'false' == $top )
486
  $top = false;
@@ -511,7 +550,7 @@ class SLB_Field_Base extends SLB_Base {
511
  $new->load_data();
512
  }
513
  }
514
-
515
  $obj =& $new;
516
  unset($new);
517
  // Stop iteration
@@ -557,7 +596,7 @@ class SLB_Field_Base extends SLB_Base {
557
  $ref =& $this->get_path_value('data', $name);
558
  $ref = $value;
559
  }
560
-
561
  /**
562
  * Sets parent object of current instance
563
  * Parent objects must be the same object type as current instance
@@ -573,11 +612,11 @@ class SLB_Field_Base extends SLB_Base {
573
  // Parent passed as object reference wrapped in array
574
  if ( is_array($parent) && isset($parent[0]) && is_object($parent[0]) )
575
  $parent = $parent[0];
576
-
577
  // No parent set but parent ID (previously) set in object
578
  if ( empty($parent) && is_string($this->parent) )
579
  $parent = $this->parent;
580
-
581
  // Retrieve reference object if ID was supplied
582
  if ( is_string($parent) ) {
583
  $parent = trim($parent);
@@ -590,7 +629,7 @@ class SLB_Field_Base extends SLB_Base {
590
  $parent = $b->fields->get($parent);
591
  }
592
  }
593
-
594
  // Set parent value on object
595
  if ( is_string($parent) || is_object($parent) )
596
  $this->parent = $parent;
@@ -638,7 +677,7 @@ class SLB_Field_Base extends SLB_Base {
638
  return $this->get_member_value('description', '','', $dir);
639
  return $desc;
640
  }
641
-
642
  /**
643
  * Sets multiple properties on field type at once
644
  * @param array $properties Properties. Each element is an array containing the arguments to set a new property
@@ -659,7 +698,7 @@ class SLB_Field_Base extends SLB_Base {
659
  unset($properties[$prop]);
660
  }
661
  }
662
-
663
  // Filter properties
664
  $properties = $this->filter_properties($properties);
665
  // Set additional instance properties
@@ -667,7 +706,7 @@ class SLB_Field_Base extends SLB_Base {
667
  $this->set_property($name, $val);
668
  }
669
  }
670
-
671
  /**
672
  * Remap properties based on $map
673
  * @uses $map For determine how child properties should map to parent properties
@@ -679,7 +718,7 @@ class SLB_Field_Base extends SLB_Base {
679
  // Return remapped properties
680
  return $this->util->array_remap($properties, $this->map);
681
  }
682
-
683
  /**
684
  * Sort properties based on priority
685
  * @uses this::property_priority
@@ -702,7 +741,7 @@ class SLB_Field_Base extends SLB_Base {
702
  $props = array_merge($props, $properties);
703
  return $props;
704
  }
705
-
706
  /**
707
  * Build properties array
708
  * @param array $props Instance properties
@@ -724,15 +763,15 @@ class SLB_Field_Base extends SLB_Base {
724
  }
725
  return $props;
726
  }
727
-
728
  function validate_id($id) {
729
  return ( is_scalar($id) && !empty($id) ) ? true : false;
730
  }
731
-
732
  function integrate_id($id) {
733
  return ( $this->validate_id($id) ) ? array('id' => $id) : array();
734
  }
735
-
736
  /**
737
  * Filter property members
738
  * @uses $property_filter to remove define members to remove from $properties
@@ -742,7 +781,7 @@ class SLB_Field_Base extends SLB_Base {
742
  function filter_properties($props = array()) {
743
  return $this->util->array_filter_keys($props, $this->property_filter);
744
  }
745
-
746
  /**
747
  * Add/Set a property on the field definition
748
  * @param string $name Name of property
@@ -775,7 +814,7 @@ class SLB_Field_Base extends SLB_Base {
775
  $val = $this->get_member_value('properties', $name);
776
  return $val;
777
  }
778
-
779
  /**
780
  * Removes a property from item
781
  * @param string $name Property ID
@@ -824,7 +863,7 @@ class SLB_Field_Base extends SLB_Base {
824
  function get_group($group) {
825
  return $this->get_member_value('property_groups', $group, array());
826
  }
827
-
828
  /**
829
  * Save field data
830
  * Child classes will define their own
@@ -834,9 +873,9 @@ class SLB_Field_Base extends SLB_Base {
834
  function save() {
835
  return true;
836
  }
837
-
838
  /*-** Hooks **-*/
839
-
840
  /**
841
  * Retrieve hooks added to object
842
  * @return array Hooks
@@ -844,7 +883,7 @@ class SLB_Field_Base extends SLB_Base {
844
  function get_hooks() {
845
  return $this->get_member_value('hooks', '', array());
846
  }
847
-
848
  /**
849
  * Add hook for object
850
  * @see add_filter() for parameter defaults
@@ -863,11 +902,11 @@ class SLB_Field_Base extends SLB_Base {
863
  elseif ( is_array($function_to_add) && !empty($function_to_add) )
864
  $id = strval($function_to_add[count($function_to_add) - 1]);
865
  else
866
- $id = 'function_' . ( count($this->hooks[$tag]) + 1 );
867
  // Add hook
868
  $this->hooks[$tag][$id] = func_get_args();
869
  }
870
-
871
  /**
872
  * Convenience method for adding an action for object
873
  * @see add_filter() for parameter defaults
@@ -879,7 +918,7 @@ class SLB_Field_Base extends SLB_Base {
879
  function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
880
  $this->add_hook($tag, $function_to_add, $priority, $accepted_args);
881
  }
882
-
883
  /**
884
  * Convenience method for adding a filter for object
885
  * @see add_filter() for parameter defaults
@@ -891,9 +930,9 @@ class SLB_Field_Base extends SLB_Base {
891
  function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
892
  $this->add_hook($tag, $function_to_add, $priority, $accepted_args);
893
  }
894
-
895
  /*-** Dependencies **-*/
896
-
897
  /**
898
  * Adds dependency to object
899
  * @param string $type Type of dependency to add (script, style)
@@ -915,14 +954,14 @@ class SLB_Field_Base extends SLB_Base {
915
  // Wrap single contexts in an array
916
  if ( is_string($context) )
917
  $context = array($context);
918
- else
919
  $context = array();
920
  }
921
  // Add file to instance property
922
  if ( isset($this->{$type}) && is_array($this->{$type}) )
923
  $this->{$type}[$handle] = array('context' => $context, 'params' => $args);
924
  }
925
-
926
  /**
927
  * Add script to object to be added in specified contexts
928
  * @param array|string $context Array of contexts to add script to page
@@ -947,7 +986,7 @@ class SLB_Field_Base extends SLB_Base {
947
  function get_scripts() {
948
  return $this->get_member_value('scripts', '', array());
949
  }
950
-
951
  /**
952
  * Add style to object to be added in specified contexts
953
  * @param array|string $context Array of contexts to add style to page
@@ -971,9 +1010,9 @@ class SLB_Field_Base extends SLB_Base {
971
  function get_styles() {
972
  return $this->get_member_value('styles', '', array());
973
  }
974
-
975
  /* Helpers */
976
-
977
  /**
978
  * Format value based on specified context
979
  * @param mixed $value Value to format
@@ -992,18 +1031,42 @@ class SLB_Field_Base extends SLB_Base {
992
  // Return formatted value
993
  return $value;
994
  }
995
-
996
  /**
997
- * Format value for output in form field
998
- * @param mixed $value Value to format
999
- * @return mixed Formatted value
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  */
1001
- function format_form($value) {
1002
- if ( is_string($value) )
1003
- $value = htmlspecialchars($value);
 
1004
  return $value;
1005
  }
1006
-
1007
  /**
1008
  * Final formatting before output
1009
  * Restores special characters, etc.
@@ -1016,25 +1079,25 @@ class SLB_Field_Base extends SLB_Base {
1016
  function format_final($value, $context = '') {
1017
  if ( !is_string($value) )
1018
  return $value;
1019
-
1020
  // Restore special chars
1021
  return $this->restore_special_chars($value, $context);
1022
  }
1023
-
1024
  function preserve_special_chars($value, $context = '') {
1025
  if ( !is_string($value) )
1026
  return $value;
1027
  $specials = $this->get_special_chars();
1028
  return str_replace(array_keys($specials), $specials, $value);
1029
  }
1030
-
1031
  function restore_special_chars($value, $context = '') {
1032
  if ( !is_string($value) )
1033
  return $value;
1034
  $specials = $this->get_special_chars();
1035
  return str_replace($specials, array_keys($specials), $value);
1036
  }
1037
-
1038
  /**
1039
  * Retrieve special characters/placeholders
1040
  * Merges defaults with class-specific characters
11
  /*-** Config **-*/
12
  protected $mode = 'object';
13
  protected $shared = false;
14
+
15
  /*-** Properties **-*/
16
+
17
  /**
18
  * @var string Unique name
19
  */
20
  var $id = '';
21
+
22
  /**
23
+ * ID formatting options.
24
+ *
25
+ * @var array $id_formats
 
26
  */
27
+ private $id_formats = [];
28
+
29
  /**
30
+ * Flag for ID format initialization status.
31
+ *
32
+ * @var bool $id_formats_init
 
 
33
  */
34
+ private $id_formats_init = false;
35
+
 
 
 
 
 
 
 
 
 
 
 
36
  /**
37
  * Special characters/phrases
38
  * Used for preserving special characters during formatting
43
  * @var array
44
  */
45
  var $special_chars = null;
46
+
47
  var $special_chars_default = array(
48
  '{' => '%SQB_L%',
49
  '}' => '%SQB_R%',
70
  * @var array Object Properties
71
  */
72
  var $properties = array();
73
+
74
  /**
75
  * Initialization properties
76
  * @var array
77
  */
78
  protected $properties_init = null;
79
+
80
  /**
81
  * Structure: Property names stored as keys in group
82
  * Root
86
  * @var array Groupings of Properties
87
  */
88
  var $property_groups = array();
89
+
90
  /**
91
  * Keys to filter out of properties array before setting properties
92
  * @var array
93
  */
94
  var $property_filter = array('group');
95
+
96
  /**
97
  * Define order of properties
98
  * Useful when processing order is important (e.g. one property depends on another)
99
  * @var array
100
  */
101
  var $property_priority = array();
102
+
103
  /**
104
  * Data for object
105
  * May also contain data for nested objects
106
  * @var mixed
107
  */
108
  var $data = null;
109
+
110
  /**
111
  * Whether data has been fetched or not
112
  * @var bool
113
  */
114
+ protected $data_loaded = false;
115
+
116
  /**
117
  * @var array Script resources to include for object
118
  */
128
  * @var array
129
  */
130
  var $hooks = array();
131
+
132
  /**
133
  * Mapping of child properties to parent members
134
  * Allows more flexibility when creating new instances of child objects using property arrays
138
  * @var array
139
  */
140
  var $map = null;
141
+
142
  /**
143
  * Options used when building collection (callbacks, etc.)
144
  * Associative array
147
  * @var array
148
  */
149
  var $build_vars = array();
150
+
151
  var $build_vars_default = array();
152
+
153
  /**
154
  * Constructor
155
  */
166
  }
167
 
168
  /* Getters/Setters */
169
+
170
  /**
171
  * Checks if the specified path exists in the object
172
  * @param array $path Path to check for
189
  return false;
190
  }
191
  }
192
+ return true;
193
  }
194
 
195
  /**
289
  if ( 'parent' == $dir )
290
  $ex_val = $this->get_parent_value($member, $name, $default);
291
  elseif ( method_exists($this, 'get_container_value') )
292
+ $ex_val = $this->get_container_value($member, $name, $default);
293
  // Handle inheritance
294
  if ( is_array($val) ) {
295
  // Combine Arrays
322
  $ret = $object->get_member_value($member, $name, $default, $dir);
323
  return $ret;
324
  }
325
+
326
  /**
327
  * Set item ID
328
  * @param string $id Unique item ID
332
  return false;
333
  $this->id = trim($id);
334
  }
335
+
336
  /**
337
  * Retrieves field ID
338
  * @param array|string $options (optional) Options or ID of format to use
341
  function get_id($options = array()) {
342
  $item_id = trim($this->id);
343
  $formats = $this->get_id_formats();
 
344
  // Setup options
345
  $wrap_default = array('open' => '', 'close' => '', 'segment_open' => '', 'segment_close' => '');
346
+
347
  $options_default = array(
348
  'format' => null,
349
  'wrap' => array(),
351
  'prefix' => '',
352
  'recursive' => false
353
  );
354
+
355
  // Load options based on format
356
  if ( !is_array($options) )
357
  $options = array('format' => $options);
365
 
366
  // Validate options
367
  $wrap = wp_parse_args($wrap, $wrap_default);
368
+
369
  if ( !is_array($segments_pre) )
370
  $segments_pre = array($segments_pre);
371
  $segments_pre = array_reverse($segments_pre);
372
+
373
  // Format ID based on options
374
  $item_id = array($item_id);
375
 
376
+ // Add parent objects to ID
377
  if ( !!$recursive ) {
378
  // Create array of ID components
379
  $m = 'get_caller';
388
  }
389
  unset($c);
390
  }
391
+
392
  // Additional segments (Pre)
393
  foreach ( $segments_pre as $seg ) {
394
  if ( is_null($seg) )
400
  elseif ( '' != strval($seg) )
401
  $item_id[] = strval($seg);
402
  }
403
+
404
  // Prefix
405
  if ( is_array($prefix) ) {
406
  // Array is sequence of instance methods to call on object
415
  continue;
416
  // Build callback
417
  $m = $this->util->m($p, $m);
418
+ // Call callback
419
  $val = call_user_func_array($m, $args);
420
  // Returned value may be an instance object
421
  if ( is_object($val) )
429
  if ( is_numeric($prefix) )
430
  $prefix = strval($prefix);
431
  if ( empty($prefix) || !is_string($prefix) )
432
+ $prefix = '';
433
 
434
  // Convert array to string
435
  $item_id = $prefix . $wrap['open'] . implode($wrap['segment_close'] . $wrap['segment_open'], array_reverse($item_id)) . $wrap['close'];
436
  return $item_id;
437
  }
438
+
439
  /**
440
+ * Retrieves ID formats.
441
+ *
442
+ * @return array ID formats.
 
 
443
  */
444
+ private function &get_id_formats() {
445
+ $this->init_id_formats();
 
 
446
  return $this->id_formats;
447
  }
448
 
449
+ /**
450
+ * Initializes default ID formats.
451
+ *
452
+ * @since 2.8.0
453
+ *
454
+ * @return void
455
+ */
456
+ private function init_id_formats() {
457
+ if ( ! $this->id_formats_init ) {
458
+ $this->id_formats_init = true;
459
+ // Initilize default formats.
460
+ $this->add_id_format(
461
+ 'attr_id',
462
+ [
463
+ 'wrap' => [ 'open' => '_', 'segment_open' => '_' ],
464
+ 'prefix' => [ 'get_container', 'get_id', 'add_prefix' ],
465
+ 'recursive' => true,
466
+ ],
467
+ true
468
+ );
469
+ $this->add_id_format(
470
+ 'attr_name',
471
+ [
472
+ 'wrap' => [ 'open' => '[', 'close' => ']', 'segment_open' => '[', 'segment_close' => ']' ],
473
+ 'prefix' => [ 'get_container', 'get_id', 'add_prefix' ],
474
+ 'recursive' => true,
475
+ ],
476
+ true
477
+ );
478
+
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Adds custom ID format.
484
+ *
485
+ * @since 2.8.0
486
+ *
487
+ * @param string $name Format name.
488
+ * @param array $wrap
489
+ * @param array $prefix
490
+ * @param bool $recursive Optional.
491
+ * @param bool $overwrite Optional. Overwrite existing format. Default false.
492
+ * @return void
493
+ */
494
+ protected function add_id_format( string $name, array $options, bool $overwrite = false ) {
495
+ // Init ID formats before adding new ones.
496
+ $this->init_id_formats();
497
+ // Do not add format if name matches existing format (when overwriting not allowed).
498
+ if ( ! $overwrite && in_array( $name, array_keys( $this->id_formats ) ) ) {
499
+ return;
500
+ }
501
+ // Normlize options.
502
+ $options = wp_parse_args( $options, [ 'wrap' => [], 'prefix' => [], 'recursive' => false ] );
503
+ // Add format.
504
+ $this->id_formats[ $name ] = $options;
505
+ }
506
+
507
  /**
508
  * Retrieve value from data member
509
  * @param string $context Context to format data for
519
  $args = wp_parse_args($args[0], $opt_d);
520
  extract($args);
521
  }
522
+
523
  if ( is_string($top) ) {
524
  if ( 'false' == $top )
525
  $top = false;
550
  $new->load_data();
551
  }
552
  }
553
+
554
  $obj =& $new;
555
  unset($new);
556
  // Stop iteration
596
  $ref =& $this->get_path_value('data', $name);
597
  $ref = $value;
598
  }
599
+
600
  /**
601
  * Sets parent object of current instance
602
  * Parent objects must be the same object type as current instance
612
  // Parent passed as object reference wrapped in array
613
  if ( is_array($parent) && isset($parent[0]) && is_object($parent[0]) )
614
  $parent = $parent[0];
615
+
616
  // No parent set but parent ID (previously) set in object
617
  if ( empty($parent) && is_string($this->parent) )
618
  $parent = $this->parent;
619
+
620
  // Retrieve reference object if ID was supplied
621
  if ( is_string($parent) ) {
622
  $parent = trim($parent);
629
  $parent = $b->fields->get($parent);
630
  }
631
  }
632
+
633
  // Set parent value on object
634
  if ( is_string($parent) || is_object($parent) )
635
  $this->parent = $parent;
677
  return $this->get_member_value('description', '','', $dir);
678
  return $desc;
679
  }
680
+
681
  /**
682
  * Sets multiple properties on field type at once
683
  * @param array $properties Properties. Each element is an array containing the arguments to set a new property
698
  unset($properties[$prop]);
699
  }
700
  }
701
+
702
  // Filter properties
703
  $properties = $this->filter_properties($properties);
704
  // Set additional instance properties
706
  $this->set_property($name, $val);
707
  }
708
  }
709
+
710
  /**
711
  * Remap properties based on $map
712
  * @uses $map For determine how child properties should map to parent properties
718
  // Return remapped properties
719
  return $this->util->array_remap($properties, $this->map);
720
  }
721
+
722
  /**
723
  * Sort properties based on priority
724
  * @uses this::property_priority
741
  $props = array_merge($props, $properties);
742
  return $props;
743
  }
744
+
745
  /**
746
  * Build properties array
747
  * @param array $props Instance properties
763
  }
764
  return $props;
765
  }
766
+
767
  function validate_id($id) {
768
  return ( is_scalar($id) && !empty($id) ) ? true : false;
769
  }
770
+
771
  function integrate_id($id) {
772
  return ( $this->validate_id($id) ) ? array('id' => $id) : array();
773
  }
774
+
775
  /**
776
  * Filter property members
777
  * @uses $property_filter to remove define members to remove from $properties
781
  function filter_properties($props = array()) {
782
  return $this->util->array_filter_keys($props, $this->property_filter);
783
  }
784
+
785
  /**
786
  * Add/Set a property on the field definition
787
  * @param string $name Name of property
814
  $val = $this->get_member_value('properties', $name);
815
  return $val;
816
  }
817
+
818
  /**
819
  * Removes a property from item
820
  * @param string $name Property ID
863
  function get_group($group) {
864
  return $this->get_member_value('property_groups', $group, array());
865
  }
866
+
867
  /**
868
  * Save field data
869
  * Child classes will define their own
873
  function save() {
874
  return true;
875
  }
876
+
877
  /*-** Hooks **-*/
878
+
879
  /**
880
  * Retrieve hooks added to object
881
  * @return array Hooks
883
  function get_hooks() {
884
  return $this->get_member_value('hooks', '', array());
885
  }
886
+
887
  /**
888
  * Add hook for object
889
  * @see add_filter() for parameter defaults
902
  elseif ( is_array($function_to_add) && !empty($function_to_add) )
903
  $id = strval($function_to_add[count($function_to_add) - 1]);
904
  else
905
+ $id = 'function_' . ( count($this->hooks[$tag]) + 1 );
906
  // Add hook
907
  $this->hooks[$tag][$id] = func_get_args();
908
  }
909
+
910
  /**
911
  * Convenience method for adding an action for object
912
  * @see add_filter() for parameter defaults
918
  function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
919
  $this->add_hook($tag, $function_to_add, $priority, $accepted_args);
920
  }
921
+
922
  /**
923
  * Convenience method for adding a filter for object
924
  * @see add_filter() for parameter defaults
930
  function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
931
  $this->add_hook($tag, $function_to_add, $priority, $accepted_args);
932
  }
933
+
934
  /*-** Dependencies **-*/
935
+
936
  /**
937
  * Adds dependency to object
938
  * @param string $type Type of dependency to add (script, style)
954
  // Wrap single contexts in an array
955
  if ( is_string($context) )
956
  $context = array($context);
957
+ else
958
  $context = array();
959
  }
960
  // Add file to instance property
961
  if ( isset($this->{$type}) && is_array($this->{$type}) )
962
  $this->{$type}[$handle] = array('context' => $context, 'params' => $args);
963
  }
964
+
965
  /**
966
  * Add script to object to be added in specified contexts
967
  * @param array|string $context Array of contexts to add script to page
986
  function get_scripts() {
987
  return $this->get_member_value('scripts', '', array());
988
  }
989
+
990
  /**
991
  * Add style to object to be added in specified contexts
992
  * @param array|string $context Array of contexts to add style to page
1010
  function get_styles() {
1011
  return $this->get_member_value('styles', '', array());
1012
  }
1013
+
1014
  /* Helpers */
1015
+
1016
  /**
1017
  * Format value based on specified context
1018
  * @param mixed $value Value to format
1031
  // Return formatted value
1032
  return $value;
1033
  }
1034
+
1035
  /**
1036
+ * Format value for output as an attribute.
1037
+ *
1038
+ * Only strings are formatted.
1039
+ *
1040
+ * @since 2.8.0
1041
+ *
1042
+ * @param mixed $value Value to format.
1043
+ * @return mixed Formatted value.
1044
+ */
1045
+ function format_attr( $value ) {
1046
+ if ( is_string( $value ) ) {
1047
+ $value = esc_attr( $value );
1048
+ }
1049
+ return $value;
1050
+ }
1051
+
1052
+ /**
1053
+ * Formats value for output as plain text.
1054
+ *
1055
+ * Escapes HTML, etc.
1056
+ * Only strings are formatted.
1057
+ *
1058
+ * @since 2.8.0
1059
+ *
1060
+ * @param mixed $value Value to format.
1061
+ * @return mixed Formatted value.
1062
  */
1063
+ function format_text( $value ) {
1064
+ if ( is_string( $value ) ) {
1065
+ $value = esc_html( $value );
1066
+ }
1067
  return $value;
1068
  }
1069
+
1070
  /**
1071
  * Final formatting before output
1072
  * Restores special characters, etc.
1079
  function format_final($value, $context = '') {
1080
  if ( !is_string($value) )
1081
  return $value;
1082
+
1083
  // Restore special chars
1084
  return $this->restore_special_chars($value, $context);
1085
  }
1086
+
1087
  function preserve_special_chars($value, $context = '') {
1088
  if ( !is_string($value) )
1089
  return $value;
1090
  $specials = $this->get_special_chars();
1091
  return str_replace(array_keys($specials), $specials, $value);
1092
  }
1093
+
1094
  function restore_special_chars($value, $context = '') {
1095
  if ( !is_string($value) )
1096
  return $value;
1097
  $specials = $this->get_special_chars();
1098
  return str_replace($specials, array_keys($specials), $value);
1099
  }
1100
+
1101
  /**
1102
  * Retrieve special characters/placeholders
1103
  * Merges defaults with class-specific characters
includes/class.field_collection.php CHANGED
@@ -8,39 +8,31 @@
8
  class SLB_Field_Collection extends SLB_Field_Base {
9
 
10
  /* Configuration */
11
-
12
  protected $mode = 'sub';
13
-
14
  /* Properties */
15
-
16
  /**
17
  * Item type
18
  * @var string
19
  */
20
  var $item_type = 'SLB_Field';
21
-
22
  /**
23
  * Indexed array of items in collection
24
  * @var array
25
  */
26
  var $items = array();
27
-
28
- var $id_formats = array (
29
- 'formatted' => array(
30
- 'wrap' => array ( 'open' => '_' ),
31
- 'recursive' => false,
32
- 'prefix' => array('get_prefix')
33
- )
34
- );
35
-
36
- var $build_vars_default = array (
37
  'groups' => array(),
38
  'context' => '',
39
  'layout' => 'form',
40
  'build' => true,
41
  'build_groups' => true,
42
  );
43
-
44
  /**
45
  * Associative array of groups in collection
46
  * Key: Group ID
@@ -52,9 +44,9 @@ class SLB_Field_Collection extends SLB_Field_Base {
52
  * @var array
53
  */
54
  var $groups = array();
55
-
56
  protected $properties_init = null;
57
-
58
  /* Constructors */
59
 
60
  /**
@@ -72,20 +64,32 @@ class SLB_Field_Collection extends SLB_Field_Base {
72
  $properties = $this->make_properties($args);
73
  // Parent constructor
74
  parent::__construct($properties);
75
-
76
  // Save initial properties
77
  $this->properties_init = $properties;
78
  }
79
-
80
  public function _init() {
81
  parent::_init();
 
 
82
  $this->load($this->properties_init, false);
 
 
 
 
 
 
 
 
 
 
83
  }
84
-
85
  /*-** Getters/Setters **-*/
86
-
87
  /* Setup */
88
-
89
  /**
90
  * Load collection with specified properties
91
  * Updates existing properties
@@ -108,9 +112,9 @@ class SLB_Field_Collection extends SLB_Field_Base {
108
  }
109
  return $this;
110
  }
111
-
112
  /* Data */
113
-
114
  /**
115
  * Retrieve external data for items in collection
116
  * Retrieved data is saved to the collection's $data property
@@ -124,7 +128,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
124
  function load_data() {
125
  $this->data_loaded = true;
126
  }
127
-
128
  /**
129
  * Set data for an item
130
  * @param mixed $item Field to set data for
@@ -155,7 +159,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
155
  }
156
 
157
  /* Item */
158
-
159
  /**
160
  * Adds item to collection
161
  * @param string|obj $id Unique name for item or item instance
@@ -176,7 +180,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
176
  if ( !is_array($properties) ) {
177
  $properties = array();
178
  }
179
-
180
  // Handle item instance
181
  if ( $id instanceof $this->item_type ) {
182
  $item = $id;
@@ -200,21 +204,21 @@ class SLB_Field_Collection extends SLB_Field_Base {
200
  $item = new $type($properties);
201
  }
202
  }
203
-
204
  if ( empty($item) || 0 == strlen($item->get_id()) ) {
205
  return false;
206
  }
207
-
208
  // Set container
209
  $item->set_container($this);
210
 
211
  // Add item to collection
212
  $this->items[$item->get_id()] = $item;
213
-
214
  if ( isset($properties['group']) ) {
215
  $this->add_to_group($properties['group'], $item->get_id());
216
  }
217
-
218
  return $item;
219
  }
220
 
@@ -235,11 +239,11 @@ class SLB_Field_Collection extends SLB_Field_Base {
235
  }
236
  // Remove item data from collection
237
  $this->remove_data($item, false);
238
-
239
  if ( !!$save )
240
  $this->save();
241
  }
242
-
243
  /**
244
  * Remove item data from collection
245
  * @param string|object $item Object or item ID to remove
@@ -251,7 +255,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
251
  $item = $this->get($item);
252
  $item = $item->get_id();
253
  }
254
-
255
  // Remove data from data member
256
  if ( is_string($item) && is_array($this->data) ) {
257
  unset($this->data[$item]);
@@ -268,7 +272,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
268
  function has($item) {
269
  return ( !is_string($item) || empty($item) || is_null($this->get_member_value('items', $item, null)) ) ? false : true;
270
  }
271
-
272
  /**
273
  * Retrieve specified item in collection
274
  * @param string|object $item Item object or ID to retrieve
@@ -288,7 +292,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
288
  } else {
289
  $item = false;
290
  }
291
-
292
  if ( !!$safe_mode && !is_object($item) ) {
293
  // Fallback: Return empty item if no item exists
294
  $type = $this->item_type;
@@ -296,7 +300,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
296
  }
297
  return $item;
298
  }
299
-
300
  /**
301
  * Retrieve item data
302
  * @param $item Item to get data for
@@ -313,14 +317,14 @@ class SLB_Field_Collection extends SLB_Field_Base {
313
  } else {
314
  $ret = parent::get_data($context, $top);
315
  }
316
-
317
  if ( is_string($item) && is_array($ret) && isset($ret[$item]) )
318
  $ret = $ret[$item];
319
  return $ret;
320
  }
321
 
322
  /* Items (Collection) */
323
-
324
  /**
325
  * Add multiple items to collection
326
  * @param array $items Items to add to collection
@@ -339,7 +343,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
339
  $this->add($id, $props, $update);
340
  }
341
  }
342
-
343
  /**
344
  * Retrieve reference to items in collection
345
  * @return array Collection items (reference)
@@ -370,7 +374,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
370
  }
371
  return $items;
372
  }
373
-
374
  /**
375
  * Build output for items in specified group
376
  * If no group specified, all items in collection are built
@@ -382,16 +386,16 @@ class SLB_Field_Collection extends SLB_Field_Base {
382
  if ( empty($items) ) {
383
  return false;
384
  }
385
-
386
  $this->util->do_action_ref_array('build_items_pre', array($this));
387
  foreach ( $items as $item ) {
388
  $item->build();
389
  }
390
  $this->util->do_action_ref_array('build_items_post', array($this));
391
  }
392
-
393
  /* Group */
394
-
395
  /**
396
  * Add groups to collection
397
  * @param array $groups Associative array of group properties
@@ -409,10 +413,10 @@ class SLB_Field_Collection extends SLB_Field_Base {
409
  $this->add_group($id, $props, null, $update);
410
  }
411
  }
412
-
413
  /**
414
  * Adds group to collection
415
- * Groups are used to display related items in the UI
416
  * @param string $id Unique name for group
417
  * @param string $title Group title
418
  * @param string $description Short description of group's purpose
@@ -484,7 +488,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
484
  $group->items = array();
485
  return $group;
486
  }
487
-
488
  /**
489
  * Checks if group exists in collection
490
  * @param string $id Group name
@@ -501,7 +505,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
501
  }
502
  return $ret;
503
  }
504
-
505
  /**
506
  * Adds item to a group in the collection
507
  * Group is created if it does not already exist
@@ -513,7 +517,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
513
  if ( empty($items) || empty($group) || ( !is_string($group) && !is_array($group) ) ) {
514
  return false;
515
  }
516
-
517
  // Get group ID
518
  if ( is_string($group) ) {
519
  $group = array($group, $priority);
@@ -527,7 +531,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
527
  if ( !is_int($priority) ) {
528
  $priority = 10;
529
  }
530
-
531
  // Prepare group
532
  if ( !$this->group_exists($gid) ) {
533
  // TODO Follow
@@ -610,7 +614,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
610
  }
611
  return $this->get_member_value('groups', $group);
612
  }
613
-
614
  /**
615
  * Retrieve a group's items
616
  * @uses SLB_Field_Collection::get_group() to retrieve group object
@@ -647,14 +651,14 @@ class SLB_Field_Collection extends SLB_Field_Base {
647
  }
648
  return $groups;
649
  }
650
-
651
  /**
652
  * Output groups
653
  * @uses self::build_vars to determine groups to build
654
  */
655
  function build_groups() {
656
  $this->util->do_action_ref_array('build_groups_pre', array($this));
657
-
658
  // Get groups to build
659
  $groups = ( !empty($this->build_vars['groups']) ) ? $this->build_vars['groups'] : array_keys($this->get_groups(array('sort' => 'priority')));
660
  // Check options
@@ -667,7 +671,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
667
  $this->build_group($group);
668
  }
669
  }
670
-
671
  $this->util->do_action_ref_array('build_groups_post', array($this));
672
  }
673
 
@@ -683,19 +687,19 @@ class SLB_Field_Collection extends SLB_Field_Base {
683
  if ( !count($this->get_items($group)) ) {
684
  return false;
685
  }
686
-
687
  // Pre action
688
  $this->util->do_action_ref_array('build_group_pre', array($this, $group));
689
-
690
  // Build items
691
  $this->build_items($group);
692
-
693
  // Post action
694
  $this->util->do_action_ref_array('build_group_post', array($this, $group));
695
  }
696
 
697
  /* Collection */
698
-
699
  /**
700
  * Build entire collection of items
701
  * Prints output
@@ -711,16 +715,16 @@ class SLB_Field_Collection extends SLB_Field_Base {
711
  // Post-build output
712
  $this->util->do_action_ref_array('build_post', array($this));
713
  }
714
-
715
  /**
716
  * Set build variable
717
  * @param string $key Variable name
718
- * @param mixed $val Variable value
719
  */
720
  function set_build_var($key, $val) {
721
  $this->build_vars[$key] = $val;
722
  }
723
-
724
  /**
725
  * Retrieve build variable
726
  * @param string $key Variable name
@@ -730,7 +734,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
730
  function get_build_var($key, $default = null) {
731
  return ( array_key_exists($key, $this->build_vars) ) ? $this->build_vars[$key] : $default;
732
  }
733
-
734
  /**
735
  * Delete build variable
736
  * @param string $key Variable name to delete
@@ -740,7 +744,7 @@ class SLB_Field_Collection extends SLB_Field_Base {
740
  unset($this->build_vars[$key]);
741
  }
742
  }
743
-
744
  /**
745
  * Parses build variables prior to use
746
  * @uses this->reset_build_vars() to reset build variables for each request
@@ -748,9 +752,9 @@ class SLB_Field_Collection extends SLB_Field_Base {
748
  */
749
  function parse_build_vars($build_vars = array()) {
750
  $this->reset_build_vars();
751
- $this->build_vars = $this->util->apply_filters('parse_build_vars', wp_parse_args($build_vars, $this->build_vars), $this);
752
  }
753
-
754
  /**
755
  * Reset build variables to defaults
756
  * Default Variables
8
  class SLB_Field_Collection extends SLB_Field_Base {
9
 
10
  /* Configuration */
11
+
12
  protected $mode = 'sub';
13
+
14
  /* Properties */
15
+
16
  /**
17
  * Item type
18
  * @var string
19
  */
20
  var $item_type = 'SLB_Field';
21
+
22
  /**
23
  * Indexed array of items in collection
24
  * @var array
25
  */
26
  var $items = array();
27
+
28
+ var $build_vars_default = array (
 
 
 
 
 
 
 
 
29
  'groups' => array(),
30
  'context' => '',
31
  'layout' => 'form',
32
  'build' => true,
33
  'build_groups' => true,
34
  );
35
+
36
  /**
37
  * Associative array of groups in collection
38
  * Key: Group ID
44
  * @var array
45
  */
46
  var $groups = array();
47
+
48
  protected $properties_init = null;
49
+
50
  /* Constructors */
51
 
52
  /**
64
  $properties = $this->make_properties($args);
65
  // Parent constructor
66
  parent::__construct($properties);
67
+
68
  // Save initial properties
69
  $this->properties_init = $properties;
70
  }
71
+
72
  public function _init() {
73
  parent::_init();
74
+
75
+ // Load properties.
76
  $this->load($this->properties_init, false);
77
+
78
+ // Add custom ID format(s).
79
+ $this->add_id_format(
80
+ 'formatted',
81
+ [
82
+ 'wrap' => [ 'open' => '_' ],
83
+ 'prefix' => [ 'get_prefix' ],
84
+ 'recursive' => false,
85
+ ]
86
+ );
87
  }
88
+
89
  /*-** Getters/Setters **-*/
90
+
91
  /* Setup */
92
+
93
  /**
94
  * Load collection with specified properties
95
  * Updates existing properties
112
  }
113
  return $this;
114
  }
115
+
116
  /* Data */
117
+
118
  /**
119
  * Retrieve external data for items in collection
120
  * Retrieved data is saved to the collection's $data property
128
  function load_data() {
129
  $this->data_loaded = true;
130
  }
131
+
132
  /**
133
  * Set data for an item
134
  * @param mixed $item Field to set data for
159
  }
160
 
161
  /* Item */
162
+
163
  /**
164
  * Adds item to collection
165
  * @param string|obj $id Unique name for item or item instance
180
  if ( !is_array($properties) ) {
181
  $properties = array();
182
  }
183
+
184
  // Handle item instance
185
  if ( $id instanceof $this->item_type ) {
186
  $item = $id;
204
  $item = new $type($properties);
205
  }
206
  }
207
+
208
  if ( empty($item) || 0 == strlen($item->get_id()) ) {
209
  return false;
210
  }
211
+
212
  // Set container
213
  $item->set_container($this);
214
 
215
  // Add item to collection
216
  $this->items[$item->get_id()] = $item;
217
+
218
  if ( isset($properties['group']) ) {
219
  $this->add_to_group($properties['group'], $item->get_id());
220
  }
221
+
222
  return $item;
223
  }
224
 
239
  }
240
  // Remove item data from collection
241
  $this->remove_data($item, false);
242
+
243
  if ( !!$save )
244
  $this->save();
245
  }
246
+
247
  /**
248
  * Remove item data from collection
249
  * @param string|object $item Object or item ID to remove
255
  $item = $this->get($item);
256
  $item = $item->get_id();
257
  }
258
+
259
  // Remove data from data member
260
  if ( is_string($item) && is_array($this->data) ) {
261
  unset($this->data[$item]);
272
  function has($item) {
273
  return ( !is_string($item) || empty($item) || is_null($this->get_member_value('items', $item, null)) ) ? false : true;
274
  }
275
+
276
  /**
277
  * Retrieve specified item in collection
278
  * @param string|object $item Item object or ID to retrieve
292
  } else {
293
  $item = false;
294
  }
295
+
296
  if ( !!$safe_mode && !is_object($item) ) {
297
  // Fallback: Return empty item if no item exists
298
  $type = $this->item_type;
300
  }
301
  return $item;
302
  }
303
+
304
  /**
305
  * Retrieve item data
306
  * @param $item Item to get data for
317
  } else {
318
  $ret = parent::get_data($context, $top);
319
  }
320
+
321
  if ( is_string($item) && is_array($ret) && isset($ret[$item]) )
322
  $ret = $ret[$item];
323
  return $ret;
324
  }
325
 
326
  /* Items (Collection) */
327
+
328
  /**
329
  * Add multiple items to collection
330
  * @param array $items Items to add to collection
343
  $this->add($id, $props, $update);
344
  }
345
  }
346
+
347
  /**
348
  * Retrieve reference to items in collection
349
  * @return array Collection items (reference)
374
  }
375
  return $items;
376
  }
377
+
378
  /**
379
  * Build output for items in specified group
380
  * If no group specified, all items in collection are built
386
  if ( empty($items) ) {
387
  return false;
388
  }
389
+
390
  $this->util->do_action_ref_array('build_items_pre', array($this));
391
  foreach ( $items as $item ) {
392
  $item->build();
393
  }
394
  $this->util->do_action_ref_array('build_items_post', array($this));
395
  }
396
+
397
  /* Group */
398
+
399
  /**
400
  * Add groups to collection
401
  * @param array $groups Associative array of group properties
413
  $this->add_group($id, $props, null, $update);
414
  }
415
  }
416
+
417
  /**
418
  * Adds group to collection
419
+ * Groups are used to display related items in the UI
420
  * @param string $id Unique name for group
421
  * @param string $title Group title
422
  * @param string $description Short description of group's purpose
488
  $group->items = array();
489
  return $group;
490
  }
491
+
492
  /**
493
  * Checks if group exists in collection
494
  * @param string $id Group name
505
  }
506
  return $ret;
507
  }
508
+
509
  /**
510
  * Adds item to a group in the collection
511
  * Group is created if it does not already exist
517
  if ( empty($items) || empty($group) || ( !is_string($group) && !is_array($group) ) ) {
518
  return false;
519
  }
520
+
521
  // Get group ID
522
  if ( is_string($group) ) {
523
  $group = array($group, $priority);
531
  if ( !is_int($priority) ) {
532
  $priority = 10;
533
  }
534
+
535
  // Prepare group
536
  if ( !$this->group_exists($gid) ) {
537
  // TODO Follow
614
  }
615
  return $this->get_member_value('groups', $group);
616
  }
617
+
618
  /**
619
  * Retrieve a group's items
620
  * @uses SLB_Field_Collection::get_group() to retrieve group object
651
  }
652
  return $groups;
653
  }
654
+
655
  /**
656
  * Output groups
657
  * @uses self::build_vars to determine groups to build
658
  */
659
  function build_groups() {
660
  $this->util->do_action_ref_array('build_groups_pre', array($this));
661
+
662
  // Get groups to build
663
  $groups = ( !empty($this->build_vars['groups']) ) ? $this->build_vars['groups'] : array_keys($this->get_groups(array('sort' => 'priority')));
664
  // Check options
671
  $this->build_group($group);
672
  }
673
  }
674
+
675
  $this->util->do_action_ref_array('build_groups_post', array($this));
676
  }
677
 
687
  if ( !count($this->get_items($group)) ) {
688
  return false;
689
  }
690
+
691
  // Pre action
692
  $this->util->do_action_ref_array('build_group_pre', array($this, $group));
693
+
694
  // Build items
695
  $this->build_items($group);
696
+
697
  // Post action
698
  $this->util->do_action_ref_array('build_group_post', array($this, $group));
699
  }
700
 
701
  /* Collection */
702
+
703
  /**
704
  * Build entire collection of items
705
  * Prints output
715
  // Post-build output
716
  $this->util->do_action_ref_array('build_post', array($this));
717
  }
718
+
719
  /**
720
  * Set build variable
721
  * @param string $key Variable name
722
+ * @param mixed $val Variable value
723
  */
724
  function set_build_var($key, $val) {
725
  $this->build_vars[$key] = $val;
726
  }
727
+
728
  /**
729
  * Retrieve build variable
730
  * @param string $key Variable name
734
  function get_build_var($key, $default = null) {
735
  return ( array_key_exists($key, $this->build_vars) ) ? $this->build_vars[$key] : $default;
736
  }
737
+
738
  /**
739
  * Delete build variable
740
  * @param string $key Variable name to delete
744
  unset($this->build_vars[$key]);
745
  }
746
  }
747
+
748
  /**
749
  * Parses build variables prior to use
750
  * @uses this->reset_build_vars() to reset build variables for each request
752
  */
753
  function parse_build_vars($build_vars = array()) {
754
  $this->reset_build_vars();
755
+ $this->build_vars = $this->util->apply_filters('parse_build_vars', wp_parse_args($build_vars, $this->build_vars), $this);
756
  }
757
+
758
  /**
759
  * Reset build variables to defaults
760
  * Default Variables
includes/class.field_type.php CHANGED
@@ -42,7 +42,7 @@ class SLB_Field_Type extends SLB_Field_Base {
42
  $defaults = $this->integrate_id($id);
43
  if ( !is_array($parent) )
44
  $defaults['parent'] = $parent;
45
-
46
  $props = $this->make_properties($args, $defaults);
47
  parent::__construct($props);
48
  }
@@ -150,8 +150,6 @@ class SLB_Field_Type extends SLB_Field_Base {
150
  return !empty($this->caller);
151
  }
152
 
153
-
154
-
155
  /**
156
  * Sets an element for the field type
157
  * @param string $name Name of element
@@ -262,75 +260,93 @@ class SLB_Field_Type extends SLB_Field_Base {
262
  * 'attributes' => (array) attributes
263
  */
264
  function parse_layout($layout, $search) {
265
- $ph_xml = '';
266
  $parse_match = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  $ph_root_tag = 'ph_root_element';
268
  $ph_start_xml = '<';
269
  $ph_end_xml = ' />';
270
  $ph_wrap_start = '<' . $ph_root_tag . '>';
271
  $ph_wrap_end = '</' . $ph_root_tag . '>';
272
- $parse_result = false;
273
 
274
- // Find all nested layouts in layout
275
- $match_value = preg_match_all($search, $layout, $parse_match, PREG_PATTERN_ORDER);
276
 
277
- if ($match_value !== false && $match_value > 0) {
278
- $parse_result = array();
279
- // Get all matched elements
280
- $parse_match = $parse_match[1];
 
 
 
 
 
 
 
 
 
 
 
 
281
 
282
- // Build XML string from placeholders
283
- foreach ($parse_match as $ph) {
284
- $ph_xml .= $ph_start_xml . $ph . $ph_end_xml . ' ';
285
- }
286
- $ph_xml = $ph_wrap_start . $ph_xml . $ph_wrap_end;
287
- // Parse XML data
288
- $ph_prs = xml_parser_create();
289
- xml_parser_set_option($ph_prs, XML_OPTION_SKIP_WHITE, 1);
290
- xml_parser_set_option($ph_prs, XML_OPTION_CASE_FOLDING, 0);
291
- $ret = xml_parse_into_struct($ph_prs, $ph_xml, $parse_result['values'], $parse_result['index']);
292
- xml_parser_free($ph_prs);
293
-
294
- // Build structured array with all parsed data
295
-
296
- unset($parse_result['index'][$ph_root_tag]);
297
-
298
- // Build structured array
299
- $result = array();
300
- foreach ($parse_result['index'] as $tag => $instances) {
301
- $result[$tag] = array();
302
- // Instances
303
- foreach ($instances as $instance) {
304
- // Skip instance if it doesn't exist in parse results
305
- if (!isset($parse_result['values'][$instance]))
306
- continue;
307
-
308
- // Stop processing instance if a previously-saved instance with the same options already exists
309
- foreach ($result[$tag] as $tag_match) {
310
- if ($tag_match['match'] == $parse_match[$instance - 1])
311
- continue 2;
312
  }
 
 
 
 
313
 
314
- // Init instance data array
315
- $inst_data = array();
316
-
317
- // Add Tag to array
318
- $inst_data['tag'] = $parse_result['values'][$instance]['tag'];
319
 
320
- // Add instance data to array
321
- $inst_data['attributes'] = (isset($parse_result['values'][$instance]['attributes'])) ? $inst_data['attributes'] = $parse_result['values'][$instance]['attributes'] : '';
 
 
322
 
323
- // Add match to array
324
- $inst_data['match'] = $parse_match[$instance - 1];
325
 
326
- // Add to result array
327
- $result[$tag][] = $inst_data;
328
- }
329
  }
330
- $parse_result = $result;
331
  }
332
 
333
- return $parse_result;
334
  }
335
 
336
  /**
@@ -346,7 +362,7 @@ class SLB_Field_Type extends SLB_Field_Base {
346
  $ph->pattern_layout = '/' . $ph->start . '([a-zA-Z0-9].*?\s+' . $ph->reserved['ref'] . '="layout.*?".*?)' . $ph->end . '/i';
347
  return $ph;
348
  }
349
-
350
  /**
351
  * Build item output
352
  * @param string $layout (optional) Layout to build
@@ -357,7 +373,7 @@ class SLB_Field_Type extends SLB_Field_Base {
357
  echo $this->build_layout($layout, $data);
358
  $this->util->do_action_ref_array('build_post', array($this));
359
  }
360
-
361
  /**
362
  * Builds HTML for a field based on its properties
363
  * @param string $layout (optional) Name of layout to build
@@ -369,32 +385,7 @@ class SLB_Field_Type extends SLB_Field_Base {
369
  $out = $this->get_layout($layout);
370
  // Only parse valid layouts
371
  if ( $this->is_valid_layout($out) ) {
372
- // Parse Layout
373
- $ph = $this->get_placeholder_defaults();
374
-
375
- // Search layout for placeholders
376
- while ( $ph->match = $this->parse_layout($out, $ph->pattern_general) ) {
377
- // Iterate through placeholders (tag, id, etc.)
378
- foreach ( $ph->match as $tag => $instances ) {
379
- // Iterate through instances of current placeholder
380
- foreach ( $instances as $instance ) {
381
- // Process value based on placeholder name
382
- $target_property = $this->util->apply_filters(array('process_placeholder_' . $tag, false), '', $this, $instance, $layout, $data);
383
- // Process value using default processors (if necessary)
384
- if ( '' == $target_property ) {
385
- $target_property = $this->util->apply_filters(array('process_placeholder', false), $target_property, $this, $instance, $layout, $data);
386
- }
387
-
388
- // Clear value if value not a string
389
- if ( !is_scalar($target_property) ) {
390
- $target_property = '';
391
- }
392
-
393
- // Replace layout placeholder with retrieved item data
394
- $out = str_replace($ph->start . $instance['match'] . $ph->end, $target_property, $out);
395
- }
396
- }
397
- }
398
  } else {
399
  $out = $out_default;
400
  }
@@ -402,4 +393,53 @@ class SLB_Field_Type extends SLB_Field_Base {
402
  $out = $this->format_final($out);
403
  return $out;
404
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  }
42
  $defaults = $this->integrate_id($id);
43
  if ( !is_array($parent) )
44
  $defaults['parent'] = $parent;
45
+
46
  $props = $this->make_properties($args, $defaults);
47
  parent::__construct($props);
48
  }
150
  return !empty($this->caller);
151
  }
152
 
 
 
153
  /**
154
  * Sets an element for the field type
155
  * @param string $name Name of element
260
  * 'attributes' => (array) attributes
261
  */
262
  function parse_layout($layout, $search) {
 
263
  $parse_match = '';
264
+ $result = [];
265
+
266
+ // Find all nested layouts in layout.
267
+ $match_value = preg_match_all( $search, $layout, $parse_match, PREG_PATTERN_ORDER );
268
+
269
+ // Stop if no matches found.
270
+ if ( ! $match_value ) {
271
+ return $result;
272
+ }
273
+
274
+ /* Process matches */
275
+
276
+ $ph_xml = '';
277
  $ph_root_tag = 'ph_root_element';
278
  $ph_start_xml = '<';
279
  $ph_end_xml = ' />';
280
  $ph_wrap_start = '<' . $ph_root_tag . '>';
281
  $ph_wrap_end = '</' . $ph_root_tag . '>';
282
+ $parse_result = [];
283
 
284
+ // Get all matched elements.
285
+ $parse_match = $parse_match[1];
286
 
287
+ // Build XML string from placeholders.
288
+ foreach ( $parse_match as $ph ) {
289
+ $ph_xml .= $ph_start_xml . $ph . $ph_end_xml . ' ';
290
+ }
291
+ $ph_xml = $ph_wrap_start . $ph_xml . $ph_wrap_end;
292
+ // Parse XML data.
293
+ $ph_prs = xml_parser_create();
294
+ xml_parser_set_option($ph_prs, XML_OPTION_SKIP_WHITE, 1);
295
+ xml_parser_set_option($ph_prs, XML_OPTION_CASE_FOLDING, 0);
296
+ $ph_parsed = xml_parse_into_struct($ph_prs, $ph_xml, $parse_result['values'], $parse_result['index']);
297
+ xml_parser_free($ph_prs);
298
+
299
+ // Stop if placeholder parsing failed.
300
+ if ( ! $ph_parsed ) {
301
+ return $result;
302
+ }
303
 
304
+ unset( $parse_result['index'][$ph_root_tag] );
305
+
306
+ // Build structured array with all parsed data.
307
+ $ph_default = [
308
+ 'tag' => '',
309
+ 'match' => '',
310
+ 'attributes' => [],
311
+ ];
312
+
313
+ // Build structured array.
314
+ foreach ( $parse_result['index'] as $tag => $instances ) {
315
+ // Create container for instances of current placeholder.
316
+ $result[ $tag ] = [];
317
+ // Process placeholder instances.
318
+ foreach ( $instances as $instance ) {
319
+ // Skip instance if it doesn't exist in parse results.
320
+ if ( !isset( $parse_result['values'][ $instance ] ) ) {
321
+ continue;
322
+ }
323
+ // Stop processing instance if a previously-saved instance with the same options already exists.
324
+ foreach ( $result[ $tag ] as $tag_match ) {
325
+ if ( $tag_match['match'] == $parse_match[ $instance - 1 ] ) {
326
+ continue 2;
 
 
 
 
 
 
 
327
  }
328
+ }
329
+ $instance_parsed = $parse_result['values'][ $instance ];
330
+ // Init instance data array.
331
+ $instance_data = $ph_default;
332
 
333
+ // Set tag.
334
+ $instance_data['tag'] = $instance_parsed['tag'];
 
 
 
335
 
336
+ // Set attributes.
337
+ if ( isset( $instance_parsed['attributes'] ) && is_array( $instance_parsed['attributes'] ) ) {
338
+ $instance_data['attributes'] = $instance_parsed['attributes'];
339
+ }
340
 
341
+ // Add match to array.
342
+ $instance_data['match'] = $parse_match[ $instance - 1 ];
343
 
344
+ // Add to result array.
345
+ $result[ $tag ][] = $instance_data;
 
346
  }
 
347
  }
348
 
349
+ return $result;
350
  }
351
 
352
  /**
362
  $ph->pattern_layout = '/' . $ph->start . '([a-zA-Z0-9].*?\s+' . $ph->reserved['ref'] . '="layout.*?".*?)' . $ph->end . '/i';
363
  return $ph;
364
  }
365
+
366
  /**
367
  * Build item output
368
  * @param string $layout (optional) Layout to build
373
  echo $this->build_layout($layout, $data);
374
  $this->util->do_action_ref_array('build_post', array($this));
375
  }
376
+
377
  /**
378
  * Builds HTML for a field based on its properties
379
  * @param string $layout (optional) Name of layout to build
385
  $out = $this->get_layout($layout);
386
  // Only parse valid layouts
387
  if ( $this->is_valid_layout($out) ) {
388
+ $out = $this->process_placeholders( $out, $layout, $data );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  } else {
390
  $out = $out_default;
391
  }
393
  $out = $this->format_final($out);
394
  return $out;
395
  }
396
+
397
+ /**
398
+ * Processes placeholders in a string.
399
+ *
400
+ * Finds and replaces placeholders in a string to their full values.
401
+ *
402
+ * @since 2.8.0
403
+ *
404
+ * @param string $str String with placeholders to replace.
405
+ * @param string $layout Optional. Name of layout being built.
406
+ * @param array $data Optional. Additional data for current item.
407
+ * @return string Original text with placeholders converted to full values.
408
+ */
409
+ public function process_placeholders( $str, $layout = 'form', $data = null ) {
410
+ // Parse Layout.
411
+ $ph = $this->get_placeholder_defaults();
412
+
413
+ // Search layout for placeholders.
414
+ while ( $ph->match = $this->parse_layout( $str, $ph->pattern_general ) ) {
415
+ // Iterate through placeholders (tag, id, etc.)
416
+ foreach ( $ph->match as $tag => $instances ) {
417
+ // Iterate through instances of current placeholder
418
+ foreach ( $instances as $instance ) {
419
+ // Process value based on placeholder name.
420
+ $target_property = $this->util->apply_filters_ref_array( "process_placeholder_${tag}", [ '', $this, &$instance, $layout, $data ], false );
421
+ // Process value using default processors (if necessary).
422
+ if ( '' === $target_property ) {
423
+ $target_property = $this->util->apply_filters_ref_array( 'process_placeholder', [ $target_property, $this, &$instance, $layout, $data ], false );
424
+ }
425
+ // Format output.
426
+ if ( ! is_null( $target_property ) ) {
427
+ $context = ( isset( $instance['attributes']['context'] ) ) ? $instance['attributes']['context'] : '';
428
+ // Handle special characters.
429
+ $target_property = $this->preserve_special_chars( $target_property, $context );
430
+ // Context-specific formatting.
431
+ $target_property = $this->format( $target_property, $context );
432
+ }
433
+
434
+ // Clear value if value not a string
435
+ if ( !is_scalar( $target_property ) ) {
436
+ $target_property = '';
437
+ }
438
+ // Replace layout placeholder with retrieved item data
439
+ $str = str_replace( $ph->start . $instance['match'] . $ph->end, $target_property, $str );
440
+ }
441
+ }
442
+ }
443
+ return $str;
444
+ }
445
  }
includes/class.fields.php CHANGED
@@ -7,21 +7,21 @@
7
  *
8
  */
9
  class SLB_Fields extends SLB_Field_Collection {
10
-
11
  var $item_type = 'SLB_Field_Type';
12
-
13
  /**
14
  * Placeholder handlers
15
  * @var array
16
  */
17
  var $placholders = null;
18
-
19
  /* Constructor */
20
-
21
  function __construct() {
22
  parent::__construct('fields');
23
  }
24
-
25
  protected function _hooks() {
26
  parent::_hooks();
27
  // Init fields
@@ -29,9 +29,9 @@ class SLB_Fields extends SLB_Field_Collection {
29
  // Init placeholders
30
  add_action('init', $this->m('register_placeholders'));
31
  }
32
-
33
  /* Field Types */
34
-
35
  /**
36
  * Initialize fields
37
  */
@@ -73,7 +73,7 @@ class SLB_Fields extends SLB_Field_Collection {
73
  $text->set_property('label');
74
  $text->set_layout('form', '{label ref_base="layout"} {inherit}');
75
  $this->add($text);
76
-
77
  // Checkbox
78
  $cb = new SLB_Field_Type('checkbox', 'input');
79
  $cb->set_property('type', 'checkbox');
@@ -88,7 +88,7 @@ class SLB_Fields extends SLB_Field_Collection {
88
  $ta->set_property('cols', 40, 'attr');
89
  $ta->set_property('rows', 3, 'attr');
90
  $this->add($ta);
91
-
92
  // Rich Text
93
  $rt = new SLB_Field_Type('richtext', 'textarea');
94
  $rt->set_property('class', 'theEditor {inherit}');
@@ -111,26 +111,26 @@ class SLB_Fields extends SLB_Field_Collection {
111
  $select->set_property('options', array());
112
  $select->set_layout('form', '{label ref_base="layout"} {form_start ref_base="layout"}{option_loop ref_base="layout"}{form_end ref_base="layout"}');
113
  $select->set_layout('option_loop', '{loop data="properties.options" layout="option" layout_data="option_data"}');
114
- $select->set_layout('option', '<{tag_option} value="{data_ext id="option_value"}">{data_ext id="option_text"}</{tag_option}>');
115
- $select->set_layout('option_data', '<{tag_option} value="{data_ext id="option_value"}" selected="selected">{data_ext id="option_text"}</{tag_option}>');
116
  $this->add($select);
117
-
118
  // Span
119
  $span = new SLB_Field_Type('span', 'base_closed');
120
  $span->set_description(__('Inline wrapper', 'simple-lightbox'));
121
  $span->set_property('tag', 'span');
122
  $span->set_property('value', 'Hello there!');
123
  $this->add($span);
124
-
125
  // Enable plugins to modify (add, remove, etc.) field types
126
  $this->util->do_action_ref_array('register_fields', array($this), false);
127
-
128
  // Signal completion of field registration
129
  $this->util->do_action_ref_array('fields_registered', array($this), false);
130
  }
131
-
132
  /* Placeholder handlers */
133
-
134
  function register_placeholders() {
135
  // Default placeholder handlers
136
  $this->register_placeholder('all', $this->m('process_placeholder_default'), 11);
@@ -141,14 +141,14 @@ class SLB_Fields extends SLB_Field_Collection {
141
  $this->register_placeholder('loop', $this->m('process_placeholder_loop'));
142
  $this->register_placeholder('label', $this->m('process_placeholder_label'));
143
  $this->register_placeholder('checked', $this->m('process_placeholder_checked'));
144
-
145
  // Allow other code to register placeholders
146
  $this->util->do_action_ref_array('register_field_placeholders', array($this), false);
147
-
148
  // Signal completion of field placeholder registration
149
  $this->util->do_action_ref_array('field_placeholders_registered', array($this), false);
150
  }
151
-
152
  /**
153
  * Register a function to handle a placeholder
154
  * Multiple handlers may be registered for a single placeholder
@@ -168,7 +168,7 @@ class SLB_Fields extends SLB_Field_Collection {
168
  $hook = $this->add_prefix('process_placeholder' . $placeholder);
169
  add_filter($hook, $callback, $priority, 5);
170
  }
171
-
172
  /**
173
  * Default placeholder processing
174
  * To be executed when current placeholder has not been handled by another handler
@@ -201,11 +201,15 @@ class SLB_Fields extends SLB_Field_Collection {
201
  if ( 'properties' == $placeholder['tag'] && ($prop_group = $item->get_group($placeholder['attributes']['group'])) && !empty($prop_group) ) {
202
  /* Process group */
203
  $group_out = array();
204
- // Iterate through properties in group and build string
205
- foreach ( array_keys($prop_group) as $prop_key ) {
206
- $prop_val = $item->get_property($prop_key);
207
- if ( !is_null($prop_val) )
208
- $group_out[] = $prop_key . '="' . $prop_val . '"';
 
 
 
 
209
  }
210
  $output = implode(' ', $group_out);
211
  }
@@ -222,28 +226,55 @@ class SLB_Fields extends SLB_Field_Collection {
222
  }
223
 
224
  /**
225
- * Build Field ID attribute
226
- * @see SLB_Field_Type::process_placeholder_default for parameter descriptions
227
- * @return string Placeholder output
 
 
 
 
 
 
 
 
 
228
  */
229
- function process_placeholder_id($output, $item, $placeholder, $layout, $data) {
230
  // Get attributes
231
- $args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_id'));
232
- return $item->get_id($args);
 
 
 
 
 
233
  }
234
-
235
  /**
236
- * Build Field name attribute
237
- * Name is formatted as an associative array for processing by PHP after submission
238
- * @see SLB_Field_Type::process_placeholder_default for parameter descriptions
239
- * @return string Placeholder output
 
 
 
 
 
 
 
 
240
  */
241
- function process_placeholder_name($output, $item, $placeholder, $layout, $data) {
242
  // Get attributes
243
- $args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_name'));
244
- return $item->get_id($args);
 
 
 
 
 
245
  }
246
-
247
  /**
248
  * Build item label
249
  * @see SLB_Fields::process_placeholder_default for parameter descriptions
@@ -257,35 +288,30 @@ class SLB_Fields extends SLB_Field_Collection {
257
  $out = $item->get_title();
258
  return $out;
259
  }
260
-
261
  /**
262
  * Retrieve data for item
263
  * @see SLB_Field_Type::process_placeholder_default for parameter descriptions
264
  * @return string Placeholder output
265
  */
266
  function process_placeholder_data($output, $item, $placeholder, $layout) {
267
- $attr_default = array (
268
- 'context' => '',
269
- );
270
- $opts = wp_parse_args($placeholder['attributes'], $attr_default);
271
- // Save context to separate variable
272
- $context = $opts['context'];
273
- unset($opts['context']);
274
  // Get data
275
  $out = $item->get_data($opts);
276
- if ( !is_null($out) ) {
277
  // Get specific member in value (e.g. value from a specific item element)
278
  if ( isset($opts['element']) && is_array($out) && ( $el = $opts['element'] ) && isset($out[$el]) )
279
  $out = $out[$el];
280
  }
281
-
282
- // Format data based on context
283
- $out = $item->preserve_special_chars($out, $context);
284
- $out = $item->format($out, $context);
285
  // Return data
286
  return $out;
287
  }
288
-
289
  /**
290
  * Set checked attribute on item
291
  * Evaluates item's data to see if item should be checked or not
@@ -325,11 +351,11 @@ class SLB_Fields extends SLB_Field_Collection {
325
  // Get data for loop
326
  $path = explode('.', $attr['data']);
327
  $loop_data = $item->get_member_value($path);
328
-
329
  // Check if data is callback
330
  if ( is_callable($loop_data) )
331
  $loop_data = call_user_func($loop_data);
332
-
333
  // Get item data
334
  $data = $item->get_data();
335
 
@@ -351,22 +377,30 @@ class SLB_Fields extends SLB_Field_Collection {
351
  // Return output
352
  return implode($out);
353
  }
354
-
355
  /**
356
- * Returns specified value from extended data array for item
357
- * @see SLB_Field_Type::process_placeholder_default for parameter descriptions
358
- * @return string Placeholder output
 
 
 
 
 
 
 
359
  */
360
- function process_placeholder_data_ext($output, $item, $placeholder, $layout, $data) {
361
- if ( isset($placeholder['attributes']['id']) && ($key = $placeholder['attributes']['id']) && isset($data[$key]) ) {
362
- $output = strval($data[$key]);
 
363
  }
364
-
365
  return $output;
366
  }
367
-
368
  /* Build */
369
-
370
  /**
371
  * Output items in a group
372
  * @param string $group ID of Group to output
7
  *
8
  */
9
  class SLB_Fields extends SLB_Field_Collection {
10
+
11
  var $item_type = 'SLB_Field_Type';
12
+
13
  /**
14
  * Placeholder handlers
15
  * @var array
16
  */
17
  var $placholders = null;
18
+
19
  /* Constructor */
20
+
21
  function __construct() {
22
  parent::__construct('fields');
23
  }
24
+
25
  protected function _hooks() {
26
  parent::_hooks();
27
  // Init fields
29
  // Init placeholders
30
  add_action('init', $this->m('register_placeholders'));
31
  }
32
+
33
  /* Field Types */
34
+
35
  /**
36
  * Initialize fields
37
  */
73
  $text->set_property('label');
74
  $text->set_layout('form', '{label ref_base="layout"} {inherit}');
75
  $this->add($text);
76
+
77
  // Checkbox
78
  $cb = new SLB_Field_Type('checkbox', 'input');
79
  $cb->set_property('type', 'checkbox');
88
  $ta->set_property('cols', 40, 'attr');
89
  $ta->set_property('rows', 3, 'attr');
90
  $this->add($ta);
91
+
92
  // Rich Text
93
  $rt = new SLB_Field_Type('richtext', 'textarea');
94
  $rt->set_property('class', 'theEditor {inherit}');
111
  $select->set_property('options', array());
112
  $select->set_layout('form', '{label ref_base="layout"} {form_start ref_base="layout"}{option_loop ref_base="layout"}{form_end ref_base="layout"}');
113
  $select->set_layout('option_loop', '{loop data="properties.options" layout="option" layout_data="option_data"}');
114
+ $select->set_layout('option', '<{tag_option} value="{data_ext id="option_value" context="attr"}">{data_ext id="option_text" context="text"}</{tag_option}>');
115
+ $select->set_layout('option_data', '<{tag_option} value="{data_ext id="option_value" context="attr"}" selected="selected">{data_ext id="option_text" context="text"}</{tag_option}>');
116
  $this->add($select);
117
+
118
  // Span
119
  $span = new SLB_Field_Type('span', 'base_closed');
120
  $span->set_description(__('Inline wrapper', 'simple-lightbox'));
121
  $span->set_property('tag', 'span');
122
  $span->set_property('value', 'Hello there!');
123
  $this->add($span);
124
+
125
  // Enable plugins to modify (add, remove, etc.) field types
126
  $this->util->do_action_ref_array('register_fields', array($this), false);
127
+
128
  // Signal completion of field registration
129
  $this->util->do_action_ref_array('fields_registered', array($this), false);
130
  }
131
+
132
  /* Placeholder handlers */
133
+
134
  function register_placeholders() {
135
  // Default placeholder handlers
136
  $this->register_placeholder('all', $this->m('process_placeholder_default'), 11);
141
  $this->register_placeholder('loop', $this->m('process_placeholder_loop'));
142
  $this->register_placeholder('label', $this->m('process_placeholder_label'));
143
  $this->register_placeholder('checked', $this->m('process_placeholder_checked'));
144
+
145
  // Allow other code to register placeholders
146
  $this->util->do_action_ref_array('register_field_placeholders', array($this), false);
147
+
148
  // Signal completion of field placeholder registration
149
  $this->util->do_action_ref_array('field_placeholders_registered', array($this), false);
150
  }
151
+
152
  /**
153
  * Register a function to handle a placeholder
154
  * Multiple handlers may be registered for a single placeholder
168
  $hook = $this->add_prefix('process_placeholder' . $placeholder);
169
  add_filter($hook, $callback, $priority, 5);
170
  }
171
+
172
  /**
173
  * Default placeholder processing
174
  * To be executed when current placeholder has not been handled by another handler
201
  if ( 'properties' == $placeholder['tag'] && ($prop_group = $item->get_group($placeholder['attributes']['group'])) && !empty($prop_group) ) {
202
  /* Process group */
203
  $group_out = array();
204
+ // Iterate through properties in group and build string.
205
+ foreach ( array_keys( $prop_group ) as $prop_key ) {
206
+ $prop_val = $item->get_property( $prop_key );
207
+ if ( !is_null( $prop_val ) ) {
208
+ // Process placeholders.
209
+ $prop_val = $item->process_placeholders( $prop_val, $layout, $data );
210
+ // Add property to attribute string output.
211
+ $group_out[] = esc_attr( $prop_key ) . '="' . esc_attr( $prop_val ) . '"';
212
+ }
213
  }
214
  $output = implode(' ', $group_out);
215
  }
226
  }
227
 
228
  /**
229
+ * Renders field ID formatted for a form field's `id` attribute.
230
+ *
231
+ * ID is formatted to be unique identifier for form field.
232
+ * Example: `options_field_id`.
233
+ * Registered as handler for `{field_id}` placeholder.
234
+ *
235
+ * @param string $output Placeholder's rendered value.
236
+ * @param SLB_Field $item Field containing placeholder.
237
+ * @param array &$placeholder Placeholder being processed.
238
+ * @param string $layout Name of layout being built.
239
+ * @param array $data Additional data for current field.
240
+ * @return string Field's ID (formatted for a form field's `id` attribute).
241
  */
242
+ function process_placeholder_id( $output, $item, &$placeholder, $layout, $data ) {
243
  // Get attributes
244
+ $args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_id'));
245
+ $output = $item->get_id($args);
246
+ // Set default placeholder context.
247
+ if ( ! isset( $placeholder['attributes']['context'] ) ) {
248
+ $placeholder['attributes']['context'] = 'attr';
249
+ }
250
+ return $output;
251
  }
252
+
253
  /**
254
+ * Renders field ID formatted for a form field's `name` attribute.
255
+ *
256
+ * ID is formatted to be part of an associative array for processing form submission.
257
+ * Example: `options[field_id]`.
258
+ * Registered as handler for `{field_name}` placeholder.
259
+ *
260
+ * @param string $output Placeholder's rendered value.
261
+ * @param SLB_Field $item Field containing placeholder.
262
+ * @param array &$placeholder Placeholder being processed.
263
+ * @param string $layout Name of layout being built.
264
+ * @param array $data Additional data for current field.
265
+ * @return string Field's ID (formatted for a form field's `name` attribute).
266
  */
267
+ function process_placeholder_name($output, $item, &$placeholder, $layout, $data) {
268
  // Get attributes
269
+ $args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_name'));
270
+ $output = $item->get_id($args);
271
+ // Set default placeholder context.
272
+ if ( ! isset( $placeholder['attributes']['context'] ) ) {
273
+ $placeholder['attributes']['context'] = 'attr';
274
+ }
275
+ return $output;
276
  }
277
+
278
  /**
279
  * Build item label
280
  * @see SLB_Fields::process_placeholder_default for parameter descriptions
288
  $out = $item->get_title();
289
  return $out;
290
  }
291
+
292
  /**
293
  * Retrieve data for item
294
  * @see SLB_Field_Type::process_placeholder_default for parameter descriptions
295
  * @return string Placeholder output
296
  */
297
  function process_placeholder_data($output, $item, $placeholder, $layout) {
298
+ $opts = $placeholder['attributes'];
299
+ // Strip context from data retrieval options (Formatting handled upstream).
300
+ if ( is_array( $opts ) ) {
301
+ unset( $opts['context'] );
302
+ }
 
 
303
  // Get data
304
  $out = $item->get_data($opts);
305
+ if ( ! is_null($out) ) {
306
  // Get specific member in value (e.g. value from a specific item element)
307
  if ( isset($opts['element']) && is_array($out) && ( $el = $opts['element'] ) && isset($out[$el]) )
308
  $out = $out[$el];
309
  }
310
+
 
 
 
311
  // Return data
312
  return $out;
313
  }
314
+
315
  /**
316
  * Set checked attribute on item
317
  * Evaluates item's data to see if item should be checked or not
351
  // Get data for loop
352
  $path = explode('.', $attr['data']);
353
  $loop_data = $item->get_member_value($path);
354
+
355
  // Check if data is callback
356
  if ( is_callable($loop_data) )
357
  $loop_data = call_user_func($loop_data);
358
+
359
  // Get item data
360
  $data = $item->get_data();
361
 
377
  // Return output
378
  return implode($out);
379
  }
380
+
381
  /**
382
+ * Returns specified value from extended data array for item.
383
+ *
384
+ * @param string $output Value to be used in place of placeholder.
385
+ * @param SLB_Field $item Field containing placeholder.
386
+ * @param array $placeholder Current placeholder.
387
+ * @see SLB_Field::parse_layout for structure of `$placeholder` array.
388
+ * @param string $layout Name of layout being built.
389
+ * @param array $data Extended data for item.
390
+ *
391
+ * @return string Processed value.
392
  */
393
+ function process_placeholder_data_ext( string $output, SLB_Field $item, array $placeholder, string $layout, array $data ) {
394
+ $key = ( isset( $placeholder['attributes']['id'] ) ) ? $placeholder['attributes']['id'] : false;
395
+ if ( !! $key && isset( $data[ $key ] ) && is_scalar( $data[ $key ] ) ) {
396
+ $output = strval( $data[ $key ] );
397
  }
398
+
399
  return $output;
400
  }
401
+
402
  /* Build */
403
+
404
  /**
405
  * Output items in a group
406
  * @param string $group ID of Group to output
includes/class.option.php CHANGED
@@ -6,17 +6,17 @@
6
  * @author Archetyped
7
  */
8
  class SLB_Option extends SLB_Field {
9
-
10
  /* Properties */
11
-
12
  public $hook_prefix = 'option';
13
-
14
  /**
15
  * Determines whether option will be sent to client
16
  * @var bool
17
  */
18
  var $in_client = false;
19
-
20
  /**
21
  * Child mapping
22
  * @see SLB_Field_Base::map
@@ -26,11 +26,11 @@ class SLB_Option extends SLB_Field {
26
  'default' => 'data',
27
  'attr' => 'properties'
28
  );
29
-
30
  var $property_priority = array ('id', 'data', 'parent');
31
-
32
  /* Init */
33
-
34
  /**
35
  * @see SLB_Field::__construct()
36
  * @uses parent::__construct() to initialize instance
@@ -51,17 +51,17 @@ class SLB_Option extends SLB_Field {
51
  // Send to parent constructor
52
  parent::__construct($props);
53
  }
54
-
55
  /* Getters/Setters */
56
-
57
  /**
58
  * Retrieve default value for option
59
  * @return mixed Default option value
60
  */
61
  function get_default($context = '') {
62
- return $this->get_data($context, false);
63
  }
64
-
65
  /**
66
  * Sets parent based on default value
67
  */
@@ -78,7 +78,7 @@ class SLB_Option extends SLB_Field {
78
  }
79
  parent::set_parent($parent);
80
  }
81
-
82
  /**
83
  * Set in_client property
84
  * @uses this::in_client
@@ -88,7 +88,7 @@ class SLB_Option extends SLB_Field {
88
  function set_in_client($in_client = false) {
89
  $this->in_client = !!$in_client;
90
  }
91
-
92
  /**
93
  * Determines whether option should be included in client output
94
  * @uses this::in_client
@@ -97,9 +97,9 @@ class SLB_Option extends SLB_Field {
97
  function get_in_client() {
98
  return $this->in_client;
99
  }
100
-
101
  /* Formatting */
102
-
103
  /**
104
  * Format data as string for browser output
105
  * @see SLB_Field_Base::format()
@@ -121,13 +121,13 @@ class SLB_Option extends SLB_Field {
121
  }
122
  return htmlentities($value);
123
  }
124
-
125
  /**
126
  * Format data using same format as default value
127
  * @see SLB_Field_Base::format()
128
  * @param mixed $value Data to format
129
  * @param string $context (optional) Current context
130
- * @return mixed Formatted option value
131
  */
132
  function format_default($value, $context = '') {
133
  // Get default value
@@ -140,7 +140,7 @@ class SLB_Option extends SLB_Field {
140
  $value = $this->format_string($value);
141
  return $value;
142
  }
143
-
144
  /**
145
  * Format data as boolean (true/false)
146
  * @see SLB_Field_Base::format()
@@ -153,7 +153,7 @@ class SLB_Option extends SLB_Field {
153
  $value = !!$value;
154
  return $value;
155
  }
156
-
157
  /**
158
  * Format data as string
159
  * @see SLB_Field_Base::format()
@@ -164,13 +164,13 @@ class SLB_Option extends SLB_Field {
164
  function format_string($value, $context = '') {
165
  if ( is_bool($value) ) {
166
  $value = ( $value ) ? 'true' : 'false';
167
- }
168
  elseif ( is_object($value) ) {
169
  $value = get_class($value);
170
  }
171
  elseif ( is_array($value) ) {
172
  $value = implode(' ', $value);
173
- }
174
  else {
175
  $value = strval($value);
176
  }
6
  * @author Archetyped
7
  */
8
  class SLB_Option extends SLB_Field {
9
+
10
  /* Properties */
11
+
12
  public $hook_prefix = 'option';
13
+
14
  /**
15
  * Determines whether option will be sent to client
16
  * @var bool
17
  */
18
  var $in_client = false;
19
+
20
  /**
21
  * Child mapping
22
  * @see SLB_Field_Base::map
26
  'default' => 'data',
27
  'attr' => 'properties'
28
  );
29
+
30
  var $property_priority = array ('id', 'data', 'parent');
31
+
32
  /* Init */
33
+
34
  /**
35
  * @see SLB_Field::__construct()
36
  * @uses parent::__construct() to initialize instance
51
  // Send to parent constructor
52
  parent::__construct($props);
53
  }
54
+
55
  /* Getters/Setters */
56
+
57
  /**
58
  * Retrieve default value for option
59
  * @return mixed Default option value
60
  */
61
  function get_default($context = '') {
62
+ return $this->get_data($context, false);
63
  }
64
+
65
  /**
66
  * Sets parent based on default value
67
  */
78
  }
79
  parent::set_parent($parent);
80
  }
81
+
82
  /**
83
  * Set in_client property
84
  * @uses this::in_client
88
  function set_in_client($in_client = false) {
89
  $this->in_client = !!$in_client;
90
  }
91
+
92
  /**
93
  * Determines whether option should be included in client output
94
  * @uses this::in_client
97
  function get_in_client() {
98
  return $this->in_client;
99
  }
100
+
101
  /* Formatting */
102
+
103
  /**
104
  * Format data as string for browser output
105
  * @see SLB_Field_Base::format()
121
  }
122
  return htmlentities($value);
123
  }
124
+
125
  /**
126
  * Format data using same format as default value
127
  * @see SLB_Field_Base::format()
128
  * @param mixed $value Data to format
129
  * @param string $context (optional) Current context
130
+ * @return mixed Formatted option value
131
  */
132
  function format_default($value, $context = '') {
133
  // Get default value
140
  $value = $this->format_string($value);
141
  return $value;
142
  }
143
+
144
  /**
145
  * Format data as boolean (true/false)
146
  * @see SLB_Field_Base::format()
153
  $value = !!$value;
154
  return $value;
155
  }
156
+
157
  /**
158
  * Format data as string
159
  * @see SLB_Field_Base::format()
164
  function format_string($value, $context = '') {
165
  if ( is_bool($value) ) {
166
  $value = ( $value ) ? 'true' : 'false';
167
+ }
168
  elseif ( is_object($value) ) {
169
  $value = get_class($value);
170
  }
171
  elseif ( is_array($value) ) {
172
  $value = implode(' ', $value);
173
+ }
174
  else {
175
  $value = strval($value);
176
  }
includes/class.options.php CHANGED
@@ -7,9 +7,9 @@
7
  * @uses SLB_Field_Collection
8
  */
9
  class SLB_Options extends SLB_Field_Collection {
10
-
11
  /* Properties */
12
-
13
  public $hook_prefix = 'options';
14
 
15
  var $item_type = 'SLB_Option';
@@ -19,24 +19,24 @@ class SLB_Options extends SLB_Field_Collection {
19
  * @var string
20
  */
21
  private $version_key = 'version';
22
-
23
  /**
24
  * Whether version has been checked
25
  * @var bool
26
  */
27
  var $version_checked = false;
28
-
29
  var $items_migrated = false;
30
-
31
  var $build_vars = array (
32
  'validate_pre' => false,
33
  'validate_post' => false,
34
  'save_pre' => false,
35
  'save_post' => false
36
  );
37
-
38
  /* Init */
39
-
40
  function __construct($id = '', $props = array()) {
41
  // Validate arguments
42
  $args = func_get_args();
@@ -49,7 +49,7 @@ class SLB_Options extends SLB_Field_Collection {
49
  parent::__construct($props);
50
  $this->add_prefix_ref($this->version_key);
51
  }
52
-
53
  protected function _hooks() {
54
  parent::_hooks();
55
  // Register fields
@@ -62,9 +62,9 @@ class SLB_Options extends SLB_Field_Collection {
62
  $this->util->add_action('admin_page_render_content', $this->m('admin_page_render_content'), 10, 3, false);
63
  $this->util->add_filter('admin_action_reset', $this->m('admin_action_reset'), 10, 3, false);
64
  }
65
-
66
  /* Legacy/Migration */
67
-
68
  /**
69
  * Checks whether new version has been installed and migrates necessary settings
70
  * @uses $version_key as option name
@@ -93,10 +93,10 @@ class SLB_Options extends SLB_Field_Collection {
93
  // Migrate
94
  $this->migrate($version_changed);
95
  }
96
-
97
  return $this->version_checked;
98
  }
99
-
100
  /**
101
  * Save plugin version to DB
102
  * If no version supplied, will fetch plugin data to determine version
@@ -110,7 +110,7 @@ class SLB_Options extends SLB_Field_Collection {
110
  }
111
  return update_option($this->version_key, $ver);
112
  }
113
-
114
  /**
115
  * Retrieve saved version data
116
  * @return string Saved version
@@ -118,7 +118,7 @@ class SLB_Options extends SLB_Field_Collection {
118
  function get_version() {
119
  return get_option($this->version_key, '');
120
  }
121
-
122
  /**
123
  * Migrate options from old versions to current version
124
  * @uses self::items_migrated to determine if simple migration has been performed in current request or not
@@ -128,13 +128,13 @@ class SLB_Options extends SLB_Field_Collection {
128
  function migrate($full = false) {
129
  if ( !$full && $this->items_migrated )
130
  return false;
131
-
132
  // Legacy options
133
  $d = null;
134
  $this->load_data();
135
-
136
  $items = $this->get_items();
137
-
138
  // Migrate separate options to unified option
139
  if ( $full ) {
140
  foreach ( $items as $opt => $props ) {
@@ -148,7 +148,7 @@ class SLB_Options extends SLB_Field_Collection {
148
  }
149
  }
150
  }
151
-
152
  // Migrate legacy items
153
  if ( is_array($this->properties_init) && isset($this->properties_init['legacy']) && is_array($this->properties_init['legacy']) ) {
154
  $l =& $this->properties_init['legacy'];
@@ -161,7 +161,7 @@ class SLB_Options extends SLB_Field_Collection {
161
  unset($l[$opt]);
162
  }
163
  }
164
-
165
  /* Separate options */
166
  if ( $full ) {
167
  foreach ( $l as $opt => $dest ) {
@@ -178,9 +178,9 @@ class SLB_Options extends SLB_Field_Collection {
178
  delete_option($oid);
179
  }
180
  }
181
-
182
  /* Simple Migration (Internal options only) */
183
-
184
  // Get existing items that are also legacy items
185
  $opts = array_intersect_key($this->get_data(), $l);
186
  foreach ( $opts as $opt => $val ) {
@@ -200,9 +200,9 @@ class SLB_Options extends SLB_Field_Collection {
200
  // Set flag
201
  $this->items_migrated = true;
202
  }
203
-
204
  /* Option setup */
205
-
206
  /**
207
  * Get elements for creating fields
208
  * @return obj
@@ -225,7 +225,7 @@ class SLB_Options extends SLB_Field_Collection {
225
  }
226
  return $o;
227
  }
228
-
229
  /**
230
  * Register option-specific fields
231
  * @param SLB_Fields $fields Reference to global fields object
@@ -235,7 +235,7 @@ class SLB_Options extends SLB_Field_Collection {
235
  // Layouts
236
  $o = $this->get_field_elements();
237
  $l =& $o->layout;
238
-
239
  $form = implode('', array (
240
  $l->opt_pre,
241
  $l->label_ref,
@@ -244,22 +244,23 @@ class SLB_Options extends SLB_Field_Collection {
244
  $l->field_post,
245
  $l->opt_post
246
  ));
247
-
248
  // Text input
249
  $otxt = new SLB_Field_Type('option_text', 'text');
250
  $otxt->set_property('class', '{inherit} code');
251
  $otxt->set_property('size', null);
252
- $otxt->set_property('value', '{data context="form"}');
253
  $otxt->set_layout('label', $l->label);
254
  $otxt->set_layout('form', $form);
255
  $fields->add($otxt);
256
-
257
  // Checkbox
258
  $ocb = new SLB_Field_Type('option_checkbox', 'checkbox');
259
  $ocb->set_layout('label', $l->label);
260
- $ocb->set_layout('form', $form);
 
261
  $fields->add($ocb);
262
-
263
  // Select
264
  $othm = new SLB_Field_Type('option_select', 'select');
265
  $othm->set_layout('label', $l->label);
@@ -268,7 +269,7 @@ class SLB_Options extends SLB_Field_Collection {
268
  $othm->set_layout('form', $l->opt_pre . '{inherit}' . $l->opt_post);
269
  $fields->add($othm);
270
  }
271
-
272
  /**
273
  * Set parent field types for options
274
  * Parent only set for Admin pages
@@ -290,66 +291,117 @@ class SLB_Options extends SLB_Field_Collection {
290
  $p = 'o:' . $p->id;
291
  }
292
  }
293
-
294
  /* Processing */
295
-
296
  /**
297
- * Validate option values
298
- * Used for validating options (e.g. admin form submission) prior to saving options to DB
299
- * Reformats values based on options' default values (i.e. bool, int, string, etc.)
300
- * Adds option items not included in original submission
301
- * @param array $values (optional) Option values
302
- * @return array Full options data
 
 
 
 
 
 
303
  */
304
- function validate($values = null) {
305
- $qvar = $this->get_id('formatted');
306
- if ( empty($values) && isset($_REQUEST[$qvar]) ) {
307
- $values = $_REQUEST[$qvar];
 
 
 
308
  }
309
- if ( is_array($values) ) {
310
- // Format data based on option type (bool, string, etc.)
311
- foreach ( $values as $id => $val ) {
312
- // Get default
313
- $d = $this->get_default($id);
314
- if ( is_bool($d) && !empty($val) )
315
- $values[$id] = true;
 
 
 
 
 
 
 
316
  }
317
-
318
- // Merge in additional options that are not in post data
319
- // Missing options (e.g. disabled checkboxes, empty fields, etc.)
320
-
321
- // Get groups that were output in request
322
- $qvar_groups = $qvar . '_groups';
323
- if ( isset($_REQUEST[$qvar_groups]) ) {
324
- $groups = explode( ',', implode(',', $_REQUEST[$qvar_groups]) );
325
-
326
- // Get group items
327
- $items = array();
328
- $items_temp = null;
329
- foreach ( $groups as $gid ) {
330
- $items_temp = $this->get_group_items($gid);
331
- $items = array_merge($items, $items_temp);
332
- }
333
- unset($items_temp);
334
- $items = call_user_func_array('array_merge', $items);
335
- foreach ( $items as $id => $opt ) {
336
- // Add options that were not included in form submission
337
- if ( !array_key_exists($id, $values) ) {
338
- if ( is_bool($opt->get_default()) )
339
- $values[$id] = false;
340
- else
341
- $values[$id] = $opt->get_default();
342
  }
343
  }
344
  }
 
345
  }
346
-
347
- // Return value
348
- return $values;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
349
  }
350
-
351
  /* Data */
352
-
353
  /**
354
  * Retrieve options from database
355
  * @uses get_option to retrieve option data
@@ -370,7 +422,7 @@ class SLB_Options extends SLB_Field_Collection {
370
  }
371
  return $data;
372
  }
373
-
374
  /**
375
  * Retrieves option data for collection
376
  * @see SLB_Field_Collection::load_data()
@@ -379,12 +431,12 @@ class SLB_Options extends SLB_Field_Collection {
379
  if ( !$this->data_loaded ) {
380
  // Retrieve data
381
  $this->data = $this->fetch_data();
382
- $this->data_loaded = true;
383
  // Check update
384
  $this->check_update();
385
  }
386
  }
387
-
388
  /**
389
  * Resets option values to their default values
390
  * @param bool $hard Reset all options if TRUE (default), Reset only unset options if FALSE
@@ -398,7 +450,7 @@ class SLB_Options extends SLB_Field_Collection {
398
  // Save
399
  $this->save();
400
  }
401
-
402
  /**
403
  * Save options data to database
404
  */
@@ -406,7 +458,7 @@ class SLB_Options extends SLB_Field_Collection {
406
  $this->normalize_data();
407
  update_option($this->get_key(), $this->data);
408
  }
409
-
410
  /**
411
  * Normalize data
412
  * Assures that data in collection match items
@@ -422,7 +474,7 @@ class SLB_Options extends SLB_Field_Collection {
422
  }
423
 
424
  /* Collection */
425
-
426
  /**
427
  * Build key for saving/retrieving data to options table
428
  * @return string Key
@@ -430,7 +482,7 @@ class SLB_Options extends SLB_Field_Collection {
430
  function get_key() {
431
  return $this->add_prefix($this->get_id());
432
  }
433
-
434
  /**
435
  * Add option to collection
436
  * @uses SLB_Field_Collection::add() to add item
@@ -442,10 +494,10 @@ class SLB_Options extends SLB_Field_Collection {
442
  function &add($id, $properties = array(), $update = false) {
443
  // Create item
444
  $args = func_get_args();
445
- $ret = call_user_func_array(array('parent', 'add'), $args);
446
  return $ret;
447
  }
448
-
449
  /**
450
  * Retrieve option value
451
  * @uses get_data() to retrieve option data
@@ -456,7 +508,7 @@ class SLB_Options extends SLB_Field_Collection {
456
  function get_value($option, $context = '') {
457
  return $this->get_data($option, $context);
458
  }
459
-
460
  /**
461
  * Retrieve option value as boolean (true/false)
462
  * @uses get_data() to retrieve option data
@@ -466,11 +518,11 @@ class SLB_Options extends SLB_Field_Collection {
466
  function get_bool($option) {
467
  return $this->get_value($option, 'bool');
468
  }
469
-
470
  function get_string($option) {
471
  return $this->get_value($option, 'string');
472
  }
473
-
474
  /**
475
  * Retrieve option's default value
476
  * @uses get_data() to retrieve option data
@@ -481,9 +533,9 @@ class SLB_Options extends SLB_Field_Collection {
481
  function get_default($option, $context = '') {
482
  return $this->get_data($option, $context, false);
483
  }
484
-
485
  /* Output */
486
-
487
  function build_init() {
488
  if ( $this->build_vars['validate_pre'] ) {
489
  $values = $this->validate();
@@ -492,7 +544,7 @@ class SLB_Options extends SLB_Field_Collection {
492
  }
493
  }
494
  }
495
-
496
  /**
497
  * Build array of option values for client output
498
  * @return array Associative array of options
@@ -507,9 +559,9 @@ class SLB_Options extends SLB_Field_Collection {
507
  }
508
  return $out;
509
  }
510
-
511
  /* Admin */
512
-
513
  /**
514
  * Handles output building for options on admin pages
515
  * @param obj|array $opts Options instance or Array of options instance and groups to build
@@ -534,7 +586,7 @@ class SLB_Options extends SLB_Field_Collection {
534
  'parse_build_vars' => array( $this->m('admin_parse_build_vars'), 10, 2 )
535
  )
536
  );
537
-
538
  // Add hooks
539
  foreach ( $hooks as $type => $hook ) {
540
  $m = 'add_' . $type;
@@ -543,10 +595,10 @@ class SLB_Options extends SLB_Field_Collection {
543
  call_user_func_array($this->util->m($m), $args);
544
  }
545
  }
546
-
547
  // Build output
548
  $this->build(array('build_groups' => $this->m('admin_build_groups')));
549
-
550
  // Remove hooks
551
  foreach ( $hooks as $type => $hook ) {
552
  $m = 'remove_' . $type;
@@ -567,10 +619,9 @@ class SLB_Options extends SLB_Field_Collection {
567
  $page = $this->get_build_var('admin_page');
568
  $state = $this->get_build_var('admin_state');
569
  $groups = $this->get_build_var('groups');
570
-
571
  // Get all groups
572
  $groups_all = $this->get_groups();
573
- $groups_built = array();
574
  if ( empty($groups) ) {
575
  $groups = array_keys($groups_all);
576
  }
@@ -583,22 +634,9 @@ class SLB_Options extends SLB_Field_Collection {
583
  // Add meta box for each group
584
  $g = $groups_all[$gid];
585
  add_meta_box($g->id, $g->title, $this->m('admin_build_group'), $state->screen, $state->context, $state->priority, array('group' => $g->id, 'page' => $page));
586
- $groups_built[] = $gid;
587
- }
588
-
589
- // Define groups built
590
- if ( !empty($groups_built) ) {
591
- echo $this->util->build_html_element(array(
592
- 'tag' => 'input',
593
- 'attributes' => array (
594
- 'type' => 'hidden',
595
- 'value' => implode(',', $groups_built),
596
- 'name' => $this->get_id('formatted') . '_groups[]'
597
- ),
598
- ));
599
  }
600
  }
601
-
602
  /**
603
  * Group output handler for admin pages
604
  * @param obj $obj Object passed by `do_meta_boxes()` call (Default: NULL)
@@ -609,14 +647,14 @@ class SLB_Options extends SLB_Field_Collection {
609
  $group = $a['group'];
610
  $this->build_group($group);
611
  }
612
-
613
  /**
614
  * Parse build vars
615
  * @uses `options_parse_build_vars` filter hook
616
  */
617
  public function admin_parse_build_vars($vars, $opts) {
618
  // Handle form submission
619
- if ( isset($_REQUEST[$opts->get_id('formatted')]) ) {
620
  $vars['validate_pre'] = $vars['save_pre'] = true;
621
  }
622
  return $vars;
7
  * @uses SLB_Field_Collection
8
  */
9
  class SLB_Options extends SLB_Field_Collection {
10
+
11
  /* Properties */
12
+
13
  public $hook_prefix = 'options';
14
 
15
  var $item_type = 'SLB_Option';
19
  * @var string
20
  */
21
  private $version_key = 'version';
22
+
23
  /**
24
  * Whether version has been checked
25
  * @var bool
26
  */
27
  var $version_checked = false;
28
+
29
  var $items_migrated = false;
30
+
31
  var $build_vars = array (
32
  'validate_pre' => false,
33
  'validate_post' => false,
34
  'save_pre' => false,
35
  'save_post' => false
36
  );
37
+
38
  /* Init */
39
+
40
  function __construct($id = '', $props = array()) {
41
  // Validate arguments
42
  $args = func_get_args();
49
  parent::__construct($props);
50
  $this->add_prefix_ref($this->version_key);
51
  }
52
+
53
  protected function _hooks() {
54
  parent::_hooks();
55
  // Register fields
62
  $this->util->add_action('admin_page_render_content', $this->m('admin_page_render_content'), 10, 3, false);
63
  $this->util->add_filter('admin_action_reset', $this->m('admin_action_reset'), 10, 3, false);
64
  }
65
+
66
  /* Legacy/Migration */
67
+
68
  /**
69
  * Checks whether new version has been installed and migrates necessary settings
70
  * @uses $version_key as option name
93
  // Migrate
94
  $this->migrate($version_changed);
95
  }
96
+
97
  return $this->version_checked;
98
  }
99
+
100
  /**
101
  * Save plugin version to DB
102
  * If no version supplied, will fetch plugin data to determine version
110
  }
111
  return update_option($this->version_key, $ver);
112
  }
113
+
114
  /**
115
  * Retrieve saved version data
116
  * @return string Saved version
118
  function get_version() {
119
  return get_option($this->version_key, '');
120
  }
121
+
122
  /**
123
  * Migrate options from old versions to current version
124
  * @uses self::items_migrated to determine if simple migration has been performed in current request or not
128
  function migrate($full = false) {
129
  if ( !$full && $this->items_migrated )
130
  return false;
131
+
132
  // Legacy options
133
  $d = null;
134
  $this->load_data();
135
+
136
  $items = $this->get_items();
137
+
138
  // Migrate separate options to unified option
139
  if ( $full ) {
140
  foreach ( $items as $opt => $props ) {
148
  }
149
  }
150
  }
151
+
152
  // Migrate legacy items
153
  if ( is_array($this->properties_init) && isset($this->properties_init['legacy']) && is_array($this->properties_init['legacy']) ) {
154
  $l =& $this->properties_init['legacy'];
161
  unset($l[$opt]);
162
  }
163
  }
164
+
165
  /* Separate options */
166
  if ( $full ) {
167
  foreach ( $l as $opt => $dest ) {
178
  delete_option($oid);
179
  }
180
  }
181
+
182
  /* Simple Migration (Internal options only) */
183
+
184
  // Get existing items that are also legacy items
185
  $opts = array_intersect_key($this->get_data(), $l);
186
  foreach ( $opts as $opt => $val ) {
200
  // Set flag
201
  $this->items_migrated = true;
202
  }
203
+
204
  /* Option setup */
205
+
206
  /**
207
  * Get elements for creating fields
208
  * @return obj
225
  }
226
  return $o;
227
  }
228
+
229
  /**
230
  * Register option-specific fields
231
  * @param SLB_Fields $fields Reference to global fields object
235
  // Layouts
236
  $o = $this->get_field_elements();
237
  $l =& $o->layout;
238
+
239
  $form = implode('', array (
240
  $l->opt_pre,
241
  $l->label_ref,
244
  $l->field_post,
245
  $l->opt_post
246
  ));
247
+
248
  // Text input
249
  $otxt = new SLB_Field_Type('option_text', 'text');
250
  $otxt->set_property('class', '{inherit} code');
251
  $otxt->set_property('size', null);
252
+ $otxt->set_property('value', '{data}');
253
  $otxt->set_layout('label', $l->label);
254
  $otxt->set_layout('form', $form);
255
  $fields->add($otxt);
256
+
257
  // Checkbox
258
  $ocb = new SLB_Field_Type('option_checkbox', 'checkbox');
259
  $ocb->set_layout('label', $l->label);
260
+ $ocb->set_layout('field_reference', sprintf( '<input type="hidden" name="%s" value="{field_name format="raw"}" />', "{$this->get_id('formatted')}_items[]" ) );
261
+ $ocb->set_layout('form', '{field_reference ref_base="layout"}' . $form);
262
  $fields->add($ocb);
263
+
264
  // Select
265
  $othm = new SLB_Field_Type('option_select', 'select');
266
  $othm->set_layout('label', $l->label);
269
  $othm->set_layout('form', $l->opt_pre . '{inherit}' . $l->opt_post);
270
  $fields->add($othm);
271
  }
272
+
273
  /**
274
  * Set parent field types for options
275
  * Parent only set for Admin pages
291
  $p = 'o:' . $p->id;
292
  }
293
  }
294
+
295
  /* Processing */
296
+
297
  /**
298
+ * Validates option data.
299
+ *
300
+ * Validates option values (e.g. prior to saving to DB, after form submission, etc.).
301
+ * Values are formatted and sanitized according to corresponding option's data type
302
+ * (e.g. boolean, string, number, etc.).
303
+ *
304
+ * @since 1.5.5
305
+ *
306
+ * @param array<string,scalar> $values Optional. Option data to validate.
307
+ * Indexed by option ID.
308
+ * Default form-submission data used.
309
+ * @return array<string,scalar> Validated data. Indexed by option ID.
310
  */
311
+ function validate( $values = null ) {
312
+ /** @var array<string,scalar> $values_valid Validated option data. Indexed by option ID. */
313
+ $values_valid = [];
314
+ // Enforce values data type.
315
+ if ( ! is_array( $values ) ) {
316
+ /** @var array<string,scalar> $values */
317
+ $values = [];
318
  }
319
+ /**
320
+ * Generates query variable using common base.
321
+ *
322
+ * @since 2.8.0
323
+ *
324
+ * @param string $text Optional. Text to append to base.
325
+ *
326
+ * @return string Query variable name. Format: "{base}_{text}". Default "{base}".
327
+ */
328
+ $qv = function ( $text = '' ) {
329
+ static $base;
330
+ // Get base.
331
+ if ( empty( $base ) ) {
332
+ $base = $this->get_id( 'formatted' );
333
  }
334
+ $out = $base;
335
+ // Append text to base.
336
+ if ( is_string( $text ) && ! empty( $text ) ) {
337
+ $out .= "_{$text}";
338
+ }
339
+ return $out;
340
+ };
341
+ // Get options form field group ID.
342
+ $qvar = $qv();
343
+ // Use form submission data when no values provided.
344
+ if ( empty( $values ) && isset( $_POST[ $qvar ] ) && check_admin_referer( $qvar, $qv( 'nonce' ) ) ) {
345
+ /** @var array<string,scalar> $values */
346
+ $values = $_POST[ $qvar ];
347
+ // Append non-submitted, but rendered fields (e.g. unchecked checkboxes)
348
+ $qvar_items = $qv( 'items' );
349
+ /** @var string[] $items_bool Boolean options rendered in submitted form. */
350
+ $items_bool = ( isset( $_POST[ $qvar_items ] ) ) ? $_POST[ $qvar_items ] : null;
351
+ if ( ! empty( $items_bool ) && is_array( $items_bool) ) {
352
+ foreach ( $items_bool as $item_id ) {
353
+ // Add missing boolean options (false == unchecked).
354
+ if ( ! array_key_exists( $item_id, $values ) && $this->has( $item_id ) && is_bool( $this->get_default( $item_id ) ) ) {
355
+ $values_valid[ $item_id ] = false;
 
 
 
356
  }
357
  }
358
  }
359
+ unset( $qvar, $qvar_items, $items_bool, $item_id );
360
  }
361
+ // Process values.
362
+ /**
363
+ * @var string $id Option ID.
364
+ * @var mixed $val Option value (raw/unsanitized).
365
+ */
366
+ foreach ( $values as $id => $val ) {
367
+ // Do not process invalid option IDs or invalid (non-scalar) data.
368
+ if ( ! $this->has( $id ) || ! is_scalar( $val ) ) {
369
+ continue;
370
+ }
371
+ // Conform to option's data type and sanitize.
372
+ /** @var scalar $d Option's default data. */
373
+ $d = $this->get_default( $id );
374
+ // Boolean.
375
+ if ( is_bool( $d ) ) {
376
+ $val = !! $val;
377
+ }
378
+ // Numeric - do not process non-numeric values for int/float fields.
379
+ elseif ( ( is_int( $d ) || is_float( $d ) ) && ! is_numeric( $val ) ) {
380
+ continue;
381
+ }
382
+ // Integer.
383
+ elseif ( is_int( $d ) ) {
384
+ $val = (int) $val;
385
+ }
386
+ // Float.
387
+ elseif ( is_float( $d ) ) {
388
+ $val = (float) $val;
389
+ }
390
+ // Defaut: Handle as string.
391
+ else {
392
+ $val = sanitize_text_field( wp_unslash( $val ) );
393
+ }
394
+ // Add to validated data.
395
+ $values_valid[ $id ] = $val;
396
+ }
397
+ unset( $id, $val );
398
+
399
+ // Return validated values.
400
+ return $values_valid;
401
  }
402
+
403
  /* Data */
404
+
405
  /**
406
  * Retrieve options from database
407
  * @uses get_option to retrieve option data
422
  }
423
  return $data;
424
  }
425
+
426
  /**
427
  * Retrieves option data for collection
428
  * @see SLB_Field_Collection::load_data()
431
  if ( !$this->data_loaded ) {
432
  // Retrieve data
433
  $this->data = $this->fetch_data();
434
+ parent::load_data();
435
  // Check update
436
  $this->check_update();
437
  }
438
  }
439
+
440
  /**
441
  * Resets option values to their default values
442
  * @param bool $hard Reset all options if TRUE (default), Reset only unset options if FALSE
450
  // Save
451
  $this->save();
452
  }
453
+
454
  /**
455
  * Save options data to database
456
  */
458
  $this->normalize_data();
459
  update_option($this->get_key(), $this->data);
460
  }
461
+
462
  /**
463
  * Normalize data
464
  * Assures that data in collection match items
474
  }
475
 
476
  /* Collection */
477
+
478
  /**
479
  * Build key for saving/retrieving data to options table
480
  * @return string Key
482
  function get_key() {
483
  return $this->add_prefix($this->get_id());
484
  }
485
+
486
  /**
487
  * Add option to collection
488
  * @uses SLB_Field_Collection::add() to add item
494
  function &add($id, $properties = array(), $update = false) {
495
  // Create item
496
  $args = func_get_args();
497
+ $ret = call_user_func_array(array('parent', 'add'), $args);
498
  return $ret;
499
  }
500
+
501
  /**
502
  * Retrieve option value
503
  * @uses get_data() to retrieve option data
508
  function get_value($option, $context = '') {
509
  return $this->get_data($option, $context);
510
  }
511
+
512
  /**
513
  * Retrieve option value as boolean (true/false)
514
  * @uses get_data() to retrieve option data
518
  function get_bool($option) {
519
  return $this->get_value($option, 'bool');
520
  }
521
+
522
  function get_string($option) {
523
  return $this->get_value($option, 'string');
524
  }
525
+
526
  /**
527
  * Retrieve option's default value
528
  * @uses get_data() to retrieve option data
533
  function get_default($option, $context = '') {
534
  return $this->get_data($option, $context, false);
535
  }
536
+
537
  /* Output */
538
+
539
  function build_init() {
540
  if ( $this->build_vars['validate_pre'] ) {
541
  $values = $this->validate();
544
  }
545
  }
546
  }
547
+
548
  /**
549
  * Build array of option values for client output
550
  * @return array Associative array of options
559
  }
560
  return $out;
561
  }
562
+
563
  /* Admin */
564
+
565
  /**
566
  * Handles output building for options on admin pages
567
  * @param obj|array $opts Options instance or Array of options instance and groups to build
586
  'parse_build_vars' => array( $this->m('admin_parse_build_vars'), 10, 2 )
587
  )
588
  );
589
+
590
  // Add hooks
591
  foreach ( $hooks as $type => $hook ) {
592
  $m = 'add_' . $type;
595
  call_user_func_array($this->util->m($m), $args);
596
  }
597
  }
598
+
599
  // Build output
600
  $this->build(array('build_groups' => $this->m('admin_build_groups')));
601
+
602
  // Remove hooks
603
  foreach ( $hooks as $type => $hook ) {
604
  $m = 'remove_' . $type;
619
  $page = $this->get_build_var('admin_page');
620
  $state = $this->get_build_var('admin_state');
621
  $groups = $this->get_build_var('groups');
622
+
623
  // Get all groups
624
  $groups_all = $this->get_groups();
 
625
  if ( empty($groups) ) {
626
  $groups = array_keys($groups_all);
627
  }
634
  // Add meta box for each group
635
  $g = $groups_all[$gid];
636
  add_meta_box($g->id, $g->title, $this->m('admin_build_group'), $state->screen, $state->context, $state->priority, array('group' => $g->id, 'page' => $page));
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  }
638
  }
639
+
640
  /**
641
  * Group output handler for admin pages
642
  * @param obj $obj Object passed by `do_meta_boxes()` call (Default: NULL)
647
  $group = $a['group'];
648
  $this->build_group($group);
649
  }
650
+
651
  /**
652
  * Parse build vars
653
  * @uses `options_parse_build_vars` filter hook
654
  */
655
  public function admin_parse_build_vars($vars, $opts) {
656
  // Handle form submission
657
+ if ( isset($_POST[$opts->get_id('formatted')]) ) {
658
  $vars['validate_pre'] = $vars['save_pre'] = true;
659
  }
660
  return $vars;
includes/class.template_tags.php CHANGED
@@ -8,36 +8,36 @@
8
  */
9
  class SLB_Template_Tags extends SLB_Collection_Controller {
10
  /* Configuration */
11
-
12
  protected $item_type = 'SLB_Template_Tag';
13
-
14
  public $hook_prefix = 'template_tags';
15
-
16
  // Use tag ID as key
17
  protected $key_prop = 'get_id';
18
-
19
  // Call $key_prop is a method to be called
20
  protected $key_call = true;
21
-
22
  /* Properties */
23
-
24
  /**
25
  * Cache properties (key, group)
26
  * @var object
27
  */
28
  protected $cache_props = null;
29
-
30
  /* Initialization */
31
-
32
  protected function _hooks() {
33
  parent::_hooks();
34
  $this->util->add_action('init', $this->m('init_defaults'));
35
  $this->util->add_action('footer', $this->m('client_output'), 1, 0, false);
36
  $this->util->add_filter('footer_script', $this->m('client_output_script'), $this->util->priority('client_footer_output'), 1, false);
37
  }
38
-
39
  /* Collection Management */
40
-
41
  /**
42
  * Add template tag
43
  * Accepts properties to create new template tag OR previously-initialized tag instance
@@ -51,9 +51,9 @@ class SLB_Template_Tags extends SLB_Collection_Controller {
51
  // Add to collection
52
  return parent::add($o);
53
  }
54
-
55
  /* Defaults */
56
-
57
  /**
58
  * Initialize default template tags
59
  * @param SLB_Template_Tags $tags Tags controller
@@ -78,9 +78,9 @@ class SLB_Template_Tags extends SLB_Collection_Controller {
78
  $tags->add($id, $props);
79
  }
80
  }
81
-
82
  /* Output */
83
-
84
  /**
85
  * Build client output
86
  */
@@ -90,7 +90,7 @@ class SLB_Template_Tags extends SLB_Collection_Controller {
90
  $tag->enqueue_scripts();
91
  }
92
  }
93
-
94
  /**
95
  * Client output script
96
  * @param array $commands Client script commands
@@ -99,7 +99,7 @@ class SLB_Template_Tags extends SLB_Collection_Controller {
99
  public function client_output_script($commands) {
100
  $out = array('/* TPLT */');
101
  $code = array();
102
-
103
  foreach ( $this->get() as $tag ) {
104
  $styles = $tag->get_styles(array('uri_format'=>'full'));
105
  if ( empty($styles) ) {
8
  */
9
  class SLB_Template_Tags extends SLB_Collection_Controller {
10
  /* Configuration */
11
+
12
  protected $item_type = 'SLB_Template_Tag';
13
+
14
  public $hook_prefix = 'template_tags';
15
+
16
  // Use tag ID as key
17
  protected $key_prop = 'get_id';
18
+
19
  // Call $key_prop is a method to be called
20
  protected $key_call = true;
21
+
22
  /* Properties */
23
+
24
  /**
25
  * Cache properties (key, group)
26
  * @var object
27
  */
28
  protected $cache_props = null;
29
+
30
  /* Initialization */
31
+
32
  protected function _hooks() {
33
  parent::_hooks();
34
  $this->util->add_action('init', $this->m('init_defaults'));
35
  $this->util->add_action('footer', $this->m('client_output'), 1, 0, false);
36
  $this->util->add_filter('footer_script', $this->m('client_output_script'), $this->util->priority('client_footer_output'), 1, false);
37
  }
38
+
39
  /* Collection Management */
40
+
41
  /**
42
  * Add template tag
43
  * Accepts properties to create new template tag OR previously-initialized tag instance
51
  // Add to collection
52
  return parent::add($o);
53
  }
54
+
55
  /* Defaults */
56
+
57
  /**
58
  * Initialize default template tags
59
  * @param SLB_Template_Tags $tags Tags controller
78
  $tags->add($id, $props);
79
  }
80
  }
81
+
82
  /* Output */
83
+
84
  /**
85
  * Build client output
86
  */
90
  $tag->enqueue_scripts();
91
  }
92
  }
93
+
94
  /**
95
  * Client output script
96
  * @param array $commands Client script commands
99
  public function client_output_script($commands) {
100
  $out = array('/* TPLT */');
101
  $code = array();
102
+
103
  foreach ( $this->get() as $tag ) {
104
  $styles = $tag->get_styles(array('uri_format'=>'full'));
105
  if ( empty($styles) ) {
includes/class.theme.php CHANGED
@@ -8,17 +8,17 @@
8
  */
9
  class SLB_Theme extends SLB_Component {
10
  /* Properties */
11
-
12
  protected $props_required = array('name');
13
-
14
  /**
15
  * Public flag
16
  * @var bool
17
  */
18
  protected $public = true;
19
-
20
  /* Get/Set */
21
-
22
  /**
23
  * Retrieve theme's ancestors
24
  * @param bool $sort_topdown (optional) Ancestor sorting (Default: Nearest to Farthest)
@@ -45,7 +45,7 @@ class SLB_Theme extends SLB_Component {
45
  }
46
  return $ret;
47
  }
48
-
49
  /**
50
  * Set public flag
51
  * @param bool $public
@@ -53,7 +53,7 @@ class SLB_Theme extends SLB_Component {
53
  public function set_public($public) {
54
  $this->public = !!$public;
55
  }
56
-
57
  /**
58
  * Get privacy state
59
  * @return bool
@@ -61,9 +61,9 @@ class SLB_Theme extends SLB_Component {
61
  public function get_public() {
62
  return !!$this->public;
63
  }
64
-
65
  /* Templates */
66
-
67
  /**
68
  * Add template file
69
  * @see `add_file()`
@@ -74,7 +74,7 @@ class SLB_Theme extends SLB_Component {
74
  protected function add_template($handle, $src) {
75
  return $this->add_file('template', $handle, $src);
76
  }
77
-
78
  /**
79
  * Retrieve template file
80
  * @see `get_file()`
@@ -85,9 +85,9 @@ class SLB_Theme extends SLB_Component {
85
  protected function get_template($handle, $format = null) {
86
  return $this->get_file('template', $handle, $format);
87
  }
88
-
89
  /* Layout */
90
-
91
  /**
92
  * Set theme layout
93
  * @uses `add_template()`
@@ -97,7 +97,7 @@ class SLB_Theme extends SLB_Component {
97
  public function set_layout($src) {
98
  return $this->add_template('layout', $src);
99
  }
100
-
101
  /**
102
  * Get layout
103
  * @param string $format (optional) Layout data format
8
  */
9
  class SLB_Theme extends SLB_Component {
10
  /* Properties */
11
+
12
  protected $props_required = array('name');
13
+
14
  /**
15
  * Public flag
16
  * @var bool
17
  */
18
  protected $public = true;
19
+
20
  /* Get/Set */
21
+
22
  /**
23
  * Retrieve theme's ancestors
24
  * @param bool $sort_topdown (optional) Ancestor sorting (Default: Nearest to Farthest)
45
  }
46
  return $ret;
47
  }
48
+
49
  /**
50
  * Set public flag
51
  * @param bool $public
53
  public function set_public($public) {
54
  $this->public = !!$public;
55
  }
56
+
57
  /**
58
  * Get privacy state
59
  * @return bool
61
  public function get_public() {
62
  return !!$this->public;
63
  }
64
+
65
  /* Templates */
66
+
67
  /**
68
  * Add template file
69
  * @see `add_file()`
74
  protected function add_template($handle, $src) {
75
  return $this->add_file('template', $handle, $src);
76
  }
77
+
78
  /**
79
  * Retrieve template file
80
  * @see `get_file()`
85
  protected function get_template($handle, $format = null) {
86
  return $this->get_file('template', $handle, $format);
87
  }
88
+
89
  /* Layout */
90
+
91
  /**
92
  * Set theme layout
93
  * @uses `add_template()`
97
  public function set_layout($src) {
98
  return $this->add_template('layout', $src);
99
  }
100
+
101
  /**
102
  * Get layout
103
  * @param string $format (optional) Layout data format
includes/class.themes.php CHANGED
@@ -8,31 +8,31 @@
8
  */
9
  class SLB_Themes extends SLB_Collection_Controller {
10
  /* Configuration */
11
-
12
  protected $item_type = 'SLB_Theme';
13
-
14
  public $hook_prefix = 'themes';
15
-
16
  protected $key_prop = 'get_id';
17
-
18
  protected $key_call = true;
19
-
20
  /* Properties */
21
-
22
  protected $id_default = null;
23
-
24
  /* Initialization */
25
-
26
  protected function _hooks() {
27
  parent::_hooks();
28
  // Register themes
29
  $this->util->add_action('init', $this->m('init_defaults'), 1);
30
-
31
  // Client output
32
  $this->util->add_action('footer', $this->m('client_output'), 1, 0, false);
33
  $this->util->add_filter('footer_script', $this->m('client_output_script'), $this->util->priority('client_footer_output'), 1, false);
34
  }
35
-
36
  protected function _options() {
37
  $opts = array (
38
  'items' => array (
@@ -46,10 +46,10 @@ class SLB_Themes extends SLB_Collection_Controller {
46
  ),
47
  )
48
  );
49
-
50
  parent::_set_options($opts);
51
  }
52
-
53
  /**
54
  * Add default themes
55
  * @param SLB_Themes $themes Themes controller
@@ -90,14 +90,14 @@ class SLB_Themes extends SLB_Collection_Controller {
90
  )
91
  ),
92
  );
93
-
94
  foreach ( $defaults as $id => $props ) {
95
  $themes->add($id, $props);
96
  }
97
  }
98
 
99
  /* Collection management */
100
-
101
  /**
102
  * Add theme
103
  * Accepts properties to create new theme or previously-created theme instance
@@ -119,7 +119,7 @@ class SLB_Themes extends SLB_Collection_Controller {
119
  // Add to collection
120
  return parent::add($o);
121
  }
122
-
123
  /**
124
  * Get themes
125
  * @param array $args (optional) Arguments
@@ -134,12 +134,12 @@ class SLB_Themes extends SLB_Collection_Controller {
134
  $r = wp_parse_args($args, $args_default);
135
  $r['include_public'] = !!$r['include_public'];
136
  $r['include_private'] = !!$r['include_private'];
137
-
138
  $items = parent::get($args);
139
-
140
  if ( empty($items) )
141
  return $items;
142
-
143
  /* Process custom arguments */
144
 
145
  // Filter
@@ -161,7 +161,7 @@ class SLB_Themes extends SLB_Collection_Controller {
161
  }
162
 
163
  /* Helpers */
164
-
165
  /**
166
  * Retrieve default theme ID
167
  * @uses `$id_default`
@@ -173,7 +173,7 @@ class SLB_Themes extends SLB_Collection_Controller {
173
  }
174
  return $this->id_default;
175
  }
176
-
177
  /**
178
  * Retrieve currently-selected theme
179
  * @return SLB_Theme Selected theme
@@ -188,29 +188,29 @@ class SLB_Themes extends SLB_Collection_Controller {
188
  }
189
  return $thms[$id];
190
  }
191
-
192
  /* Output */
193
-
194
  /**
195
  * Build client output
196
  */
197
  public function client_output() {
198
  // Process active theme
199
  $thm = $this->get_selected();
200
-
201
  // Get theme ancestors
202
  $thms = $thm->get_ancestors(true);
203
  $thms[] = $thm;
204
-
205
  foreach ( $thms as $thm ) {
206
  // Load files
207
  $thm->enqueue_scripts();
208
  }
209
  }
210
-
211
  /**
212
  * Client output script
213
- *
214
  * @param array $commands Client script commands
215
  * @return array Modified script commands
216
  */
@@ -221,10 +221,10 @@ class SLB_Themes extends SLB_Collection_Controller {
221
  // Process theme ancestors
222
  $thms = $thm->get_ancestors(true);
223
  $thms[] = $thm;
224
-
225
  $out = array('/* THM */');
226
  $code = array();
227
-
228
  // Build output for each theme
229
  foreach ( $thms as $thm ) {
230
  // Setup client parameters
@@ -248,7 +248,7 @@ class SLB_Themes extends SLB_Collection_Controller {
248
  }
249
  // Add properties to parameters
250
  $params[] = json_encode($thm_props);
251
-
252
  // Add theme to client
253
  $code[] = $this->util->call_client_method('View.extend_theme', $params, false);
254
  }
@@ -259,9 +259,9 @@ class SLB_Themes extends SLB_Collection_Controller {
259
  }
260
  return $commands;
261
  }
262
-
263
  /* Options */
264
-
265
  /**
266
  * Retrieve themes for use in option field
267
  * @uses self::theme_default
@@ -276,17 +276,17 @@ class SLB_Themes extends SLB_Collection_Controller {
276
  $itm_d = $items[$d];
277
  unset($items[$d]);
278
  }
279
-
280
  // Sort themes by name
281
  uasort( $items, function( $a, $b ) {
282
  return strcmp( $a->get_name(), $b->get_name() );
283
  });
284
-
285
  // Insert default theme at top of array
286
  if ( isset($itm_d) ) {
287
  $items = array( $d => $itm_d ) + $items;
288
  }
289
-
290
  // Build options
291
  foreach ( $items as $item ) {
292
  $items[$item->get_id()] = $item->get_name();
8
  */
9
  class SLB_Themes extends SLB_Collection_Controller {
10
  /* Configuration */
11
+
12
  protected $item_type = 'SLB_Theme';
13
+
14
  public $hook_prefix = 'themes';
15
+
16
  protected $key_prop = 'get_id';
17
+
18
  protected $key_call = true;
19
+
20
  /* Properties */
21
+
22
  protected $id_default = null;
23
+
24
  /* Initialization */
25
+
26
  protected function _hooks() {
27
  parent::_hooks();
28
  // Register themes
29
  $this->util->add_action('init', $this->m('init_defaults'), 1);
30
+
31
  // Client output
32
  $this->util->add_action('footer', $this->m('client_output'), 1, 0, false);
33
  $this->util->add_filter('footer_script', $this->m('client_output_script'), $this->util->priority('client_footer_output'), 1, false);
34
  }
35
+
36
  protected function _options() {
37
  $opts = array (
38
  'items' => array (
46
  ),
47
  )
48
  );
49
+
50
  parent::_set_options($opts);
51
  }
52
+
53
  /**
54
  * Add default themes
55
  * @param SLB_Themes $themes Themes controller
90
  )
91
  ),
92
  );
93
+
94
  foreach ( $defaults as $id => $props ) {
95
  $themes->add($id, $props);
96
  }
97
  }
98
 
99
  /* Collection management */
100
+
101
  /**
102
  * Add theme
103
  * Accepts properties to create new theme or previously-created theme instance
119
  // Add to collection
120
  return parent::add($o);
121
  }
122
+
123
  /**
124
  * Get themes
125
  * @param array $args (optional) Arguments
134
  $r = wp_parse_args($args, $args_default);
135
  $r['include_public'] = !!$r['include_public'];
136
  $r['include_private'] = !!$r['include_private'];
137
+
138
  $items = parent::get($args);
139
+
140
  if ( empty($items) )
141
  return $items;
142
+
143
  /* Process custom arguments */
144
 
145
  // Filter
161
  }
162
 
163
  /* Helpers */
164
+
165
  /**
166
  * Retrieve default theme ID
167
  * @uses `$id_default`
173
  }
174
  return $this->id_default;
175
  }
176
+
177
  /**
178
  * Retrieve currently-selected theme
179
  * @return SLB_Theme Selected theme
188
  }
189
  return $thms[$id];
190
  }
191
+
192
  /* Output */
193
+
194
  /**
195
  * Build client output
196
  */
197
  public function client_output() {
198
  // Process active theme
199
  $thm = $this->get_selected();
200
+
201
  // Get theme ancestors
202
  $thms = $thm->get_ancestors(true);
203
  $thms[] = $thm;
204
+
205
  foreach ( $thms as $thm ) {
206
  // Load files
207
  $thm->enqueue_scripts();
208
  }
209
  }
210
+
211
  /**
212
  * Client output script
213
+ *
214
  * @param array $commands Client script commands
215
  * @return array Modified script commands
216
  */
221
  // Process theme ancestors
222
  $thms = $thm->get_ancestors(true);
223
  $thms[] = $thm;
224
+
225
  $out = array('/* THM */');
226
  $code = array();
227
+
228
  // Build output for each theme
229
  foreach ( $thms as $thm ) {
230
  // Setup client parameters
248
  }
249
  // Add properties to parameters
250
  $params[] = json_encode($thm_props);
251
+
252
  // Add theme to client
253
  $code[] = $this->util->call_client_method('View.extend_theme', $params, false);
254
  }
259
  }
260
  return $commands;
261
  }
262
+
263
  /* Options */
264
+
265
  /**
266
  * Retrieve themes for use in option field
267
  * @uses self::theme_default
276
  $itm_d = $items[$d];
277
  unset($items[$d]);
278
  }
279
+
280
  // Sort themes by name
281
  uasort( $items, function( $a, $b ) {
282
  return strcmp( $a->get_name(), $b->get_name() );
283
  });
284
+
285
  // Insert default theme at top of array
286
  if ( isset($itm_d) ) {
287
  $items = array( $d => $itm_d ) + $items;
288
  }
289
+
290
  // Build options
291
  foreach ( $items as $item ) {
292
  $items[$item->get_id()] = $item->get_name();
includes/class.utilities.php CHANGED
@@ -2,22 +2,22 @@
2
 
3
  /**
4
  * Utility methods
5
- *
6
  * @package Simple Lightbox
7
  * @subpackage Utilities
8
  * @author Archetyped
9
  *
10
  */
11
  class SLB_Utilities {
12
-
13
  /* Properties */
14
-
15
  /**
16
  * Instance parent
17
  * @var object
18
  */
19
  private $_parent = null;
20
-
21
  /**
22
  * Plugin Base
23
  * @var string
@@ -38,13 +38,13 @@ class SLB_Utilities {
38
  'AuthorURI' => 'Author URI',
39
  )
40
  );
41
-
42
  /**
43
  * Plugin base path
44
  * @var string
45
  */
46
  private $_path_base = null;
47
-
48
  /**
49
  * Standard hook priorities
50
  * @var array
@@ -55,15 +55,15 @@ class SLB_Utilities {
55
  'safe' => 15,
56
  'client_footer_output' => 25,
57
  );
58
-
59
  /* Constructors */
60
-
61
  function __construct($obj) {
62
  if ( is_object($obj) ) {
63
  $this->_parent = $obj;
64
  }
65
  }
66
-
67
  /**
68
  * Returns callback array to instance method
69
  * @param object $obj Instance object
@@ -81,11 +81,11 @@ class SLB_Utilities {
81
  $cb = array($obj, $method);
82
  return $cb;
83
  }
84
-
85
  /* Helper Functions */
86
-
87
  /*-** Prefix **-*/
88
-
89
  /**
90
  * Get valid separator
91
  * @param string $sep (optional) Separator supplied
@@ -96,7 +96,7 @@ class SLB_Utilities {
96
  $sep = '';
97
  return ( is_string($sep) ) ? $sep : '_';
98
  }
99
-
100
  /**
101
  * Retrieve class prefix (with separator if set)
102
  * @param bool|string $sep Separator to append to class prefix (Default: no separator)
@@ -107,7 +107,7 @@ class SLB_Utilities {
107
  $prefix = ( !empty($this->_parent->prefix) ) ? $this->_parent->prefix . $sep : '';
108
  return $prefix;
109
  }
110
-
111
  /**
112
  * Check if a string is prefixed
113
  * @param string|array $text Text to check for prefix
@@ -122,7 +122,7 @@ class SLB_Utilities {
122
  $text = $text[0];
123
  return ( !empty($text) && stripos($text, $this->get_prefix($sep)) === 0 );
124
  }
125
-
126
  /**
127
  * Prepend plugin prefix to some text
128
  * @param string|array $text Text to add to prefix
@@ -141,7 +141,7 @@ class SLB_Utilities {
141
  array_unshift($text, $this->get_prefix());
142
  return implode($sep, $text);
143
  }
144
-
145
  /**
146
  * Prepend uppercased plugin prefix to some text
147
  * @param string|array $text Text to add to prefix
@@ -155,7 +155,7 @@ class SLB_Utilities {
155
  $pre = $this->get_prefix();
156
  return str_replace($pre . $sep, strtoupper($pre) . $sep, $var);
157
  }
158
-
159
  /**
160
  * Add prefix to variable reference
161
  * Updates actual variable rather than return value
@@ -169,7 +169,7 @@ class SLB_Utilities {
169
  $args = func_get_args();
170
  $var = call_user_func_array($this->m($this, 'add_prefix'), $args);
171
  }
172
-
173
  /**
174
  * Remove prefix from specified string
175
  * @param string $text String to remove prefix from
@@ -180,7 +180,7 @@ class SLB_Utilities {
180
  $text = substr($text, strlen($this->get_prefix($sep)));
181
  return $text;
182
  }
183
-
184
  /**
185
  * Returns Database prefix for plugin-related DB Tables
186
  * @return string Database prefix
@@ -189,9 +189,9 @@ class SLB_Utilities {
189
  global $wpdb;
190
  return $wpdb->prefix . $this->get_prefix('_');
191
  }
192
-
193
  /*-** Priority **-*/
194
-
195
  /**
196
  * Retrieve standard priority
197
  * @var string $id Priority ID to retrieve
@@ -204,9 +204,9 @@ class SLB_Utilities {
204
  }
205
  return $pri;
206
  }
207
-
208
  /* Wrapped Values */
209
-
210
  /**
211
  * Create wrapper object
212
  * Properties
@@ -221,13 +221,13 @@ class SLB_Utilities {
221
  // Validate existing wrapper
222
  if ( is_object($start) && isset($start->start) && isset($start->end) )
223
  return $start;
224
-
225
  // Initialize wrapper
226
  $w = array (
227
  'start' => '[',
228
  'end' => ']',
229
  );
230
-
231
  if ( !empty($start) ) {
232
  if ( is_string($start) ) {
233
  $w['start'] = $start;
@@ -244,10 +244,10 @@ class SLB_Utilities {
244
  if ( is_string($end) ) {
245
  $w['end'] = $end;
246
  }
247
-
248
  return (object) $w;
249
  }
250
-
251
  /**
252
  * Check if text is wrapped by specified character(s)
253
  * @uses this->get_wrapper() to Validate wrapper text
@@ -260,11 +260,11 @@ class SLB_Utilities {
260
  return false;
261
  // Validate wrapper
262
  $w = $this->get_wrapper($start, $end);
263
-
264
  // Check for wrapper
265
  return ( substr($text, 0, strlen($w->start)) == $w->start && substr($text, -1, strlen($w->end)) == $w->end ) ? true : false;
266
  }
267
-
268
  /**
269
  * Remove wrapper from specified text
270
  * @uses this->has_wrapper() to check if text is wrapped
@@ -279,10 +279,10 @@ class SLB_Utilities {
279
  $w = $this->get_wrapper($start, $end);
280
  $text = substr($text, strlen($w->start), strlen($text) - strlen($w->start) - strlen($w->end) );
281
  }
282
-
283
  return $text;
284
  }
285
-
286
  /**
287
  * Add wrapper to specified text
288
  * @uses Utilities::get_wrapper() to retrieve wrapper object
@@ -298,9 +298,9 @@ class SLB_Utilities {
298
  $text = $w->start . $text . $w->end;
299
  return $text;
300
  }
301
-
302
  /*-** Client **-*/
303
-
304
  /**
305
  * Parses client files array
306
  * > Adds ID property (prefixed file key)
@@ -311,11 +311,11 @@ class SLB_Utilities {
311
  * > deps (array) [optional]: Dependencies
312
  * > Values wrapped in square brackets (`[` & `]`) are internal files
313
  * > callback (string|array) [optional]: Global callback to determine whether file should be loaded
314
- * > Values wrapped in square brackets (`[` & `]`) are internal methods (of parent object)
315
  * > context (array) [optional]: Context(s) in which to load the file
316
  * Acceptable values
317
  * > string: Context name
318
- * > array: Context name + callback (both must return TRUE to load file)
319
  * > Callback follows same pattern as `callback` member
320
  * @param array $files Files array
321
  * @return object Client files
@@ -362,15 +362,15 @@ class SLB_Utilities {
362
  else
363
  unset($p[$m]);
364
  }
365
-
366
  // Normalize file properties
367
  $p = array_merge($defaults, $p);
368
-
369
  /* File name */
370
-
371
  // Validate file
372
  $file =& $p['file'];
373
-
374
  // Determine if filename or callback
375
  if ( !$this->is_file($file) )
376
  $file = ( is_callable($file) ) ? $file : null;
@@ -379,9 +379,9 @@ class SLB_Utilities {
379
  unset($files[$h]);
380
  continue;
381
  }
382
-
383
  /* Dependencies */
384
-
385
  // Format internal dependencies
386
  foreach ( $p['deps'] as $idx => $dep ) {
387
  if ( $this->has_wrapper($dep) ) {
@@ -389,9 +389,9 @@ class SLB_Utilities {
389
  $p['deps'][$idx] = $this->add_prefix($dep);
390
  }
391
  }
392
-
393
  /* Context */
394
-
395
  // Validate callback
396
  $cb =& $p['callback'];
397
  if ( !is_null($cb) && !is_callable($cb) ) {
@@ -399,7 +399,7 @@ class SLB_Utilities {
399
  unset($files[$h]);
400
  continue;
401
  }
402
-
403
  // Validate contexts
404
  $ctxs =& $p['context'];
405
  $ctxs = array_unique($ctxs);
@@ -423,7 +423,7 @@ class SLB_Utilities {
423
  $ctx = false;
424
  break;
425
  }
426
-
427
  // Remove invalid contexts
428
  if ( empty($ctx) ) {
429
  unset($ctxs[$idx]);
@@ -437,9 +437,9 @@ class SLB_Utilities {
437
  continue;
438
  }
439
  $ctxs = array_values($ctxs);
440
-
441
  /* Finalize Properties */
442
-
443
  // Convert properties to object
444
  $files[$h] = (object) $p;
445
  }
@@ -463,7 +463,7 @@ class SLB_Utilities {
463
  }
464
  return $obj;
465
  }
466
-
467
  /**
468
  * Build jQuery JS expression to add data to specified client object
469
  * @param string|obj $obj Name of client object (Set to root object if not a valid name)
@@ -508,7 +508,7 @@ class SLB_Utilities {
508
 
509
  /**
510
  * Validate client object $obj before running command $cmd
511
- *
512
  * @param string $obj Full object name
513
  * @param string $cmd (optional) Command to wrap in validation
514
  * @return string Command wrapped in validation block
@@ -517,7 +517,7 @@ class SLB_Utilities {
517
  public function validate_client_object($obj, $cmd = null) {
518
  // Get base object
519
  $base = $this->get_client_object();
520
-
521
  // Build condition
522
  $sep = '.';
523
  $obj = trim($obj, $sep);
@@ -530,14 +530,14 @@ class SLB_Utilities {
530
  $fmt .= ' && %1$s.has_child(\'%2$s\')';
531
  }
532
  $condition = sprintf($fmt, $base, $obj);
533
-
534
  // Wrap command in validation
535
  if ( !empty($cmd) && is_string($cmd) ) {
536
  $condition = sprintf('if ( %1$s ) { %2$s }', $condition, $cmd);
537
  }
538
  return $condition;
539
  }
540
-
541
  /**
542
  * Build client method call
543
  * @uses get_client_object() to generate the body of the method call
@@ -554,17 +554,17 @@ class SLB_Utilities {
554
  }
555
  $encode = !!$encode;
556
  $validate = !!$validate;
557
-
558
  // Build parameters
559
  if ( !is_null($params) ) {
560
  if ( $encode ) {
561
- $params = json_encode($params);
562
  } elseif ( is_array($params) ) {
563
- $params = implode(',', $params);
564
  }
565
  }
566
  if ( !is_string($params) ) {
567
- $params = '';
568
  }
569
  $ret = sprintf('%s(%s);', $this->get_client_object($method), $params);
570
  if ( $validate ) {
@@ -572,9 +572,9 @@ class SLB_Utilities {
572
  }
573
  return $ret;
574
  }
575
-
576
  /*-** WP **-*/
577
-
578
  /**
579
  * Checks if $post is a valid Post object
580
  * If $post is not valid, assigns global post object to $post (if available)
@@ -598,8 +598,8 @@ class SLB_Utilities {
598
  return false;
599
  return true;
600
  }
601
-
602
-
603
  /**
604
  * Retrieve parent object
605
  * @return obj|bool Parent object (FALSE if no valid parent set)
@@ -609,9 +609,9 @@ class SLB_Utilities {
609
  return $this->_parent;
610
  } else {
611
  return false;
612
- }
613
  }
614
-
615
  /**
616
  * Retrieve parent property value
617
  * @uses self::get_parent()
@@ -621,11 +621,11 @@ class SLB_Utilities {
621
  */
622
  function get_parent_property($prop, $default = '') {
623
  $p = $this->get_parent();
624
- return ( !!$p && property_exists($p, $prop) ) ? $p->{$prop} : $default;
625
  }
626
-
627
  /* Hooks */
628
-
629
  /**
630
  * Retrieve formatted name for internal hooks
631
  * Prefixes with parent prefix and hook prefix
@@ -648,7 +648,7 @@ class SLB_Utilities {
648
  // Prefix
649
  return $this->add_prefix($hook . $tag);
650
  }
651
-
652
  /**
653
  * Run internal action
654
  * Namespaces $tag
@@ -667,7 +667,7 @@ class SLB_Utilities {
667
  $args[0] = $this->get_hook($tag, $hook_prefix);
668
  return call_user_func_array('do_action', $args);
669
  }
670
-
671
  /**
672
  * Run internal action passing arguments in array
673
  * @uses do_action_ref_array()
@@ -676,7 +676,7 @@ class SLB_Utilities {
676
  function do_action_ref_array($tag, $args, $hook_prefix = true) {
677
  return do_action_ref_array($this->get_hook($tag, $hook_prefix), $args);
678
  }
679
-
680
  /**
681
  * Run internal filter
682
  * Namespaces $tag
@@ -695,16 +695,16 @@ class SLB_Utilities {
695
  $args[0] = $this->get_hook($tag, $hook_prefix);
696
  return call_user_func_array('apply_filters', $args);
697
  }
698
-
699
  /**
700
  * Run internal filter passing arguments in array
701
  * @uses apply_filters_ref_array()
702
  * @param bool|string $hook_prefix (optional) Secondary prefix to use for hook (Default: Use predefined hook name, FALSE: no secondary hook)
703
  */
704
  function apply_filters_ref_array($tag, $args, $hook_prefix = true) {
705
- return apply_filters_ref_array($this->get_hook($tag, $hook_prefix), $args);
706
  }
707
-
708
  /**
709
  * Add internal action
710
  * Namespaces $tag
@@ -715,7 +715,7 @@ class SLB_Utilities {
715
  function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
716
  return add_action($this->get_hook($tag, $hook_prefix), $function_to_add, $priority, $accepted_args);
717
  }
718
-
719
  /**
720
  * Add internal filter
721
  * Namespaces $tag
@@ -726,7 +726,7 @@ class SLB_Utilities {
726
  function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
727
  return add_filter($this->get_hook($tag, $hook_prefix), $function_to_add, $priority, $accepted_args);
728
  }
729
-
730
  /**
731
  * Remove internal action
732
  * Namespaces $tag
@@ -735,9 +735,9 @@ class SLB_Utilities {
735
  * @param bool|string $hook_prefix (optional) Secondary prefix to use for hook (Default: Use predefined hook name, FALSE: no secondary hook)
736
  */
737
  function remove_action($tag, $function_to_remove, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
738
- return remove_action($this->get_hook($tag, $hook_prefix), $function_to_remove, $priority, $accepted_args);
739
  }
740
-
741
  /**
742
  * Remove internal filter
743
  * Namespaces $tag
@@ -748,22 +748,22 @@ class SLB_Utilities {
748
  function remove_filter($tag, $function_to_remove, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
749
  return remove_filter($this->get_hook($tag, $hook_prefix), $function_to_remove, $priority, $accepted_args);
750
  }
751
-
752
  /* Shortcode */
753
-
754
  /**
755
  * Process specific shortcode(s) in content
756
  * Default: Process all existing shortcodes
757
  * @uses $shortcode_tags - array tag => callback
758
  * @uses do_shortcode()
759
- *
760
  * @param string $content Content to process for shortcodes
761
  * @param string|array $shortcode Single tag or array of tags to process
762
  * > Associative array sets temporary callbacks for shortcodes (`tag => callback`)
763
  */
764
  public function do_shortcode($content, $shortcode = null) {
765
  global $shortcode_tags;
766
-
767
  // Process custom shortcodes
768
  if ( !is_null($shortcode) ) {
769
  // Cast to array
@@ -782,19 +782,19 @@ class SLB_Utilities {
782
  }
783
  }
784
  }
785
-
786
  // Process shortcodes in content
787
  $content = do_shortcode($content);
788
-
789
  // Restore default shortcode handlers
790
  if ( isset($tags_temp) ) {
791
  $shortcode_tags = $tags_temp;
792
  unset($tags_temp);
793
  }
794
-
795
  return $content;
796
  }
797
-
798
  /**
799
  * Build shortcode tag
800
  * @param string $tag Shortcode base
@@ -811,7 +811,7 @@ class SLB_Utilities {
811
  }
812
 
813
  /* Meta */
814
-
815
  /**
816
  * Retrieves post metadata for internal methods
817
  * Metadata set internally is wrapped in an array so it is unwrapped before returned the retrieved value
@@ -827,7 +827,7 @@ class SLB_Utilities {
827
  $meta_value = $meta_value[0];
828
  return $meta_value;
829
  }
830
-
831
  /**
832
  * Wraps metadata in array for storage in database
833
  * @param mixed $meta_value Value to be set as metadata
@@ -836,7 +836,7 @@ class SLB_Utilities {
836
  function post_meta_prepare_value($meta_value) {
837
  return array($meta_value);
838
  }
839
-
840
  /**
841
  * Adds Metadata for a post to database
842
  * For internal methods
@@ -851,7 +851,7 @@ class SLB_Utilities {
851
  $meta_value = $this->post_meta_value_prepare($meta_value);
852
  return add_post_meta($post_id, $meta_key, $meta_value, $unique);
853
  }
854
-
855
  /**
856
  * Updates post metadata for internal data/methods
857
  * @see update_post_meta()
@@ -865,10 +865,10 @@ class SLB_Utilities {
865
  $meta_value = $this->post_meta_prepare_value($meta_value);
866
  return update_post_meta($post_id, $meta_key, $meta_value, $prev_value);
867
  }
868
-
869
  /**
870
  * Builds postmeta key for custom data set by plugin
871
- * @param string $key Base key name
872
  * @return string Formatted postmeta key
873
  */
874
  function post_meta_get_key($key) {
@@ -880,10 +880,10 @@ class SLB_Utilities {
880
  return $sep . implode($sep, $key);
881
  }
882
  }
883
-
884
  return $key;
885
  }
886
-
887
  /**
888
  * Creates a meta key for storing post meta data
889
  * Prefixes standard prefixed text with underscore to hide meta data on post edit forms
@@ -893,9 +893,9 @@ class SLB_Utilities {
893
  function make_meta_key($text = '') {
894
  return '_' . $this->add_prefix($text);
895
  }
896
-
897
  /* Class */
898
-
899
  /**
900
  * Retrieve name of internal class
901
  * @param string $class Base name of class
@@ -903,10 +903,10 @@ class SLB_Utilities {
903
  */
904
  function get_class($class) {
905
  return $this->add_prefix_uc($class);
906
- }
907
-
908
  /* Context */
909
-
910
  /**
911
  * Retrieve context for current request
912
  * @return array Context
@@ -952,18 +952,18 @@ class SLB_Utilities {
952
  $u = wp_get_current_user();
953
  $ctx[] = $this->build_context('user', ( $u->ID ) ? 'registered' : 'guest', false);
954
  }
955
-
956
  return $ctx;
957
  }
958
-
959
  /**
960
  * Builds context from multiple components
961
  * Usage:
962
  * > $prefix can be omitted and context strings can be added as needed
963
  * > Multiple context strings may be passed to be joined together
964
- *
965
  * @param string (optional) $context Variable number of components to add to context
966
- * @param bool (optional) $prefix Whether or not to prefix context with request type (public or admin) [Default: TRUE]
967
  * @return string Context
968
  */
969
  function build_context($context = null, $prefix = true) {
@@ -972,8 +972,8 @@ class SLB_Utilities {
972
  if ( !empty($args) ) {
973
  $prefix = ( is_bool($args[count($args) - 1]) ) ? array_pop($args) : true;
974
  }
975
-
976
- // Validate
977
  $context = array_filter($args, 'is_string');
978
  $sep = '_';
979
 
@@ -982,7 +982,7 @@ class SLB_Utilities {
982
  array_unshift($context, ( is_admin() ) ? 'admin' : 'public' );
983
  return implode($sep, $context);
984
  }
985
-
986
  /**
987
  * Check if context exists in current request
988
  * @param string $context Context to check for
@@ -1011,9 +1011,9 @@ class SLB_Utilities {
1011
  $ctx->context = $this->get_context();
1012
  $this->extend_client_object($ctx, true);
1013
  }
1014
-
1015
  /* Path */
1016
-
1017
  /**
1018
  * Joins and normalizes the slashes in the paths passed to method
1019
  * All forward/back slashes are converted to forward slashes
@@ -1035,7 +1035,7 @@ class SLB_Utilities {
1035
  if ( is_bool($arg_last) ) {
1036
  $arg_last = array($arg_last);
1037
  }
1038
-
1039
  if ( is_array($arg_last) && count($arg_last) > 0 && is_bool($arg_last[0]) ) {
1040
  // Remove slash paramter from args array
1041
  array_pop($parts);
@@ -1048,19 +1048,19 @@ class SLB_Utilities {
1048
  }
1049
  // Extract to slash options local variables
1050
  list($trailing_slash, $leading_slash) = $slashes;
1051
-
1052
  // Clean path segments
1053
  foreach ( $parts as $key => $part ) {
1054
  // Trim slashes/spaces
1055
  $parts[$key] = trim($part, " " . $sl_f . $sl_b);
1056
-
1057
  // Verify path segment still contains value
1058
  if ( empty($parts[$key]) ) {
1059
  unset($parts[$key]);
1060
  continue;
1061
  }
1062
  }
1063
-
1064
  // Join path parts together
1065
  $parts = implode($sl_b, $parts);
1066
  $parts = str_replace($sl_b, $sl_f, $parts);
@@ -1074,7 +1074,7 @@ class SLB_Utilities {
1074
  }
1075
  return $parts;
1076
  }
1077
-
1078
  /**
1079
  * Returns URL of file (assumes that it is in plugin directory)
1080
  * @param string $file name of file get URL
@@ -1087,7 +1087,7 @@ class SLB_Utilities {
1087
  }
1088
  return $file;
1089
  }
1090
-
1091
  /**
1092
  * Returns path to plugin file
1093
  * @param string $file file name
@@ -1100,13 +1100,13 @@ class SLB_Utilities {
1100
  }
1101
  return $file;
1102
  }
1103
-
1104
  function get_plugin_file_path($file, $trailing_slash = false) {
1105
  if ( is_string($file) && '' != trim($file) )
1106
  $file = $this->normalize_path($this->get_plugin_base(), $file, $trailing_slash);
1107
  return $file;
1108
  }
1109
-
1110
  /**
1111
  * Checks if value is valid file name
1112
  * @param string $filename File name to check
@@ -1116,7 +1116,7 @@ class SLB_Utilities {
1116
  $ext = $this->get_file_extension($filename);
1117
  return ( empty($ext) ) ? false : true;
1118
  }
1119
-
1120
  /**
1121
  * Check if string is valid URI
1122
  * @param string $uri String to check
@@ -1125,7 +1125,7 @@ class SLB_Utilities {
1125
  function is_uri($uri) {
1126
  return ( preg_match('|^(https?:)?//|', $uri) ) ? true : false;
1127
  }
1128
-
1129
  /**
1130
  * Retrieves file extension
1131
  * @param string $file file name/path
@@ -1142,13 +1142,13 @@ class SLB_Utilities {
1142
  if ( ( $qpos = strpos($file, '?') ) && $qpos !== false ) {
1143
  $file = substr($file, 0, $qpos);
1144
  }
1145
- if ( ( $rpos = strrpos($file, $sep) ) > 0 )
1146
  $ret = substr($file, $rpos + 1);
1147
  if ( !!$lowercase )
1148
  $ret = strtolower($ret);
1149
  return $ret;
1150
  }
1151
-
1152
  /**
1153
  * Checks if file has specified extension
1154
  * @uses get_file_extension()
@@ -1163,10 +1163,10 @@ class SLB_Utilities {
1163
  if ( !$case_sensitive ) {
1164
  // Normalize extensions
1165
  $extension = array_map('strtolower', $extension);
1166
- }
1167
  return ( in_array($this->get_file_extension($file, !$case_sensitive), $extension) ) ? true : false;
1168
  }
1169
-
1170
  /**
1171
  * Removes file extension from file name
1172
  * The extension is the text following the last period ('.') in the file name
@@ -1181,7 +1181,7 @@ class SLB_Utilities {
1181
  }
1182
  return $file;
1183
  }
1184
-
1185
  /**
1186
  * Retrieve base URL for plugin-specific files
1187
  * @uses get_plugin_base()
@@ -1208,10 +1208,10 @@ class SLB_Utilities {
1208
  $ret = $this->get_relative_path($ret, $relative);
1209
  }
1210
  }
1211
-
1212
  return $ret;
1213
  }
1214
-
1215
  /**
1216
  * Retrieve plugin's base path
1217
  * @uses WP_PLUGIN_DIR
@@ -1251,7 +1251,7 @@ class SLB_Utilities {
1251
  }
1252
  return $ret;
1253
  }
1254
-
1255
  /**
1256
  * Retrieve relative path for absolute paths
1257
  * @param string $path Path to modify
@@ -1273,7 +1273,7 @@ class SLB_Utilities {
1273
  }
1274
  return $path;
1275
  }
1276
-
1277
  /**
1278
  * Retrieve plugin's base directory
1279
  * @uses WP_PLUGIN_DIR
@@ -1288,7 +1288,7 @@ class SLB_Utilities {
1288
  }
1289
  return $ret;
1290
  }
1291
-
1292
  /**
1293
  * Retrieve plugin's base file path
1294
  * @uses get_path_base()
@@ -1321,7 +1321,7 @@ class SLB_Utilities {
1321
  // Return
1322
  return $ret;
1323
  }
1324
-
1325
  /**
1326
  * Retrieve plugin's internal name
1327
  * Internal name is used by WP core
@@ -1336,13 +1336,13 @@ class SLB_Utilities {
1336
  }
1337
  return $ret;
1338
  }
1339
-
1340
  private function set_plugin_info($data) {
1341
  if ( is_array($data) ) {
1342
  $this->_plugin['data'] = $data;
1343
  }
1344
  }
1345
-
1346
  /**
1347
  * Retrieve plugin info
1348
  * Parses info comment in main plugin file
@@ -1353,7 +1353,7 @@ class SLB_Utilities {
1353
  $ret = $this->_plugin['data'];
1354
  // Get plugin data
1355
  if ( empty($ret) ) {
1356
- $this->get_plugin_base_file();
1357
  $ret = $this->_plugin['data'];
1358
  }
1359
  // Return specified field
@@ -1362,7 +1362,7 @@ class SLB_Utilities {
1362
  }
1363
  return $ret;
1364
  }
1365
-
1366
  /**
1367
  * Retrieve plugin version
1368
  * @uses get_plugin_info()
@@ -1380,7 +1380,7 @@ class SLB_Utilities {
1380
  // Return
1381
  return $ret;
1382
  }
1383
-
1384
  /**
1385
  * Retrieve current post type based on URL query variables
1386
  * @return string|null Current post type
@@ -1395,7 +1395,7 @@ class SLB_Utilities {
1395
  }
1396
  return $pt;
1397
  }
1398
-
1399
  /**
1400
  * Retrieve current action based on URL query variables
1401
  * @param mixed $default (optional) Default action if no action exists
@@ -1403,7 +1403,7 @@ class SLB_Utilities {
1403
  */
1404
  function get_action($default = null) {
1405
  $action = '';
1406
-
1407
  // Check if action is set in URL
1408
  if ( isset($_GET['action']) )
1409
  $action = $_GET['action'];
@@ -1419,7 +1419,7 @@ class SLB_Utilities {
1419
  'edit' => array('edit', 'edit-pages')
1420
  );
1421
  $page = basename($_SERVER['SCRIPT_NAME'], '.php');
1422
-
1423
  foreach ( $actions as $act => $pages ) {
1424
  if ( in_array($page, $pages) ) {
1425
  $action = $act;
@@ -1431,13 +1431,13 @@ class SLB_Utilities {
1431
  $action = $default;
1432
  return $action;
1433
  }
1434
-
1435
  /*-** General **-*/
1436
-
1437
  /**
1438
  * Checks if a property exists in a class or object
1439
  * Compatibility method for PHP 4
1440
- * @param mixed $class Class or object to check
1441
  * @param string $property Name of property to look for in $class
1442
  */
1443
  function property_exists($class, $property) {
@@ -1449,7 +1449,7 @@ class SLB_Utilities {
1449
  return array_key_exists($property, $class);
1450
  }
1451
  }
1452
-
1453
  /**
1454
  * Retrieve specified property from object or array
1455
  * @param object|array $obj Object or array to get property from
@@ -1471,7 +1471,7 @@ class SLB_Utilities {
1471
  return $cvars[$property];
1472
  }
1473
  }
1474
-
1475
  /**
1476
  * Remap array members based on a
1477
  * mapping of source/destination keys
@@ -1503,7 +1503,7 @@ class SLB_Utilities {
1503
  // Return remapped properties
1504
  return $arr;
1505
  }
1506
-
1507
  function array_filter_keys($arr, $keys) {
1508
  if ( is_array($arr) && !empty($arr) && is_array($keys) && !empty($keys) ) {
1509
  foreach ( $keys as $rem ) {
@@ -1514,10 +1514,10 @@ class SLB_Utilities {
1514
 
1515
  return $arr;
1516
  }
1517
-
1518
  /**
1519
  * Insert an item into an array at the specified position
1520
- * @param mixed $item Item to insert into array
1521
  * @param int $pos Index position to insert item into array
1522
  * @return array Modified array
1523
  */
@@ -1525,7 +1525,7 @@ class SLB_Utilities {
1525
  array_splice($array, $pos, 0, $item);
1526
  return $array;
1527
  }
1528
-
1529
  /**
1530
  * Merges 1 or more arrays together
1531
  * Methodology
@@ -1575,10 +1575,10 @@ class SLB_Utilities {
1575
  }
1576
  return $merged;
1577
  }
1578
-
1579
  /**
1580
  * Replaces string value in one array with the value of the matching element in a another array
1581
- *
1582
  * @param string $search Text to search for in array
1583
  * @param array $arr_replace Array to use for replacing values
1584
  * @param array $arr_subject Array to search for specified value
@@ -1596,10 +1596,10 @@ class SLB_Utilities {
1596
  if (is_array($val) && is_array($arr_replace[$key]))
1597
  $arr_subject[$key] = $this->array_replace_recursive($search, $arr_replace[$key], $val);
1598
  }
1599
-
1600
  return $arr_subject;
1601
  }
1602
-
1603
  /**
1604
  * Checks if item at specified path in array is set
1605
  * @param array $arr Array to check for item
@@ -1610,7 +1610,7 @@ class SLB_Utilities {
1610
  $f_path = $this->get_array_path($path);
1611
  return eval('return isset($arr' . $f_path . ');');
1612
  }
1613
-
1614
  /**
1615
  * Build formatted string based on array values
1616
  * Array values in formatted string will be ordered by index order
@@ -1653,7 +1653,7 @@ class SLB_Utilities {
1653
  }
1654
  return $fmtd;
1655
  }
1656
-
1657
  /**
1658
  * Builds array of path elements based on arguments
1659
  * Each item in path array represents a deeper level in structure path is for (object, array, filesystem, etc.)
@@ -1663,12 +1663,12 @@ class SLB_Utilities {
1663
  function build_path() {
1664
  $path = array();
1665
  $args = func_get_args();
1666
-
1667
  // Iterate through parameters and build path
1668
  foreach ( $args as $arg ) {
1669
  if ( empty($arg) )
1670
  continue;
1671
-
1672
  if (is_array($arg)) {
1673
  // Recurse through array items to pull out any more arrays
1674
  foreach ($arg as $key => $val) {
@@ -1679,10 +1679,10 @@ class SLB_Utilities {
1679
  $path[] = $arg;
1680
  }
1681
  }
1682
-
1683
  return $path;
1684
  }
1685
-
1686
  /**
1687
  * Build generic element
1688
  * @param array $args
@@ -1703,23 +1703,23 @@ class SLB_Utilities {
1703
  );
1704
  $args = wp_parse_args($args, $args_default);
1705
  $args['format'] = wp_parse_args($args['format'], $format_default);
1706
-
1707
  // Validate
1708
  if ( !is_string($args['tag']) || empty($args['tag']) ) {
1709
  return $ret;
1710
  }
1711
-
1712
  $args = (object) $args;
1713
-
1714
  $args->attributes = $this->build_attribute_string($args->attributes);
1715
  if ( strlen($args->attributes) > 0 ) {
1716
  $args->attributes = ' ' . $args->attributes;
1717
  }
1718
-
1719
  // Build output
1720
  $args->format = (object) $args->format;
1721
  $ret = sprintf( $args->format->open, $args->tag . $args->attributes);
1722
-
1723
  // Wrap content if necessary
1724
  if ( $args->wrap || ( is_string($args->content) && !empty($args->content) ) ) {
1725
  $ret .= $args->content . sprintf( $args->format->close, $args->tag);
@@ -1727,7 +1727,7 @@ class SLB_Utilities {
1727
 
1728
  return $ret;
1729
  }
1730
-
1731
  /**
1732
  * Parse string of attributes into array
1733
  * For XML/XHTML tag attributes
@@ -1755,7 +1755,7 @@ class SLB_Utilities {
1755
 
1756
  return array_merge($defaults, $attr);
1757
  }
1758
-
1759
  /**
1760
  * Builds attribute string for HTML element
1761
  * @param array $attr Attributes
@@ -1776,8 +1776,8 @@ class SLB_Utilities {
1776
  }
1777
  return $ret;
1778
  }
1779
-
1780
- /* HTML */
1781
 
1782
  /**
1783
  * Generate HTML element based on values
@@ -1798,7 +1798,7 @@ class SLB_Utilities {
1798
  // Build element
1799
  return $this->build_element($args);
1800
  }
1801
-
1802
  /**
1803
  * Build HTML link element
1804
  * @uses build_html_element() to build link output
@@ -1811,7 +1811,7 @@ class SLB_Utilities {
1811
  $attributes = array_merge(array('href' => $uri, 'title' => $content), $attributes);
1812
  return $this->build_html_element(array('tag' => 'a', 'wrap' => true, 'content' => $content, 'attributes' => $attributes));
1813
  }
1814
-
1815
  /**
1816
  * Generate external stylesheet element
1817
  * @param $url Stylesheet URL
@@ -1821,10 +1821,10 @@ class SLB_Utilities {
1821
  $attributes = array('href' => $url, 'type' => 'text/css', 'rel' => 'stylesheet');
1822
  return $this->build_html_element(array('tag' => 'link', 'wrap' => false, 'attributes' => $attributes));
1823
  }
1824
-
1825
  /**
1826
  * Build client-side script element
1827
- *
1828
  * @param string $content Script content
1829
  * @param string $id (optional) Element ID
1830
  * @param bool $wrap_jquery (optional) Wrap commands in jQuery? (Default: Yes)
@@ -1844,14 +1844,14 @@ class SLB_Utilities {
1844
  if ( $wrap_jquery ) {
1845
  $start[] = 'if ( !!window.jQuery ) {(function($){';
1846
  $end[] = '})(jQuery);}';
1847
-
1848
  // Add event handler (if necessary)
1849
  if ( $wait_doc_ready ) {
1850
  $start[] = '$(document).ready(function(){';
1851
  $end[] = '})';
1852
  }
1853
  }
1854
-
1855
  // Reverse order of end values
1856
  $end = array_reverse($end);
1857
  $content = implode('', array_merge($start, array($content), $end));
2
 
3
  /**
4
  * Utility methods
5
+ *
6
  * @package Simple Lightbox
7
  * @subpackage Utilities
8
  * @author Archetyped
9
  *
10
  */
11
  class SLB_Utilities {
12
+
13
  /* Properties */
14
+
15
  /**
16
  * Instance parent
17
  * @var object
18
  */
19
  private $_parent = null;
20
+
21
  /**
22
  * Plugin Base
23
  * @var string
38
  'AuthorURI' => 'Author URI',
39
  )
40
  );
41
+
42
  /**
43
  * Plugin base path
44
  * @var string
45
  */
46
  private $_path_base = null;
47
+
48
  /**
49
  * Standard hook priorities
50
  * @var array
55
  'safe' => 15,
56
  'client_footer_output' => 25,
57
  );
58
+
59
  /* Constructors */
60
+
61
  function __construct($obj) {
62
  if ( is_object($obj) ) {
63
  $this->_parent = $obj;
64
  }
65
  }
66
+
67
  /**
68
  * Returns callback array to instance method
69
  * @param object $obj Instance object
81
  $cb = array($obj, $method);
82
  return $cb;
83
  }
84
+
85
  /* Helper Functions */
86
+
87
  /*-** Prefix **-*/
88
+
89
  /**
90
  * Get valid separator
91
  * @param string $sep (optional) Separator supplied
96
  $sep = '';
97
  return ( is_string($sep) ) ? $sep : '_';
98
  }
99
+
100
  /**
101
  * Retrieve class prefix (with separator if set)
102
  * @param bool|string $sep Separator to append to class prefix (Default: no separator)
107
  $prefix = ( !empty($this->_parent->prefix) ) ? $this->_parent->prefix . $sep : '';
108
  return $prefix;
109
  }
110
+
111
  /**
112
  * Check if a string is prefixed
113
  * @param string|array $text Text to check for prefix
122
  $text = $text[0];
123
  return ( !empty($text) && stripos($text, $this->get_prefix($sep)) === 0 );
124
  }
125
+
126
  /**
127
  * Prepend plugin prefix to some text
128
  * @param string|array $text Text to add to prefix
141
  array_unshift($text, $this->get_prefix());
142
  return implode($sep, $text);
143
  }
144
+
145
  /**
146
  * Prepend uppercased plugin prefix to some text
147
  * @param string|array $text Text to add to prefix
155
  $pre = $this->get_prefix();
156
  return str_replace($pre . $sep, strtoupper($pre) . $sep, $var);
157
  }
158
+
159
  /**
160
  * Add prefix to variable reference
161
  * Updates actual variable rather than return value
169
  $args = func_get_args();
170
  $var = call_user_func_array($this->m($this, 'add_prefix'), $args);
171
  }
172
+
173
  /**
174
  * Remove prefix from specified string
175
  * @param string $text String to remove prefix from
180
  $text = substr($text, strlen($this->get_prefix($sep)));
181
  return $text;
182
  }
183
+
184
  /**
185
  * Returns Database prefix for plugin-related DB Tables
186
  * @return string Database prefix
189
  global $wpdb;
190
  return $wpdb->prefix . $this->get_prefix('_');
191
  }
192
+
193
  /*-** Priority **-*/
194
+
195
  /**
196
  * Retrieve standard priority
197
  * @var string $id Priority ID to retrieve
204
  }
205
  return $pri;
206
  }
207
+
208
  /* Wrapped Values */
209
+
210
  /**
211
  * Create wrapper object
212
  * Properties
221
  // Validate existing wrapper
222
  if ( is_object($start) && isset($start->start) && isset($start->end) )
223
  return $start;
224
+
225
  // Initialize wrapper
226
  $w = array (
227
  'start' => '[',
228
  'end' => ']',
229
  );
230
+
231
  if ( !empty($start) ) {
232
  if ( is_string($start) ) {
233
  $w['start'] = $start;
244
  if ( is_string($end) ) {
245
  $w['end'] = $end;
246
  }
247
+
248
  return (object) $w;
249
  }
250
+
251
  /**
252
  * Check if text is wrapped by specified character(s)
253
  * @uses this->get_wrapper() to Validate wrapper text
260
  return false;
261
  // Validate wrapper
262
  $w = $this->get_wrapper($start, $end);
263
+
264
  // Check for wrapper
265
  return ( substr($text, 0, strlen($w->start)) == $w->start && substr($text, -1, strlen($w->end)) == $w->end ) ? true : false;
266
  }
267
+
268
  /**
269
  * Remove wrapper from specified text
270
  * @uses this->has_wrapper() to check if text is wrapped
279
  $w = $this->get_wrapper($start, $end);
280
  $text = substr($text, strlen($w->start), strlen($text) - strlen($w->start) - strlen($w->end) );
281
  }
282
+
283
  return $text;
284
  }
285
+
286
  /**
287
  * Add wrapper to specified text
288
  * @uses Utilities::get_wrapper() to retrieve wrapper object
298
  $text = $w->start . $text . $w->end;
299
  return $text;
300
  }
301
+
302
  /*-** Client **-*/
303
+
304
  /**
305
  * Parses client files array
306
  * > Adds ID property (prefixed file key)
311
  * > deps (array) [optional]: Dependencies
312
  * > Values wrapped in square brackets (`[` & `]`) are internal files
313
  * > callback (string|array) [optional]: Global callback to determine whether file should be loaded
314
+ * > Values wrapped in square brackets (`[` & `]`) are internal methods (of parent object)
315
  * > context (array) [optional]: Context(s) in which to load the file
316
  * Acceptable values
317
  * > string: Context name
318
+ * > array: Context name + callback (both must return TRUE to load file)
319
  * > Callback follows same pattern as `callback` member
320
  * @param array $files Files array
321
  * @return object Client files
362
  else
363
  unset($p[$m]);
364
  }
365
+
366
  // Normalize file properties
367
  $p = array_merge($defaults, $p);
368
+
369
  /* File name */
370
+
371
  // Validate file
372
  $file =& $p['file'];
373
+
374
  // Determine if filename or callback
375
  if ( !$this->is_file($file) )
376
  $file = ( is_callable($file) ) ? $file : null;
379
  unset($files[$h]);
380
  continue;
381
  }
382
+
383
  /* Dependencies */
384
+
385
  // Format internal dependencies
386
  foreach ( $p['deps'] as $idx => $dep ) {
387
  if ( $this->has_wrapper($dep) ) {
389
  $p['deps'][$idx] = $this->add_prefix($dep);
390
  }
391
  }
392
+
393
  /* Context */
394
+
395
  // Validate callback
396
  $cb =& $p['callback'];
397
  if ( !is_null($cb) && !is_callable($cb) ) {
399
  unset($files[$h]);
400
  continue;
401
  }
402
+
403
  // Validate contexts
404
  $ctxs =& $p['context'];
405
  $ctxs = array_unique($ctxs);
423
  $ctx = false;
424
  break;
425
  }
426
+
427
  // Remove invalid contexts
428
  if ( empty($ctx) ) {
429
  unset($ctxs[$idx]);
437
  continue;
438
  }
439
  $ctxs = array_values($ctxs);
440
+
441
  /* Finalize Properties */
442
+
443
  // Convert properties to object
444
  $files[$h] = (object) $p;
445
  }
463
  }
464
  return $obj;
465
  }
466
+
467
  /**
468
  * Build jQuery JS expression to add data to specified client object
469
  * @param string|obj $obj Name of client object (Set to root object if not a valid name)
508
 
509
  /**
510
  * Validate client object $obj before running command $cmd
511
+ *
512
  * @param string $obj Full object name
513
  * @param string $cmd (optional) Command to wrap in validation
514
  * @return string Command wrapped in validation block
517
  public function validate_client_object($obj, $cmd = null) {
518
  // Get base object
519
  $base = $this->get_client_object();
520
+
521
  // Build condition
522
  $sep = '.';
523
  $obj = trim($obj, $sep);
530
  $fmt .= ' && %1$s.has_child(\'%2$s\')';
531
  }
532
  $condition = sprintf($fmt, $base, $obj);
533
+
534
  // Wrap command in validation
535
  if ( !empty($cmd) && is_string($cmd) ) {
536
  $condition = sprintf('if ( %1$s ) { %2$s }', $condition, $cmd);
537
  }
538
  return $condition;
539
  }
540
+
541
  /**
542
  * Build client method call
543
  * @uses get_client_object() to generate the body of the method call
554
  }
555
  $encode = !!$encode;
556
  $validate = !!$validate;
557
+
558
  // Build parameters
559
  if ( !is_null($params) ) {
560
  if ( $encode ) {
561
+ $params = wp_json_encode($params);
562
  } elseif ( is_array($params) ) {
563
+ $params = implode(',', $params);
564
  }
565
  }
566
  if ( !is_string($params) ) {
567
+ $params = '';
568
  }
569
  $ret = sprintf('%s(%s);', $this->get_client_object($method), $params);
570
  if ( $validate ) {
572
  }
573
  return $ret;
574
  }
575
+
576
  /*-** WP **-*/
577
+
578
  /**
579
  * Checks if $post is a valid Post object
580
  * If $post is not valid, assigns global post object to $post (if available)
598
  return false;
599
  return true;
600
  }
601
+
602
+
603
  /**
604
  * Retrieve parent object
605
  * @return obj|bool Parent object (FALSE if no valid parent set)
609
  return $this->_parent;
610
  } else {
611
  return false;
612
+ }
613
  }
614
+
615
  /**
616
  * Retrieve parent property value
617
  * @uses self::get_parent()
621
  */
622
  function get_parent_property($prop, $default = '') {
623
  $p = $this->get_parent();
624
+ return ( !!$p && property_exists($p, $prop) ) ? $p->{$prop} : $default;
625
  }
626
+
627
  /* Hooks */
628
+
629
  /**
630
  * Retrieve formatted name for internal hooks
631
  * Prefixes with parent prefix and hook prefix
648
  // Prefix
649
  return $this->add_prefix($hook . $tag);
650
  }
651
+
652
  /**
653
  * Run internal action
654
  * Namespaces $tag
667
  $args[0] = $this->get_hook($tag, $hook_prefix);
668
  return call_user_func_array('do_action', $args);
669
  }
670
+
671
  /**
672
  * Run internal action passing arguments in array
673
  * @uses do_action_ref_array()
676
  function do_action_ref_array($tag, $args, $hook_prefix = true) {
677
  return do_action_ref_array($this->get_hook($tag, $hook_prefix), $args);
678
  }
679
+
680
  /**
681
  * Run internal filter
682
  * Namespaces $tag
695
  $args[0] = $this->get_hook($tag, $hook_prefix);
696
  return call_user_func_array('apply_filters', $args);
697
  }
698
+
699
  /**
700
  * Run internal filter passing arguments in array
701
  * @uses apply_filters_ref_array()
702
  * @param bool|string $hook_prefix (optional) Secondary prefix to use for hook (Default: Use predefined hook name, FALSE: no secondary hook)
703
  */
704
  function apply_filters_ref_array($tag, $args, $hook_prefix = true) {
705
+ return apply_filters_ref_array($this->get_hook($tag, $hook_prefix), $args);
706
  }
707
+
708
  /**
709
  * Add internal action
710
  * Namespaces $tag
715
  function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
716
  return add_action($this->get_hook($tag, $hook_prefix), $function_to_add, $priority, $accepted_args);
717
  }
718
+
719
  /**
720
  * Add internal filter
721
  * Namespaces $tag
726
  function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
727
  return add_filter($this->get_hook($tag, $hook_prefix), $function_to_add, $priority, $accepted_args);
728
  }
729
+
730
  /**
731
  * Remove internal action
732
  * Namespaces $tag
735
  * @param bool|string $hook_prefix (optional) Secondary prefix to use for hook (Default: Use predefined hook name, FALSE: no secondary hook)
736
  */
737
  function remove_action($tag, $function_to_remove, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
738
+ return remove_action($this->get_hook($tag, $hook_prefix), $function_to_remove, $priority, $accepted_args);
739
  }
740
+
741
  /**
742
  * Remove internal filter
743
  * Namespaces $tag
748
  function remove_filter($tag, $function_to_remove, $priority = 10, $accepted_args = 1, $hook_prefix = true) {
749
  return remove_filter($this->get_hook($tag, $hook_prefix), $function_to_remove, $priority, $accepted_args);
750
  }
751
+
752
  /* Shortcode */
753
+
754
  /**
755
  * Process specific shortcode(s) in content
756
  * Default: Process all existing shortcodes
757
  * @uses $shortcode_tags - array tag => callback
758
  * @uses do_shortcode()
759
+ *
760
  * @param string $content Content to process for shortcodes
761
  * @param string|array $shortcode Single tag or array of tags to process
762
  * > Associative array sets temporary callbacks for shortcodes (`tag => callback`)
763
  */
764
  public function do_shortcode($content, $shortcode = null) {
765
  global $shortcode_tags;
766
+
767
  // Process custom shortcodes
768
  if ( !is_null($shortcode) ) {
769
  // Cast to array
782
  }
783
  }
784
  }
785
+
786
  // Process shortcodes in content
787
  $content = do_shortcode($content);
788
+
789
  // Restore default shortcode handlers
790
  if ( isset($tags_temp) ) {
791
  $shortcode_tags = $tags_temp;
792
  unset($tags_temp);
793
  }
794
+
795
  return $content;
796
  }
797
+
798
  /**
799
  * Build shortcode tag
800
  * @param string $tag Shortcode base
811
  }
812
 
813
  /* Meta */
814
+
815
  /**
816
  * Retrieves post metadata for internal methods
817
  * Metadata set internally is wrapped in an array so it is unwrapped before returned the retrieved value
827
  $meta_value = $meta_value[0];
828
  return $meta_value;
829
  }
830
+
831
  /**
832
  * Wraps metadata in array for storage in database
833
  * @param mixed $meta_value Value to be set as metadata
836
  function post_meta_prepare_value($meta_value) {
837
  return array($meta_value);
838
  }
839
+
840
  /**
841
  * Adds Metadata for a post to database
842
  * For internal methods
851
  $meta_value = $this->post_meta_value_prepare($meta_value);
852
  return add_post_meta($post_id, $meta_key, $meta_value, $unique);
853
  }
854
+
855
  /**
856
  * Updates post metadata for internal data/methods
857
  * @see update_post_meta()
865
  $meta_value = $this->post_meta_prepare_value($meta_value);
866
  return update_post_meta($post_id, $meta_key, $meta_value, $prev_value);
867
  }
868
+
869
  /**
870
  * Builds postmeta key for custom data set by plugin
871
+ * @param string $key Base key name
872
  * @return string Formatted postmeta key
873
  */
874
  function post_meta_get_key($key) {
880
  return $sep . implode($sep, $key);
881
  }
882
  }
883
+
884
  return $key;
885
  }
886
+
887
  /**
888
  * Creates a meta key for storing post meta data
889
  * Prefixes standard prefixed text with underscore to hide meta data on post edit forms
893
  function make_meta_key($text = '') {
894
  return '_' . $this->add_prefix($text);
895
  }
896
+
897
  /* Class */
898
+
899
  /**
900
  * Retrieve name of internal class
901
  * @param string $class Base name of class
903
  */
904
  function get_class($class) {
905
  return $this->add_prefix_uc($class);
906
+ }
907
+
908
  /* Context */
909
+
910
  /**
911
  * Retrieve context for current request
912
  * @return array Context
952
  $u = wp_get_current_user();
953
  $ctx[] = $this->build_context('user', ( $u->ID ) ? 'registered' : 'guest', false);
954
  }
955
+
956
  return $ctx;
957
  }
958
+
959
  /**
960
  * Builds context from multiple components
961
  * Usage:
962
  * > $prefix can be omitted and context strings can be added as needed
963
  * > Multiple context strings may be passed to be joined together
964
+ *
965
  * @param string (optional) $context Variable number of components to add to context
966
+ * @param bool (optional) $prefix Whether or not to prefix context with request type (public or admin) [Default: TRUE]
967
  * @return string Context
968
  */
969
  function build_context($context = null, $prefix = true) {
972
  if ( !empty($args) ) {
973
  $prefix = ( is_bool($args[count($args) - 1]) ) ? array_pop($args) : true;
974
  }
975
+
976
+ // Validate
977
  $context = array_filter($args, 'is_string');
978
  $sep = '_';
979
 
982
  array_unshift($context, ( is_admin() ) ? 'admin' : 'public' );
983
  return implode($sep, $context);
984
  }
985
+
986
  /**
987
  * Check if context exists in current request
988
  * @param string $context Context to check for
1011
  $ctx->context = $this->get_context();
1012
  $this->extend_client_object($ctx, true);
1013
  }
1014
+
1015
  /* Path */
1016
+
1017
  /**
1018
  * Joins and normalizes the slashes in the paths passed to method
1019
  * All forward/back slashes are converted to forward slashes
1035
  if ( is_bool($arg_last) ) {
1036
  $arg_last = array($arg_last);
1037
  }
1038
+
1039
  if ( is_array($arg_last) && count($arg_last) > 0 && is_bool($arg_last[0]) ) {
1040
  // Remove slash paramter from args array
1041
  array_pop($parts);
1048
  }
1049
  // Extract to slash options local variables
1050
  list($trailing_slash, $leading_slash) = $slashes;
1051
+
1052
  // Clean path segments
1053
  foreach ( $parts as $key => $part ) {
1054
  // Trim slashes/spaces
1055
  $parts[$key] = trim($part, " " . $sl_f . $sl_b);
1056
+
1057
  // Verify path segment still contains value
1058
  if ( empty($parts[$key]) ) {
1059
  unset($parts[$key]);
1060
  continue;
1061
  }
1062
  }
1063
+
1064
  // Join path parts together
1065
  $parts = implode($sl_b, $parts);
1066
  $parts = str_replace($sl_b, $sl_f, $parts);
1074
  }
1075
  return $parts;
1076
  }
1077
+
1078
  /**
1079
  * Returns URL of file (assumes that it is in plugin directory)
1080
  * @param string $file name of file get URL
1087
  }
1088
  return $file;
1089
  }
1090
+
1091
  /**
1092
  * Returns path to plugin file
1093
  * @param string $file file name
1100
  }
1101
  return $file;
1102
  }
1103
+
1104
  function get_plugin_file_path($file, $trailing_slash = false) {
1105
  if ( is_string($file) && '' != trim($file) )
1106
  $file = $this->normalize_path($this->get_plugin_base(), $file, $trailing_slash);
1107
  return $file;
1108
  }
1109
+
1110
  /**
1111
  * Checks if value is valid file name
1112
  * @param string $filename File name to check
1116
  $ext = $this->get_file_extension($filename);
1117
  return ( empty($ext) ) ? false : true;
1118
  }
1119
+
1120
  /**
1121
  * Check if string is valid URI
1122
  * @param string $uri String to check
1125
  function is_uri($uri) {
1126
  return ( preg_match('|^(https?:)?//|', $uri) ) ? true : false;
1127
  }
1128
+
1129
  /**
1130
  * Retrieves file extension
1131
  * @param string $file file name/path
1142
  if ( ( $qpos = strpos($file, '?') ) && $qpos !== false ) {
1143
  $file = substr($file, 0, $qpos);
1144
  }
1145
+ if ( ( $rpos = strrpos($file, $sep) ) > 0 )
1146
  $ret = substr($file, $rpos + 1);
1147
  if ( !!$lowercase )
1148
  $ret = strtolower($ret);
1149
  return $ret;
1150
  }
1151
+
1152
  /**
1153
  * Checks if file has specified extension
1154
  * @uses get_file_extension()
1163
  if ( !$case_sensitive ) {
1164
  // Normalize extensions
1165
  $extension = array_map('strtolower', $extension);
1166
+ }
1167
  return ( in_array($this->get_file_extension($file, !$case_sensitive), $extension) ) ? true : false;
1168
  }
1169
+
1170
  /**
1171
  * Removes file extension from file name
1172
  * The extension is the text following the last period ('.') in the file name
1181
  }
1182
  return $file;
1183
  }
1184
+
1185
  /**
1186
  * Retrieve base URL for plugin-specific files
1187
  * @uses get_plugin_base()
1208
  $ret = $this->get_relative_path($ret, $relative);
1209
  }
1210
  }
1211
+
1212
  return $ret;
1213
  }
1214
+
1215
  /**
1216
  * Retrieve plugin's base path
1217
  * @uses WP_PLUGIN_DIR
1251
  }
1252
  return $ret;
1253
  }
1254
+
1255
  /**
1256
  * Retrieve relative path for absolute paths
1257
  * @param string $path Path to modify
1273
  }
1274
  return $path;
1275
  }
1276
+
1277
  /**
1278
  * Retrieve plugin's base directory
1279
  * @uses WP_PLUGIN_DIR
1288
  }
1289
  return $ret;
1290
  }
1291
+
1292
  /**
1293
  * Retrieve plugin's base file path
1294
  * @uses get_path_base()
1321
  // Return
1322
  return $ret;
1323
  }
1324
+
1325
  /**
1326
  * Retrieve plugin's internal name
1327
  * Internal name is used by WP core
1336
  }
1337
  return $ret;
1338
  }
1339
+
1340
  private function set_plugin_info($data) {
1341
  if ( is_array($data) ) {
1342
  $this->_plugin['data'] = $data;
1343
  }
1344
  }
1345
+
1346
  /**
1347
  * Retrieve plugin info
1348
  * Parses info comment in main plugin file
1353
  $ret = $this->_plugin['data'];
1354
  // Get plugin data
1355
  if ( empty($ret) ) {
1356
+ $this->get_plugin_base_file();
1357
  $ret = $this->_plugin['data'];
1358
  }
1359
  // Return specified field
1362
  }
1363
  return $ret;
1364
  }
1365
+
1366
  /**
1367
  * Retrieve plugin version
1368
  * @uses get_plugin_info()
1380
  // Return
1381
  return $ret;
1382
  }
1383
+
1384
  /**
1385
  * Retrieve current post type based on URL query variables
1386
  * @return string|null Current post type
1395
  }
1396
  return $pt;
1397
  }
1398
+
1399
  /**
1400
  * Retrieve current action based on URL query variables
1401
  * @param mixed $default (optional) Default action if no action exists
1403
  */
1404
  function get_action($default = null) {
1405
  $action = '';
1406
+
1407
  // Check if action is set in URL
1408
  if ( isset($_GET['action']) )
1409
  $action = $_GET['action'];
1419
  'edit' => array('edit', 'edit-pages')
1420
  );
1421
  $page = basename($_SERVER['SCRIPT_NAME'], '.php');
1422
+
1423
  foreach ( $actions as $act => $pages ) {
1424
  if ( in_array($page, $pages) ) {
1425
  $action = $act;
1431
  $action = $default;
1432
  return $action;
1433
  }
1434
+
1435
  /*-** General **-*/
1436
+
1437
  /**
1438
  * Checks if a property exists in a class or object
1439
  * Compatibility method for PHP 4
1440
+ * @param mixed $class Class or object to check
1441
  * @param string $property Name of property to look for in $class
1442
  */
1443
  function property_exists($class, $property) {
1449
  return array_key_exists($property, $class);
1450
  }
1451
  }
1452
+
1453
  /**
1454
  * Retrieve specified property from object or array
1455
  * @param object|array $obj Object or array to get property from
1471
  return $cvars[$property];
1472
  }
1473
  }
1474
+
1475
  /**
1476
  * Remap array members based on a
1477
  * mapping of source/destination keys
1503
  // Return remapped properties
1504
  return $arr;
1505
  }
1506
+
1507
  function array_filter_keys($arr, $keys) {
1508
  if ( is_array($arr) && !empty($arr) && is_array($keys) && !empty($keys) ) {
1509
  foreach ( $keys as $rem ) {
1514
 
1515
  return $arr;
1516
  }
1517
+
1518
  /**
1519
  * Insert an item into an array at the specified position
1520
+ * @param mixed $item Item to insert into array
1521
  * @param int $pos Index position to insert item into array
1522
  * @return array Modified array
1523
  */
1525
  array_splice($array, $pos, 0, $item);
1526
  return $array;
1527
  }
1528
+
1529
  /**
1530
  * Merges 1 or more arrays together
1531
  * Methodology
1575
  }
1576
  return $merged;
1577
  }
1578
+
1579
  /**
1580
  * Replaces string value in one array with the value of the matching element in a another array
1581
+ *
1582
  * @param string $search Text to search for in array
1583
  * @param array $arr_replace Array to use for replacing values
1584
  * @param array $arr_subject Array to search for specified value
1596
  if (is_array($val) && is_array($arr_replace[$key]))
1597
  $arr_subject[$key] = $this->array_replace_recursive($search, $arr_replace[$key], $val);
1598
  }
1599
+
1600
  return $arr_subject;
1601
  }
1602
+
1603
  /**
1604
  * Checks if item at specified path in array is set
1605
  * @param array $arr Array to check for item
1610
  $f_path = $this->get_array_path($path);
1611
  return eval('return isset($arr' . $f_path . ');');
1612
  }
1613
+
1614
  /**
1615
  * Build formatted string based on array values
1616
  * Array values in formatted string will be ordered by index order
1653
  }
1654
  return $fmtd;
1655
  }
1656
+
1657
  /**
1658
  * Builds array of path elements based on arguments
1659
  * Each item in path array represents a deeper level in structure path is for (object, array, filesystem, etc.)
1663
  function build_path() {
1664
  $path = array();
1665
  $args = func_get_args();
1666
+
1667
  // Iterate through parameters and build path
1668
  foreach ( $args as $arg ) {
1669
  if ( empty($arg) )
1670
  continue;
1671
+
1672
  if (is_array($arg)) {
1673
  // Recurse through array items to pull out any more arrays
1674
  foreach ($arg as $key => $val) {
1679
  $path[] = $arg;
1680
  }
1681
  }
1682
+
1683
  return $path;
1684
  }
1685
+
1686
  /**
1687
  * Build generic element
1688
  * @param array $args
1703
  );
1704
  $args = wp_parse_args($args, $args_default);
1705
  $args['format'] = wp_parse_args($args['format'], $format_default);
1706
+
1707
  // Validate
1708
  if ( !is_string($args['tag']) || empty($args['tag']) ) {
1709
  return $ret;
1710
  }
1711
+
1712
  $args = (object) $args;
1713
+
1714
  $args->attributes = $this->build_attribute_string($args->attributes);
1715
  if ( strlen($args->attributes) > 0 ) {
1716
  $args->attributes = ' ' . $args->attributes;
1717
  }
1718
+
1719
  // Build output
1720
  $args->format = (object) $args->format;
1721
  $ret = sprintf( $args->format->open, $args->tag . $args->attributes);
1722
+
1723
  // Wrap content if necessary
1724
  if ( $args->wrap || ( is_string($args->content) && !empty($args->content) ) ) {
1725
  $ret .= $args->content . sprintf( $args->format->close, $args->tag);
1727
 
1728
  return $ret;
1729
  }
1730
+
1731
  /**
1732
  * Parse string of attributes into array
1733
  * For XML/XHTML tag attributes
1755
 
1756
  return array_merge($defaults, $attr);
1757
  }
1758
+
1759
  /**
1760
  * Builds attribute string for HTML element
1761
  * @param array $attr Attributes
1776
  }
1777
  return $ret;
1778
  }
1779
+
1780
+ /* HTML */
1781
 
1782
  /**
1783
  * Generate HTML element based on values
1798
  // Build element
1799
  return $this->build_element($args);
1800
  }
1801
+
1802
  /**
1803
  * Build HTML link element
1804
  * @uses build_html_element() to build link output
1811
  $attributes = array_merge(array('href' => $uri, 'title' => $content), $attributes);
1812
  return $this->build_html_element(array('tag' => 'a', 'wrap' => true, 'content' => $content, 'attributes' => $attributes));
1813
  }
1814
+
1815
  /**
1816
  * Generate external stylesheet element
1817
  * @param $url Stylesheet URL
1821
  $attributes = array('href' => $url, 'type' => 'text/css', 'rel' => 'stylesheet');
1822
  return $this->build_html_element(array('tag' => 'link', 'wrap' => false, 'attributes' => $attributes));
1823
  }
1824
+
1825
  /**
1826
  * Build client-side script element
1827
+ *
1828
  * @param string $content Script content
1829
  * @param string $id (optional) Element ID
1830
  * @param bool $wrap_jquery (optional) Wrap commands in jQuery? (Default: Yes)
1844
  if ( $wrap_jquery ) {
1845
  $start[] = 'if ( !!window.jQuery ) {(function($){';
1846
  $end[] = '})(jQuery);}';
1847
+
1848
  // Add event handler (if necessary)
1849
  if ( $wait_doc_ready ) {
1850
  $start[] = '$(document).ready(function(){';
1851
  $end[] = '})';
1852
  }
1853
  }
1854
+
1855
  // Reverse order of end values
1856
  $end = array_reverse($end);
1857
  $content = implode('', array_merge($start, array($content), $end));
main.php CHANGED
@@ -1,22 +1,22 @@
1
  <?php
2
  /**
3
- * Plugin entrypoint
4
  *
5
  * @package Simple Lightbox
6
  * @author Archetyped <support@archetyped.com>
7
- * @copyright 2018 Archetyped
8
- */
9
-
10
- /*
11
- Plugin Name: Simple Lightbox
12
- Plugin URI: http://archetyped.com/tools/simple-lightbox/
13
- Description: The highly customizable lightbox for WordPress
14
- Version: 2.7.1
15
- Text Domain: simple-lightbox
16
- Domain Path: /l10n
17
- Author: Archetyped
18
- Author URI: http://archetyped.com
19
- Support URI: https://github.com/archetyped/simple-lightbox/wiki/Feedback-&-Support
20
  */
21
 
22
  require_once dirname( __FILE__ ) . '/includes/class-requirements-check.php';
1
  <?php
2
  /**
3
+ * Simple Lightbox
4
  *
5
  * @package Simple Lightbox
6
  * @author Archetyped <support@archetyped.com>
7
+ * @copyright 2019 Archetyped
8
+ *
9
+ * Plugin Name: Simple Lightbox
10
+ * Plugin URI: http://archetyped.com/tools/simple-lightbox/
11
+ * Description: The highly customizable lightbox for WordPress
12
+ * Version: 2.8.0
13
+ * Requires at least: 5.3
14
+ * Requires PHP: 7.2
15
+ * Text Domain: simple-lightbox
16
+ * Domain Path: /l10n
17
+ * Author: Archetyped
18
+ * Author URI: http://archetyped.com
19
+ * Support URI: https://github.com/archetyped/simple-lightbox/wiki/Feedback-&-Support
20
  */
21
 
22
  require_once dirname( __FILE__ ) . '/includes/class-requirements-check.php';
package-lock.json CHANGED
@@ -1,15 +1,33 @@
1
  {
2
  "name": "simple-lightbox",
3
- "version": "2.7.1",
4
  "lockfileVersion": 1,
5
  "requires": true,
6
  "dependencies": {
 
 
 
 
 
 
7
  "abbrev": {
8
  "version": "1.1.1",
9
  "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
10
  "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
11
  "dev": true
12
  },
 
 
 
 
 
 
 
 
 
 
 
 
13
  "amdefine": {
14
  "version": "1.0.1",
15
  "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
@@ -23,10 +41,13 @@
23
  "dev": true
24
  },
25
  "ansi-styles": {
26
- "version": "2.2.1",
27
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
28
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
29
- "dev": true
 
 
 
30
  },
31
  "aproba": {
32
  "version": "1.2.0",
@@ -35,13 +56,13 @@
35
  "dev": true
36
  },
37
  "are-we-there-yet": {
38
- "version": "1.1.4",
39
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
40
- "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
41
  "dev": true,
42
  "requires": {
43
- "delegates": "1.0.0",
44
- "readable-stream": "2.3.6"
45
  },
46
  "dependencies": {
47
  "isarray": {
@@ -56,22 +77,28 @@
56
  "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
57
  "dev": true,
58
  "requires": {
59
- "core-util-is": "1.0.2",
60
- "inherits": "2.0.3",
61
- "isarray": "1.0.0",
62
- "process-nextick-args": "2.0.0",
63
- "safe-buffer": "5.1.2",
64
- "string_decoder": "1.1.1",
65
- "util-deprecate": "1.0.2"
66
  }
67
  },
 
 
 
 
 
 
68
  "string_decoder": {
69
  "version": "1.1.1",
70
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
71
  "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
72
  "dev": true,
73
  "requires": {
74
- "safe-buffer": "5.1.2"
75
  }
76
  }
77
  }
@@ -82,13 +109,21 @@
82
  "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
83
  "dev": true,
84
  "requires": {
85
- "sprintf-js": "1.0.3"
 
 
 
 
 
 
 
 
86
  }
87
  },
88
  "array-differ": {
89
- "version": "1.0.0",
90
- "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
91
- "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
92
  "dev": true
93
  },
94
  "array-find-index": {
@@ -98,36 +133,30 @@
98
  "dev": true
99
  },
100
  "array-union": {
101
- "version": "1.0.2",
102
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
103
- "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
104
- "dev": true,
105
- "requires": {
106
- "array-uniq": "1.0.3"
107
- }
108
- },
109
- "array-uniq": {
110
- "version": "1.0.3",
111
- "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
112
- "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
113
  "dev": true
114
  },
115
  "arrify": {
116
- "version": "1.0.1",
117
- "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
118
- "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
119
  "dev": true
120
  },
121
  "asn1": {
122
- "version": "0.2.3",
123
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
124
- "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
125
- "dev": true
 
 
 
126
  },
127
  "assert-plus": {
128
- "version": "0.2.0",
129
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
130
- "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
131
  "dev": true
132
  },
133
  "async": {
@@ -149,15 +178,15 @@
149
  "dev": true
150
  },
151
  "aws-sign2": {
152
- "version": "0.6.0",
153
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
154
- "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
155
  "dev": true
156
  },
157
  "aws4": {
158
- "version": "1.7.0",
159
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
160
- "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==",
161
  "dev": true
162
  },
163
  "balanced-match": {
@@ -167,13 +196,12 @@
167
  "dev": true
168
  },
169
  "bcrypt-pbkdf": {
170
- "version": "1.0.1",
171
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
172
- "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
173
  "dev": true,
174
- "optional": true,
175
  "requires": {
176
- "tweetnacl": "0.14.5"
177
  }
178
  },
179
  "beeper": {
@@ -188,48 +216,19 @@
188
  "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
189
  "dev": true,
190
  "requires": {
191
- "inherits": "2.0.3"
192
- }
193
- },
194
- "body-parser": {
195
- "version": "1.14.2",
196
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz",
197
- "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=",
198
- "dev": true,
199
- "requires": {
200
- "bytes": "2.2.0",
201
- "content-type": "1.0.4",
202
- "debug": "2.2.0",
203
- "depd": "1.1.2",
204
- "http-errors": "1.3.1",
205
- "iconv-lite": "0.4.13",
206
- "on-finished": "2.3.0",
207
- "qs": "5.2.0",
208
- "raw-body": "2.1.7",
209
- "type-is": "1.6.16"
210
- },
211
- "dependencies": {
212
- "iconv-lite": {
213
- "version": "0.4.13",
214
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
215
- "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
216
- "dev": true
217
- },
218
- "qs": {
219
- "version": "5.2.0",
220
- "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz",
221
- "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=",
222
- "dev": true
223
- }
224
  }
225
  },
226
- "boom": {
227
- "version": "2.10.1",
228
- "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
229
- "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
230
  "dev": true,
231
  "requires": {
232
- "hoek": "2.16.3"
 
 
 
233
  }
234
  },
235
  "brace-expansion": {
@@ -238,35 +237,14 @@
238
  "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
239
  "dev": true,
240
  "requires": {
241
- "balanced-match": "1.0.0",
242
  "concat-map": "0.0.1"
243
  }
244
  },
245
- "browserify-zlib": {
246
- "version": "0.1.4",
247
- "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
248
- "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
249
- "dev": true,
250
- "requires": {
251
- "pako": "0.2.9"
252
- }
253
- },
254
- "buffer-from": {
255
- "version": "1.0.0",
256
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz",
257
- "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==",
258
- "dev": true
259
- },
260
- "builtin-modules": {
261
- "version": "1.1.1",
262
- "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
263
- "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
264
- "dev": true
265
- },
266
  "bytes": {
267
- "version": "2.2.0",
268
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz",
269
- "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=",
270
  "dev": true
271
  },
272
  "cache-swap": {
@@ -275,21 +253,10 @@
275
  "integrity": "sha1-HFQaoQilAQb2ML3Zj+HeyLoTP1E=",
276
  "dev": true,
277
  "requires": {
278
- "graceful-fs": "4.1.11",
279
- "mkdirp": "0.5.1",
280
- "object-assign": "4.1.1",
281
- "rimraf": "2.6.2"
282
- },
283
- "dependencies": {
284
- "rimraf": {
285
- "version": "2.6.2",
286
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
287
- "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
288
- "dev": true,
289
- "requires": {
290
- "glob": "7.0.6"
291
- }
292
- }
293
  }
294
  },
295
  "camelcase": {
@@ -304,27 +271,25 @@
304
  "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
305
  "dev": true,
306
  "requires": {
307
- "camelcase": "2.1.1",
308
- "map-obj": "1.0.1"
309
  }
310
  },
311
  "caseless": {
312
- "version": "0.11.0",
313
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
314
- "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=",
315
  "dev": true
316
  },
317
  "chalk": {
318
- "version": "1.1.3",
319
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
320
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
321
  "dev": true,
322
  "requires": {
323
- "ansi-styles": "2.2.1",
324
- "escape-string-regexp": "1.0.5",
325
- "has-ansi": "2.0.0",
326
- "strip-ansi": "3.0.1",
327
- "supports-color": "2.0.0"
328
  }
329
  },
330
  "cli": {
@@ -334,21 +299,21 @@
334
  "dev": true,
335
  "requires": {
336
  "exit": "0.1.2",
337
- "glob": "7.1.2"
338
  },
339
  "dependencies": {
340
  "glob": {
341
- "version": "7.1.2",
342
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
343
- "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
344
  "dev": true,
345
  "requires": {
346
- "fs.realpath": "1.0.0",
347
- "inflight": "1.0.6",
348
- "inherits": "2.0.3",
349
- "minimatch": "3.0.4",
350
- "once": "1.4.0",
351
- "path-is-absolute": "1.0.1"
352
  }
353
  }
354
  }
@@ -359,9 +324,9 @@
359
  "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
360
  "dev": true,
361
  "requires": {
362
- "string-width": "1.0.2",
363
- "strip-ansi": "3.0.1",
364
- "wrap-ansi": "2.1.0"
365
  }
366
  },
367
  "code-point-at": {
@@ -376,6 +341,21 @@
376
  "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=",
377
  "dev": true
378
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  "colors": {
380
  "version": "1.1.2",
381
  "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
@@ -383,18 +363,18 @@
383
  "dev": true
384
  },
385
  "combined-stream": {
386
- "version": "1.0.6",
387
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
388
- "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
389
  "dev": true,
390
  "requires": {
391
- "delayed-stream": "1.0.0"
392
  }
393
  },
394
  "commander": {
395
- "version": "2.15.1",
396
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
397
- "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
398
  "dev": true
399
  },
400
  "concat-map": {
@@ -403,57 +383,13 @@
403
  "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
404
  "dev": true
405
  },
406
- "concat-stream": {
407
- "version": "1.6.2",
408
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
409
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
410
- "dev": true,
411
- "requires": {
412
- "buffer-from": "1.0.0",
413
- "inherits": "2.0.3",
414
- "readable-stream": "2.3.6",
415
- "typedarray": "0.0.6"
416
- },
417
- "dependencies": {
418
- "isarray": {
419
- "version": "1.0.0",
420
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
421
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
422
- "dev": true
423
- },
424
- "readable-stream": {
425
- "version": "2.3.6",
426
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
427
- "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
428
- "dev": true,
429
- "requires": {
430
- "core-util-is": "1.0.2",
431
- "inherits": "2.0.3",
432
- "isarray": "1.0.0",
433
- "process-nextick-args": "2.0.0",
434
- "safe-buffer": "5.1.2",
435
- "string_decoder": "1.1.1",
436
- "util-deprecate": "1.0.2"
437
- }
438
- },
439
- "string_decoder": {
440
- "version": "1.1.1",
441
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
442
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
443
- "dev": true,
444
- "requires": {
445
- "safe-buffer": "5.1.2"
446
- }
447
- }
448
- }
449
- },
450
  "console-browserify": {
451
  "version": "1.1.0",
452
  "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
453
  "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
454
  "dev": true,
455
  "requires": {
456
- "date-now": "0.1.4"
457
  }
458
  },
459
  "console-control-strings": {
@@ -462,10 +398,10 @@
462
  "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
463
  "dev": true
464
  },
465
- "content-type": {
466
- "version": "1.0.4",
467
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
468
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
469
  "dev": true
470
  },
471
  "core-util-is": {
@@ -480,38 +416,29 @@
480
  "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
481
  "dev": true,
482
  "requires": {
483
- "lru-cache": "4.1.2",
484
- "which": "1.2.14"
485
  },
486
  "dependencies": {
487
  "lru-cache": {
488
- "version": "4.1.2",
489
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz",
490
- "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==",
491
  "dev": true,
492
  "requires": {
493
- "pseudomap": "1.0.2",
494
- "yallist": "2.1.2"
495
  }
496
  }
497
  }
498
  },
499
- "cryptiles": {
500
- "version": "2.0.5",
501
- "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
502
- "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
503
- "dev": true,
504
- "requires": {
505
- "boom": "2.10.1"
506
- }
507
- },
508
  "currently-unhandled": {
509
  "version": "0.4.1",
510
  "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
511
  "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
512
  "dev": true,
513
  "requires": {
514
- "array-find-index": "1.0.2"
515
  }
516
  },
517
  "dashdash": {
@@ -520,15 +447,7 @@
520
  "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
521
  "dev": true,
522
  "requires": {
523
- "assert-plus": "1.0.0"
524
- },
525
- "dependencies": {
526
- "assert-plus": {
527
- "version": "1.0.0",
528
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
529
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
530
- "dev": true
531
- }
532
  }
533
  },
534
  "date-now": {
@@ -543,7 +462,7 @@
543
  "integrity": "sha1-GIdtC9pMGf5w3Tv0sDTygbEqQLY=",
544
  "dev": true,
545
  "requires": {
546
- "time-zone": "0.1.0"
547
  }
548
  },
549
  "dateformat": {
@@ -552,17 +471,17 @@
552
  "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
553
  "dev": true,
554
  "requires": {
555
- "get-stdin": "4.0.1",
556
- "meow": "3.7.0"
557
  }
558
  },
559
  "debug": {
560
- "version": "2.2.0",
561
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
562
- "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
563
  "dev": true,
564
  "requires": {
565
- "ms": "0.7.1"
566
  }
567
  },
568
  "decamelize": {
@@ -583,40 +502,34 @@
583
  "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
584
  "dev": true
585
  },
586
- "depd": {
587
- "version": "1.1.2",
588
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
589
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
590
- "dev": true
591
- },
592
  "dom-serializer": {
593
- "version": "0.1.0",
594
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
595
- "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
596
  "dev": true,
597
  "requires": {
598
- "domelementtype": "1.1.3",
599
- "entities": "1.1.1"
600
  },
601
  "dependencies": {
602
  "domelementtype": {
603
- "version": "1.1.3",
604
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
605
- "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
606
  "dev": true
607
  },
608
  "entities": {
609
- "version": "1.1.1",
610
- "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
611
- "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
612
  "dev": true
613
  }
614
  }
615
  },
616
  "domelementtype": {
617
- "version": "1.3.0",
618
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
619
- "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
620
  "dev": true
621
  },
622
  "domhandler": {
@@ -625,7 +538,7 @@
625
  "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
626
  "dev": true,
627
  "requires": {
628
- "domelementtype": "1.3.0"
629
  }
630
  },
631
  "domutils": {
@@ -634,49 +547,49 @@
634
  "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
635
  "dev": true,
636
  "requires": {
637
- "dom-serializer": "0.1.0",
638
- "domelementtype": "1.3.0"
639
  }
640
  },
641
- "each-async": {
642
- "version": "1.1.1",
643
- "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz",
644
- "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=",
645
- "dev": true,
646
- "requires": {
647
- "onetime": "1.1.0",
648
- "set-immediate-shim": "1.0.1"
649
- }
650
  },
651
  "ecc-jsbn": {
652
- "version": "0.1.1",
653
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
654
- "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
655
  "dev": true,
656
- "optional": true,
657
  "requires": {
658
- "jsbn": "0.1.1"
 
659
  }
660
  },
661
- "ee-first": {
662
- "version": "1.1.1",
663
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
664
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
665
- "dev": true
666
- },
667
  "entities": {
668
  "version": "1.0.0",
669
  "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
670
  "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=",
671
  "dev": true
672
  },
 
 
 
 
 
 
 
 
 
 
673
  "error-ex": {
674
- "version": "1.3.1",
675
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
676
- "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
677
  "dev": true,
678
  "requires": {
679
- "is-arrayish": "0.2.1"
680
  }
681
  },
682
  "escape-string-regexp": {
@@ -686,9 +599,9 @@
686
  "dev": true
687
  },
688
  "esprima": {
689
- "version": "2.7.3",
690
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
691
- "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
692
  "dev": true
693
  },
694
  "eventemitter2": {
@@ -704,9 +617,9 @@
704
  "dev": true
705
  },
706
  "extend": {
707
- "version": "3.0.1",
708
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
709
- "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
710
  "dev": true
711
  },
712
  "extsprintf": {
@@ -715,13 +628,25 @@
715
  "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
716
  "dev": true
717
  },
 
 
 
 
 
 
 
 
 
 
 
 
718
  "faye-websocket": {
719
  "version": "0.10.0",
720
  "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
721
  "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
722
  "dev": true,
723
  "requires": {
724
- "websocket-driver": "0.7.0"
725
  }
726
  },
727
  "figures": {
@@ -730,8 +655,8 @@
730
  "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
731
  "dev": true,
732
  "requires": {
733
- "escape-string-regexp": "1.0.5",
734
- "object-assign": "4.1.1"
735
  }
736
  },
737
  "find-up": {
@@ -740,8 +665,8 @@
740
  "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
741
  "dev": true,
742
  "requires": {
743
- "path-exists": "2.1.0",
744
- "pinkie-promise": "2.0.1"
745
  }
746
  },
747
  "findup-sync": {
@@ -750,7 +675,7 @@
750
  "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
751
  "dev": true,
752
  "requires": {
753
- "glob": "5.0.15"
754
  },
755
  "dependencies": {
756
  "glob": {
@@ -759,11 +684,11 @@
759
  "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
760
  "dev": true,
761
  "requires": {
762
- "inflight": "1.0.6",
763
- "inherits": "2.0.3",
764
- "minimatch": "3.0.4",
765
- "once": "1.4.0",
766
- "path-is-absolute": "1.0.1"
767
  }
768
  }
769
  }
@@ -775,14 +700,14 @@
775
  "dev": true
776
  },
777
  "form-data": {
778
- "version": "2.1.4",
779
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
780
- "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
781
  "dev": true,
782
  "requires": {
783
- "asynckit": "0.4.0",
784
- "combined-stream": "1.0.6",
785
- "mime-types": "2.1.18"
786
  }
787
  },
788
  "fs.realpath": {
@@ -792,15 +717,15 @@
792
  "dev": true
793
  },
794
  "fstream": {
795
- "version": "1.0.11",
796
- "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
797
- "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
798
  "dev": true,
799
  "requires": {
800
- "graceful-fs": "4.1.11",
801
- "inherits": "2.0.3",
802
- "mkdirp": "0.5.1",
803
- "rimraf": "2.2.8"
804
  }
805
  },
806
  "gauge": {
@@ -809,44 +734,29 @@
809
  "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
810
  "dev": true,
811
  "requires": {
812
- "aproba": "1.2.0",
813
- "console-control-strings": "1.1.0",
814
- "has-unicode": "2.0.1",
815
- "object-assign": "4.1.1",
816
- "signal-exit": "3.0.2",
817
- "string-width": "1.0.2",
818
- "strip-ansi": "3.0.1",
819
- "wide-align": "1.1.2"
820
  }
821
  },
822
  "gaze": {
823
- "version": "1.1.2",
824
- "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz",
825
- "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=",
826
- "dev": true,
827
- "requires": {
828
- "globule": "1.2.0"
829
- }
830
- },
831
- "generate-function": {
832
- "version": "2.0.0",
833
- "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
834
- "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=",
835
- "dev": true
836
- },
837
- "generate-object-property": {
838
- "version": "1.2.0",
839
- "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
840
- "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
841
  "dev": true,
842
  "requires": {
843
- "is-property": "1.0.2"
844
  }
845
  },
846
  "get-caller-file": {
847
- "version": "1.0.2",
848
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
849
- "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
850
  "dev": true
851
  },
852
  "get-stdin": {
@@ -867,15 +777,7 @@
867
  "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
868
  "dev": true,
869
  "requires": {
870
- "assert-plus": "1.0.0"
871
- },
872
- "dependencies": {
873
- "assert-plus": {
874
- "version": "1.0.0",
875
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
876
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
877
- "dev": true
878
- }
879
  }
880
  },
881
  "glob": {
@@ -884,69 +786,70 @@
884
  "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
885
  "dev": true,
886
  "requires": {
887
- "fs.realpath": "1.0.0",
888
- "inflight": "1.0.6",
889
- "inherits": "2.0.3",
890
- "minimatch": "3.0.4",
891
- "once": "1.4.0",
892
- "path-is-absolute": "1.0.1"
893
  }
894
  },
895
  "globule": {
896
- "version": "1.2.0",
897
- "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz",
898
- "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=",
899
  "dev": true,
900
  "requires": {
901
- "glob": "7.1.2",
902
- "lodash": "4.17.10",
903
- "minimatch": "3.0.4"
904
  },
905
  "dependencies": {
906
  "glob": {
907
- "version": "7.1.2",
908
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
909
- "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
910
  "dev": true,
911
  "requires": {
912
- "fs.realpath": "1.0.0",
913
- "inflight": "1.0.6",
914
- "inherits": "2.0.3",
915
- "minimatch": "3.0.4",
916
- "once": "1.4.0",
917
- "path-is-absolute": "1.0.1"
918
  }
919
  }
920
  }
921
  },
922
  "graceful-fs": {
923
- "version": "4.1.11",
924
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
925
- "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
926
  "dev": true
927
  },
928
  "grunt": {
929
- "version": "1.0.2",
930
- "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.2.tgz",
931
- "integrity": "sha1-TmpeaVtwRy/VME9fqeNCNoNqc7w=",
932
- "dev": true,
933
- "requires": {
934
- "coffeescript": "1.10.0",
935
- "dateformat": "1.0.12",
936
- "eventemitter2": "0.4.14",
937
- "exit": "0.1.2",
938
- "findup-sync": "0.3.0",
939
- "glob": "7.0.6",
940
- "grunt-cli": "1.2.0",
941
- "grunt-known-options": "1.1.0",
942
- "grunt-legacy-log": "1.0.2",
943
- "grunt-legacy-util": "1.0.0",
944
- "iconv-lite": "0.4.21",
945
- "js-yaml": "3.5.5",
946
- "minimatch": "3.0.4",
947
- "nopt": "3.0.6",
948
- "path-is-absolute": "1.0.1",
949
- "rimraf": "2.2.8"
 
950
  },
951
  "dependencies": {
952
  "grunt-cli": {
@@ -955,106 +858,107 @@
955
  "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
956
  "dev": true,
957
  "requires": {
958
- "findup-sync": "0.3.0",
959
- "grunt-known-options": "1.1.0",
960
- "nopt": "3.0.6",
961
- "resolve": "1.1.7"
962
  }
 
 
 
 
 
 
963
  }
964
  }
965
  },
966
  "grunt-contrib-jshint": {
967
- "version": "1.1.0",
968
- "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-1.1.0.tgz",
969
- "integrity": "sha1-Np2QmyWTxA6L55lAshNAhQx5Oaw=",
970
  "dev": true,
971
  "requires": {
972
- "chalk": "1.1.3",
973
- "hooker": "0.2.3",
974
- "jshint": "2.9.5"
975
  }
976
  },
977
  "grunt-contrib-uglify": {
978
- "version": "3.3.0",
979
- "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-3.3.0.tgz",
980
- "integrity": "sha512-W9O7lJE3PlD8VCc5fyaf98QV7f5wEDiU4PBIh0+/6UBbk2LhgzEFS0/p+taH5UD3+PlEn7QPN0o06Z0To6SqXw==",
981
  "dev": true,
982
  "requires": {
983
- "chalk": "1.1.3",
984
- "maxmin": "1.1.0",
985
- "uglify-js": "3.3.22",
986
- "uri-path": "1.0.0"
987
  }
988
  },
989
  "grunt-contrib-watch": {
990
- "version": "1.0.1",
991
- "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.1.tgz",
992
- "integrity": "sha512-8Zka/svGl6+ZwF7d6z/CfXwsb4cDODnajmZsY4nUAs9Ob0kJEcsLiDf5qm2HdDoEcm3NHjWCrFiWx+PZ2y4D7A==",
993
  "dev": true,
994
  "requires": {
995
- "async": "1.5.2",
996
- "gaze": "1.1.2",
997
- "lodash": "4.17.10",
998
- "tiny-lr": "0.2.1"
 
 
 
 
 
 
 
 
 
 
 
999
  }
1000
  },
1001
  "grunt-known-options": {
1002
- "version": "1.1.0",
1003
- "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz",
1004
- "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=",
1005
  "dev": true
1006
  },
1007
  "grunt-legacy-log": {
1008
- "version": "1.0.2",
1009
- "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.2.tgz",
1010
- "integrity": "sha512-WdedTJ/6zCXnI/coaouzqvkI19uwqbcPkdsXiDRKJyB5rOUlOxnCnTVbpeUdEckKVir2uHF3rDBYppj2p6N3+g==",
1011
  "dev": true,
1012
  "requires": {
1013
- "colors": "1.1.2",
1014
- "grunt-legacy-log-utils": "1.0.0",
1015
- "hooker": "0.2.3",
1016
- "lodash": "4.17.10"
1017
  }
1018
  },
1019
  "grunt-legacy-log-utils": {
1020
- "version": "1.0.0",
1021
- "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz",
1022
- "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=",
1023
  "dev": true,
1024
  "requires": {
1025
- "chalk": "1.1.3",
1026
- "lodash": "4.3.0"
1027
- },
1028
- "dependencies": {
1029
- "lodash": {
1030
- "version": "4.3.0",
1031
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
1032
- "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
1033
- "dev": true
1034
- }
1035
  }
1036
  },
1037
  "grunt-legacy-util": {
1038
- "version": "1.0.0",
1039
- "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz",
1040
- "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=",
1041
  "dev": true,
1042
  "requires": {
1043
- "async": "1.5.2",
1044
- "exit": "0.1.2",
1045
- "getobject": "0.1.0",
1046
- "hooker": "0.2.3",
1047
- "lodash": "4.3.0",
1048
- "underscore.string": "3.2.3",
1049
- "which": "1.2.14"
1050
- },
1051
- "dependencies": {
1052
- "lodash": {
1053
- "version": "4.3.0",
1054
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
1055
- "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
1056
- "dev": true
1057
- }
1058
  }
1059
  },
1060
  "grunt-phplint": {
@@ -1063,8 +967,8 @@
1063
  "integrity": "sha1-bb4uauxTqiKc+sCtmnyZ4kGEhI0=",
1064
  "dev": true,
1065
  "requires": {
1066
- "cache-swap": "0.3.0",
1067
- "grunt": "0.4.5"
1068
  },
1069
  "dependencies": {
1070
  "argparse": {
@@ -1073,8 +977,8 @@
1073
  "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=",
1074
  "dev": true,
1075
  "requires": {
1076
- "underscore": "1.7.0",
1077
- "underscore.string": "2.4.0"
1078
  },
1079
  "dependencies": {
1080
  "underscore.string": {
@@ -1121,8 +1025,8 @@
1121
  "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=",
1122
  "dev": true,
1123
  "requires": {
1124
- "glob": "3.2.11",
1125
- "lodash": "2.4.2"
1126
  },
1127
  "dependencies": {
1128
  "glob": {
@@ -1131,8 +1035,8 @@
1131
  "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
1132
  "dev": true,
1133
  "requires": {
1134
- "inherits": "2.0.3",
1135
- "minimatch": "0.3.0"
1136
  }
1137
  },
1138
  "lodash": {
@@ -1147,8 +1051,8 @@
1147
  "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
1148
  "dev": true,
1149
  "requires": {
1150
- "lru-cache": "2.7.3",
1151
- "sigmund": "1.0.1"
1152
  }
1153
  }
1154
  }
@@ -1159,9 +1063,9 @@
1159
  "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
1160
  "dev": true,
1161
  "requires": {
1162
- "graceful-fs": "1.2.3",
1163
- "inherits": "1.0.2",
1164
- "minimatch": "0.2.14"
1165
  },
1166
  "dependencies": {
1167
  "inherits": {
@@ -1184,26 +1088,26 @@
1184
  "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=",
1185
  "dev": true,
1186
  "requires": {
1187
- "async": "0.1.22",
1188
- "coffee-script": "1.3.3",
1189
- "colors": "0.6.2",
1190
  "dateformat": "1.0.2-1.2.3",
1191
- "eventemitter2": "0.4.14",
1192
- "exit": "0.1.2",
1193
- "findup-sync": "0.1.3",
1194
- "getobject": "0.1.0",
1195
- "glob": "3.1.21",
1196
- "grunt-legacy-log": "0.1.3",
1197
- "grunt-legacy-util": "0.2.0",
1198
- "hooker": "0.2.3",
1199
- "iconv-lite": "0.2.11",
1200
- "js-yaml": "2.0.5",
1201
- "lodash": "0.9.2",
1202
- "minimatch": "0.2.14",
1203
- "nopt": "1.0.10",
1204
- "rimraf": "2.2.8",
1205
- "underscore.string": "2.2.1",
1206
- "which": "1.0.9"
1207
  }
1208
  },
1209
  "grunt-legacy-log": {
@@ -1212,11 +1116,11 @@
1212
  "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=",
1213
  "dev": true,
1214
  "requires": {
1215
- "colors": "0.6.2",
1216
- "grunt-legacy-log-utils": "0.1.1",
1217
- "hooker": "0.2.3",
1218
- "lodash": "2.4.2",
1219
- "underscore.string": "2.3.3"
1220
  },
1221
  "dependencies": {
1222
  "lodash": {
@@ -1239,9 +1143,9 @@
1239
  "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=",
1240
  "dev": true,
1241
  "requires": {
1242
- "colors": "0.6.2",
1243
- "lodash": "2.4.2",
1244
- "underscore.string": "2.3.3"
1245
  },
1246
  "dependencies": {
1247
  "lodash": {
@@ -1264,13 +1168,13 @@
1264
  "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=",
1265
  "dev": true,
1266
  "requires": {
1267
- "async": "0.1.22",
1268
- "exit": "0.1.2",
1269
- "getobject": "0.1.0",
1270
- "hooker": "0.2.3",
1271
- "lodash": "0.9.2",
1272
- "underscore.string": "2.2.1",
1273
- "which": "1.0.9"
1274
  }
1275
  },
1276
  "iconv-lite": {
@@ -1285,8 +1189,8 @@
1285
  "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=",
1286
  "dev": true,
1287
  "requires": {
1288
- "argparse": "0.1.16",
1289
- "esprima": "1.0.4"
1290
  }
1291
  },
1292
  "lodash": {
@@ -1301,8 +1205,8 @@
1301
  "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
1302
  "dev": true,
1303
  "requires": {
1304
- "lru-cache": "2.7.3",
1305
- "sigmund": "1.0.1"
1306
  }
1307
  },
1308
  "nopt": {
@@ -1311,9 +1215,15 @@
1311
  "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
1312
  "dev": true,
1313
  "requires": {
1314
- "abbrev": "1.1.1"
1315
  }
1316
  },
 
 
 
 
 
 
1317
  "underscore.string": {
1318
  "version": "2.2.1",
1319
  "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz",
@@ -1329,36 +1239,34 @@
1329
  }
1330
  },
1331
  "grunt-sass": {
1332
- "version": "2.1.0",
1333
- "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-2.1.0.tgz",
1334
- "integrity": "sha512-XkexnQt/9rhReNd+Y7T0n/2g5FqYOQKfi2iSlpwDqvgs7EgEaGTxNhnWzHnbW5oNRvzL9AHopBG3AgRxL0d+DA==",
1335
- "dev": true,
1336
- "requires": {
1337
- "each-async": "1.1.1",
1338
- "node-sass": "4.9.0",
1339
- "object-assign": "4.1.1"
1340
- }
1341
  },
1342
  "gzip-size": {
1343
- "version": "1.0.0",
1344
- "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz",
1345
- "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=",
1346
  "dev": true,
1347
  "requires": {
1348
- "browserify-zlib": "0.1.4",
1349
- "concat-stream": "1.6.2"
1350
  }
1351
  },
 
 
 
 
 
 
1352
  "har-validator": {
1353
- "version": "2.0.6",
1354
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
1355
- "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
1356
  "dev": true,
1357
  "requires": {
1358
- "chalk": "1.1.3",
1359
- "commander": "2.15.1",
1360
- "is-my-json-valid": "2.17.2",
1361
- "pinkie-promise": "2.0.1"
1362
  }
1363
  },
1364
  "has-ansi": {
@@ -1367,33 +1275,21 @@
1367
  "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
1368
  "dev": true,
1369
  "requires": {
1370
- "ansi-regex": "2.1.1"
1371
  }
1372
  },
 
 
 
 
 
 
1373
  "has-unicode": {
1374
  "version": "2.0.1",
1375
  "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
1376
  "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
1377
  "dev": true
1378
  },
1379
- "hawk": {
1380
- "version": "3.1.3",
1381
- "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
1382
- "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
1383
- "dev": true,
1384
- "requires": {
1385
- "boom": "2.10.1",
1386
- "cryptiles": "2.0.5",
1387
- "hoek": "2.16.3",
1388
- "sntp": "1.0.9"
1389
- }
1390
- },
1391
- "hoek": {
1392
- "version": "2.16.3",
1393
- "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
1394
- "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
1395
- "dev": true
1396
- },
1397
  "hooker": {
1398
  "version": "0.2.3",
1399
  "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
@@ -1401,9 +1297,9 @@
1401
  "dev": true
1402
  },
1403
  "hosted-git-info": {
1404
- "version": "2.6.0",
1405
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
1406
- "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
1407
  "dev": true
1408
  },
1409
  "htmlparser2": {
@@ -1412,47 +1308,37 @@
1412
  "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
1413
  "dev": true,
1414
  "requires": {
1415
- "domelementtype": "1.3.0",
1416
- "domhandler": "2.3.0",
1417
- "domutils": "1.5.1",
1418
- "entities": "1.0.0",
1419
- "readable-stream": "1.1.14"
1420
- }
1421
- },
1422
- "http-errors": {
1423
- "version": "1.3.1",
1424
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
1425
- "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=",
1426
- "dev": true,
1427
- "requires": {
1428
- "inherits": "2.0.3",
1429
- "statuses": "1.5.0"
1430
  }
1431
  },
1432
  "http-parser-js": {
1433
- "version": "0.4.12",
1434
- "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.12.tgz",
1435
- "integrity": "sha1-uc+/Sizybw/DSxDKFImid3HjR08=",
1436
  "dev": true
1437
  },
1438
  "http-signature": {
1439
- "version": "1.1.1",
1440
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
1441
- "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
1442
  "dev": true,
1443
  "requires": {
1444
- "assert-plus": "0.2.0",
1445
- "jsprim": "1.4.1",
1446
- "sshpk": "1.14.1"
1447
  }
1448
  },
1449
  "iconv-lite": {
1450
- "version": "0.4.21",
1451
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz",
1452
- "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==",
1453
  "dev": true,
1454
  "requires": {
1455
- "safer-buffer": "2.1.2"
1456
  }
1457
  },
1458
  "in-publish": {
@@ -1467,7 +1353,7 @@
1467
  "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
1468
  "dev": true,
1469
  "requires": {
1470
- "repeating": "2.0.1"
1471
  }
1472
  },
1473
  "inflight": {
@@ -1476,14 +1362,14 @@
1476
  "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1477
  "dev": true,
1478
  "requires": {
1479
- "once": "1.4.0",
1480
- "wrappy": "1.0.2"
1481
  }
1482
  },
1483
  "inherits": {
1484
- "version": "2.0.3",
1485
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
1486
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
1487
  "dev": true
1488
  },
1489
  "invert-kv": {
@@ -1504,22 +1390,13 @@
1504
  "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
1505
  "dev": true
1506
  },
1507
- "is-builtin-module": {
1508
- "version": "1.0.0",
1509
- "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
1510
- "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
1511
- "dev": true,
1512
- "requires": {
1513
- "builtin-modules": "1.1.1"
1514
- }
1515
- },
1516
  "is-finite": {
1517
  "version": "1.0.2",
1518
  "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
1519
  "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
1520
  "dev": true,
1521
  "requires": {
1522
- "number-is-nan": "1.0.1"
1523
  }
1524
  },
1525
  "is-fullwidth-code-point": {
@@ -1528,38 +1405,13 @@
1528
  "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
1529
  "dev": true,
1530
  "requires": {
1531
- "number-is-nan": "1.0.1"
1532
  }
1533
  },
1534
- "is-my-ip-valid": {
1535
  "version": "1.0.0",
1536
- "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
1537
- "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==",
1538
- "dev": true
1539
- },
1540
- "is-my-json-valid": {
1541
- "version": "2.17.2",
1542
- "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz",
1543
- "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==",
1544
- "dev": true,
1545
- "requires": {
1546
- "generate-function": "2.0.0",
1547
- "generate-object-property": "1.2.0",
1548
- "is-my-ip-valid": "1.0.0",
1549
- "jsonpointer": "4.0.1",
1550
- "xtend": "4.0.1"
1551
- }
1552
- },
1553
- "is-property": {
1554
- "version": "1.0.2",
1555
- "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
1556
- "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
1557
- "dev": true
1558
- },
1559
- "is-typedarray": {
1560
- "version": "1.0.0",
1561
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
1562
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
1563
  "dev": true
1564
  },
1565
  "is-utf8": {
@@ -1587,50 +1439,41 @@
1587
  "dev": true
1588
  },
1589
  "js-base64": {
1590
- "version": "2.4.3",
1591
- "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz",
1592
- "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==",
1593
  "dev": true
1594
  },
1595
  "js-yaml": {
1596
- "version": "3.5.5",
1597
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
1598
- "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=",
1599
  "dev": true,
1600
  "requires": {
1601
- "argparse": "1.0.10",
1602
- "esprima": "2.7.3"
1603
  }
1604
  },
1605
  "jsbn": {
1606
  "version": "0.1.1",
1607
  "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
1608
  "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
1609
- "dev": true,
1610
- "optional": true
1611
  },
1612
  "jshint": {
1613
- "version": "2.9.5",
1614
- "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz",
1615
- "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=",
1616
  "dev": true,
1617
  "requires": {
1618
- "cli": "1.0.1",
1619
- "console-browserify": "1.1.0",
1620
- "exit": "0.1.2",
1621
- "htmlparser2": "3.8.3",
1622
- "lodash": "3.7.0",
1623
- "minimatch": "3.0.4",
1624
- "shelljs": "0.3.0",
1625
- "strip-json-comments": "1.0.4"
1626
- },
1627
- "dependencies": {
1628
- "lodash": {
1629
- "version": "3.7.0",
1630
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz",
1631
- "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=",
1632
- "dev": true
1633
- }
1634
  }
1635
  },
1636
  "jshint-stylish": {
@@ -1639,12 +1482,39 @@
1639
  "integrity": "sha1-JCCCosA1rgP9gQROBXDMQgjPbmE=",
1640
  "dev": true,
1641
  "requires": {
1642
- "beeper": "1.1.1",
1643
- "chalk": "1.1.3",
1644
- "log-symbols": "1.0.2",
1645
- "plur": "2.1.2",
1646
- "string-length": "1.0.1",
1647
- "text-table": "0.2.0"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1648
  }
1649
  },
1650
  "json-schema": {
@@ -1653,18 +1523,18 @@
1653
  "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
1654
  "dev": true
1655
  },
 
 
 
 
 
 
1656
  "json-stringify-safe": {
1657
  "version": "5.0.1",
1658
  "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
1659
  "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
1660
  "dev": true
1661
  },
1662
- "jsonpointer": {
1663
- "version": "4.0.1",
1664
- "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
1665
- "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
1666
- "dev": true
1667
- },
1668
  "jsprim": {
1669
  "version": "1.4.1",
1670
  "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -1675,14 +1545,6 @@
1675
  "extsprintf": "1.3.0",
1676
  "json-schema": "0.2.3",
1677
  "verror": "1.10.0"
1678
- },
1679
- "dependencies": {
1680
- "assert-plus": {
1681
- "version": "1.0.0",
1682
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
1683
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
1684
- "dev": true
1685
- }
1686
  }
1687
  },
1688
  "lcid": {
@@ -1691,25 +1553,25 @@
1691
  "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
1692
  "dev": true,
1693
  "requires": {
1694
- "invert-kv": "1.0.0"
1695
  }
1696
  },
1697
  "livereload-js": {
1698
- "version": "2.3.0",
1699
- "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz",
1700
- "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==",
1701
  "dev": true
1702
  },
1703
  "load-grunt-tasks": {
1704
- "version": "3.5.2",
1705
- "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.5.2.tgz",
1706
- "integrity": "sha1-ByhWEYD9IP+KaSdQWFL8WKrqDIg=",
1707
  "dev": true,
1708
  "requires": {
1709
- "arrify": "1.0.1",
1710
- "multimatch": "2.1.0",
1711
- "pkg-up": "1.0.0",
1712
- "resolve-pkg": "0.1.0"
1713
  }
1714
  },
1715
  "load-json-file": {
@@ -1718,35 +1580,35 @@
1718
  "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
1719
  "dev": true,
1720
  "requires": {
1721
- "graceful-fs": "4.1.11",
1722
- "parse-json": "2.2.0",
1723
- "pify": "2.3.0",
1724
- "pinkie-promise": "2.0.1",
1725
- "strip-bom": "2.0.0"
1726
  }
1727
  },
1728
- "lodash": {
1729
- "version": "4.17.10",
1730
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
1731
- "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
1732
- "dev": true
1733
- },
1734
- "lodash.assign": {
1735
- "version": "4.2.0",
1736
- "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
1737
- "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
1738
- "dev": true
1739
- },
1740
- "lodash.clonedeep": {
1741
- "version": "4.5.0",
1742
- "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
1743
- "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
1744
- "dev": true
1745
  },
1746
- "lodash.mergewith": {
1747
- "version": "4.6.1",
1748
- "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
1749
- "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==",
1750
  "dev": true
1751
  },
1752
  "log-symbols": {
@@ -1755,7 +1617,34 @@
1755
  "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
1756
  "dev": true,
1757
  "requires": {
1758
- "chalk": "1.1.3"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1759
  }
1760
  },
1761
  "loud-rejection": {
@@ -1764,8 +1653,8 @@
1764
  "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
1765
  "dev": true,
1766
  "requires": {
1767
- "currently-unhandled": "0.4.1",
1768
- "signal-exit": "3.0.2"
1769
  }
1770
  },
1771
  "lru-cache": {
@@ -1781,54 +1670,75 @@
1781
  "dev": true
1782
  },
1783
  "maxmin": {
1784
- "version": "1.1.0",
1785
- "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz",
1786
- "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=",
1787
  "dev": true,
1788
  "requires": {
1789
- "chalk": "1.1.3",
1790
- "figures": "1.7.0",
1791
- "gzip-size": "1.0.0",
1792
- "pretty-bytes": "1.0.4"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1793
  }
1794
  },
1795
- "media-typer": {
1796
- "version": "0.3.0",
1797
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
1798
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
1799
- "dev": true
1800
- },
1801
  "meow": {
1802
  "version": "3.7.0",
1803
  "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
1804
  "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
1805
  "dev": true,
1806
  "requires": {
1807
- "camelcase-keys": "2.1.0",
1808
- "decamelize": "1.2.0",
1809
- "loud-rejection": "1.6.0",
1810
- "map-obj": "1.0.1",
1811
- "minimist": "1.2.0",
1812
- "normalize-package-data": "2.4.0",
1813
- "object-assign": "4.1.1",
1814
- "read-pkg-up": "1.0.1",
1815
- "redent": "1.0.0",
1816
- "trim-newlines": "1.0.0"
1817
  }
1818
  },
1819
  "mime-db": {
1820
- "version": "1.33.0",
1821
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
1822
- "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
1823
  "dev": true
1824
  },
1825
  "mime-types": {
1826
- "version": "2.1.18",
1827
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
1828
- "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
1829
  "dev": true,
1830
  "requires": {
1831
- "mime-db": "1.33.0"
1832
  }
1833
  },
1834
  "minimatch": {
@@ -1837,7 +1747,7 @@
1837
  "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
1838
  "dev": true,
1839
  "requires": {
1840
- "brace-expansion": "1.1.11"
1841
  }
1842
  },
1843
  "minimist": {
@@ -1864,48 +1774,48 @@
1864
  }
1865
  },
1866
  "ms": {
1867
- "version": "0.7.1",
1868
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
1869
- "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
1870
  "dev": true
1871
  },
1872
  "multimatch": {
1873
- "version": "2.1.0",
1874
- "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
1875
- "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
1876
  "dev": true,
1877
  "requires": {
1878
- "array-differ": "1.0.0",
1879
- "array-union": "1.0.2",
1880
- "arrify": "1.0.1",
1881
- "minimatch": "3.0.4"
 
1882
  }
1883
  },
1884
  "nan": {
1885
- "version": "2.10.0",
1886
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
1887
- "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
1888
  "dev": true
1889
  },
1890
  "node-gyp": {
1891
- "version": "3.6.2",
1892
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz",
1893
- "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=",
1894
- "dev": true,
1895
- "requires": {
1896
- "fstream": "1.0.11",
1897
- "glob": "7.0.6",
1898
- "graceful-fs": "4.1.11",
1899
- "minimatch": "3.0.4",
1900
- "mkdirp": "0.5.1",
1901
- "nopt": "3.0.6",
1902
- "npmlog": "4.1.2",
1903
- "osenv": "0.1.5",
1904
- "request": "2.79.0",
1905
- "rimraf": "2.2.8",
1906
- "semver": "5.3.0",
1907
- "tar": "2.2.1",
1908
- "which": "1.2.14"
1909
  },
1910
  "dependencies": {
1911
  "semver": {
@@ -1917,30 +1827,55 @@
1917
  }
1918
  },
1919
  "node-sass": {
1920
- "version": "4.9.0",
1921
- "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz",
1922
- "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==",
1923
- "dev": true,
1924
- "requires": {
1925
- "async-foreach": "0.1.3",
1926
- "chalk": "1.1.3",
1927
- "cross-spawn": "3.0.1",
1928
- "gaze": "1.1.2",
1929
- "get-stdin": "4.0.1",
1930
- "glob": "7.0.6",
1931
- "in-publish": "2.0.0",
1932
- "lodash.assign": "4.2.0",
1933
- "lodash.clonedeep": "4.5.0",
1934
- "lodash.mergewith": "4.6.1",
1935
- "meow": "3.7.0",
1936
- "mkdirp": "0.5.1",
1937
- "nan": "2.10.0",
1938
- "node-gyp": "3.6.2",
1939
- "npmlog": "4.1.2",
1940
- "request": "2.79.0",
1941
- "sass-graph": "2.2.4",
1942
- "stdout-stream": "1.4.0",
1943
- "true-case-path": "1.0.2"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1944
  }
1945
  },
1946
  "nopt": {
@@ -1949,19 +1884,19 @@
1949
  "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
1950
  "dev": true,
1951
  "requires": {
1952
- "abbrev": "1.1.1"
1953
  }
1954
  },
1955
  "normalize-package-data": {
1956
- "version": "2.4.0",
1957
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
1958
- "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
1959
  "dev": true,
1960
  "requires": {
1961
- "hosted-git-info": "2.6.0",
1962
- "is-builtin-module": "1.0.0",
1963
- "semver": "5.5.0",
1964
- "validate-npm-package-license": "3.0.3"
1965
  }
1966
  },
1967
  "npmlog": {
@@ -1970,10 +1905,10 @@
1970
  "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
1971
  "dev": true,
1972
  "requires": {
1973
- "are-we-there-yet": "1.1.4",
1974
- "console-control-strings": "1.1.0",
1975
- "gauge": "2.7.4",
1976
- "set-blocking": "2.0.0"
1977
  }
1978
  },
1979
  "number-is-nan": {
@@ -1983,9 +1918,9 @@
1983
  "dev": true
1984
  },
1985
  "oauth-sign": {
1986
- "version": "0.8.2",
1987
- "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
1988
- "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
1989
  "dev": true
1990
  },
1991
  "object-assign": {
@@ -1994,30 +1929,15 @@
1994
  "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
1995
  "dev": true
1996
  },
1997
- "on-finished": {
1998
- "version": "2.3.0",
1999
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
2000
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
2001
- "dev": true,
2002
- "requires": {
2003
- "ee-first": "1.1.1"
2004
- }
2005
- },
2006
  "once": {
2007
  "version": "1.4.0",
2008
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
2009
  "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
2010
  "dev": true,
2011
  "requires": {
2012
- "wrappy": "1.0.2"
2013
  }
2014
  },
2015
- "onetime": {
2016
- "version": "1.1.0",
2017
- "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
2018
- "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
2019
- "dev": true
2020
- },
2021
  "os-homedir": {
2022
  "version": "1.0.2",
2023
  "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -2030,7 +1950,7 @@
2030
  "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
2031
  "dev": true,
2032
  "requires": {
2033
- "lcid": "1.0.0"
2034
  }
2035
  },
2036
  "os-tmpdir": {
@@ -2045,14 +1965,32 @@
2045
  "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
2046
  "dev": true,
2047
  "requires": {
2048
- "os-homedir": "1.0.2",
2049
- "os-tmpdir": "1.0.2"
2050
  }
2051
  },
2052
- "pako": {
2053
- "version": "0.2.9",
2054
- "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
2055
- "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2056
  "dev": true
2057
  },
2058
  "parse-json": {
@@ -2061,7 +1999,7 @@
2061
  "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
2062
  "dev": true,
2063
  "requires": {
2064
- "error-ex": "1.3.1"
2065
  }
2066
  },
2067
  "parse-ms": {
@@ -2070,19 +2008,13 @@
2070
  "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=",
2071
  "dev": true
2072
  },
2073
- "parseurl": {
2074
- "version": "1.3.2",
2075
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
2076
- "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
2077
- "dev": true
2078
- },
2079
  "path-exists": {
2080
  "version": "2.1.0",
2081
  "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
2082
  "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
2083
  "dev": true,
2084
  "requires": {
2085
- "pinkie-promise": "2.0.1"
2086
  }
2087
  },
2088
  "path-is-absolute": {
@@ -2091,17 +2023,29 @@
2091
  "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
2092
  "dev": true
2093
  },
 
 
 
 
 
 
2094
  "path-type": {
2095
  "version": "1.1.0",
2096
  "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
2097
  "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
2098
  "dev": true,
2099
  "requires": {
2100
- "graceful-fs": "4.1.11",
2101
- "pify": "2.3.0",
2102
- "pinkie-promise": "2.0.1"
2103
  }
2104
  },
 
 
 
 
 
 
2105
  "pify": {
2106
  "version": "2.3.0",
2107
  "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@@ -2120,16 +2064,27 @@
2120
  "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
2121
  "dev": true,
2122
  "requires": {
2123
- "pinkie": "2.0.4"
2124
  }
2125
  },
2126
  "pkg-up": {
2127
- "version": "1.0.0",
2128
- "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz",
2129
- "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=",
2130
  "dev": true,
2131
  "requires": {
2132
- "find-up": "1.1.2"
 
 
 
 
 
 
 
 
 
 
 
2133
  }
2134
  },
2135
  "plur": {
@@ -2138,17 +2093,16 @@
2138
  "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=",
2139
  "dev": true,
2140
  "requires": {
2141
- "irregular-plurals": "1.4.0"
2142
  }
2143
  },
2144
  "pretty-bytes": {
2145
- "version": "1.0.4",
2146
- "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
2147
- "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
2148
  "dev": true,
2149
  "requires": {
2150
- "get-stdin": "4.0.1",
2151
- "meow": "3.7.0"
2152
  }
2153
  },
2154
  "pretty-ms": {
@@ -2157,9 +2111,9 @@
2157
  "integrity": "sha1-QlfCVt8/sLRR1q/6qwIYhBJpgdw=",
2158
  "dev": true,
2159
  "requires": {
2160
- "is-finite": "1.0.2",
2161
- "parse-ms": "1.0.1",
2162
- "plur": "1.0.0"
2163
  },
2164
  "dependencies": {
2165
  "plur": {
@@ -2171,9 +2125,9 @@
2171
  }
2172
  },
2173
  "process-nextick-args": {
2174
- "version": "2.0.0",
2175
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
2176
- "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
2177
  "dev": true
2178
  },
2179
  "pseudomap": {
@@ -2182,41 +2136,32 @@
2182
  "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
2183
  "dev": true
2184
  },
 
 
 
 
 
 
2185
  "punycode": {
2186
- "version": "1.4.1",
2187
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
2188
- "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
2189
  "dev": true
2190
  },
2191
  "qs": {
2192
- "version": "5.1.0",
2193
- "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz",
2194
- "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=",
2195
  "dev": true
2196
  },
2197
  "raw-body": {
2198
- "version": "2.1.7",
2199
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
2200
- "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
2201
  "dev": true,
2202
  "requires": {
2203
- "bytes": "2.4.0",
2204
- "iconv-lite": "0.4.13",
2205
- "unpipe": "1.0.0"
2206
- },
2207
- "dependencies": {
2208
- "bytes": {
2209
- "version": "2.4.0",
2210
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
2211
- "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=",
2212
- "dev": true
2213
- },
2214
- "iconv-lite": {
2215
- "version": "0.4.13",
2216
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
2217
- "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
2218
- "dev": true
2219
- }
2220
  }
2221
  },
2222
  "read-pkg": {
@@ -2225,9 +2170,9 @@
2225
  "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
2226
  "dev": true,
2227
  "requires": {
2228
- "load-json-file": "1.1.0",
2229
- "normalize-package-data": "2.4.0",
2230
- "path-type": "1.1.0"
2231
  }
2232
  },
2233
  "read-pkg-up": {
@@ -2236,8 +2181,8 @@
2236
  "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
2237
  "dev": true,
2238
  "requires": {
2239
- "find-up": "1.1.2",
2240
- "read-pkg": "1.1.0"
2241
  }
2242
  },
2243
  "readable-stream": {
@@ -2246,10 +2191,10 @@
2246
  "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
2247
  "dev": true,
2248
  "requires": {
2249
- "core-util-is": "1.0.2",
2250
- "inherits": "2.0.3",
2251
  "isarray": "0.0.1",
2252
- "string_decoder": "0.10.31"
2253
  }
2254
  },
2255
  "redent": {
@@ -2258,8 +2203,8 @@
2258
  "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
2259
  "dev": true,
2260
  "requires": {
2261
- "indent-string": "2.1.0",
2262
- "strip-indent": "1.0.1"
2263
  }
2264
  },
2265
  "repeating": {
@@ -2268,41 +2213,41 @@
2268
  "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
2269
  "dev": true,
2270
  "requires": {
2271
- "is-finite": "1.0.2"
2272
  }
2273
  },
2274
  "request": {
2275
- "version": "2.79.0",
2276
- "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
2277
- "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
2278
- "dev": true,
2279
- "requires": {
2280
- "aws-sign2": "0.6.0",
2281
- "aws4": "1.7.0",
2282
- "caseless": "0.11.0",
2283
- "combined-stream": "1.0.6",
2284
- "extend": "3.0.1",
2285
- "forever-agent": "0.6.1",
2286
- "form-data": "2.1.4",
2287
- "har-validator": "2.0.6",
2288
- "hawk": "3.1.3",
2289
- "http-signature": "1.1.1",
2290
- "is-typedarray": "1.0.0",
2291
- "isstream": "0.1.2",
2292
- "json-stringify-safe": "5.0.1",
2293
- "mime-types": "2.1.18",
2294
- "oauth-sign": "0.8.2",
2295
- "qs": "6.3.2",
2296
- "stringstream": "0.0.5",
2297
- "tough-cookie": "2.3.4",
2298
- "tunnel-agent": "0.4.3",
2299
- "uuid": "3.2.1"
2300
  },
2301
  "dependencies": {
2302
  "qs": {
2303
- "version": "6.3.2",
2304
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
2305
- "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=",
2306
  "dev": true
2307
  }
2308
  }
@@ -2320,36 +2265,64 @@
2320
  "dev": true
2321
  },
2322
  "resolve": {
2323
- "version": "1.1.7",
2324
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
2325
- "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
2326
- "dev": true
 
 
 
2327
  },
2328
  "resolve-from": {
2329
- "version": "2.0.0",
2330
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
2331
- "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
2332
  "dev": true
2333
  },
2334
  "resolve-pkg": {
2335
- "version": "0.1.0",
2336
- "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-0.1.0.tgz",
2337
- "integrity": "sha1-AsyZNBDik2livZcWahsHfalyVTE=",
2338
  "dev": true,
2339
  "requires": {
2340
- "resolve-from": "2.0.0"
2341
  }
2342
  },
2343
  "rimraf": {
2344
- "version": "2.2.8",
2345
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
2346
- "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
2347
- "dev": true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2348
  },
2349
  "safe-buffer": {
2350
- "version": "5.1.2",
2351
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
2352
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
 
 
 
 
 
 
2353
  "dev": true
2354
  },
2355
  "safer-buffer": {
@@ -2364,10 +2337,10 @@
2364
  "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
2365
  "dev": true,
2366
  "requires": {
2367
- "glob": "7.0.6",
2368
- "lodash": "4.17.10",
2369
- "scss-tokenizer": "0.2.3",
2370
- "yargs": "7.1.0"
2371
  }
2372
  },
2373
  "scss-tokenizer": {
@@ -2376,8 +2349,8 @@
2376
  "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
2377
  "dev": true,
2378
  "requires": {
2379
- "js-base64": "2.4.3",
2380
- "source-map": "0.4.4"
2381
  },
2382
  "dependencies": {
2383
  "source-map": {
@@ -2386,15 +2359,15 @@
2386
  "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
2387
  "dev": true,
2388
  "requires": {
2389
- "amdefine": "1.0.1"
2390
  }
2391
  }
2392
  }
2393
  },
2394
  "semver": {
2395
- "version": "5.5.0",
2396
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
2397
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
2398
  "dev": true
2399
  },
2400
  "set-blocking": {
@@ -2403,12 +2376,6 @@
2403
  "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
2404
  "dev": true
2405
  },
2406
- "set-immediate-shim": {
2407
- "version": "1.0.1",
2408
- "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
2409
- "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
2410
- "dev": true
2411
- },
2412
  "shelljs": {
2413
  "version": "0.3.0",
2414
  "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
@@ -2427,15 +2394,6 @@
2427
  "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
2428
  "dev": true
2429
  },
2430
- "sntp": {
2431
- "version": "1.0.9",
2432
- "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
2433
- "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
2434
- "dev": true,
2435
- "requires": {
2436
- "hoek": "2.16.3"
2437
- }
2438
- },
2439
  "source-map": {
2440
  "version": "0.6.1",
2441
  "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -2443,19 +2401,19 @@
2443
  "dev": true
2444
  },
2445
  "spdx-correct": {
2446
- "version": "3.0.0",
2447
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
2448
- "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
2449
  "dev": true,
2450
  "requires": {
2451
- "spdx-expression-parse": "3.0.0",
2452
- "spdx-license-ids": "3.0.0"
2453
  }
2454
  },
2455
  "spdx-exceptions": {
2456
- "version": "2.1.0",
2457
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
2458
- "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
2459
  "dev": true
2460
  },
2461
  "spdx-expression-parse": {
@@ -2464,59 +2422,46 @@
2464
  "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
2465
  "dev": true,
2466
  "requires": {
2467
- "spdx-exceptions": "2.1.0",
2468
- "spdx-license-ids": "3.0.0"
2469
  }
2470
  },
2471
  "spdx-license-ids": {
2472
- "version": "3.0.0",
2473
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
2474
- "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
2475
  "dev": true
2476
  },
2477
  "sprintf-js": {
2478
- "version": "1.0.3",
2479
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
2480
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
2481
  "dev": true
2482
  },
2483
  "sshpk": {
2484
- "version": "1.14.1",
2485
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
2486
- "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
2487
  "dev": true,
2488
  "requires": {
2489
- "asn1": "0.2.3",
2490
- "assert-plus": "1.0.0",
2491
- "bcrypt-pbkdf": "1.0.1",
2492
- "dashdash": "1.14.1",
2493
- "ecc-jsbn": "0.1.1",
2494
- "getpass": "0.1.7",
2495
- "jsbn": "0.1.1",
2496
- "tweetnacl": "0.14.5"
2497
- },
2498
- "dependencies": {
2499
- "assert-plus": {
2500
- "version": "1.0.0",
2501
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
2502
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
2503
- "dev": true
2504
- }
2505
  }
2506
  },
2507
- "statuses": {
2508
- "version": "1.5.0",
2509
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
2510
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
2511
- "dev": true
2512
- },
2513
  "stdout-stream": {
2514
- "version": "1.4.0",
2515
- "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz",
2516
- "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=",
2517
  "dev": true,
2518
  "requires": {
2519
- "readable-stream": "2.3.6"
2520
  },
2521
  "dependencies": {
2522
  "isarray": {
@@ -2531,22 +2476,28 @@
2531
  "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
2532
  "dev": true,
2533
  "requires": {
2534
- "core-util-is": "1.0.2",
2535
- "inherits": "2.0.3",
2536
- "isarray": "1.0.0",
2537
- "process-nextick-args": "2.0.0",
2538
- "safe-buffer": "5.1.2",
2539
- "string_decoder": "1.1.1",
2540
- "util-deprecate": "1.0.2"
2541
  }
2542
  },
 
 
 
 
 
 
2543
  "string_decoder": {
2544
  "version": "1.1.1",
2545
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
2546
  "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
2547
  "dev": true,
2548
  "requires": {
2549
- "safe-buffer": "5.1.2"
2550
  }
2551
  }
2552
  }
@@ -2557,18 +2508,24 @@
2557
  "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=",
2558
  "dev": true,
2559
  "requires": {
2560
- "strip-ansi": "3.0.1"
2561
  }
2562
  },
 
 
 
 
 
 
2563
  "string-width": {
2564
  "version": "1.0.2",
2565
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
2566
  "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
2567
  "dev": true,
2568
  "requires": {
2569
- "code-point-at": "1.1.0",
2570
- "is-fullwidth-code-point": "1.0.0",
2571
- "strip-ansi": "3.0.1"
2572
  }
2573
  },
2574
  "string_decoder": {
@@ -2577,19 +2534,13 @@
2577
  "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
2578
  "dev": true
2579
  },
2580
- "stringstream": {
2581
- "version": "0.0.5",
2582
- "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
2583
- "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
2584
- "dev": true
2585
- },
2586
  "strip-ansi": {
2587
  "version": "3.0.1",
2588
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
2589
  "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
2590
  "dev": true,
2591
  "requires": {
2592
- "ansi-regex": "2.1.1"
2593
  }
2594
  },
2595
  "strip-bom": {
@@ -2598,7 +2549,7 @@
2598
  "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
2599
  "dev": true,
2600
  "requires": {
2601
- "is-utf8": "0.2.1"
2602
  }
2603
  },
2604
  "strip-indent": {
@@ -2607,7 +2558,7 @@
2607
  "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
2608
  "dev": true,
2609
  "requires": {
2610
- "get-stdin": "4.0.1"
2611
  }
2612
  },
2613
  "strip-json-comments": {
@@ -2617,20 +2568,23 @@
2617
  "dev": true
2618
  },
2619
  "supports-color": {
2620
- "version": "2.0.0",
2621
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
2622
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
2623
- "dev": true
 
 
 
2624
  },
2625
  "tar": {
2626
- "version": "2.2.1",
2627
- "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
2628
- "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
2629
  "dev": true,
2630
  "requires": {
2631
- "block-stream": "0.0.9",
2632
- "fstream": "1.0.11",
2633
- "inherits": "2.0.3"
2634
  }
2635
  },
2636
  "text-table": {
@@ -2640,18 +2594,45 @@
2640
  "dev": true
2641
  },
2642
  "time-grunt": {
2643
- "version": "1.4.0",
2644
- "resolved": "https://registry.npmjs.org/time-grunt/-/time-grunt-1.4.0.tgz",
2645
- "integrity": "sha1-BiIT5mDJB+hvRAVWwB6mWXtxJCA=",
2646
  "dev": true,
2647
  "requires": {
2648
- "chalk": "1.1.3",
2649
- "date-time": "1.1.0",
2650
- "figures": "1.7.0",
2651
- "hooker": "0.2.3",
2652
- "number-is-nan": "1.0.1",
2653
- "pretty-ms": "2.1.0",
2654
- "text-table": "0.2.0"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2655
  }
2656
  },
2657
  "time-zone": {
@@ -2661,26 +2642,35 @@
2661
  "dev": true
2662
  },
2663
  "tiny-lr": {
2664
- "version": "0.2.1",
2665
- "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz",
2666
- "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=",
2667
  "dev": true,
2668
  "requires": {
2669
- "body-parser": "1.14.2",
2670
- "debug": "2.2.0",
2671
- "faye-websocket": "0.10.0",
2672
- "livereload-js": "2.3.0",
2673
- "parseurl": "1.3.2",
2674
- "qs": "5.1.0"
2675
  }
2676
  },
2677
  "tough-cookie": {
2678
- "version": "2.3.4",
2679
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
2680
- "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
2681
  "dev": true,
2682
  "requires": {
2683
- "punycode": "1.4.1"
 
 
 
 
 
 
 
 
 
2684
  }
2685
  },
2686
  "trim-newlines": {
@@ -2690,66 +2680,53 @@
2690
  "dev": true
2691
  },
2692
  "true-case-path": {
2693
- "version": "1.0.2",
2694
- "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz",
2695
- "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=",
2696
  "dev": true,
2697
  "requires": {
2698
- "glob": "6.0.4"
2699
  },
2700
  "dependencies": {
2701
  "glob": {
2702
- "version": "6.0.4",
2703
- "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
2704
- "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
2705
  "dev": true,
2706
  "requires": {
2707
- "inflight": "1.0.6",
2708
- "inherits": "2.0.3",
2709
- "minimatch": "3.0.4",
2710
- "once": "1.4.0",
2711
- "path-is-absolute": "1.0.1"
 
2712
  }
2713
  }
2714
  }
2715
  },
2716
  "tunnel-agent": {
2717
- "version": "0.4.3",
2718
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
2719
- "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=",
2720
- "dev": true
 
 
 
2721
  },
2722
  "tweetnacl": {
2723
  "version": "0.14.5",
2724
  "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
2725
  "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
2726
- "dev": true,
2727
- "optional": true
2728
- },
2729
- "type-is": {
2730
- "version": "1.6.16",
2731
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
2732
- "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
2733
- "dev": true,
2734
- "requires": {
2735
- "media-typer": "0.3.0",
2736
- "mime-types": "2.1.18"
2737
- }
2738
- },
2739
- "typedarray": {
2740
- "version": "0.0.6",
2741
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
2742
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
2743
  "dev": true
2744
  },
2745
  "uglify-js": {
2746
- "version": "3.3.22",
2747
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.22.tgz",
2748
- "integrity": "sha512-tqw96rL6/BG+7LM5VItdhDjTQmL5zG/I0b2RqWytlgeHe2eydZHuBHdA9vuGpCDhH/ZskNGcqDhivoR2xt8RIw==",
2749
  "dev": true,
2750
  "requires": {
2751
- "commander": "2.15.1",
2752
- "source-map": "0.6.1"
2753
  }
2754
  },
2755
  "underscore": {
@@ -2759,16 +2736,23 @@
2759
  "dev": true
2760
  },
2761
  "underscore.string": {
2762
- "version": "3.2.3",
2763
- "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
2764
- "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=",
2765
- "dev": true
 
 
 
 
2766
  },
2767
- "unpipe": {
2768
- "version": "1.0.0",
2769
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
2770
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
2771
- "dev": true
 
 
 
2772
  },
2773
  "uri-path": {
2774
  "version": "1.0.0",
@@ -2783,19 +2767,19 @@
2783
  "dev": true
2784
  },
2785
  "uuid": {
2786
- "version": "3.2.1",
2787
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
2788
- "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
2789
  "dev": true
2790
  },
2791
  "validate-npm-package-license": {
2792
- "version": "3.0.3",
2793
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
2794
- "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
2795
  "dev": true,
2796
  "requires": {
2797
- "spdx-correct": "3.0.0",
2798
- "spdx-expression-parse": "3.0.0"
2799
  }
2800
  },
2801
  "verror": {
@@ -2804,27 +2788,20 @@
2804
  "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
2805
  "dev": true,
2806
  "requires": {
2807
- "assert-plus": "1.0.0",
2808
  "core-util-is": "1.0.2",
2809
- "extsprintf": "1.3.0"
2810
- },
2811
- "dependencies": {
2812
- "assert-plus": {
2813
- "version": "1.0.0",
2814
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
2815
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
2816
- "dev": true
2817
- }
2818
  }
2819
  },
2820
  "websocket-driver": {
2821
- "version": "0.7.0",
2822
- "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
2823
- "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
2824
  "dev": true,
2825
  "requires": {
2826
- "http-parser-js": "0.4.12",
2827
- "websocket-extensions": "0.1.3"
 
2828
  }
2829
  },
2830
  "websocket-extensions": {
@@ -2834,12 +2811,12 @@
2834
  "dev": true
2835
  },
2836
  "which": {
2837
- "version": "1.2.14",
2838
- "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
2839
- "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
2840
  "dev": true,
2841
  "requires": {
2842
- "isexe": "2.0.0"
2843
  }
2844
  },
2845
  "which-module": {
@@ -2849,12 +2826,12 @@
2849
  "dev": true
2850
  },
2851
  "wide-align": {
2852
- "version": "1.1.2",
2853
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
2854
- "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
2855
  "dev": true,
2856
  "requires": {
2857
- "string-width": "1.0.2"
2858
  }
2859
  },
2860
  "wrap-ansi": {
@@ -2863,8 +2840,8 @@
2863
  "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
2864
  "dev": true,
2865
  "requires": {
2866
- "string-width": "1.0.2",
2867
- "strip-ansi": "3.0.1"
2868
  }
2869
  },
2870
  "wrappy": {
@@ -2874,9 +2851,9 @@
2874
  "dev": true
2875
  },
2876
  "xtend": {
2877
- "version": "4.0.1",
2878
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
2879
- "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
2880
  "dev": true
2881
  },
2882
  "y18n": {
@@ -2897,19 +2874,19 @@
2897
  "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
2898
  "dev": true,
2899
  "requires": {
2900
- "camelcase": "3.0.0",
2901
- "cliui": "3.2.0",
2902
- "decamelize": "1.2.0",
2903
- "get-caller-file": "1.0.2",
2904
- "os-locale": "1.4.0",
2905
- "read-pkg-up": "1.0.1",
2906
- "require-directory": "2.1.1",
2907
- "require-main-filename": "1.0.1",
2908
- "set-blocking": "2.0.0",
2909
- "string-width": "1.0.2",
2910
- "which-module": "1.0.0",
2911
- "y18n": "3.2.1",
2912
- "yargs-parser": "5.0.0"
2913
  },
2914
  "dependencies": {
2915
  "camelcase": {
@@ -2926,7 +2903,7 @@
2926
  "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
2927
  "dev": true,
2928
  "requires": {
2929
- "camelcase": "3.0.0"
2930
  },
2931
  "dependencies": {
2932
  "camelcase": {
1
  {
2
  "name": "simple-lightbox",
3
+ "version": "2.8.0",
4
  "lockfileVersion": 1,
5
  "requires": true,
6
  "dependencies": {
7
+ "@types/minimatch": {
8
+ "version": "3.0.3",
9
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
10
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
11
+ "dev": true
12
+ },
13
  "abbrev": {
14
  "version": "1.1.1",
15
  "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
16
  "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
17
  "dev": true
18
  },
19
+ "ajv": {
20
+ "version": "6.10.2",
21
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
22
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
23
+ "dev": true,
24
+ "requires": {
25
+ "fast-deep-equal": "^2.0.1",
26
+ "fast-json-stable-stringify": "^2.0.0",
27
+ "json-schema-traverse": "^0.4.1",
28
+ "uri-js": "^4.2.2"
29
+ }
30
+ },
31
  "amdefine": {
32
  "version": "1.0.1",
33
  "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
41
  "dev": true
42
  },
43
  "ansi-styles": {
44
+ "version": "3.2.1",
45
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
46
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
47
+ "dev": true,
48
+ "requires": {
49
+ "color-convert": "^1.9.0"
50
+ }
51
  },
52
  "aproba": {
53
  "version": "1.2.0",
56
  "dev": true
57
  },
58
  "are-we-there-yet": {
59
+ "version": "1.1.5",
60
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
61
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
62
  "dev": true,
63
  "requires": {
64
+ "delegates": "^1.0.0",
65
+ "readable-stream": "^2.0.6"
66
  },
67
  "dependencies": {
68
  "isarray": {
77
  "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
78
  "dev": true,
79
  "requires": {
80
+ "core-util-is": "~1.0.0",
81
+ "inherits": "~2.0.3",
82
+ "isarray": "~1.0.0",
83
+ "process-nextick-args": "~2.0.0",
84
+ "safe-buffer": "~5.1.1",
85
+ "string_decoder": "~1.1.1",
86
+ "util-deprecate": "~1.0.1"
87
  }
88
  },
89
+ "safe-buffer": {
90
+ "version": "5.1.2",
91
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
92
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
93
+ "dev": true
94
+ },
95
  "string_decoder": {
96
  "version": "1.1.1",
97
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
98
  "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
99
  "dev": true,
100
  "requires": {
101
+ "safe-buffer": "~5.1.0"
102
  }
103
  }
104
  }
109
  "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
110
  "dev": true,
111
  "requires": {
112
+ "sprintf-js": "~1.0.2"
113
+ },
114
+ "dependencies": {
115
+ "sprintf-js": {
116
+ "version": "1.0.3",
117
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
118
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
119
+ "dev": true
120
+ }
121
  }
122
  },
123
  "array-differ": {
124
+ "version": "3.0.0",
125
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
126
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
127
  "dev": true
128
  },
129
  "array-find-index": {
133
  "dev": true
134
  },
135
  "array-union": {
136
+ "version": "2.1.0",
137
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
138
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
 
 
 
 
 
 
 
 
 
139
  "dev": true
140
  },
141
  "arrify": {
142
+ "version": "2.0.1",
143
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
144
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
145
  "dev": true
146
  },
147
  "asn1": {
148
+ "version": "0.2.4",
149
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
150
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
151
+ "dev": true,
152
+ "requires": {
153
+ "safer-buffer": "~2.1.0"
154
+ }
155
  },
156
  "assert-plus": {
157
+ "version": "1.0.0",
158
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
159
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
160
  "dev": true
161
  },
162
  "async": {
178
  "dev": true
179
  },
180
  "aws-sign2": {
181
+ "version": "0.7.0",
182
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
183
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
184
  "dev": true
185
  },
186
  "aws4": {
187
+ "version": "1.8.0",
188
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
189
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
190
  "dev": true
191
  },
192
  "balanced-match": {
196
  "dev": true
197
  },
198
  "bcrypt-pbkdf": {
199
+ "version": "1.0.2",
200
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
201
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
202
  "dev": true,
 
203
  "requires": {
204
+ "tweetnacl": "^0.14.3"
205
  }
206
  },
207
  "beeper": {
216
  "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
217
  "dev": true,
218
  "requires": {
219
+ "inherits": "~2.0.0"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  }
221
  },
222
+ "body": {
223
+ "version": "5.1.0",
224
+ "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz",
225
+ "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=",
226
  "dev": true,
227
  "requires": {
228
+ "continuable-cache": "^0.3.1",
229
+ "error": "^7.0.0",
230
+ "raw-body": "~1.1.0",
231
+ "safe-json-parse": "~1.0.1"
232
  }
233
  },
234
  "brace-expansion": {
237
  "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
238
  "dev": true,
239
  "requires": {
240
+ "balanced-match": "^1.0.0",
241
  "concat-map": "0.0.1"
242
  }
243
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  "bytes": {
245
+ "version": "1.0.0",
246
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz",
247
+ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=",
248
  "dev": true
249
  },
250
  "cache-swap": {
253
  "integrity": "sha1-HFQaoQilAQb2ML3Zj+HeyLoTP1E=",
254
  "dev": true,
255
  "requires": {
256
+ "graceful-fs": "^4.1.2",
257
+ "mkdirp": "^0.5.1",
258
+ "object-assign": "^4.0.1",
259
+ "rimraf": "^2.4.0"
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
  },
262
  "camelcase": {
271
  "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
272
  "dev": true,
273
  "requires": {
274
+ "camelcase": "^2.0.0",
275
+ "map-obj": "^1.0.0"
276
  }
277
  },
278
  "caseless": {
279
+ "version": "0.12.0",
280
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
281
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
282
  "dev": true
283
  },
284
  "chalk": {
285
+ "version": "2.4.2",
286
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
287
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
288
  "dev": true,
289
  "requires": {
290
+ "ansi-styles": "^3.2.1",
291
+ "escape-string-regexp": "^1.0.5",
292
+ "supports-color": "^5.3.0"
 
 
293
  }
294
  },
295
  "cli": {
299
  "dev": true,
300
  "requires": {
301
  "exit": "0.1.2",
302
+ "glob": "^7.1.1"
303
  },
304
  "dependencies": {
305
  "glob": {
306
+ "version": "7.1.4",
307
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
308
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
309
  "dev": true,
310
  "requires": {
311
+ "fs.realpath": "^1.0.0",
312
+ "inflight": "^1.0.4",
313
+ "inherits": "2",
314
+ "minimatch": "^3.0.4",
315
+ "once": "^1.3.0",
316
+ "path-is-absolute": "^1.0.0"
317
  }
318
  }
319
  }
324
  "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
325
  "dev": true,
326
  "requires": {
327
+ "string-width": "^1.0.1",
328
+ "strip-ansi": "^3.0.1",
329
+ "wrap-ansi": "^2.0.0"
330
  }
331
  },
332
  "code-point-at": {
341
  "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=",
342
  "dev": true
343
  },
344
+ "color-convert": {
345
+ "version": "1.9.3",
346
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
347
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
348
+ "dev": true,
349
+ "requires": {
350
+ "color-name": "1.1.3"
351
+ }
352
+ },
353
+ "color-name": {
354
+ "version": "1.1.3",
355
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
356
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
357
+ "dev": true
358
+ },
359
  "colors": {
360
  "version": "1.1.2",
361
  "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
363
  "dev": true
364
  },
365
  "combined-stream": {
366
+ "version": "1.0.8",
367
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
368
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
369
  "dev": true,
370
  "requires": {
371
+ "delayed-stream": "~1.0.0"
372
  }
373
  },
374
  "commander": {
375
+ "version": "2.20.0",
376
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
377
+ "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
378
  "dev": true
379
  },
380
  "concat-map": {
383
  "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
384
  "dev": true
385
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  "console-browserify": {
387
  "version": "1.1.0",
388
  "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
389
  "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
390
  "dev": true,
391
  "requires": {
392
+ "date-now": "^0.1.4"
393
  }
394
  },
395
  "console-control-strings": {
398
  "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
399
  "dev": true
400
  },
401
+ "continuable-cache": {
402
+ "version": "0.3.1",
403
+ "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz",
404
+ "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=",
405
  "dev": true
406
  },
407
  "core-util-is": {
416
  "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
417
  "dev": true,
418
  "requires": {
419
+ "lru-cache": "^4.0.1",
420
+ "which": "^1.2.9"
421
  },
422
  "dependencies": {
423
  "lru-cache": {
424
+ "version": "4.1.5",
425
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
426
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
427
  "dev": true,
428
  "requires": {
429
+ "pseudomap": "^1.0.2",
430
+ "yallist": "^2.1.2"
431
  }
432
  }
433
  }
434
  },
 
 
 
 
 
 
 
 
 
435
  "currently-unhandled": {
436
  "version": "0.4.1",
437
  "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
438
  "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
439
  "dev": true,
440
  "requires": {
441
+ "array-find-index": "^1.0.1"
442
  }
443
  },
444
  "dashdash": {
447
  "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
448
  "dev": true,
449
  "requires": {
450
+ "assert-plus": "^1.0.0"
 
 
 
 
 
 
 
 
451
  }
452
  },
453
  "date-now": {
462
  "integrity": "sha1-GIdtC9pMGf5w3Tv0sDTygbEqQLY=",
463
  "dev": true,
464
  "requires": {
465
+ "time-zone": "^0.1.0"
466
  }
467
  },
468
  "dateformat": {
471
  "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
472
  "dev": true,
473
  "requires": {
474
+ "get-stdin": "^4.0.1",
475
+ "meow": "^3.3.0"
476
  }
477
  },
478
  "debug": {
479
+ "version": "3.2.6",
480
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
481
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
482
  "dev": true,
483
  "requires": {
484
+ "ms": "^2.1.1"
485
  }
486
  },
487
  "decamelize": {
502
  "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
503
  "dev": true
504
  },
 
 
 
 
 
 
505
  "dom-serializer": {
506
+ "version": "0.2.1",
507
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz",
508
+ "integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==",
509
  "dev": true,
510
  "requires": {
511
+ "domelementtype": "^2.0.1",
512
+ "entities": "^2.0.0"
513
  },
514
  "dependencies": {
515
  "domelementtype": {
516
+ "version": "2.0.1",
517
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
518
+ "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
519
  "dev": true
520
  },
521
  "entities": {
522
+ "version": "2.0.0",
523
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
524
+ "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==",
525
  "dev": true
526
  }
527
  }
528
  },
529
  "domelementtype": {
530
+ "version": "1.3.1",
531
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
532
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
533
  "dev": true
534
  },
535
  "domhandler": {
538
  "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
539
  "dev": true,
540
  "requires": {
541
+ "domelementtype": "1"
542
  }
543
  },
544
  "domutils": {
547
  "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
548
  "dev": true,
549
  "requires": {
550
+ "dom-serializer": "0",
551
+ "domelementtype": "1"
552
  }
553
  },
554
+ "duplexer": {
555
+ "version": "0.1.1",
556
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
557
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
558
+ "dev": true
 
 
 
 
559
  },
560
  "ecc-jsbn": {
561
+ "version": "0.1.2",
562
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
563
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
564
  "dev": true,
 
565
  "requires": {
566
+ "jsbn": "~0.1.0",
567
+ "safer-buffer": "^2.1.0"
568
  }
569
  },
 
 
 
 
 
 
570
  "entities": {
571
  "version": "1.0.0",
572
  "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
573
  "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=",
574
  "dev": true
575
  },
576
+ "error": {
577
+ "version": "7.0.2",
578
+ "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz",
579
+ "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=",
580
+ "dev": true,
581
+ "requires": {
582
+ "string-template": "~0.2.1",
583
+ "xtend": "~4.0.0"
584
+ }
585
+ },
586
  "error-ex": {
587
+ "version": "1.3.2",
588
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
589
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
590
  "dev": true,
591
  "requires": {
592
+ "is-arrayish": "^0.2.1"
593
  }
594
  },
595
  "escape-string-regexp": {
599
  "dev": true
600
  },
601
  "esprima": {
602
+ "version": "4.0.1",
603
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
604
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
605
  "dev": true
606
  },
607
  "eventemitter2": {
617
  "dev": true
618
  },
619
  "extend": {
620
+ "version": "3.0.2",
621
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
622
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
623
  "dev": true
624
  },
625
  "extsprintf": {
628
  "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
629
  "dev": true
630
  },
631
+ "fast-deep-equal": {
632
+ "version": "2.0.1",
633
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
634
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
635
+ "dev": true
636
+ },
637
+ "fast-json-stable-stringify": {
638
+ "version": "2.0.0",
639
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
640
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
641
+ "dev": true
642
+ },
643
  "faye-websocket": {
644
  "version": "0.10.0",
645
  "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
646
  "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
647
  "dev": true,
648
  "requires": {
649
+ "websocket-driver": ">=0.5.1"
650
  }
651
  },
652
  "figures": {
655
  "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
656
  "dev": true,
657
  "requires": {
658
+ "escape-string-regexp": "^1.0.5",
659
+ "object-assign": "^4.1.0"
660
  }
661
  },
662
  "find-up": {
665
  "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
666
  "dev": true,
667
  "requires": {
668
+ "path-exists": "^2.0.0",
669
+ "pinkie-promise": "^2.0.0"
670
  }
671
  },
672
  "findup-sync": {
675
  "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
676
  "dev": true,
677
  "requires": {
678
+ "glob": "~5.0.0"
679
  },
680
  "dependencies": {
681
  "glob": {
684
  "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
685
  "dev": true,
686
  "requires": {
687
+ "inflight": "^1.0.4",
688
+ "inherits": "2",
689
+ "minimatch": "2 || 3",
690
+ "once": "^1.3.0",
691
+ "path-is-absolute": "^1.0.0"
692
  }
693
  }
694
  }
700
  "dev": true
701
  },
702
  "form-data": {
703
+ "version": "2.3.3",
704
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
705
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
706
  "dev": true,
707
  "requires": {
708
+ "asynckit": "^0.4.0",
709
+ "combined-stream": "^1.0.6",
710
+ "mime-types": "^2.1.12"
711
  }
712
  },
713
  "fs.realpath": {
717
  "dev": true
718
  },
719
  "fstream": {
720
+ "version": "1.0.12",
721
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
722
+ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
723
  "dev": true,
724
  "requires": {
725
+ "graceful-fs": "^4.1.2",
726
+ "inherits": "~2.0.0",
727
+ "mkdirp": ">=0.5 0",
728
+ "rimraf": "2"
729
  }
730
  },
731
  "gauge": {
734
  "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
735
  "dev": true,
736
  "requires": {
737
+ "aproba": "^1.0.3",
738
+ "console-control-strings": "^1.0.0",
739
+ "has-unicode": "^2.0.0",
740
+ "object-assign": "^4.1.0",
741
+ "signal-exit": "^3.0.0",
742
+ "string-width": "^1.0.1",
743
+ "strip-ansi": "^3.0.1",
744
+ "wide-align": "^1.1.0"
745
  }
746
  },
747
  "gaze": {
748
+ "version": "1.1.3",
749
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
750
+ "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
751
  "dev": true,
752
  "requires": {
753
+ "globule": "^1.0.0"
754
  }
755
  },
756
  "get-caller-file": {
757
+ "version": "1.0.3",
758
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
759
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
760
  "dev": true
761
  },
762
  "get-stdin": {
777
  "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
778
  "dev": true,
779
  "requires": {
780
+ "assert-plus": "^1.0.0"
 
 
 
 
 
 
 
 
781
  }
782
  },
783
  "glob": {
786
  "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
787
  "dev": true,
788
  "requires": {
789
+ "fs.realpath": "^1.0.0",
790
+ "inflight": "^1.0.4",
791
+ "inherits": "2",
792
+ "minimatch": "^3.0.2",
793
+ "once": "^1.3.0",
794
+ "path-is-absolute": "^1.0.0"
795
  }
796
  },
797
  "globule": {
798
+ "version": "1.2.1",
799
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
800
+ "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
801
  "dev": true,
802
  "requires": {
803
+ "glob": "~7.1.1",
804
+ "lodash": "~4.17.10",
805
+ "minimatch": "~3.0.2"
806
  },
807
  "dependencies": {
808
  "glob": {
809
+ "version": "7.1.4",
810
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
811
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
812
  "dev": true,
813
  "requires": {
814
+ "fs.realpath": "^1.0.0",
815
+ "inflight": "^1.0.4",
816
+ "inherits": "2",
817
+ "minimatch": "^3.0.4",
818
+ "once": "^1.3.0",
819
+ "path-is-absolute": "^1.0.0"
820
  }
821
  }
822
  }
823
  },
824
  "graceful-fs": {
825
+ "version": "4.2.0",
826
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
827
+ "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
828
  "dev": true
829
  },
830
  "grunt": {
831
+ "version": "1.0.4",
832
+ "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.4.tgz",
833
+ "integrity": "sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ==",
834
+ "dev": true,
835
+ "requires": {
836
+ "coffeescript": "~1.10.0",
837
+ "dateformat": "~1.0.12",
838
+ "eventemitter2": "~0.4.13",
839
+ "exit": "~0.1.1",
840
+ "findup-sync": "~0.3.0",
841
+ "glob": "~7.0.0",
842
+ "grunt-cli": "~1.2.0",
843
+ "grunt-known-options": "~1.1.0",
844
+ "grunt-legacy-log": "~2.0.0",
845
+ "grunt-legacy-util": "~1.1.1",
846
+ "iconv-lite": "~0.4.13",
847
+ "js-yaml": "~3.13.0",
848
+ "minimatch": "~3.0.2",
849
+ "mkdirp": "~0.5.1",
850
+ "nopt": "~3.0.6",
851
+ "path-is-absolute": "~1.0.0",
852
+ "rimraf": "~2.6.2"
853
  },
854
  "dependencies": {
855
  "grunt-cli": {
858
  "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
859
  "dev": true,
860
  "requires": {
861
+ "findup-sync": "~0.3.0",
862
+ "grunt-known-options": "~1.1.0",
863
+ "nopt": "~3.0.6",
864
+ "resolve": "~1.1.0"
865
  }
866
+ },
867
+ "resolve": {
868
+ "version": "1.1.7",
869
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
870
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
871
+ "dev": true
872
  }
873
  }
874
  },
875
  "grunt-contrib-jshint": {
876
+ "version": "2.1.0",
877
+ "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-2.1.0.tgz",
878
+ "integrity": "sha512-65S2/C/6RfjY/umTxfwXXn+wVvaYmykHkHSsW6Q6rhkbv3oudTEgqnFFZvWzWCoHUb+3GMZLbP3oSrNyvshmIQ==",
879
  "dev": true,
880
  "requires": {
881
+ "chalk": "^2.4.2",
882
+ "hooker": "^0.2.3",
883
+ "jshint": "~2.10.2"
884
  }
885
  },
886
  "grunt-contrib-uglify": {
887
+ "version": "4.0.1",
888
+ "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-4.0.1.tgz",
889
+ "integrity": "sha512-dwf8/+4uW1+7pH72WButOEnzErPGmtUvc8p08B0eQS/6ON0WdeQu0+WFeafaPTbbY1GqtS25lsHWaDeiTQNWPg==",
890
  "dev": true,
891
  "requires": {
892
+ "chalk": "^2.4.1",
893
+ "maxmin": "^2.1.0",
894
+ "uglify-js": "^3.5.0",
895
+ "uri-path": "^1.0.0"
896
  }
897
  },
898
  "grunt-contrib-watch": {
899
+ "version": "1.1.0",
900
+ "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz",
901
+ "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==",
902
  "dev": true,
903
  "requires": {
904
+ "async": "^2.6.0",
905
+ "gaze": "^1.1.0",
906
+ "lodash": "^4.17.10",
907
+ "tiny-lr": "^1.1.1"
908
+ },
909
+ "dependencies": {
910
+ "async": {
911
+ "version": "2.6.3",
912
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
913
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
914
+ "dev": true,
915
+ "requires": {
916
+ "lodash": "^4.17.14"
917
+ }
918
+ }
919
  }
920
  },
921
  "grunt-known-options": {
922
+ "version": "1.1.1",
923
+ "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz",
924
+ "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==",
925
  "dev": true
926
  },
927
  "grunt-legacy-log": {
928
+ "version": "2.0.0",
929
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz",
930
+ "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==",
931
  "dev": true,
932
  "requires": {
933
+ "colors": "~1.1.2",
934
+ "grunt-legacy-log-utils": "~2.0.0",
935
+ "hooker": "~0.2.3",
936
+ "lodash": "~4.17.5"
937
  }
938
  },
939
  "grunt-legacy-log-utils": {
940
+ "version": "2.0.1",
941
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz",
942
+ "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==",
943
  "dev": true,
944
  "requires": {
945
+ "chalk": "~2.4.1",
946
+ "lodash": "~4.17.10"
 
 
 
 
 
 
 
 
947
  }
948
  },
949
  "grunt-legacy-util": {
950
+ "version": "1.1.1",
951
+ "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz",
952
+ "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==",
953
  "dev": true,
954
  "requires": {
955
+ "async": "~1.5.2",
956
+ "exit": "~0.1.1",
957
+ "getobject": "~0.1.0",
958
+ "hooker": "~0.2.3",
959
+ "lodash": "~4.17.10",
960
+ "underscore.string": "~3.3.4",
961
+ "which": "~1.3.0"
 
 
 
 
 
 
 
 
962
  }
963
  },
964
  "grunt-phplint": {
967
  "integrity": "sha1-bb4uauxTqiKc+sCtmnyZ4kGEhI0=",
968
  "dev": true,
969
  "requires": {
970
+ "cache-swap": "~0.3.0",
971
+ "grunt": "~0.4.1"
972
  },
973
  "dependencies": {
974
  "argparse": {
977
  "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=",
978
  "dev": true,
979
  "requires": {
980
+ "underscore": "~1.7.0",
981
+ "underscore.string": "~2.4.0"
982
  },
983
  "dependencies": {
984
  "underscore.string": {
1025
  "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=",
1026
  "dev": true,
1027
  "requires": {
1028
+ "glob": "~3.2.9",
1029
+ "lodash": "~2.4.1"
1030
  },
1031
  "dependencies": {
1032
  "glob": {
1035
  "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
1036
  "dev": true,
1037
  "requires": {
1038
+ "inherits": "2",
1039
+ "minimatch": "0.3"
1040
  }
1041
  },
1042
  "lodash": {
1051
  "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
1052
  "dev": true,
1053
  "requires": {
1054
+ "lru-cache": "2",
1055
+ "sigmund": "~1.0.0"
1056
  }
1057
  }
1058
  }
1063
  "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
1064
  "dev": true,
1065
  "requires": {
1066
+ "graceful-fs": "~1.2.0",
1067
+ "inherits": "1",
1068
+ "minimatch": "~0.2.11"
1069
  },
1070
  "dependencies": {
1071
  "inherits": {
1088
  "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=",
1089
  "dev": true,
1090
  "requires": {
1091
+ "async": "~0.1.22",
1092
+ "coffee-script": "~1.3.3",
1093
+ "colors": "~0.6.2",
1094
  "dateformat": "1.0.2-1.2.3",
1095
+ "eventemitter2": "~0.4.13",
1096
+ "exit": "~0.1.1",
1097
+ "findup-sync": "~0.1.2",
1098
+ "getobject": "~0.1.0",
1099
+ "glob": "~3.1.21",
1100
+ "grunt-legacy-log": "~0.1.0",
1101
+ "grunt-legacy-util": "~0.2.0",
1102
+ "hooker": "~0.2.3",
1103
+ "iconv-lite": "~0.2.11",
1104
+ "js-yaml": "~2.0.5",
1105
+ "lodash": "~0.9.2",
1106
+ "minimatch": "~0.2.12",
1107
+ "nopt": "~1.0.10",
1108
+ "rimraf": "~2.2.8",
1109
+ "underscore.string": "~2.2.1",
1110
+ "which": "~1.0.5"
1111
  }
1112
  },
1113
  "grunt-legacy-log": {
1116
  "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=",
1117
  "dev": true,
1118
  "requires": {
1119
+ "colors": "~0.6.2",
1120
+ "grunt-legacy-log-utils": "~0.1.1",
1121
+ "hooker": "~0.2.3",
1122
+ "lodash": "~2.4.1",
1123
+ "underscore.string": "~2.3.3"
1124
  },
1125
  "dependencies": {
1126
  "lodash": {
1143
  "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=",
1144
  "dev": true,
1145
  "requires": {
1146
+ "colors": "~0.6.2",
1147
+ "lodash": "~2.4.1",
1148
+ "underscore.string": "~2.3.3"
1149
  },
1150
  "dependencies": {
1151
  "lodash": {
1168
  "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=",
1169
  "dev": true,
1170
  "requires": {
1171
+ "async": "~0.1.22",
1172
+ "exit": "~0.1.1",
1173
+ "getobject": "~0.1.0",
1174
+ "hooker": "~0.2.3",
1175
+ "lodash": "~0.9.2",
1176
+ "underscore.string": "~2.2.1",
1177
+ "which": "~1.0.5"
1178
  }
1179
  },
1180
  "iconv-lite": {
1189
  "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=",
1190
  "dev": true,
1191
  "requires": {
1192
+ "argparse": "~ 0.1.11",
1193
+ "esprima": "~ 1.0.2"
1194
  }
1195
  },
1196
  "lodash": {
1205
  "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
1206
  "dev": true,
1207
  "requires": {
1208
+ "lru-cache": "2",
1209
+ "sigmund": "~1.0.0"
1210
  }
1211
  },
1212
  "nopt": {
1215
  "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
1216
  "dev": true,
1217
  "requires": {
1218
+ "abbrev": "1"
1219
  }
1220
  },
1221
+ "rimraf": {
1222
+ "version": "2.2.8",
1223
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
1224
+ "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
1225
+ "dev": true
1226
+ },
1227
  "underscore.string": {
1228
  "version": "2.2.1",
1229
  "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz",
1239
  }
1240
  },
1241
  "grunt-sass": {
1242
+ "version": "3.0.2",
1243
+ "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.0.2.tgz",
1244
+ "integrity": "sha512-Ogq4cWqBre71gZIkgxIxevgzZHSIIsrKu/5yvPDl4Mvib0A4TRTJEQUdpQ0YV1iai0DPjayz02vDJE6KUVHQ2w==",
1245
+ "dev": true
 
 
 
 
 
1246
  },
1247
  "gzip-size": {
1248
+ "version": "3.0.0",
1249
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz",
1250
+ "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=",
1251
  "dev": true,
1252
  "requires": {
1253
+ "duplexer": "^0.1.1"
 
1254
  }
1255
  },
1256
+ "har-schema": {
1257
+ "version": "2.0.0",
1258
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
1259
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
1260
+ "dev": true
1261
+ },
1262
  "har-validator": {
1263
+ "version": "5.1.3",
1264
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
1265
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
1266
  "dev": true,
1267
  "requires": {
1268
+ "ajv": "^6.5.5",
1269
+ "har-schema": "^2.0.0"
 
 
1270
  }
1271
  },
1272
  "has-ansi": {
1275
  "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
1276
  "dev": true,
1277
  "requires": {
1278
+ "ansi-regex": "^2.0.0"
1279
  }
1280
  },
1281
+ "has-flag": {
1282
+ "version": "3.0.0",
1283
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
1284
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
1285
+ "dev": true
1286
+ },
1287
  "has-unicode": {
1288
  "version": "2.0.1",
1289
  "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
1290
  "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
1291
  "dev": true
1292
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1293
  "hooker": {
1294
  "version": "0.2.3",
1295
  "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
1297
  "dev": true
1298
  },
1299
  "hosted-git-info": {
1300
+ "version": "2.7.1",
1301
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
1302
+ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
1303
  "dev": true
1304
  },
1305
  "htmlparser2": {
1308
  "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
1309
  "dev": true,
1310
  "requires": {
1311
+ "domelementtype": "1",
1312
+ "domhandler": "2.3",
1313
+ "domutils": "1.5",
1314
+ "entities": "1.0",
1315
+ "readable-stream": "1.1"
 
 
 
 
 
 
 
 
 
 
1316
  }
1317
  },
1318
  "http-parser-js": {
1319
+ "version": "0.4.10",
1320
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
1321
+ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
1322
  "dev": true
1323
  },
1324
  "http-signature": {
1325
+ "version": "1.2.0",
1326
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
1327
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
1328
  "dev": true,
1329
  "requires": {
1330
+ "assert-plus": "^1.0.0",
1331
+ "jsprim": "^1.2.2",
1332
+ "sshpk": "^1.7.0"
1333
  }
1334
  },
1335
  "iconv-lite": {
1336
+ "version": "0.4.24",
1337
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
1338
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
1339
  "dev": true,
1340
  "requires": {
1341
+ "safer-buffer": ">= 2.1.2 < 3"
1342
  }
1343
  },
1344
  "in-publish": {
1353
  "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
1354
  "dev": true,
1355
  "requires": {
1356
+ "repeating": "^2.0.0"
1357
  }
1358
  },
1359
  "inflight": {
1362
  "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1363
  "dev": true,
1364
  "requires": {
1365
+ "once": "^1.3.0",
1366
+ "wrappy": "1"
1367
  }
1368
  },
1369
  "inherits": {
1370
+ "version": "2.0.4",
1371
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1372
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1373
  "dev": true
1374
  },
1375
  "invert-kv": {
1390
  "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
1391
  "dev": true
1392
  },
 
 
 
 
 
 
 
 
 
1393
  "is-finite": {
1394
  "version": "1.0.2",
1395
  "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
1396
  "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
1397
  "dev": true,
1398
  "requires": {
1399
+ "number-is-nan": "^1.0.0"
1400
  }
1401
  },
1402
  "is-fullwidth-code-point": {
1405
  "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
1406
  "dev": true,
1407
  "requires": {
1408
+ "number-is-nan": "^1.0.0"
1409
  }
1410
  },
1411
+ "is-typedarray": {
1412
  "version": "1.0.0",
1413
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
1414
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1415
  "dev": true
1416
  },
1417
  "is-utf8": {
1439
  "dev": true
1440
  },
1441
  "js-base64": {
1442
+ "version": "2.5.1",
1443
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
1444
+ "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
1445
  "dev": true
1446
  },
1447
  "js-yaml": {
1448
+ "version": "3.13.1",
1449
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
1450
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
1451
  "dev": true,
1452
  "requires": {
1453
+ "argparse": "^1.0.7",
1454
+ "esprima": "^4.0.0"
1455
  }
1456
  },
1457
  "jsbn": {
1458
  "version": "0.1.1",
1459
  "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
1460
  "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
1461
+ "dev": true
 
1462
  },
1463
  "jshint": {
1464
+ "version": "2.10.2",
1465
+ "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz",
1466
+ "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==",
1467
  "dev": true,
1468
  "requires": {
1469
+ "cli": "~1.0.0",
1470
+ "console-browserify": "1.1.x",
1471
+ "exit": "0.1.x",
1472
+ "htmlparser2": "3.8.x",
1473
+ "lodash": "~4.17.11",
1474
+ "minimatch": "~3.0.2",
1475
+ "shelljs": "0.3.x",
1476
+ "strip-json-comments": "1.0.x"
 
 
 
 
 
 
 
 
1477
  }
1478
  },
1479
  "jshint-stylish": {
1482
  "integrity": "sha1-JCCCosA1rgP9gQROBXDMQgjPbmE=",
1483
  "dev": true,
1484
  "requires": {
1485
+ "beeper": "^1.1.0",
1486
+ "chalk": "^1.0.0",
1487
+ "log-symbols": "^1.0.0",
1488
+ "plur": "^2.1.0",
1489
+ "string-length": "^1.0.0",
1490
+ "text-table": "^0.2.0"
1491
+ },
1492
+ "dependencies": {
1493
+ "ansi-styles": {
1494
+ "version": "2.2.1",
1495
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
1496
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
1497
+ "dev": true
1498
+ },
1499
+ "chalk": {
1500
+ "version": "1.1.3",
1501
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
1502
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
1503
+ "dev": true,
1504
+ "requires": {
1505
+ "ansi-styles": "^2.2.1",
1506
+ "escape-string-regexp": "^1.0.2",
1507
+ "has-ansi": "^2.0.0",
1508
+ "strip-ansi": "^3.0.0",
1509
+ "supports-color": "^2.0.0"
1510
+ }
1511
+ },
1512
+ "supports-color": {
1513
+ "version": "2.0.0",
1514
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
1515
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
1516
+ "dev": true
1517
+ }
1518
  }
1519
  },
1520
  "json-schema": {
1523
  "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
1524
  "dev": true
1525
  },
1526
+ "json-schema-traverse": {
1527
+ "version": "0.4.1",
1528
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1529
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
1530
+ "dev": true
1531
+ },
1532
  "json-stringify-safe": {
1533
  "version": "5.0.1",
1534
  "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
1535
  "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
1536
  "dev": true
1537
  },
 
 
 
 
 
 
1538
  "jsprim": {
1539
  "version": "1.4.1",
1540
  "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
1545
  "extsprintf": "1.3.0",
1546
  "json-schema": "0.2.3",
1547
  "verror": "1.10.0"
 
 
 
 
 
 
 
 
1548
  }
1549
  },
1550
  "lcid": {
1553
  "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
1554
  "dev": true,
1555
  "requires": {
1556
+ "invert-kv": "^1.0.0"
1557
  }
1558
  },
1559
  "livereload-js": {
1560
+ "version": "2.4.0",
1561
+ "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz",
1562
+ "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==",
1563
  "dev": true
1564
  },
1565
  "load-grunt-tasks": {
1566
+ "version": "5.1.0",
1567
+ "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-5.1.0.tgz",
1568
+ "integrity": "sha512-oNj0Jlka1TsfDe+9He0kcA1cRln+TMoTsEByW7ij6kyktNLxBKJtslCFEvFrLC2Dj0S19IWJh3fOCIjLby2Xrg==",
1569
  "dev": true,
1570
  "requires": {
1571
+ "arrify": "^2.0.1",
1572
+ "multimatch": "^4.0.0",
1573
+ "pkg-up": "^3.1.0",
1574
+ "resolve-pkg": "^2.0.0"
1575
  }
1576
  },
1577
  "load-json-file": {
1580
  "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
1581
  "dev": true,
1582
  "requires": {
1583
+ "graceful-fs": "^4.1.2",
1584
+ "parse-json": "^2.2.0",
1585
+ "pify": "^2.0.0",
1586
+ "pinkie-promise": "^2.0.0",
1587
+ "strip-bom": "^2.0.0"
1588
  }
1589
  },
1590
+ "locate-path": {
1591
+ "version": "3.0.0",
1592
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
1593
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
1594
+ "dev": true,
1595
+ "requires": {
1596
+ "p-locate": "^3.0.0",
1597
+ "path-exists": "^3.0.0"
1598
+ },
1599
+ "dependencies": {
1600
+ "path-exists": {
1601
+ "version": "3.0.0",
1602
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
1603
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
1604
+ "dev": true
1605
+ }
1606
+ }
1607
  },
1608
+ "lodash": {
1609
+ "version": "4.17.15",
1610
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
1611
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
1612
  "dev": true
1613
  },
1614
  "log-symbols": {
1617
  "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
1618
  "dev": true,
1619
  "requires": {
1620
+ "chalk": "^1.0.0"
1621
+ },
1622
+ "dependencies": {
1623
+ "ansi-styles": {
1624
+ "version": "2.2.1",
1625
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
1626
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
1627
+ "dev": true
1628
+ },
1629
+ "chalk": {
1630
+ "version": "1.1.3",
1631
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
1632
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
1633
+ "dev": true,
1634
+ "requires": {
1635
+ "ansi-styles": "^2.2.1",
1636
+ "escape-string-regexp": "^1.0.2",
1637
+ "has-ansi": "^2.0.0",
1638
+ "strip-ansi": "^3.0.0",
1639
+ "supports-color": "^2.0.0"
1640
+ }
1641
+ },
1642
+ "supports-color": {
1643
+ "version": "2.0.0",
1644
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
1645
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
1646
+ "dev": true
1647
+ }
1648
  }
1649
  },
1650
  "loud-rejection": {
1653
  "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
1654
  "dev": true,
1655
  "requires": {
1656
+ "currently-unhandled": "^0.4.1",
1657
+ "signal-exit": "^3.0.0"
1658
  }
1659
  },
1660
  "lru-cache": {
1670
  "dev": true
1671
  },
1672
  "maxmin": {
1673
+ "version": "2.1.0",
1674
+ "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz",
1675
+ "integrity": "sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=",
1676
  "dev": true,
1677
  "requires": {
1678
+ "chalk": "^1.0.0",
1679
+ "figures": "^1.0.1",
1680
+ "gzip-size": "^3.0.0",
1681
+ "pretty-bytes": "^3.0.0"
1682
+ },
1683
+ "dependencies": {
1684
+ "ansi-styles": {
1685
+ "version": "2.2.1",
1686
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
1687
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
1688
+ "dev": true
1689
+ },
1690
+ "chalk": {
1691
+ "version": "1.1.3",
1692
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
1693
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
1694
+ "dev": true,
1695
+ "requires": {
1696
+ "ansi-styles": "^2.2.1",
1697
+ "escape-string-regexp": "^1.0.2",
1698
+ "has-ansi": "^2.0.0",
1699
+ "strip-ansi": "^3.0.0",
1700
+ "supports-color": "^2.0.0"
1701
+ }
1702
+ },
1703
+ "supports-color": {
1704
+ "version": "2.0.0",
1705
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
1706
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
1707
+ "dev": true
1708
+ }
1709
  }
1710
  },
 
 
 
 
 
 
1711
  "meow": {
1712
  "version": "3.7.0",
1713
  "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
1714
  "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
1715
  "dev": true,
1716
  "requires": {
1717
+ "camelcase-keys": "^2.0.0",
1718
+ "decamelize": "^1.1.2",
1719
+ "loud-rejection": "^1.0.0",
1720
+ "map-obj": "^1.0.1",
1721
+ "minimist": "^1.1.3",
1722
+ "normalize-package-data": "^2.3.4",
1723
+ "object-assign": "^4.0.1",
1724
+ "read-pkg-up": "^1.0.1",
1725
+ "redent": "^1.0.0",
1726
+ "trim-newlines": "^1.0.0"
1727
  }
1728
  },
1729
  "mime-db": {
1730
+ "version": "1.40.0",
1731
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
1732
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
1733
  "dev": true
1734
  },
1735
  "mime-types": {
1736
+ "version": "2.1.24",
1737
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
1738
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
1739
  "dev": true,
1740
  "requires": {
1741
+ "mime-db": "1.40.0"
1742
  }
1743
  },
1744
  "minimatch": {
1747
  "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
1748
  "dev": true,
1749
  "requires": {
1750
+ "brace-expansion": "^1.1.7"
1751
  }
1752
  },
1753
  "minimist": {
1774
  }
1775
  },
1776
  "ms": {
1777
+ "version": "2.1.2",
1778
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1779
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
1780
  "dev": true
1781
  },
1782
  "multimatch": {
1783
+ "version": "4.0.0",
1784
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz",
1785
+ "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==",
1786
  "dev": true,
1787
  "requires": {
1788
+ "@types/minimatch": "^3.0.3",
1789
+ "array-differ": "^3.0.0",
1790
+ "array-union": "^2.1.0",
1791
+ "arrify": "^2.0.1",
1792
+ "minimatch": "^3.0.4"
1793
  }
1794
  },
1795
  "nan": {
1796
+ "version": "2.14.0",
1797
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
1798
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
1799
  "dev": true
1800
  },
1801
  "node-gyp": {
1802
+ "version": "3.8.0",
1803
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
1804
+ "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
1805
+ "dev": true,
1806
+ "requires": {
1807
+ "fstream": "^1.0.0",
1808
+ "glob": "^7.0.3",
1809
+ "graceful-fs": "^4.1.2",
1810
+ "mkdirp": "^0.5.0",
1811
+ "nopt": "2 || 3",
1812
+ "npmlog": "0 || 1 || 2 || 3 || 4",
1813
+ "osenv": "0",
1814
+ "request": "^2.87.0",
1815
+ "rimraf": "2",
1816
+ "semver": "~5.3.0",
1817
+ "tar": "^2.0.0",
1818
+ "which": "1"
 
1819
  },
1820
  "dependencies": {
1821
  "semver": {
1827
  }
1828
  },
1829
  "node-sass": {
1830
+ "version": "4.12.0",
1831
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
1832
+ "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
1833
+ "dev": true,
1834
+ "requires": {
1835
+ "async-foreach": "^0.1.3",
1836
+ "chalk": "^1.1.1",
1837
+ "cross-spawn": "^3.0.0",
1838
+ "gaze": "^1.0.0",
1839
+ "get-stdin": "^4.0.1",
1840
+ "glob": "^7.0.3",
1841
+ "in-publish": "^2.0.0",
1842
+ "lodash": "^4.17.11",
1843
+ "meow": "^3.7.0",
1844
+ "mkdirp": "^0.5.1",
1845
+ "nan": "^2.13.2",
1846
+ "node-gyp": "^3.8.0",
1847
+ "npmlog": "^4.0.0",
1848
+ "request": "^2.88.0",
1849
+ "sass-graph": "^2.2.4",
1850
+ "stdout-stream": "^1.4.0",
1851
+ "true-case-path": "^1.0.2"
1852
+ },
1853
+ "dependencies": {
1854
+ "ansi-styles": {
1855
+ "version": "2.2.1",
1856
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
1857
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
1858
+ "dev": true
1859
+ },
1860
+ "chalk": {
1861
+ "version": "1.1.3",
1862
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
1863
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
1864
+ "dev": true,
1865
+ "requires": {
1866
+ "ansi-styles": "^2.2.1",
1867
+ "escape-string-regexp": "^1.0.2",
1868
+ "has-ansi": "^2.0.0",
1869
+ "strip-ansi": "^3.0.0",
1870
+ "supports-color": "^2.0.0"
1871
+ }
1872
+ },
1873
+ "supports-color": {
1874
+ "version": "2.0.0",
1875
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
1876
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
1877
+ "dev": true
1878
+ }
1879
  }
1880
  },
1881
  "nopt": {
1884
  "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
1885
  "dev": true,
1886
  "requires": {
1887
+ "abbrev": "1"
1888
  }
1889
  },
1890
  "normalize-package-data": {
1891
+ "version": "2.5.0",
1892
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
1893
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
1894
  "dev": true,
1895
  "requires": {
1896
+ "hosted-git-info": "^2.1.4",
1897
+ "resolve": "^1.10.0",
1898
+ "semver": "2 || 3 || 4 || 5",
1899
+ "validate-npm-package-license": "^3.0.1"
1900
  }
1901
  },
1902
  "npmlog": {
1905
  "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
1906
  "dev": true,
1907
  "requires": {
1908
+ "are-we-there-yet": "~1.1.2",
1909
+ "console-control-strings": "~1.1.0",
1910
+ "gauge": "~2.7.3",
1911
+ "set-blocking": "~2.0.0"
1912
  }
1913
  },
1914
  "number-is-nan": {
1918
  "dev": true
1919
  },
1920
  "oauth-sign": {
1921
+ "version": "0.9.0",
1922
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
1923
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
1924
  "dev": true
1925
  },
1926
  "object-assign": {
1929
  "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
1930
  "dev": true
1931
  },
 
 
 
 
 
 
 
 
 
1932
  "once": {
1933
  "version": "1.4.0",
1934
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1935
  "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1936
  "dev": true,
1937
  "requires": {
1938
+ "wrappy": "1"
1939
  }
1940
  },
 
 
 
 
 
 
1941
  "os-homedir": {
1942
  "version": "1.0.2",
1943
  "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
1950
  "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
1951
  "dev": true,
1952
  "requires": {
1953
+ "lcid": "^1.0.0"
1954
  }
1955
  },
1956
  "os-tmpdir": {
1965
  "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
1966
  "dev": true,
1967
  "requires": {
1968
+ "os-homedir": "^1.0.0",
1969
+ "os-tmpdir": "^1.0.0"
1970
  }
1971
  },
1972
+ "p-limit": {
1973
+ "version": "2.2.0",
1974
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
1975
+ "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
1976
+ "dev": true,
1977
+ "requires": {
1978
+ "p-try": "^2.0.0"
1979
+ }
1980
+ },
1981
+ "p-locate": {
1982
+ "version": "3.0.0",
1983
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
1984
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
1985
+ "dev": true,
1986
+ "requires": {
1987
+ "p-limit": "^2.0.0"
1988
+ }
1989
+ },
1990
+ "p-try": {
1991
+ "version": "2.2.0",
1992
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
1993
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
1994
  "dev": true
1995
  },
1996
  "parse-json": {
1999
  "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
2000
  "dev": true,
2001
  "requires": {
2002
+ "error-ex": "^1.2.0"
2003
  }
2004
  },
2005
  "parse-ms": {
2008
  "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=",
2009
  "dev": true
2010
  },
 
 
 
 
 
 
2011
  "path-exists": {
2012
  "version": "2.1.0",
2013
  "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
2014
  "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
2015
  "dev": true,
2016
  "requires": {
2017
+ "pinkie-promise": "^2.0.0"
2018
  }
2019
  },
2020
  "path-is-absolute": {
2023
  "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
2024
  "dev": true
2025
  },
2026
+ "path-parse": {
2027
+ "version": "1.0.6",
2028
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
2029
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
2030
+ "dev": true
2031
+ },
2032
  "path-type": {
2033
  "version": "1.1.0",
2034
  "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
2035
  "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
2036
  "dev": true,
2037
  "requires": {
2038
+ "graceful-fs": "^4.1.2",
2039
+ "pify": "^2.0.0",
2040
+ "pinkie-promise": "^2.0.0"
2041
  }
2042
  },
2043
+ "performance-now": {
2044
+ "version": "2.1.0",
2045
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
2046
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
2047
+ "dev": true
2048
+ },
2049
  "pify": {
2050
  "version": "2.3.0",
2051
  "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
2064
  "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
2065
  "dev": true,
2066
  "requires": {
2067
+ "pinkie": "^2.0.0"
2068
  }
2069
  },
2070
  "pkg-up": {
2071
+ "version": "3.1.0",
2072
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
2073
+ "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
2074
  "dev": true,
2075
  "requires": {
2076
+ "find-up": "^3.0.0"
2077
+ },
2078
+ "dependencies": {
2079
+ "find-up": {
2080
+ "version": "3.0.0",
2081
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
2082
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
2083
+ "dev": true,
2084
+ "requires": {
2085
+ "locate-path": "^3.0.0"
2086
+ }
2087
+ }
2088
  }
2089
  },
2090
  "plur": {
2093
  "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=",
2094
  "dev": true,
2095
  "requires": {
2096
+ "irregular-plurals": "^1.0.0"
2097
  }
2098
  },
2099
  "pretty-bytes": {
2100
+ "version": "3.0.1",
2101
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz",
2102
+ "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=",
2103
  "dev": true,
2104
  "requires": {
2105
+ "number-is-nan": "^1.0.0"
 
2106
  }
2107
  },
2108
  "pretty-ms": {
2111
  "integrity": "sha1-QlfCVt8/sLRR1q/6qwIYhBJpgdw=",
2112
  "dev": true,
2113
  "requires": {
2114
+ "is-finite": "^1.0.1",
2115
+ "parse-ms": "^1.0.0",
2116
+ "plur": "^1.0.0"
2117
  },
2118
  "dependencies": {
2119
  "plur": {
2125
  }
2126
  },
2127
  "process-nextick-args": {
2128
+ "version": "2.0.1",
2129
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
2130
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
2131
  "dev": true
2132
  },
2133
  "pseudomap": {
2136
  "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
2137
  "dev": true
2138
  },
2139
+ "psl": {
2140
+ "version": "1.3.0",
2141
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz",
2142
+ "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==",
2143
+ "dev": true
2144
+ },
2145
  "punycode": {
2146
+ "version": "2.1.1",
2147
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
2148
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
2149
  "dev": true
2150
  },
2151
  "qs": {
2152
+ "version": "6.7.0",
2153
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
2154
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
2155
  "dev": true
2156
  },
2157
  "raw-body": {
2158
+ "version": "1.1.7",
2159
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz",
2160
+ "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=",
2161
  "dev": true,
2162
  "requires": {
2163
+ "bytes": "1",
2164
+ "string_decoder": "0.10"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2165
  }
2166
  },
2167
  "read-pkg": {
2170
  "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
2171
  "dev": true,
2172
  "requires": {
2173
+ "load-json-file": "^1.0.0",
2174
+ "normalize-package-data": "^2.3.2",
2175
+ "path-type": "^1.0.0"
2176
  }
2177
  },
2178
  "read-pkg-up": {
2181
  "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
2182
  "dev": true,
2183
  "requires": {
2184
+ "find-up": "^1.0.0",
2185
+ "read-pkg": "^1.0.0"
2186
  }
2187
  },
2188
  "readable-stream": {
2191
  "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
2192
  "dev": true,
2193
  "requires": {
2194
+ "core-util-is": "~1.0.0",
2195
+ "inherits": "~2.0.1",
2196
  "isarray": "0.0.1",
2197
+ "string_decoder": "~0.10.x"
2198
  }
2199
  },
2200
  "redent": {
2203
  "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
2204
  "dev": true,
2205
  "requires": {
2206
+ "indent-string": "^2.1.0",
2207
+ "strip-indent": "^1.0.1"
2208
  }
2209
  },
2210
  "repeating": {
2213
  "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
2214
  "dev": true,
2215
  "requires": {
2216
+ "is-finite": "^1.0.0"
2217
  }
2218
  },
2219
  "request": {
2220
+ "version": "2.88.0",
2221
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
2222
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
2223
+ "dev": true,
2224
+ "requires": {
2225
+ "aws-sign2": "~0.7.0",
2226
+ "aws4": "^1.8.0",
2227
+ "caseless": "~0.12.0",
2228
+ "combined-stream": "~1.0.6",
2229
+ "extend": "~3.0.2",
2230
+ "forever-agent": "~0.6.1",
2231
+ "form-data": "~2.3.2",
2232
+ "har-validator": "~5.1.0",
2233
+ "http-signature": "~1.2.0",
2234
+ "is-typedarray": "~1.0.0",
2235
+ "isstream": "~0.1.2",
2236
+ "json-stringify-safe": "~5.0.1",
2237
+ "mime-types": "~2.1.19",
2238
+ "oauth-sign": "~0.9.0",
2239
+ "performance-now": "^2.1.0",
2240
+ "qs": "~6.5.2",
2241
+ "safe-buffer": "^5.1.2",
2242
+ "tough-cookie": "~2.4.3",
2243
+ "tunnel-agent": "^0.6.0",
2244
+ "uuid": "^3.3.2"
2245
  },
2246
  "dependencies": {
2247
  "qs": {
2248
+ "version": "6.5.2",
2249
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
2250
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
2251
  "dev": true
2252
  }
2253
  }
2265
  "dev": true
2266
  },
2267
  "resolve": {
2268
+ "version": "1.12.0",
2269
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
2270
+ "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
2271
+ "dev": true,
2272
+ "requires": {
2273
+ "path-parse": "^1.0.6"
2274
+ }
2275
  },
2276
  "resolve-from": {
2277
+ "version": "5.0.0",
2278
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
2279
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
2280
  "dev": true
2281
  },
2282
  "resolve-pkg": {
2283
+ "version": "2.0.0",
2284
+ "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz",
2285
+ "integrity": "sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==",
2286
  "dev": true,
2287
  "requires": {
2288
+ "resolve-from": "^5.0.0"
2289
  }
2290
  },
2291
  "rimraf": {
2292
+ "version": "2.6.3",
2293
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
2294
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
2295
+ "dev": true,
2296
+ "requires": {
2297
+ "glob": "^7.1.3"
2298
+ },
2299
+ "dependencies": {
2300
+ "glob": {
2301
+ "version": "7.1.4",
2302
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
2303
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
2304
+ "dev": true,
2305
+ "requires": {
2306
+ "fs.realpath": "^1.0.0",
2307
+ "inflight": "^1.0.4",
2308
+ "inherits": "2",
2309
+ "minimatch": "^3.0.4",
2310
+ "once": "^1.3.0",
2311
+ "path-is-absolute": "^1.0.0"
2312
+ }
2313
+ }
2314
+ }
2315
  },
2316
  "safe-buffer": {
2317
+ "version": "5.2.0",
2318
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
2319
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
2320
+ "dev": true
2321
+ },
2322
+ "safe-json-parse": {
2323
+ "version": "1.0.1",
2324
+ "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz",
2325
+ "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=",
2326
  "dev": true
2327
  },
2328
  "safer-buffer": {
2337
  "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
2338
  "dev": true,
2339
  "requires": {
2340
+ "glob": "^7.0.0",
2341
+ "lodash": "^4.0.0",
2342
+ "scss-tokenizer": "^0.2.3",
2343
+ "yargs": "^7.0.0"
2344
  }
2345
  },
2346
  "scss-tokenizer": {
2349
  "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
2350
  "dev": true,
2351
  "requires": {
2352
+ "js-base64": "^2.1.8",
2353
+ "source-map": "^0.4.2"
2354
  },
2355
  "dependencies": {
2356
  "source-map": {
2359
  "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
2360
  "dev": true,
2361
  "requires": {
2362
+ "amdefine": ">=0.0.4"
2363
  }
2364
  }
2365
  }
2366
  },
2367
  "semver": {
2368
+ "version": "5.7.0",
2369
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
2370
+ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
2371
  "dev": true
2372
  },
2373
  "set-blocking": {
2376
  "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
2377
  "dev": true
2378
  },
 
 
 
 
 
 
2379
  "shelljs": {
2380
  "version": "0.3.0",
2381
  "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
2394
  "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
2395
  "dev": true
2396
  },
 
 
 
 
 
 
 
 
 
2397
  "source-map": {
2398
  "version": "0.6.1",
2399
  "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
2401
  "dev": true
2402
  },
2403
  "spdx-correct": {
2404
+ "version": "3.1.0",
2405
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
2406
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
2407
  "dev": true,
2408
  "requires": {
2409
+ "spdx-expression-parse": "^3.0.0",
2410
+ "spdx-license-ids": "^3.0.0"
2411
  }
2412
  },
2413
  "spdx-exceptions": {
2414
+ "version": "2.2.0",
2415
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
2416
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
2417
  "dev": true
2418
  },
2419
  "spdx-expression-parse": {
2422
  "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
2423
  "dev": true,
2424
  "requires": {
2425
+ "spdx-exceptions": "^2.1.0",
2426
+ "spdx-license-ids": "^3.0.0"
2427
  }
2428
  },
2429
  "spdx-license-ids": {
2430
+ "version": "3.0.5",
2431
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
2432
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
2433
  "dev": true
2434
  },
2435
  "sprintf-js": {
2436
+ "version": "1.1.2",
2437
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
2438
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
2439
  "dev": true
2440
  },
2441
  "sshpk": {
2442
+ "version": "1.16.1",
2443
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
2444
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
2445
  "dev": true,
2446
  "requires": {
2447
+ "asn1": "~0.2.3",
2448
+ "assert-plus": "^1.0.0",
2449
+ "bcrypt-pbkdf": "^1.0.0",
2450
+ "dashdash": "^1.12.0",
2451
+ "ecc-jsbn": "~0.1.1",
2452
+ "getpass": "^0.1.1",
2453
+ "jsbn": "~0.1.0",
2454
+ "safer-buffer": "^2.0.2",
2455
+ "tweetnacl": "~0.14.0"
 
 
 
 
 
 
 
2456
  }
2457
  },
 
 
 
 
 
 
2458
  "stdout-stream": {
2459
+ "version": "1.4.1",
2460
+ "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
2461
+ "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
2462
  "dev": true,
2463
  "requires": {
2464
+ "readable-stream": "^2.0.1"
2465
  },
2466
  "dependencies": {
2467
  "isarray": {
2476
  "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
2477
  "dev": true,
2478
  "requires": {
2479
+ "core-util-is": "~1.0.0",
2480
+ "inherits": "~2.0.3",
2481
+ "isarray": "~1.0.0",
2482
+ "process-nextick-args": "~2.0.0",
2483
+ "safe-buffer": "~5.1.1",
2484
+ "string_decoder": "~1.1.1",
2485
+ "util-deprecate": "~1.0.1"
2486
  }
2487
  },
2488
+ "safe-buffer": {
2489
+ "version": "5.1.2",
2490
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
2491
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
2492
+ "dev": true
2493
+ },
2494
  "string_decoder": {
2495
  "version": "1.1.1",
2496
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
2497
  "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
2498
  "dev": true,
2499
  "requires": {
2500
+ "safe-buffer": "~5.1.0"
2501
  }
2502
  }
2503
  }
2508
  "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=",
2509
  "dev": true,
2510
  "requires": {
2511
+ "strip-ansi": "^3.0.0"
2512
  }
2513
  },
2514
+ "string-template": {
2515
+ "version": "0.2.1",
2516
+ "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz",
2517
+ "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=",
2518
+ "dev": true
2519
+ },
2520
  "string-width": {
2521
  "version": "1.0.2",
2522
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
2523
  "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
2524
  "dev": true,
2525
  "requires": {
2526
+ "code-point-at": "^1.0.0",
2527
+ "is-fullwidth-code-point": "^1.0.0",
2528
+ "strip-ansi": "^3.0.0"
2529
  }
2530
  },
2531
  "string_decoder": {
2534
  "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
2535
  "dev": true
2536
  },
 
 
 
 
 
 
2537
  "strip-ansi": {
2538
  "version": "3.0.1",
2539
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
2540
  "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
2541
  "dev": true,
2542
  "requires": {
2543
+ "ansi-regex": "^2.0.0"
2544
  }
2545
  },
2546
  "strip-bom": {
2549
  "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
2550
  "dev": true,
2551
  "requires": {
2552
+ "is-utf8": "^0.2.0"
2553
  }
2554
  },
2555
  "strip-indent": {
2558
  "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
2559
  "dev": true,
2560
  "requires": {
2561
+ "get-stdin": "^4.0.1"
2562
  }
2563
  },
2564
  "strip-json-comments": {
2568
  "dev": true
2569
  },
2570
  "supports-color": {
2571
+ "version": "5.5.0",
2572
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
2573
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
2574
+ "dev": true,
2575
+ "requires": {
2576
+ "has-flag": "^3.0.0"
2577
+ }
2578
  },
2579
  "tar": {
2580
+ "version": "2.2.2",
2581
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
2582
+ "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
2583
  "dev": true,
2584
  "requires": {
2585
+ "block-stream": "*",
2586
+ "fstream": "^1.0.12",
2587
+ "inherits": "2"
2588
  }
2589
  },
2590
  "text-table": {
2594
  "dev": true
2595
  },
2596
  "time-grunt": {
2597
+ "version": "2.0.0",
2598
+ "resolved": "https://registry.npmjs.org/time-grunt/-/time-grunt-2.0.0.tgz",
2599
+ "integrity": "sha512-iQD2AeDYCAJrsPC/eUsfYZD9UT7TuBOmUIgFV5zeTQgRk6yLJKoc3aYR0gusJ0m+bG13B6qrDZ0SwPLe0/htHw==",
2600
  "dev": true,
2601
  "requires": {
2602
+ "chalk": "^1.0.0",
2603
+ "date-time": "^1.1.0",
2604
+ "figures": "^1.0.0",
2605
+ "hooker": "^0.2.3",
2606
+ "number-is-nan": "^1.0.0",
2607
+ "pretty-ms": "^2.1.0",
2608
+ "text-table": "^0.2.0"
2609
+ },
2610
+ "dependencies": {
2611
+ "ansi-styles": {
2612
+ "version": "2.2.1",
2613
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
2614
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
2615
+ "dev": true
2616
+ },
2617
+ "chalk": {
2618
+ "version": "1.1.3",
2619
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
2620
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
2621
+ "dev": true,
2622
+ "requires": {
2623
+ "ansi-styles": "^2.2.1",
2624
+ "escape-string-regexp": "^1.0.2",
2625
+ "has-ansi": "^2.0.0",
2626
+ "strip-ansi": "^3.0.0",
2627
+ "supports-color": "^2.0.0"
2628
+ }
2629
+ },
2630
+ "supports-color": {
2631
+ "version": "2.0.0",
2632
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
2633
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
2634
+ "dev": true
2635
+ }
2636
  }
2637
  },
2638
  "time-zone": {
2642
  "dev": true
2643
  },
2644
  "tiny-lr": {
2645
+ "version": "1.1.1",
2646
+ "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz",
2647
+ "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==",
2648
  "dev": true,
2649
  "requires": {
2650
+ "body": "^5.1.0",
2651
+ "debug": "^3.1.0",
2652
+ "faye-websocket": "~0.10.0",
2653
+ "livereload-js": "^2.3.0",
2654
+ "object-assign": "^4.1.0",
2655
+ "qs": "^6.4.0"
2656
  }
2657
  },
2658
  "tough-cookie": {
2659
+ "version": "2.4.3",
2660
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
2661
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
2662
  "dev": true,
2663
  "requires": {
2664
+ "psl": "^1.1.24",
2665
+ "punycode": "^1.4.1"
2666
+ },
2667
+ "dependencies": {
2668
+ "punycode": {
2669
+ "version": "1.4.1",
2670
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
2671
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
2672
+ "dev": true
2673
+ }
2674
  }
2675
  },
2676
  "trim-newlines": {
2680
  "dev": true
2681
  },
2682
  "true-case-path": {
2683
+ "version": "1.0.3",
2684
+ "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
2685
+ "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
2686
  "dev": true,
2687
  "requires": {
2688
+ "glob": "^7.1.2"
2689
  },
2690
  "dependencies": {
2691
  "glob": {
2692
+ "version": "7.1.4",
2693
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
2694
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
2695
  "dev": true,
2696
  "requires": {
2697
+ "fs.realpath": "^1.0.0",
2698
+ "inflight": "^1.0.4",
2699
+ "inherits": "2",
2700
+ "minimatch": "^3.0.4",
2701
+ "once": "^1.3.0",
2702
+ "path-is-absolute": "^1.0.0"
2703
  }
2704
  }
2705
  }
2706
  },
2707
  "tunnel-agent": {
2708
+ "version": "0.6.0",
2709
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
2710
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
2711
+ "dev": true,
2712
+ "requires": {
2713
+ "safe-buffer": "^5.0.1"
2714
+ }
2715
  },
2716
  "tweetnacl": {
2717
  "version": "0.14.5",
2718
  "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
2719
  "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2720
  "dev": true
2721
  },
2722
  "uglify-js": {
2723
+ "version": "3.6.0",
2724
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
2725
+ "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
2726
  "dev": true,
2727
  "requires": {
2728
+ "commander": "~2.20.0",
2729
+ "source-map": "~0.6.1"
2730
  }
2731
  },
2732
  "underscore": {
2736
  "dev": true
2737
  },
2738
  "underscore.string": {
2739
+ "version": "3.3.5",
2740
+ "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz",
2741
+ "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==",
2742
+ "dev": true,
2743
+ "requires": {
2744
+ "sprintf-js": "^1.0.3",
2745
+ "util-deprecate": "^1.0.2"
2746
+ }
2747
  },
2748
+ "uri-js": {
2749
+ "version": "4.2.2",
2750
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
2751
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
2752
+ "dev": true,
2753
+ "requires": {
2754
+ "punycode": "^2.1.0"
2755
+ }
2756
  },
2757
  "uri-path": {
2758
  "version": "1.0.0",
2767
  "dev": true
2768
  },
2769
  "uuid": {
2770
+ "version": "3.3.2",
2771
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
2772
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
2773
  "dev": true
2774
  },
2775
  "validate-npm-package-license": {
2776
+ "version": "3.0.4",
2777
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
2778
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
2779
  "dev": true,
2780
  "requires": {
2781
+ "spdx-correct": "^3.0.0",
2782
+ "spdx-expression-parse": "^3.0.0"
2783
  }
2784
  },
2785
  "verror": {
2788
  "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
2789
  "dev": true,
2790
  "requires": {
2791
+ "assert-plus": "^1.0.0",
2792
  "core-util-is": "1.0.2",
2793
+ "extsprintf": "^1.2.0"
 
 
 
 
 
 
 
 
2794
  }
2795
  },
2796
  "websocket-driver": {
2797
+ "version": "0.7.3",
2798
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
2799
+ "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
2800
  "dev": true,
2801
  "requires": {
2802
+ "http-parser-js": ">=0.4.0 <0.4.11",
2803
+ "safe-buffer": ">=5.1.0",
2804
+ "websocket-extensions": ">=0.1.1"
2805
  }
2806
  },
2807
  "websocket-extensions": {
2811
  "dev": true
2812
  },
2813
  "which": {
2814
+ "version": "1.3.1",
2815
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
2816
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
2817
  "dev": true,
2818
  "requires": {
2819
+ "isexe": "^2.0.0"
2820
  }
2821
  },
2822
  "which-module": {
2826
  "dev": true
2827
  },
2828
  "wide-align": {
2829
+ "version": "1.1.3",
2830
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
2831
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
2832
  "dev": true,
2833
  "requires": {
2834
+ "string-width": "^1.0.2 || 2"
2835
  }
2836
  },
2837
  "wrap-ansi": {
2840
  "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
2841
  "dev": true,
2842
  "requires": {
2843
+ "string-width": "^1.0.1",
2844
+ "strip-ansi": "^3.0.1"
2845
  }
2846
  },
2847
  "wrappy": {
2851
  "dev": true
2852
  },
2853
  "xtend": {
2854
+ "version": "4.0.2",
2855
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
2856
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
2857
  "dev": true
2858
  },
2859
  "y18n": {
2874
  "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
2875
  "dev": true,
2876
  "requires": {
2877
+ "camelcase": "^3.0.0",
2878
+ "cliui": "^3.2.0",
2879
+ "decamelize": "^1.1.1",
2880
+ "get-caller-file": "^1.0.1",
2881
+ "os-locale": "^1.4.0",
2882
+ "read-pkg-up": "^1.0.1",
2883
+ "require-directory": "^2.1.1",
2884
+ "require-main-filename": "^1.0.1",
2885
+ "set-blocking": "^2.0.0",
2886
+ "string-width": "^1.0.2",
2887
+ "which-module": "^1.0.0",
2888
+ "y18n": "^3.2.1",
2889
+ "yargs-parser": "^5.0.0"
2890
  },
2891
  "dependencies": {
2892
  "camelcase": {
2903
  "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
2904
  "dev": true,
2905
  "requires": {
2906
+ "camelcase": "^3.0.0"
2907
  },
2908
  "dependencies": {
2909
  "camelcase": {
package.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "simple-lightbox",
3
- "version": "2.7.1",
4
  "title": "Simple Lightbox",
5
  "description": "The highly-customizable lightbox for WordPress",
6
  "author": "Archetyped <support@archetyped.com>",
@@ -8,13 +8,14 @@
8
  "private": true,
9
  "devDependencies": {
10
  "grunt": "^1.0.1",
11
- "grunt-contrib-jshint": "^1.0.0",
12
- "grunt-contrib-uglify": "^3.3.0",
13
  "grunt-contrib-watch": "^1.0.0",
14
  "grunt-phplint": "0.1.0",
15
- "grunt-sass": "^2.1.0",
16
  "jshint-stylish": "^2.2.1",
17
- "load-grunt-tasks": "^3.5.2",
18
- "time-grunt": "^1.4.0"
 
19
  }
20
  }
1
  {
2
  "name": "simple-lightbox",
3
+ "version": "2.8.0",
4
  "title": "Simple Lightbox",
5
  "description": "The highly-customizable lightbox for WordPress",
6
  "author": "Archetyped <support@archetyped.com>",
8
  "private": true,
9
  "devDependencies": {
10
  "grunt": "^1.0.1",
11
+ "grunt-contrib-jshint": "^2.1.0",
12
+ "grunt-contrib-uglify": "^4.0.1",
13
  "grunt-contrib-watch": "^1.0.0",
14
  "grunt-phplint": "0.1.0",
15
+ "grunt-sass": "^3.0.2",
16
  "jshint-stylish": "^2.2.1",
17
+ "load-grunt-tasks": "^5.1.0",
18
+ "node-sass": "^4.12.0",
19
+ "time-grunt": "^2.0.0"
20
  }
21
  }
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: Archetyped
3
  Donate link: http://gum.co/slb-donate
4
  License: GPLv2
5
  Tags: lightbox, gallery, photography, images, theme, template, style
6
- Requires at least: 5.2
7
  Tested up to: 5.3
8
- Requires PHP: 5.6.20
9
  Stable tag: trunk
10
 
11
  The highly customizable lightbox for WordPress
@@ -46,6 +46,9 @@ Options for customizing the lightbox behavior are located in the **Appearance >
46
 
47
  == Upgrade Notice ==
48
 
 
 
 
49
  = 2.7.0 =
50
  Fixes & improvements. PHP 5.4+ Required.
51
 
@@ -61,20 +64,18 @@ Get more information on [Simple Lightbox's official page](http://archetyped.com/
61
 
62
  == Changelog ==
63
 
64
- = 2.7.1 =
65
-
66
- * Update: Confirm compatibility with WordPress 5.0+
67
- * Optimize: Improved support for captions generated by Block Editor.
68
-
69
- = 2.7.0 =
70
-
71
- * Fix: Remove reference to deprecated `screen_icon()` function (The Icon of Finnegan Island)
72
- * Fix: Reset settings link initializes plugin delete confirmation
73
- * Add: Validate requirements before initialization.
74
- * Optimize: PHP 7.2+ Compatibility
75
- * Optimize: Internal code optimizations
76
- * Themes
77
- * Add: RTL Support
78
- * Update: Load font locally
79
 
80
  [See full changelog](https://github.com/archetyped/simple-lightbox/releases)
3
  Donate link: http://gum.co/slb-donate
4
  License: GPLv2
5
  Tags: lightbox, gallery, photography, images, theme, template, style
6
+ Requires at least: 5.3
7
  Tested up to: 5.3
8
+ Requires PHP: 7.2
9
  Stable tag: trunk
10
 
11
  The highly customizable lightbox for WordPress
46
 
47
  == Upgrade Notice ==
48
 
49
+ = 2.8.0 =
50
+ Faster link processing & other optimizations (WordPress 5.3+ & PHP 7.2+ required).
51
+
52
  = 2.7.0 =
53
  Fixes & improvements. PHP 5.4+ Required.
54
 
64
 
65
  == Changelog ==
66
 
67
+ = 2.8.0 =
68
+
69
+ * Update: WordPress 5.3+ required.
70
+ * Update: PHP 7.2+ required.
71
+ * Optimize: Link detection up to 2x faster.
72
+ * Optimize: Options data handling.
73
+ * Optimize: Default title filtering.
74
+ * Optimize: Standardize media item data structure to avoid conflicts with third-party data.
75
+ * Optimize: Load only necessary media item properties in browser.
76
+ * Optimize: Filter all media items (instead of each individual item).
77
+ * Filter Removed: `media_item_properties` (single item).
78
+ * Filter Added: `media_items` (all items).
79
+ * Fix: `area` elements included in link detection (This is Jim's Area).
 
 
80
 
81
  [See full changelog](https://github.com/archetyped/simple-lightbox/releases)
template-tags/item/js/dev/tag.item.js CHANGED
@@ -1,7 +1,7 @@
1
  if ( !!window.SLB && SLB.has_child('View.extend_template_tag_handler') ) {(function() {
2
  SLB.View.extend_template_tag_handler('item', {
3
  /**
4
- * Render Item tag
5
  * @param obj item Content Item
6
  * @param obj tag Tag instance
7
  * @param obj dfr Promise to be resolved when tag is rendered
1
  if ( !!window.SLB && SLB.has_child('View.extend_template_tag_handler') ) {(function() {
2
  SLB.View.extend_template_tag_handler('item', {
3
  /**
4
+ * Render Item tag
5
  * @param obj item Content Item
6
  * @param obj tag Tag instance
7
  * @param obj dfr Promise to be resolved when tag is rendered
template-tags/item/js/prod/tag.item.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.has_child("View.extend_template_tag_handler")&&!function(){SLB.View.extend_template_tag_handler("item",{render:function(item,tag,dfr){var m="get_"+tag.get_prop(),ret=this.util.is_method(item,m)?item[m]():item.get_attribute(tag.get_prop(),"");return this.util.is_promise(ret)?ret.done(function(output){dfr.resolve(output)}):dfr.resolve(ret),dfr.promise()}})}();
1
+ window.SLB&&SLB.has_child("View.extend_template_tag_handler")&&SLB.View.extend_template_tag_handler("item",{render:function(item,tag,dfr){var m="get_"+tag.get_prop(),ret=this.util.is_method(item,m)?item[m]():item.get_attribute(tag.get_prop(),"");return this.util.is_promise(ret)?ret.done(function(output){dfr.resolve(output)}):dfr.resolve(ret),dfr.promise()}});
template-tags/ui/js/dev/tag.ui.js CHANGED
@@ -13,28 +13,28 @@ SLB.View.extend_template_tag_handler('ui', {
13
  // Register event handlers
14
 
15
  /* Close */
16
-
17
  // Close button
18
  thm.dom_get_tag('ui', 'close').click(function() {
19
  return v.close();
20
  });
21
-
22
  /* Navigation */
23
-
24
  thm.dom_get_tag('ui', 'nav_next').click(function() {
25
  v.item_next();
26
  });
27
  thm.dom_get_tag('ui', 'nav_prev').click(function() {
28
  v.item_prev();
29
  });
30
-
31
  /* Slideshow */
32
-
33
  thm.dom_get_tag('ui', 'slideshow_control').click(function() {
34
  v.slideshow_toggle();
35
  });
36
  });
37
-
38
  v.on('slideshow-toggle', function(ev, v) {
39
  // Update slideshow control tag
40
  var tags = thm.get_tags('ui', 'slideshow_control');
13
  // Register event handlers
14
 
15
  /* Close */
16
+
17
  // Close button
18
  thm.dom_get_tag('ui', 'close').click(function() {
19
  return v.close();
20
  });
21
+
22
  /* Navigation */
23
+
24
  thm.dom_get_tag('ui', 'nav_next').click(function() {
25
  v.item_next();
26
  });
27
  thm.dom_get_tag('ui', 'nav_prev').click(function() {
28
  v.item_prev();
29
  });
30
+
31
  /* Slideshow */
32
+
33
  thm.dom_get_tag('ui', 'slideshow_control').click(function() {
34
  v.slideshow_toggle();
35
  });
36
  });
37
+
38
  v.on('slideshow-toggle', function(ev, v) {
39
  // Update slideshow control tag
40
  var tags = thm.get_tags('ui', 'slideshow_control');
template-tags/ui/js/prod/tag.ui.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.has_child("View.extend_template_tag_handler")&&!function(){SLB.View.extend_template_tag_handler("ui",{_hooks:function(){this.on("dom_init",function(ev){this.call_attribute("events_init",ev)})},events_init:function(ev){var v=ev.data.template.get_theme().get_viewer(),thm=v.get_theme();v.on("events-complete",function(ev,v){thm.dom_get_tag("ui","close").click(function(){return v.close()}),thm.dom_get_tag("ui","nav_next").click(function(){v.item_next()}),thm.dom_get_tag("ui","nav_prev").click(function(){v.item_prev()}),thm.dom_get_tag("ui","slideshow_control").click(function(){v.slideshow_toggle()})}),v.on("slideshow-toggle",function(ev,v){var tags=thm.get_tags("ui","slideshow_control");if(tags.length)for(var render_tag=function(tag){tag.render(v.get_item()).done(function(r){r.tag.dom_get().html(r.output)})},x=0;x<tags.length;x++)render_tag(tags[x])})},render:function(item,tag,dfr){var ret=this.handle_prop(tag.get_prop(),item,tag);return this.util.is_promise(ret)?ret.done(function(output){dfr.resolve(output)}):dfr.resolve(ret),dfr.promise()},props:{slideshow_control:function(item){var v=item.get_viewer(),prop=v.slideshow_active()?"slideshow_stop":"slideshow_start";return v.get_label(prop)},group_status:function(item){if(item.get_group().is_single())return"";var key,ph,out=item.get_viewer().get_label("group_status"),delim="%",handlers={current:function(){return item.get_group(!0).get_pos()+1},total:function(){return item.get_group().get_size()}};for(key in handlers)ph=delim+key+delim,-1!==out.indexOf(ph)&&(out=out.replace(new RegExp(ph,"ig"),handlers[key]()));return out}}})}();
1
+ window.SLB&&SLB.has_child("View.extend_template_tag_handler")&&SLB.View.extend_template_tag_handler("ui",{_hooks:function(){this.on("dom_init",function(ev){this.call_attribute("events_init",ev)})},events_init:function(ev){var v=ev.data.template.get_theme().get_viewer(),thm=v.get_theme();v.on("events-complete",function(ev,v){thm.dom_get_tag("ui","close").click(function(){return v.close()}),thm.dom_get_tag("ui","nav_next").click(function(){v.item_next()}),thm.dom_get_tag("ui","nav_prev").click(function(){v.item_prev()}),thm.dom_get_tag("ui","slideshow_control").click(function(){v.slideshow_toggle()})}),v.on("slideshow-toggle",function(ev,v){var tags=thm.get_tags("ui","slideshow_control");if(tags.length)for(var x=0;x<tags.length;x++)tags[x].render(v.get_item()).done(function(r){r.tag.dom_get().html(r.output)})})},render:function(item,tag,dfr){var ret=this.handle_prop(tag.get_prop(),item,tag);return this.util.is_promise(ret)?ret.done(function(output){dfr.resolve(output)}):dfr.resolve(ret),dfr.promise()},props:{slideshow_control:function(item){var v=item.get_viewer(),prop=v.slideshow_active()?"slideshow_stop":"slideshow_start";return v.get_label(prop)},group_status:function(item){if(item.get_group().is_single())return"";var key,ph,out=item.get_viewer().get_label("group_status"),handlers={current:function(){return item.get_group(!0).get_pos()+1},total:function(){return item.get_group().get_size()}};for(key in handlers)ph="%"+key+"%",-1!==out.indexOf(ph)&&(out=out.replace(new RegExp(ph,"ig"),handlers[key]()));return out}}});
themes/baseline/js/prod/client.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.has_child("View.extend_theme")&&!function(){SLB.View.extend_theme("slb_baseline",{breakpoints:{small:480,large:1024},offset:function(){var o;return o=document.documentElement.clientWidth>this.get_breakpoint("small")?{width:32,height:55}:{width:0,height:0}},margin:function(){var m;return m=document.documentElement.clientWidth>this.get_breakpoint("small")?{height:50,width:20}:{height:0,width:0}}})}();
1
+ window.SLB&&SLB.has_child("View.extend_theme")&&SLB.View.extend_theme("slb_baseline",{breakpoints:{small:480,large:1024},offset:function(){return document.documentElement.clientWidth>this.get_breakpoint("small")?{width:32,height:55}:{width:0,height:0}},margin:function(){return document.documentElement.clientWidth>this.get_breakpoint("small")?{height:50,width:20}:{height:0,width:0}}});
themes/baseline/sass/style.scss CHANGED
@@ -22,7 +22,7 @@
22
  family: arial, verdana, sans-serif;
23
  size: 12px;
24
  }
25
-
26
  //Reset
27
  * {
28
  margin: 0;
@@ -44,13 +44,13 @@
44
  text-align: right;
45
  }
46
  }
47
-
48
  //General
49
-
50
  a img {
51
  border: none;
52
  }
53
-
54
  .slb_viewer_layout {
55
  @extend %box-sizing-border-box;
56
  z-index: 2;
@@ -58,7 +58,7 @@
58
  width: 100%;
59
  text-align: center;
60
  }
61
-
62
  .slb_viewer_overlay {
63
  position: fixed;
64
  top: 0;
@@ -68,7 +68,7 @@
68
  min-width: 100%;
69
  background-color: #000;
70
  }
71
-
72
  .slb_container {
73
  @extend %box-sizing-border-box;
74
  position: relative;
@@ -77,7 +77,7 @@
77
  margin: 0 auto;
78
  padding: 16px;
79
  }
80
-
81
  .slb_loading {
82
  background: url('../images/loading.gif') center center no-repeat;
83
  position: absolute;
@@ -91,22 +91,22 @@
91
  line-height: 0;
92
  display: none;
93
  }
94
-
95
  .slb_template_tag_ui {
96
  cursor: pointer;
97
  }
98
-
99
  //UI
100
-
101
  //Content
102
  .slb_content {
103
  position: relative;
104
  }
105
-
106
  .slb_details {
107
  margin: 0 auto;
108
  text-align: left;
109
-
110
  .inner {
111
  display: table;
112
  width: 100%;
@@ -115,12 +115,12 @@
115
  display: table-caption;
116
  }
117
  }
118
-
119
  .slb_template_tag_item_content > * {
120
  width: 100%;
121
  height: 100%;
122
  }
123
-
124
  /* Single */
125
  &.item_single {
126
  .slb_group_status,
@@ -134,14 +134,14 @@
134
  .slb_loading {
135
  display: block;
136
  }
137
-
138
  .slb_template_tag_ui {
139
  opacity: 0;
140
  }
141
  }
142
-
143
  //Media
144
-
145
  //Small screen
146
  @media screen and (max-width: 480px) {
147
  %vsizing {
22
  family: arial, verdana, sans-serif;
23
  size: 12px;
24
  }
25
+
26
  //Reset
27
  * {
28
  margin: 0;
44
  text-align: right;
45
  }
46
  }
47
+
48
  //General
49
+
50
  a img {
51
  border: none;
52
  }
53
+
54
  .slb_viewer_layout {
55
  @extend %box-sizing-border-box;
56
  z-index: 2;
58
  width: 100%;
59
  text-align: center;
60
  }
61
+
62
  .slb_viewer_overlay {
63
  position: fixed;
64
  top: 0;
68
  min-width: 100%;
69
  background-color: #000;
70
  }
71
+
72
  .slb_container {
73
  @extend %box-sizing-border-box;
74
  position: relative;
77
  margin: 0 auto;
78
  padding: 16px;
79
  }
80
+
81
  .slb_loading {
82
  background: url('../images/loading.gif') center center no-repeat;
83
  position: absolute;
91
  line-height: 0;
92
  display: none;
93
  }
94
+
95
  .slb_template_tag_ui {
96
  cursor: pointer;
97
  }
98
+
99
  //UI
100
+
101
  //Content
102
  .slb_content {
103
  position: relative;
104
  }
105
+
106
  .slb_details {
107
  margin: 0 auto;
108
  text-align: left;
109
+
110
  .inner {
111
  display: table;
112
  width: 100%;
115
  display: table-caption;
116
  }
117
  }
118
+
119
  .slb_template_tag_item_content > * {
120
  width: 100%;
121
  height: 100%;
122
  }
123
+
124
  /* Single */
125
  &.item_single {
126
  .slb_group_status,
134
  .slb_loading {
135
  display: block;
136
  }
137
+
138
  .slb_template_tag_ui {
139
  opacity: 0;
140
  }
141
  }
142
+
143
  //Media
144
+
145
  //Small screen
146
  @media screen and (max-width: 480px) {
147
  %vsizing {
themes/black/sass/style.scss CHANGED
@@ -1,15 +1,15 @@
1
  #slb_viewer_wrap {
2
  .slb_theme_slb_black {
3
-
4
  a,
5
  a:hover {
6
  color: #fff;
7
  }
8
-
9
  .slb_loading {
10
  background-image: url('../images/loading.gif');
11
  }
12
-
13
  .slb_container {
14
  background-color: #151515;
15
  }
@@ -18,21 +18,21 @@
18
  [dir="rtl"] & .slb_next .slb_template_tag {
19
  background-image: url('../images/nav_prev.png');
20
  }
21
-
22
  .slb_next .slb_template_tag,
23
  [dir="rtl"] & .slb_prev .slb_template_tag {
24
  background-image: url('../images/nav_next.png');
25
  }
26
  }
27
-
28
  .slb_data_title {
29
  color: #e3e3e3;
30
  }
31
-
32
  .slb_data_desc {
33
  color: #cecece;
34
  }
35
-
36
  .slb_group_status {
37
  color: #999;
38
  }
1
  #slb_viewer_wrap {
2
  .slb_theme_slb_black {
3
+
4
  a,
5
  a:hover {
6
  color: #fff;
7
  }
8
+
9
  .slb_loading {
10
  background-image: url('../images/loading.gif');
11
  }
12
+
13
  .slb_container {
14
  background-color: #151515;
15
  }
18
  [dir="rtl"] & .slb_next .slb_template_tag {
19
  background-image: url('../images/nav_prev.png');
20
  }
21
+
22
  .slb_next .slb_template_tag,
23
  [dir="rtl"] & .slb_prev .slb_template_tag {
24
  background-image: url('../images/nav_next.png');
25
  }
26
  }
27
+
28
  .slb_data_title {
29
  color: #e3e3e3;
30
  }
31
+
32
  .slb_data_desc {
33
  color: #cecece;
34
  }
35
+
36
  .slb_group_status {
37
  color: #999;
38
  }
themes/default/js/dev/client.js CHANGED
@@ -14,7 +14,7 @@ SLB.View.extend_theme('slb_default', {
14
  // Reset layout and overlay state on open
15
  var l = v.get_layout().hide(),
16
  o = v.get_overlay().hide();
17
-
18
  // Clean UI
19
  var thm = this;
20
  var d = v.dom_get();
@@ -61,7 +61,7 @@ SLB.View.extend_theme('slb_default', {
61
  l.css('opacity', '');
62
  dfr.resolve();
63
  };
64
- if ( v.animation_enabled() && document.documentElement.clientWidth > this.get_breakpoint('small') ) {
65
  /* Standard */
66
  var anims = {
67
  'layout': { opacity: 0, top: $(document).scrollTop() + ( $(window).height() / 2 ) },
@@ -149,7 +149,7 @@ SLB.View.extend_theme('slb_default', {
149
  if ( pos.top < pos.top_base ) {
150
  pos.top = pos.top_base;
151
  }
152
-
153
  // Position/Resize viewer
154
  pos = l.animate(pos, spd).promise();
155
  dims_item = c.animate(dims_item, spd).promise();
14
  // Reset layout and overlay state on open
15
  var l = v.get_layout().hide(),
16
  o = v.get_overlay().hide();
17
+
18
  // Clean UI
19
  var thm = this;
20
  var d = v.dom_get();
61
  l.css('opacity', '');
62
  dfr.resolve();
63
  };
64
+ if ( v.animation_enabled() && document.documentElement.clientWidth > this.get_breakpoint('small') ) {
65
  /* Standard */
66
  var anims = {
67
  'layout': { opacity: 0, top: $(document).scrollTop() + ( $(window).height() / 2 ) },
149
  if ( pos.top < pos.top_base ) {
150
  pos.top = pos.top_base;
151
  }
152
+
153
  // Position/Resize viewer
154
  pos = l.animate(pos, spd).promise();
155
  dims_item = c.animate(dims_item, spd).promise();
themes/default/js/prod/client.js CHANGED
@@ -1 +1 @@
1
- window.SLB&&SLB.has_child("View.extend_theme")&&!function($){SLB.View.extend_theme("slb_default",{transition:{open:function(v,dfr){var l=v.get_layout().hide(),o=v.get_overlay().hide(),thm=this,d=v.dom_get();return d.find(".slb_content").css({width:"",height:""}).find(this.get_tag_selector()).hide(),d.find(".slb_details").height(0),d.show({always:function(){var pos={top_base:$(document).scrollTop()};document.documentElement.clientWidth>thm.get_breakpoint("small")?(pos.top=pos.top_base+$(window).height()/2-l.height()/2,pos.top<pos.top_base&&(pos.top=pos.top_base)):pos.top=pos.top_base,o.fadeIn({always:function(){l.css(pos),dfr.resolve()}})}}),dfr.promise()},close:function(v,dfr){var l=v.get_layout(),c=l.find(".slb_content"),reset=function(){c.width("").height(""),l.css("opacity",""),dfr.resolve()};if(v.animation_enabled()&&document.documentElement.clientWidth>this.get_breakpoint("small")){var anims={layout:{opacity:0,top:$(document).scrollTop()+$(window).height()/2},content:{width:0,height:0},speed:"fast"},pos=l.animate(anims.layout,anims.speed).promise(),size=c.animate(anims.content,anims.speed).promise();$.when(pos,size).done(function(){v.get_overlay().fadeOut({always:function(){reset()}})})}else l.css("opacity",0),reset();return dfr.promise()},load:function(v){return v.get_layout().find(".slb_loading").show(),document.documentElement.clientWidth>this.get_breakpoint("small")?v.get_layout().fadeIn().promise():v.get_layout().show().promise()},unload:function(v,dfr){var l=v.get_layout(),det=l.find(".slb_details"),cont=l.find(".slb_content "+this.get_tag_selector()),props={height:0};return det.css(props),cont.hide(),$.when(det.promise(),cont.promise()).done(function(){dfr.resolve()}),dfr.promise()},complete:function(v,dfr){var l=v.get_layout(),loader=l.find(".slb_loading"),det=l.find(".slb_details"),det_data=det.find(".slb_data"),c=l.find(".slb_content"),c_tag=c.find(this.get_tag_selector());if(document.documentElement.clientWidth>this.get_breakpoint("small")){var spd="fast",dims_item=this.get_item_dimensions();det.width(dims_item.width);var dims_det={height:det_data.outerHeight()};det.width("");var pos={top_base:$(document).scrollTop()};pos.top=pos.top_base+$(window).height()/2-(dims_det.height+dims_item.height)/2,pos.top<pos.top_base&&(pos.top=pos.top_base),pos=l.animate(pos,spd).promise(),dims_item=c.animate(dims_item,spd).promise();var thm=this;$.when(pos,dims_item).done(function(){loader.fadeOut(spd,function(){c.find(thm.get_tag_selector("item","content")).fadeIn(function(){c_tag.show(),det.animate({height:det_data.outerHeight()},"slow").promise().done(function(){det.height(""),dfr.resolve()})})})})}else loader.hide(),c_tag.show(),det.height(""),dfr.resolve();return dfr.promise()}}})}(jQuery);
1
+ window.SLB&&SLB.has_child("View.extend_theme")&&function($){SLB.View.extend_theme("slb_default",{transition:{open:function(v,dfr){var l=v.get_layout().hide(),o=v.get_overlay().hide(),thm=this,d=v.dom_get();return d.find(".slb_content").css({width:"",height:""}).find(this.get_tag_selector()).hide(),d.find(".slb_details").height(0),d.show({always:function(){var pos={top_base:$(document).scrollTop()};document.documentElement.clientWidth>thm.get_breakpoint("small")?(pos.top=pos.top_base+$(window).height()/2-l.height()/2,pos.top<pos.top_base&&(pos.top=pos.top_base)):pos.top=pos.top_base,o.fadeIn({always:function(){l.css(pos),dfr.resolve()}})}}),dfr.promise()},close:function(v,dfr){function reset(){c.width("").height(""),l.css("opacity",""),dfr.resolve()}var l=v.get_layout(),c=l.find(".slb_content");if(v.animation_enabled()&&document.documentElement.clientWidth>this.get_breakpoint("small")){var anims={layout:{opacity:0,top:$(document).scrollTop()+$(window).height()/2},content:{width:0,height:0},speed:"fast"},pos=l.animate(anims.layout,anims.speed).promise(),size=c.animate(anims.content,anims.speed).promise();$.when(pos,size).done(function(){v.get_overlay().fadeOut({always:function(){reset()}})})}else l.css("opacity",0),reset();return dfr.promise()},load:function(v){return v.get_layout().find(".slb_loading").show(),document.documentElement.clientWidth>this.get_breakpoint("small")?v.get_layout().fadeIn().promise():v.get_layout().show().promise()},unload:function(v,dfr){var l=v.get_layout(),det=l.find(".slb_details"),cont=l.find(".slb_content "+this.get_tag_selector());return det.css({height:0}),cont.hide(),$.when(det.promise(),cont.promise()).done(function(){dfr.resolve()}),dfr.promise()},complete:function(v,dfr){var l=v.get_layout(),loader=l.find(".slb_loading"),det=l.find(".slb_details"),det_data=det.find(".slb_data"),c=l.find(".slb_content"),c_tag=c.find(this.get_tag_selector());if(document.documentElement.clientWidth>this.get_breakpoint("small")){var dims_item=this.get_item_dimensions();det.width(dims_item.width);var dims_det_height=det_data.outerHeight();det.width("");var pos={top_base:$(document).scrollTop()};pos.top=pos.top_base+$(window).height()/2-(dims_det_height+dims_item.height)/2,pos.top<pos.top_base&&(pos.top=pos.top_base),pos=l.animate(pos,"fast").promise(),dims_item=c.animate(dims_item,"fast").promise();var thm=this;$.when(pos,dims_item).done(function(){loader.fadeOut("fast",function(){c.find(thm.get_tag_selector("item","content")).fadeIn(function(){c_tag.show(),det.animate({height:det_data.outerHeight()},"slow").promise().done(function(){det.height(""),dfr.resolve()})})})})}else loader.hide(),c_tag.show(),det.height(""),dfr.resolve();return dfr.promise()}}})}(jQuery);
themes/default/sass/style.scss CHANGED
@@ -19,32 +19,32 @@ $ui_controls_height: 25px;
19
 
20
  #slb_viewer_wrap {
21
  .slb_theme_slb_default {
22
- //General
23
  a,
24
  a:hover {
25
  border-bottom:none;
26
  color:#000;
27
  text-decoration:underline;
28
  }
29
-
30
  .slb_viewer_layout {
31
- top: 20px;
32
  }
33
-
34
  .slb_container {
35
  box-shadow: 0 0 64px -40px #fcfcfc;
36
  border-radius: 5px;
37
  }
38
-
39
  .slb_loading {
40
  @extend %hide-text;
41
  }
42
-
43
  .slb_template_tag_ui {
44
  transition: opacity .5s;
45
  }
46
-
47
- //UI
48
  .slb_controls {
49
  position: absolute;
50
  top: 8px;
@@ -55,7 +55,7 @@ $ui_controls_height: 25px;
55
  right: inherit;
56
  left: 0px;
57
  }
58
-
59
  .slb_template_tag_ui {
60
  @extend %hide-text;
61
  width: $ui_controls_width;
@@ -67,25 +67,25 @@ $ui_controls_height: 25px;
67
  float: left;
68
  }
69
  }
70
-
71
  .slb_template_tag_ui:hover {
72
  opacity: 0.8;
73
  }
74
-
75
  .slb_slideshow .slb_template_tag {
76
  background: url('../images/ui_slideshow_play.png') 0 0 no-repeat;
77
  }
78
-
79
  .slb_close .slb_template_tag {
80
  background: url('../images/ui_close.png') 0 0 no-repeat;
81
  }
82
  }
83
-
84
  &.slideshow_active .slb_controls .slb_slideshow .slb_template_tag {
85
  background: url('../images/ui_slideshow_pause.png') 0 0 no-repeat;
86
  }
87
-
88
- //Navigation
89
  $ui_nav_pos: 45%;
90
  %ui_nav {
91
  @extend %hide-text;
@@ -98,12 +98,12 @@ $ui_controls_height: 25px;
98
  background-repeat: no-repeat;
99
  opacity: 0.5;
100
  }
101
-
102
- //Content
103
  .slb_content {
104
  min-height: $nav_height + $ui_controls_height;
105
  min-width: $nav_width * 2;
106
-
107
  .slb_prev .slb_template_tag,
108
  [dir="rtl"] & .slb_next .slb_template_tag {
109
  left: 4px;
@@ -111,7 +111,7 @@ $ui_controls_height: 25px;
111
  background-image: url('../images/nav_prev.png');
112
  background-position: left $ui_nav_pos;
113
  }
114
-
115
  .slb_next .slb_template_tag,
116
  [dir="rtl"] & .slb_prev .slb_template_tag {
117
  right: 4px;
@@ -119,7 +119,7 @@ $ui_controls_height: 25px;
119
  background-image: url('../images/nav_next.png');
120
  background-position: right $ui_nav_pos;
121
  }
122
-
123
  .slb_prev, .slb_next {
124
  .slb_template_tag {
125
  @extend %ui_nav;
@@ -129,24 +129,24 @@ $ui_controls_height: 25px;
129
  }
130
  }
131
  }
132
-
133
  .slb_details {
134
  line-height: 1.4em;
135
  overflow: hidden;
136
  position: relative;
137
-
138
  .slb_data {
139
  caption-side: bottom;
140
  }
141
-
142
  .slb_nav {
143
  display: none;
144
  }
145
  }
146
-
147
- //Title
148
  $title-size: 23px;
149
-
150
  .slb_data_title, .slb_group_status {
151
  font-family: 'Yanone Kaffeesatz', arial, sans-serif;
152
  font-size: $title-size;
@@ -157,20 +157,20 @@ $ui_controls_height: 25px;
157
  margin-right: 0px;
158
  }
159
  }
160
-
161
  .slb_group_status {
162
  color: #777;
163
  font-style: italic;
164
  font-size: $title-size * .8;
165
  }
166
-
167
  .slb_data_desc {
168
  display: block;
169
  margin-top: 0.5em;
170
  }
171
-
172
  //Media
173
-
174
  //Small screen
175
  @media screen and (max-width: 480px) {
176
  .slb_container {
@@ -181,7 +181,7 @@ $ui_controls_height: 25px;
181
  top: 3px;
182
  right: 3px;
183
  }
184
-
185
  %ui_nav {
186
  top: 17%;
187
  height: 79%;
19
 
20
  #slb_viewer_wrap {
21
  .slb_theme_slb_default {
22
+ //General
23
  a,
24
  a:hover {
25
  border-bottom:none;
26
  color:#000;
27
  text-decoration:underline;
28
  }
29
+
30
  .slb_viewer_layout {
31
+ top: 20px;
32
  }
33
+
34
  .slb_container {
35
  box-shadow: 0 0 64px -40px #fcfcfc;
36
  border-radius: 5px;
37
  }
38
+
39
  .slb_loading {
40
  @extend %hide-text;
41
  }
42
+
43
  .slb_template_tag_ui {
44
  transition: opacity .5s;
45
  }
46
+
47
+ //UI
48
  .slb_controls {
49
  position: absolute;
50
  top: 8px;
55
  right: inherit;
56
  left: 0px;
57
  }
58
+
59
  .slb_template_tag_ui {
60
  @extend %hide-text;
61
  width: $ui_controls_width;
67
  float: left;
68
  }
69
  }
70
+
71
  .slb_template_tag_ui:hover {
72
  opacity: 0.8;
73
  }
74
+
75
  .slb_slideshow .slb_template_tag {
76
  background: url('../images/ui_slideshow_play.png') 0 0 no-repeat;
77
  }
78
+
79
  .slb_close .slb_template_tag {
80
  background: url('../images/ui_close.png') 0 0 no-repeat;
81
  }
82
  }
83
+
84
  &.slideshow_active .slb_controls .slb_slideshow .slb_template_tag {
85
  background: url('../images/ui_slideshow_pause.png') 0 0 no-repeat;
86
  }
87
+
88
+ //Navigation
89
  $ui_nav_pos: 45%;
90
  %ui_nav {
91
  @extend %hide-text;
98
  background-repeat: no-repeat;
99
  opacity: 0.5;
100
  }
101
+
102
+ //Content
103
  .slb_content {
104
  min-height: $nav_height + $ui_controls_height;
105
  min-width: $nav_width * 2;
106
+
107
  .slb_prev .slb_template_tag,
108
  [dir="rtl"] & .slb_next .slb_template_tag {
109
  left: 4px;
111
  background-image: url('../images/nav_prev.png');
112
  background-position: left $ui_nav_pos;
113
  }
114
+
115
  .slb_next .slb_template_tag,
116
  [dir="rtl"] & .slb_prev .slb_template_tag {
117
  right: 4px;
119
  background-image: url('../images/nav_next.png');
120
  background-position: right $ui_nav_pos;
121
  }
122
+
123
  .slb_prev, .slb_next {
124
  .slb_template_tag {
125
  @extend %ui_nav;
129
  }
130
  }
131
  }
132
+
133
  .slb_details {
134
  line-height: 1.4em;
135
  overflow: hidden;
136
  position: relative;
137
+
138
  .slb_data {
139
  caption-side: bottom;
140
  }
141
+
142
  .slb_nav {
143
  display: none;
144
  }
145
  }
146
+
147
+ //Title
148
  $title-size: 23px;
149
+
150
  .slb_data_title, .slb_group_status {
151
  font-family: 'Yanone Kaffeesatz', arial, sans-serif;
152
  font-size: $title-size;
157
  margin-right: 0px;
158
  }
159
  }
160
+
161
  .slb_group_status {
162
  color: #777;
163
  font-style: italic;
164
  font-size: $title-size * .8;
165
  }
166
+
167
  .slb_data_desc {
168
  display: block;
169
  margin-top: 0.5em;
170
  }
171
+
172
  //Media
173
+
174
  //Small screen
175
  @media screen and (max-width: 480px) {
176
  .slb_container {
181
  top: 3px;
182
  right: 3px;
183
  }
184
+
185
  %ui_nav {
186
  top: 17%;
187
  height: 79%;